From e99954fe636e45ea56e20c41f5f3570fd3e6a387 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Iv=C3=A1n=20G=C3=B3mez=20Pinta?=
<44321109+GomezIvann@users.noreply.github.com>
Date: Thu, 10 Apr 2025 11:43:01 +0200
Subject: [PATCH 1/4] Image component refactor
---
apps/website/pages/components/image/code.tsx | 17 +++
apps/website/pages/components/image/index.tsx | 24 ++---
apps/website/pages/components/image/usage.tsx | 21 ----
.../components/image/ImagePageLayout.tsx | 8 +-
.../components/image/code/ImageCodePage.tsx | 102 +++++++++---------
.../ImageOverviewPage.tsx} | 40 ++++---
packages/lib/src/image/Image.tsx | 71 ++++++------
packages/lib/src/image/types.ts | 6 --
8 files changed, 134 insertions(+), 155 deletions(-)
create mode 100644 apps/website/pages/components/image/code.tsx
delete mode 100644 apps/website/pages/components/image/usage.tsx
rename apps/website/screens/components/image/{usage/ImageUsagePage.tsx => overview/ImageOverviewPage.tsx} (86%)
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..245d4b0355 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. |
- |
diff --git a/apps/website/screens/components/image/usage/ImageUsagePage.tsx b/apps/website/screens/components/image/overview/ImageOverviewPage.tsx
similarity index 86%
rename from apps/website/screens/components/image/usage/ImageUsagePage.tsx
rename to apps/website/screens/components/image/overview/ImageOverviewPage.tsx
index cdb24b8e7d..c4c8d4780d 100644
--- a/apps/website/screens/components/image/usage/ImageUsagePage.tsx
+++ b/apps/website/screens/components/image/overview/ImageOverviewPage.tsx
@@ -6,11 +6,11 @@ import QuickNavContainerLayout from "@/common/QuickNavContainerLayout";
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.
@@ -102,39 +102,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 +142,13 @@ const sections = [
},
];
-const ImageUsagePage = () => {
- return (
-
-
-
-
-
-
- );
-};
+const ImageOverviewPage = () => (
+
+
+
+
+
+
+);
-export default ImageUsagePage;
+export default ImageOverviewPage;
diff --git a/packages/lib/src/image/Image.tsx b/packages/lib/src/image/Image.tsx
index 01c1d9a898..5f3d1b3193 100644
--- a/packages/lib/src/image/Image.tsx
+++ b/packages/lib/src/image/Image.tsx
@@ -1,24 +1,23 @@
-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-ml);
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-m);
+ font-style: normal;
+ font-weight: var(--typography-label-regular);
+ line-height: normal;
`;
const CaptionWrapper = ({ caption, children }: { caption: ImagePropsType["caption"]; children: ReactNode }) =>
@@ -34,38 +33,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 (
-
-
-
-
-
+
+
+
);
}
diff --git a/packages/lib/src/image/types.ts b/packages/lib/src/image/types.ts
index c78742f830..e06cce9c85 100644
--- a/packages/lib/src/image/types.ts
+++ b/packages/lib/src/image/types.ts
@@ -66,10 +66,4 @@ type Props = {
onError?: ReactEventHandler;
};
-export type CaptionWrapperProps = {
- condition: boolean;
- wrapper: (children: ReactNode) => JSX.Element;
- children: ReactNode;
-};
-
export default Props;
From be7d20dabe88b649f2bb50ed8db1b7761d99d73c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Iv=C3=A1n=20G=C3=B3mez=20Pinta?=
<44321109+GomezIvann@users.noreply.github.com>
Date: Thu, 10 Apr 2025 12:56:43 +0200
Subject: [PATCH 2/4] Image design & doc updates
---
.../image/overview/ImageOverviewPage.tsx | 24 +++++++++++++++++-
.../image/overview/images/image_anatomy.png | Bin 0 -> 364745 bytes
packages/lib/src/image/Image.tsx | 6 ++---
3 files changed, 25 insertions(+), 5 deletions(-)
create mode 100644 apps/website/screens/components/image/overview/images/image_anatomy.png
diff --git a/apps/website/screens/components/image/overview/ImageOverviewPage.tsx b/apps/website/screens/components/image/overview/ImageOverviewPage.tsx
index c4c8d4780d..5aa798ba45 100644
--- a/apps/website/screens/components/image/overview/ImageOverviewPage.tsx
+++ b/apps/website/screens/components/image/overview/ImageOverviewPage.tsx
@@ -1,8 +1,10 @@
-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 = [
{
@@ -30,6 +32,26 @@ const sections = [
>
),
},
+ {
+ title: "Anatomy",
+ content: (
+ <>
+
+
+
+ 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: (
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 0000000000000000000000000000000000000000..87e669238e3b50ab1eede31e5e7db95e1ea8a126
GIT binary patch
literal 364745
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