diff --git a/apps/website/pages/components/image/code.tsx b/apps/website/pages/components/image/code.tsx new file mode 100644 index 0000000000..414f22b22b --- /dev/null +++ b/apps/website/pages/components/image/code.tsx @@ -0,0 +1,17 @@ +import Head from "next/head"; +import type { ReactElement } from "react"; +import ImageCodePage from "screens/components/image/code/ImageCodePage"; +import ImagePageLayout from "screens/components/image/ImagePageLayout"; + +const Code = () => ( + <> + + Image code — Halstack Design System + + + +); + +Code.getLayout = (page: ReactElement) => {page}; + +export default Code; diff --git a/apps/website/pages/components/image/index.tsx b/apps/website/pages/components/image/index.tsx index 6c2f07f025..96c0877704 100644 --- a/apps/website/pages/components/image/index.tsx +++ b/apps/website/pages/components/image/index.tsx @@ -1,21 +1,17 @@ import Head from "next/head"; import type { ReactElement } from "react"; import ImagePageLayout from "screens/components/image/ImagePageLayout"; -import ImageCodePage from "screens/components/image/code/ImageCodePage"; +import ImageOverviewPage from "screens/components/image/overview/ImageOverviewPage"; -const Index = () => { - return ( - <> - - Image — Halstack Design System - - - - ); -}; +const Index = () => ( + <> + + Image — Halstack Design System + + + +); -Index.getLayout = function getLayout(page: ReactElement) { - return {page}; -}; +Index.getLayout = (page: ReactElement) => {page}; export default Index; diff --git a/apps/website/pages/components/image/usage.tsx b/apps/website/pages/components/image/usage.tsx deleted file mode 100644 index 2649e3fd21..0000000000 --- a/apps/website/pages/components/image/usage.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import Head from "next/head"; -import type { ReactElement } from "react"; -import ImagePageLayout from "screens/components/image/ImagePageLayout"; -import ImageUsagePage from "screens/components/image/usage/ImageUsagePage"; - -const Usage = () => { - return ( - <> - - Image Usage — Halstack Design System - - - - ); -}; - -Usage.getLayout = function getLayout(page: ReactElement) { - return {page}; -}; - -export default Usage; diff --git a/apps/website/screens/components/image/ImagePageLayout.tsx b/apps/website/screens/components/image/ImagePageLayout.tsx index 8935daceba..3de90020ef 100644 --- a/apps/website/screens/components/image/ImagePageLayout.tsx +++ b/apps/website/screens/components/image/ImagePageLayout.tsx @@ -6,8 +6,8 @@ import { ReactNode } from "react"; const ImagePageHeading = ({ children }: { children: ReactNode }) => { const tabs = [ - { label: "Code", path: "/components/image" }, - { label: "Usage", path: "/components/image/usage" }, + { label: "Overview", path: "/components/image" }, + { label: "Code", path: "/components/image/code" }, ]; return ( @@ -15,8 +15,8 @@ const ImagePageHeading = ({ children }: { children: ReactNode }) => { - The Image component is used to embed images in Halstack-based user interfaces. - + The image component is used to embed images in Halstack-based user interfaces. + {children} diff --git a/apps/website/screens/components/image/code/ImageCodePage.tsx b/apps/website/screens/components/image/code/ImageCodePage.tsx index 3a5adb2ddf..1b00474b3e 100644 --- a/apps/website/screens/components/image/code/ImageCodePage.tsx +++ b/apps/website/screens/components/image/code/ImageCodePage.tsx @@ -53,6 +53,14 @@ const sections = [ - + + height + + string + + Sets the rendered height of the image. + - + lazyLoading @@ -67,110 +75,102 @@ const sections = [ + objectFit - - - src - - - - string - - URL of the image. - - - - - srcSet - - string + 'contain' | 'cover' | 'fill' | 'none' | 'scale-down' - List of one or more strings separated by commas indicating a set of possible images for the user agent to - use. See{" "} - + Sets the object-fit CSS property. See{" "} + MDN {" "} for further information. - - + + 'fill' + - sizes + objectPosition string - One or more strings separated by commas, indicating a set of source sizes. If the srcSet{" "} - attribute is absent or contains no values with a width descriptor, then this attribute has no effect. See{" "} - + Sets the object-position CSS property. See{" "} + MDN {" "} for further information. - - + + '50% 50%' + - width + onError - string + {"React.ReactEventHandler "} - Sets the rendered width of the image. + This function will be called when the image fails to load. - - height + onLoad - string + {"React.ReactEventHandler "} - Sets the rendered height of the image. + This function will be called when the image is loaded. - - objectFit + sizes - 'contain' | 'cover' | 'fill' | 'none' | 'scale-down' + string - Sets the object-fit CSS property. See{" "} - + One or more strings separated by commas, indicating a set of source sizes. If the srcSet{" "} + attribute is absent or contains no values with a width descriptor, then this attribute has no effect. See{" "} + MDN {" "} for further information. + - + + - 'fill' + + + src + + + + string + URL of the image. + - - objectPosition + srcSet string - Sets the object-position CSS property. See{" "} - + List of one or more strings separated by commas indicating a set of possible images for the user agent to + use. See{" "} + MDN {" "} for further information. - - '50% 50%' - - - - onLoad - - {"React.ReactEventHandler "} - - This function will be called when the image is loaded. - - onError + width - {"React.ReactEventHandler "} + string - This function will be called when the image fails to load. + Sets the rendered width of the image. - @@ -187,15 +187,13 @@ const sections = [ }, ]; -const ImageCodePage = () => { - return ( - - - - - - - ); -}; +const ImageCodePage = () => ( + + + + + + +); export default ImageCodePage; diff --git a/apps/website/screens/components/image/usage/ImageUsagePage.tsx b/apps/website/screens/components/image/overview/ImageOverviewPage.tsx similarity index 76% rename from apps/website/screens/components/image/usage/ImageUsagePage.tsx rename to apps/website/screens/components/image/overview/ImageOverviewPage.tsx index cdb24b8e7d..5aa798ba45 100644 --- a/apps/website/screens/components/image/usage/ImageUsagePage.tsx +++ b/apps/website/screens/components/image/overview/ImageOverviewPage.tsx @@ -1,16 +1,18 @@ -import { DxcImage, DxcParagraph, DxcFlex, DxcBulletedList } from "@dxc-technology/halstack-react"; +import { DxcParagraph, DxcFlex, DxcBulletedList } from "@dxc-technology/halstack-react"; import Code from "@/common/Code"; import DocFooter from "@/common/DocFooter"; import QuickNavContainer from "@/common/QuickNavContainer"; import QuickNavContainerLayout from "@/common/QuickNavContainerLayout"; +import Image from "@/common/Image"; +import anatomy from "./images/image_anatomy.png"; const sections = [ { - title: "Overview", + title: "Introduction", content: ( <> - The Image component serves as a versatile tool for efficiently loading and displaying visual content across + The image component serves as a versatile tool for efficiently loading and displaying visual content across diverse contexts within your application. This powerful component is designed to optimize performance while enhancing the overall user experience. By leveraging its capabilities, developers can seamlessly integrate images into their projects, ensuring smooth rendering and responsive behavior. @@ -30,6 +32,26 @@ const sections = [ ), }, + { + title: "Anatomy", + content: ( + <> + Image's anatomy + + + Image: a visual element used to illustrate content, provide context, or support + storytelling. It should be relevant and meaningful, helping users better understand the subject or message + being conveyed. + + + Caption (Optional): a short piece of descriptive text placed below the image. It + provides context, credits, or additional explanation for the image, improving accessibility and user + comprehension. + + + + ), + }, { title: "Accessibility", content: ( @@ -102,39 +124,39 @@ const sections = [ content: ( - Use high-quality images. Always use high-resolution images to deliver a crisp and clear + Use high-quality images: always use high-resolution images to deliver a crisp and clear display, especially on high-density (retina) screens. This ensures a professional look and prevents pixelation. - Optimize images. Compress and optimize images for the web to minimize file sizes. Reducing + Optimize images: compress and optimize images for the web to minimize file sizes. Reducing load times and bandwidth consumption is crucial for performance, especially on mobile devices. - Leverage modern formats. Whenever possible, use newer image formats like WebP for improved + Leverage modern formats: whenever possible, use newer image formats like WebP for improved compression without sacrificing quality. Be sure to provide fallback formats for browsers that don't support them. - Allow lazy loading. Implement lazy loading (loading="lazy") for images that + Allow lazy loading: implement lazy loading (loading="lazy") for images that appear later on the page (below the fold). This helps speed up initial page loads and improve overall performance. - Use responsive image techniques. Make use of srcset and sizes props + Use responsive image techniques: make use of srcset and sizes props to serve images that adapt to different screen resolutions and sizes, ensuring the best display quality across devices. - Avoid using images for text content. Text embedded within images reduces accessibility and + Avoid using images for text content: text embedded within images reduces accessibility and harms SEO. Always use HTML text to ensure readability by screen readers and search engines. - Limit decorative images. Avoid overloading pages with unnecessary decorative images. This not + Limit decorative images: avoid overloading pages with unnecessary decorative images. This not only reduces performance but can also distract users from the main content. - Avoid images for icons. Use scalable vector graphics (SVGs) instead of images for icons. SVGs + Avoid images for icons: use scalable vector graphics (SVGs) instead of images for icons. SVGs offer better performance, scalability, and accessibility across various screen sizes. @@ -142,15 +164,13 @@ const sections = [ }, ]; -const ImageUsagePage = () => { - return ( - - - - - - - ); -}; +const ImageOverviewPage = () => ( + + + + + + +); -export default ImageUsagePage; +export default ImageOverviewPage; diff --git a/apps/website/screens/components/image/overview/images/image_anatomy.png b/apps/website/screens/components/image/overview/images/image_anatomy.png new file mode 100644 index 0000000000..87e669238e Binary files /dev/null and b/apps/website/screens/components/image/overview/images/image_anatomy.png differ diff --git a/packages/lib/src/image/Image.tsx b/packages/lib/src/image/Image.tsx index 01c1d9a898..05e8e92ec9 100644 --- a/packages/lib/src/image/Image.tsx +++ b/packages/lib/src/image/Image.tsx @@ -1,24 +1,21 @@ -import styled, { ThemeProvider } from "styled-components"; -import { ReactNode, useCallback, useContext } from "react"; -import ImagePropsType, { CaptionWrapperProps } from "./types"; -import HalstackContext from "../HalstackContext"; +import styled from "styled-components"; +import { ReactNode } from "react"; +import ImagePropsType from "./types"; const Figure = styled.figure` display: flex; flex-direction: column; - gap: 1rem; + gap: var(--spacing-gap-s); width: fit-content; margin: 0; padding: 0; `; const CaptionContainer = styled.figcaption` - color: ${(props) => props.theme.captionFontColor}; - font-family: ${(props) => props.theme.captionFontFamily}; - font-size: ${(props) => props.theme.captionFontSize}; - font-style: ${(props) => props.theme.captionFontStyle}; - font-weight: ${(props) => props.theme.captionFontWeight}; - line-height: ${(props) => props.theme.captionLineHeight}; + color: var(--color-fg-neutral-dark); + font-family: var(--typography-font-family); + font-size: var(--typography-label-s); + font-weight: var(--typography-label-regular); `; const CaptionWrapper = ({ caption, children }: { caption: ImagePropsType["caption"]; children: ReactNode }) => @@ -34,38 +31,34 @@ const CaptionWrapper = ({ caption, children }: { caption: ImagePropsType["captio export default function DxcImage({ alt, caption, - lazyLoading = false, - src, - srcSet, - sizes, - width, height, + lazyLoading = false, objectFit, objectPosition, - onLoad, onError, + onLoad, + sizes, + src, + srcSet, + width, }: ImagePropsType) { - const colorsTheme = useContext(HalstackContext); - return ( - - - {alt} - - + + {alt} + ); } diff --git a/packages/lib/src/image/types.ts b/packages/lib/src/image/types.ts index c78742f830..15d741890f 100644 --- a/packages/lib/src/image/types.ts +++ b/packages/lib/src/image/types.ts @@ -1,4 +1,4 @@ -import { ReactEventHandler, ReactNode } from "react"; +import { ReactEventHandler } from "react"; type Props = { /** @@ -13,21 +13,35 @@ type Props = { * which is required regardless of the presence of the caption or not. */ caption?: string; + /** + * Sets the rendered height of the image. + */ + height?: string; /** * If true, the image will be loaded only when it is visible on the screen (lazy loading). * Otherwise and by default, the image will be loaded as soon as the component is mounted (eager loading). */ lazyLoading?: boolean; /** - * URL of the image. This prop is required and must be valid. + * Sets the object-fit CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit */ - src: string; + objectFit?: "contain" | "cover" | "fill" | "none" | "scale-down"; /** - * List of one or more strings separated by commas indicating a set of possible images for the user agent to use. + * Sets the object-position CSS property. * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/srcset + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/object-position */ - srcSet?: string; + objectPosition?: string; + /** + * This function will be called when the image fails to load. + */ + onError?: ReactEventHandler; + /** + * This function will be called when the image is loaded. + */ + onLoad?: ReactEventHandler; /** * One or more strings separated by commas, indicating a set of source sizes. * If the srcSet attribute is absent or contains no values with a width descriptor, @@ -37,39 +51,19 @@ type Props = { */ sizes?: string; /** - * Sets the rendered width of the image. - */ - width?: string; - /** - * Sets the rendered height of the image. - */ - height?: string; - /** - * Sets the object-fit CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit + * URL of the image. This prop is required and must be valid. */ - objectFit?: "contain" | "cover" | "fill" | "none" | "scale-down"; + src: string; /** - * Sets the object-position CSS property. + * List of one or more strings separated by commas indicating a set of possible images for the user agent to use. * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/object-position - */ - objectPosition?: string; - /** - * This function will be called when the image is loaded. + * See MDN: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/srcset */ - onLoad?: ReactEventHandler; + srcSet?: string; /** - * This function will be called when the image fails to load. + * Sets the rendered width of the image. */ - onError?: ReactEventHandler; -}; - -export type CaptionWrapperProps = { - condition: boolean; - wrapper: (children: ReactNode) => JSX.Element; - children: ReactNode; + width?: string; }; export default Props;