diff --git a/apps/website/pages/_app.tsx b/apps/website/pages/_app.tsx index 236dbabce..928f4ec85 100644 --- a/apps/website/pages/_app.tsx +++ b/apps/website/pages/_app.tsx @@ -5,7 +5,7 @@ import Head from "next/head"; import { DxcApplicationLayout, DxcTextInput, DxcToastsQueue } from "@dxc-technology/halstack-react"; import MainContent from "@/common/MainContent"; import { useRouter } from "next/router"; -import { LinksSectionDetails, LinksSections } from "@/common/pagesList"; +import { LinkDetails, LinksSectionDetails, LinksSections } from "@/common/pagesList"; import StatusBadge from "@/common/StatusBadge"; import "../global-styles.css"; import createCache, { EmotionCache } from "@emotion/cache"; @@ -33,66 +33,70 @@ export default function App({ Component, pageProps, emotionCache = clientSideEmo const [isExpanded, setIsExpanded] = useState(true); const { asPath: currentPath } = useRouter(); - const filterSections = (sections: Section[], query: string): Section[] => { - const q = query.trim().toLowerCase(); - if (!q) return sections; + const matchPaths = (linkPath: string) => { + const desiredPaths = [linkPath, `${linkPath}/code`]; + const pathToBeMatched = currentPath?.split("#")[0]?.slice(0, -1); + return pathToBeMatched ? desiredPaths.includes(pathToBeMatched) : false; + }; - const filterItem = (item: Item | GroupItem): Item | GroupItem | null => { - const labelMatches = item.label.toLowerCase().includes(q); + const createNavItem = (link: LinkDetails): Item => ({ + label: link.label, + href: link.path, + selected: matchPaths(link.path), + badge: link.status && link.status !== "stable" ? : undefined, + renderItem: ({ children }: { children: ReactNode }) => ( + + {children} + + ), + }); - if (!isGroupItem(item)) return labelMatches ? item : null; + const normalizeNavTabs = (links: (LinkDetails | LinksSectionDetails)[]): (Item | GroupItem)[] => { + return links.map((link) => { + if ("links" in link) { + return { + label: link.label, + items: normalizeNavTabs(link.links), + } as GroupItem; + } - const items = item.items.reduce<(Item | GroupItem)[]>((acc, child) => { - const filtered = filterItem(child); - if (filtered) acc.push(filtered); - return acc; - }, []); + return createNavItem(link); + }); + }; - return labelMatches || items.length ? { ...item, items } : null; - }; + const filterNavTree = (items: (Item | GroupItem)[], q: string): (Item | GroupItem)[] => { + const result: (Item | GroupItem)[] = []; - return sections.reduce((acc, section) => { - const items = section.items.reduce<(Item | GroupItem)[]>((acc, item) => { - const filtered = filterItem(item); - if (filtered) acc.push(filtered); - return acc; - }, []); - if (items.length) acc.push({ ...section, items }); - return acc; - }, []); - }; + for (const item of items) { + if (isGroupItem(item)) { + const filteredChildren = filterNavTree(item.items, q); + const matches = item.label.toLowerCase().includes(q); - const mapLinksToGroupItems = (sections: LinksSectionDetails[]): Section[] => { - const matchPaths = (linkPath: string) => { - const desiredPaths = [linkPath, `${linkPath}/code`]; - const pathToBeMatched = currentPath?.split("#")[0]?.slice(0, -1); - return pathToBeMatched ? desiredPaths.includes(pathToBeMatched) : false; - }; + if (matches || filteredChildren.length > 0) { + result.push({ ...item, items: filteredChildren }); + } + } else { + if (item.label.toLowerCase().includes(q)) { + result.push(item); + } + } + } - return sections.map((section) => ({ - title: section.label, - items: section.links.map((link) => ({ - label: link.label, - href: link.path, - selected: matchPaths(link.path), - ...(link.status && { - badge: link.status !== "stable" ? : undefined, - }), - renderItem: ({ children }: { children: ReactNode }) => ( - - {children} - - ), - })), - })); + return result; }; - // TODO: ADD NEW CATEGORIZATION + const navItems: Section[] = useMemo(() => { + return LinksSections.map((section) => { + const baseItems = normalizeNavTabs(section.links); + + const items = filter ? filterNavTree(baseItems, filter.trim().toLowerCase()) : baseItems; - const filteredSections = useMemo(() => { - const sections = mapLinksToGroupItems(LinksSections); - return filterSections(sections, filter); - }, [filter]); + return { + title: section.label, + items, + }; + }).filter((section) => section.items.length > 0); + }, [currentPath, filter]); return ( @@ -103,14 +107,14 @@ export default function App({ Component, pageProps, emotionCache = clientSideEmo header={} sidenav={ } topContent={ isExpanded && ( { + onChange={({ value }) => { setFilter(value); }} size="fillParent" diff --git a/apps/website/pages/foundations/tokens/alias.tsx b/apps/website/pages/foundations/tokens/alias.tsx new file mode 100644 index 000000000..1e795f28f --- /dev/null +++ b/apps/website/pages/foundations/tokens/alias.tsx @@ -0,0 +1,13 @@ +import Head from "next/head"; +import AliasTokensPage from "screens/foundations/tokens/AliasTokenList"; + +const Tokens = () => ( + <> + + Alias Tokens — Halstack Design System + + + +); + +export default Tokens; diff --git a/apps/website/pages/foundations/tokens/core.tsx b/apps/website/pages/foundations/tokens/core.tsx new file mode 100644 index 000000000..81f02310d --- /dev/null +++ b/apps/website/pages/foundations/tokens/core.tsx @@ -0,0 +1,13 @@ +import Head from "next/head"; +import CoreTokensPage from "screens/foundations/tokens/CoreTokenList"; + +const Tokens = () => ( + <> + + Core Tokens — Halstack Design System + + + +); + +export default Tokens; diff --git a/apps/website/pages/foundations/tokens.tsx b/apps/website/pages/foundations/tokens/index.tsx similarity index 100% rename from apps/website/pages/foundations/tokens.tsx rename to apps/website/pages/foundations/tokens/index.tsx diff --git a/apps/website/pages/migration/16/component-updates.tsx b/apps/website/pages/migration/16/component-updates.tsx new file mode 100644 index 000000000..0292cb1a7 --- /dev/null +++ b/apps/website/pages/migration/16/component-updates.tsx @@ -0,0 +1,13 @@ +import Head from "next/head"; +import Components16MigrationPage from "screens/migration/Components16MigrationPage"; + +const Components16Migration = () => ( + <> + + Component updates in v16 — Halstack Design System + + + +); + +export default Components16Migration; diff --git a/apps/website/pages/migration/16/migrating-to-emotion.tsx b/apps/website/pages/migration/16/migrating-to-emotion.tsx new file mode 100644 index 000000000..3469b0e4a --- /dev/null +++ b/apps/website/pages/migration/16/migrating-to-emotion.tsx @@ -0,0 +1,13 @@ +import Head from "next/head"; +import EmotionPage from "screens/migration/EmotionMigrationPage"; + +const EmotionMigration = () => ( + <> + + Migrating to Emotion — Halstack Design System + + + +); + +export default EmotionMigration; diff --git a/apps/website/pages/migration/16/migrating-tokens.tsx b/apps/website/pages/migration/16/migrating-tokens.tsx new file mode 100644 index 000000000..44e174f40 --- /dev/null +++ b/apps/website/pages/migration/16/migrating-tokens.tsx @@ -0,0 +1,13 @@ +import Head from "next/head"; +import TokensMigrationPage from "screens/migration/TokensMigrationPage"; + +const TokensMigration = () => ( + <> + + Migrating tokens — Halstack Design System + + + +); + +export default TokensMigration; diff --git a/apps/website/screens/common/componentsList.json b/apps/website/screens/common/componentsList.json index 48a94562c..a0969f03b 100644 --- a/apps/website/screens/common/componentsList.json +++ b/apps/website/screens/common/componentsList.json @@ -44,7 +44,7 @@ { "label": "Data grid", "path": "/components/data-grid", - "status": "experimental" + "status": "new" }, { "label": "Date input", diff --git a/apps/website/screens/common/pagesList.ts b/apps/website/screens/common/pagesList.tsx similarity index 57% rename from apps/website/screens/common/pagesList.ts rename to apps/website/screens/common/pagesList.tsx index 48f6e4e01..cbca8f016 100644 --- a/apps/website/screens/common/pagesList.ts +++ b/apps/website/screens/common/pagesList.tsx @@ -2,7 +2,7 @@ import componentsList from "./componentsList.json"; export type ComponentStatus = "experimental" | "new" | "stable" | "legacy" | "deprecated"; -type LinkDetails = { +export type LinkDetails = { label: string; path: string; status?: ComponentStatus; @@ -10,7 +10,7 @@ type LinkDetails = { export type LinksSectionDetails = { label: string; - links: LinkDetails[]; + links: (LinkDetails | LinksSectionDetails)[]; }; type NavigationLinks = { @@ -37,46 +37,69 @@ const principlesLinks: LinkDetails[] = [ { label: "Localization", path: "/principles/localization" }, ]; -const foundationsLinks: LinkDetails[] = [ +const tokensLinks: LinkDetails[] = [ + { label: "Overview", path: "/foundations/tokens" }, + { label: "Core tokens", path: "/foundations/tokens/core" }, + { label: "Alias tokens", path: "/foundations/tokens/alias" }, +]; + +const foundationsLinks: (LinkDetails | LinksSectionDetails)[] = [ { label: "Color", path: "/foundations/color" }, { label: "Elevation", path: "/foundations/elevation" }, { label: "Height", path: "/foundations/height" }, { label: "Iconography", path: "/foundations/iconography" }, { label: "Layout", path: "/foundations/layout" }, { label: "Spacing", path: "/foundations/spacing" }, - { label: "Tokens", path: "/foundations/tokens" }, + { label: "Tokens", links: tokensLinks }, { label: "Typography", path: "/foundations/typography" }, ]; +const v16Links: LinkDetails[] = [ + { label: "Component updates", path: "/migration/16/component-updates" }, + { label: "Migrating to Emotion", path: "/migration/16/migrating-to-emotion" }, + { label: "Migrating tokens", path: "/migration/16/migrating-tokens" }, +]; + +const migrationLinks: LinksSectionDetails[] = [{ label: "v16", links: v16Links }]; + const componentsLinks = componentsList as LinkDetails[]; export const LinksSections: LinksSectionDetails[] = [ { label: "Overview", links: overviewLinks }, { label: "Principles", links: principlesLinks }, { label: "Foundations", links: foundationsLinks }, + { label: "Migration", links: migrationLinks }, { label: "Utilities", links: utilitiesLinks }, { label: "Components", links: componentsLinks }, ]; +const isNavLink = (item: LinkDetails | LinksSectionDetails): item is LinkDetails => "path" in item; + +const flattenLinks = (items: (LinkDetails | LinksSectionDetails)[]): LinkDetails[] => + items.flatMap((item) => (isNavLink(item) ? [item] : flattenLinks(item.links))); + const getCurrentLinkIndex = (links: LinkDetails[], currentPath: string) => { - let currentLinkIndex = -1; - let matchedWords = 0; - links.forEach((link, index) => { - if (currentPath.startsWith(link.path) && link.path.length > matchedWords) { - currentLinkIndex = index; - matchedWords = link.path.length; + let current = -1; + let best = 0; + + links.forEach((link, i) => { + if (currentPath.startsWith(link.path) && link.path.length > best) { + current = i; + best = link.path.length; } }); - return currentLinkIndex; + + return current; }; export const getNavigationLinks = (currentPath: string): NavigationLinks => { - const links = LinksSections.flatMap((section) => section.links); - const currentLinkIndex = getCurrentLinkIndex(links, currentPath); - return currentLinkIndex === -1 - ? {} - : { - nextLink: currentLinkIndex + 1 < links.length ? links[currentLinkIndex + 1] : undefined, - previousLink: currentLinkIndex - 1 >= 0 ? links[currentLinkIndex - 1] : undefined, - }; + const flatLinks = flattenLinks(LinksSections); + + const index = getCurrentLinkIndex(flatLinks, currentPath); + if (index === -1) return {}; + + return { + previousLink: flatLinks[index - 1], + nextLink: flatLinks[index + 1], + }; }; diff --git a/apps/website/screens/components/accordion/code/AccordionCodePage.tsx b/apps/website/screens/components/accordion/code/AccordionCodePage.tsx index 5a86d0019..49bfbeb3b 100644 --- a/apps/website/screens/components/accordion/code/AccordionCodePage.tsx +++ b/apps/website/screens/components/accordion/code/AccordionCodePage.tsx @@ -126,12 +126,7 @@ const sections = [ - - - - - badge - - + badge {"{ position: 'before' | 'after'; element: ReactNode }"} @@ -190,12 +185,7 @@ const sections = [ - - - - - statusLight - - + statusLight React.ReactNode @@ -203,12 +193,7 @@ const sections = [ - - - - - subLabel - - + subLabel string diff --git a/apps/website/screens/components/alert/code/AlertCodePage.tsx b/apps/website/screens/components/alert/code/AlertCodePage.tsx index 9c86bf51d..96ce03ed8 100644 --- a/apps/website/screens/components/alert/code/AlertCodePage.tsx +++ b/apps/website/screens/components/alert/code/AlertCodePage.tsx @@ -51,13 +51,11 @@ const sections = [ message - - {"Message | Message[]"} -

- being Message an object with the following properties: -

- {messageTypeString} - + {"Message | Message[]"} +

+ being Message an object with the following properties: +

+ {messageTypeString} List of messages to be displayed. Each message has a close action that will, apart from remove from the @@ -78,17 +76,17 @@ const sections = [ The mode of the alert. The possible values are:
  • - inline: The alert must be displayed in the same place where it is declared. The user can - navigate between the messages if the message is an array. + inline: The alert must be displayed in the same place where it is declared. The user + can navigate between the messages if the message is an array.
  • - modal: The alert will be displayed in the middle of the screen with an overlay layer behind. In - this mode, the user has the responsibility of hiding the alert with the onClose event of - the message, otherwise the overlaid modal will remain visible. + modal: The alert will be displayed in the middle of the screen with an overlay layer + behind. In this mode, the user has the responsibility of hiding the alert with the{" "} + onClose event of the message, otherwise the overlaid modal will remain visible.
  • - banner: The alert must be displayed at the top of the screen. The user can navigate between the - messages if the message is an array. + banner: The alert must be displayed at the top of the screen. The user can navigate + between the messages if the message is an array.
diff --git a/apps/website/screens/components/data-grid/code/DataGridCodePage.tsx b/apps/website/screens/components/data-grid/code/DataGridCodePage.tsx index fda3d6c0f..ecfdd9237 100644 --- a/apps/website/screens/components/data-grid/code/DataGridCodePage.tsx +++ b/apps/website/screens/components/data-grid/code/DataGridCodePage.tsx @@ -94,31 +94,31 @@ const sections = [ Each GridColumn object has the following properties:
  • - key: Key that will be rendered from each row in rows. + key: Key that will be rendered from each row in rows.
  • - label: Label that will be used for the column header. + label: Label that will be used for the column header.
  • - resizable: Whether the column is resizable or not. + resizable: Whether the column is resizable or not.
  • - sortable: Whether the column is sortable or not. + sortable: Whether the column is sortable or not.
  • - sortFn: Custom function with the criteria for the column sorting. + sortFn: Custom function with the criteria for the column sorting.
  • - draggable: Whether the column can be dragged or not to another position or not. + draggable: Whether the column can be dragged or not to another position or not.
  • - textEditable: Whether the column cells are editable or not. + textEditable: Whether the column cells are editable or not.
  • - summaryKey: Value that will be rendered from the summaryRow + summaryKey: Value that will be rendered from the summaryRow
  • - alignment: Sets the alignment inside the cells. + alignment: Sets the alignment inside the cells.
diff --git a/apps/website/screens/components/dropdown/code/DropdownCodePage.tsx b/apps/website/screens/components/dropdown/code/DropdownCodePage.tsx index b6fc5a5c9..714a56705 100644 --- a/apps/website/screens/components/dropdown/code/DropdownCodePage.tsx +++ b/apps/website/screens/components/dropdown/code/DropdownCodePage.tsx @@ -132,10 +132,10 @@ const sections = [ An array of objects representing the options. Each object has the following properties:
  • - label: Option display value. + label: Option display value.
  • - icon:{" "} + icon:{" "} Material Symbol {" "} @@ -144,7 +144,7 @@ const sections = [ prefix the symbol name with "filled_".
  • - value: Option inner value. + value: Option inner value.
diff --git a/apps/website/screens/components/file-input/code/FileInputCodePage.tsx b/apps/website/screens/components/file-input/code/FileInputCodePage.tsx index 2a9cf2176..736427146 100644 --- a/apps/website/screens/components/file-input/code/FileInputCodePage.tsx +++ b/apps/website/screens/components/file-input/code/FileInputCodePage.tsx @@ -214,14 +214,14 @@ const sections = [ An array of files representing the selected files. Each file has the following properties:
  • - file: Selected file. + file: Selected file.
  • - error: Error of the file. If it is defined, it will be shown and the file item will be mark as - invalid. + error: Error of the file. If it is defined, it will be shown and the file item will + be mark as invalid.
  • - preview: Preview of the file. + preview: Preview of the file.
diff --git a/apps/website/screens/components/footer/code/FooterCodePage.tsx b/apps/website/screens/components/footer/code/FooterCodePage.tsx index 4dee76a7b..1073f5553 100644 --- a/apps/website/screens/components/footer/code/FooterCodePage.tsx +++ b/apps/website/screens/components/footer/code/FooterCodePage.tsx @@ -44,26 +44,15 @@ const sections = [ object has the following properties:
  • - text: Text for the link. + text: Text for the link.
  • - href: URL of the page the link goes to. + href: URL of the page the link goes to.
- - - children - - ReactNode - - - Contains DxcFooter.LeftContent and DxcFooter.RightContent components to customize the left and right - content of the footer respectively. - - - - copyright @@ -80,7 +69,7 @@ const sections = [ - ReactNode + React.ReactNode Content to be displayed on the left side of the footer under the logo. - @@ -93,19 +82,13 @@ const sections = [ - - {logoTypeString} - + {logoTypeString} Logo to be displayed inside the footer. - - - - mode - - + mode 'default' | 'reduced' @@ -113,10 +96,10 @@ const sections = [ The available footer modes:
  • - default: Footer with full content. + default: Footer with full content.
  • - reduced: Smaller footer with minimal content. + reduced: Smaller footer with minimal content.
@@ -132,7 +115,7 @@ const sections = [ - ReactNode + React.ReactNode Content to be displayed on the right side of the footer before the socialLinks if provided. - @@ -147,14 +130,14 @@ const sections = [ footer. Each object has the following properties:
  • - href: URL of the page the link goes to. + href: URL of the page the link goes to.
  • - title: Text representing advisory information related to the social link. Under the hood, it - also serves as an accessible label for the icon. + title: Text representing advisory information related to the social link. Under the + hood, it also serves as an accessible label for the icon.
  • - logo:{" "} + logo:{" "} Material Symbol {" "} diff --git a/apps/website/screens/components/grid/code/GridCodePage.tsx b/apps/website/screens/components/grid/code/GridCodePage.tsx index b54030a9f..3584dc0b1 100644 --- a/apps/website/screens/components/grid/code/GridCodePage.tsx +++ b/apps/website/screens/components/grid/code/GridCodePage.tsx @@ -115,10 +115,10 @@ const sections = [ properties:
    • - rowGap: gutter between rows. + rowGap: gutter between rows.
    • - columnGap: gutter between columns. + columnGap: gutter between columns.
    @@ -143,10 +143,10 @@ const sections = [ properties:
    • - justifyContent: aligns the grid along the inline (row) axis. + justifyContent: aligns the grid along the inline (row) axis.
    • - alignContent: aligns the grid along the block (column) axis. + alignContent: aligns the grid along the block (column) axis.
    @@ -168,10 +168,10 @@ const sections = [ properties:
    • - justifyItems: aligns grid items along the inline (row) axis. + justifyItems: aligns grid items along the inline (row) axis.
    • - alignItems: aligns grid items along the block (column) axis. + alignItems: aligns grid items along the block (column) axis.
    @@ -303,10 +303,10 @@ const sections = [ properties:
    • - start: starting position within the grid column. + start: starting position within the grid column.
    • - end: ending position within the grid column. + end: ending position within the grid column.
    @@ -326,10 +326,10 @@ const sections = [ properties:
    • - justifySelf: aligns a grid item inside a cell along the inline (row) axis. + justifySelf: aligns a grid item inside a cell along the inline (row) axis.
    • - alignSelf: aligns a grid item inside a cell along the block (column) axis. + alignSelf: aligns a grid item inside a cell along the block (column) axis.
    @@ -351,10 +351,10 @@ const sections = [ properties:
    • - start: starting position within the grid row. + start: starting position within the grid row.
    • - end: ending position within the grid row. + end: ending position within the grid row.
    diff --git a/apps/website/screens/components/number-input/code/NumberInputCodePage.tsx b/apps/website/screens/components/number-input/code/NumberInputCodePage.tsx index dc25c8b21..62104a8ba 100644 --- a/apps/website/screens/components/number-input/code/NumberInputCodePage.tsx +++ b/apps/website/screens/components/number-input/code/NumberInputCodePage.tsx @@ -6,7 +6,6 @@ import controlled from "./examples/controlled"; import uncontrolled from "./examples/uncontrolled"; import errorUsage from "./examples/errorHandling"; import Code, { TableCode } from "@/common/Code"; -import StatusBadge from "@/common/StatusBadge"; const sections = [ { @@ -219,12 +218,7 @@ const sections = [ - - - - - showControls - - + showControls boolean diff --git a/apps/website/screens/components/quick-nav/code/QuickNavCodePage.tsx b/apps/website/screens/components/quick-nav/code/QuickNavCodePage.tsx index 1c89ea016..fc3c6aa93 100644 --- a/apps/website/screens/components/quick-nav/code/QuickNavCodePage.tsx +++ b/apps/website/screens/components/quick-nav/code/QuickNavCodePage.tsx @@ -37,12 +37,12 @@ const sections = [ navigation when appropriate. Each link has the following properties:
    • - label: Text to be shown in the link. The content must be wrapped with an id equal to the - slugified label (in lower case and the white spaces replaced by '-') in order to be able to - navigate to the section that the label references. + label: Text to be shown in the link. The content must be wrapped with an id equal to + the slugified label (in lower case and the white spaces replaced by '-') in order to be able + to navigate to the section that the label references.
    • - links: Sublinks of the link. + links: Sublinks of the link.
    diff --git a/apps/website/screens/components/radio-group/code/RadioGroupCodePage.tsx b/apps/website/screens/components/radio-group/code/RadioGroupCodePage.tsx index 2b5ec74c4..9e9eaf8f8 100644 --- a/apps/website/screens/components/radio-group/code/RadioGroupCodePage.tsx +++ b/apps/website/screens/components/radio-group/code/RadioGroupCodePage.tsx @@ -150,14 +150,14 @@ const sections = [ An array of objects representing the selectable options. Each object Option has the following properties:
    • - label: Label of the option placed next to the radio input. + label: Label of the option placed next to the radio input.
    • - value: Value of the option. It should be unique and not an empty string, which is reserved to - the optional item added by the optional prop. + value: Value of the option. It should be unique and not an empty string, which is + reserved to the optional item added by the optional prop.
    • - disabled: disables the option. + disabled: disables the option.
    diff --git a/apps/website/screens/components/resultset-table/code/ResultsetTableCodePage.tsx b/apps/website/screens/components/resultset-table/code/ResultsetTableCodePage.tsx index 387af74e8..303379047 100644 --- a/apps/website/screens/components/resultset-table/code/ResultsetTableCodePage.tsx +++ b/apps/website/screens/components/resultset-table/code/ResultsetTableCodePage.tsx @@ -67,22 +67,17 @@ const sections = [ An array of objects representing the columns of the table. Each object has the following properties:
    • - displayValue: Column display value. + displayValue: Column display value.
    • - isSortable: Boolean value to indicate whether the column is sortable or not. + isSortable: Boolean value to indicate whether the column is sortable or not.
    - - - - - hidePaginator - - + hidePaginator boolean @@ -132,12 +127,7 @@ const sections = [ - - - - - mode - - + mode 'default' | 'reduced' @@ -145,10 +135,10 @@ const sections = [ The available table modes:
    • - default: Default table size. + default: Default table size.
    • - reduced: More compact table with less spacing for high density information. + reduced: More compact table with less spacing for high density information.
    @@ -176,10 +166,10 @@ const sections = [ table. Each row is a set of cells that have the following properties:
    • - displayValue: Value to be displayed in the cell. + displayValue: Value to be displayed in the cell.
    • - sortValue: Value to be used when sorting the table by that column. If not indicated + sortValue: Value to be used when sorting the table by that column. If not indicated displayValue will be used for sorting.
    diff --git a/apps/website/screens/components/select/code/SelectCodePage.tsx b/apps/website/screens/components/select/code/SelectCodePage.tsx index 8116e1229..502d7f507 100644 --- a/apps/website/screens/components/select/code/SelectCodePage.tsx +++ b/apps/website/screens/components/select/code/SelectCodePage.tsx @@ -206,14 +206,14 @@ const sections = [ Option
    • - label: Label of the option to be shown in the select's listbox. + label: Label of the option to be shown in the select's listbox.
    • - value: Value of the option. It should be unique and not an empty string, which is reserved to - the empty option added by optional prop. + value: Value of the option. It should be unique and not an empty string, which is + reserved to the empty option added by optional prop.
    • - icon:{" "} + icon:{" "} Material Symbol {" "} @@ -226,10 +226,10 @@ const sections = [
      • - label: Label of the group to be shown in the select's listbox. + label: Label of the group to be shown in the select's listbox.
      • - options: List of Option instances. + options: List of Option instances.

      diff --git a/apps/website/screens/components/sidenav/SidenavPageLayout.tsx b/apps/website/screens/components/sidenav/SidenavPageLayout.tsx index 72413b817..0d3df5bc3 100644 --- a/apps/website/screens/components/sidenav/SidenavPageLayout.tsx +++ b/apps/website/screens/components/sidenav/SidenavPageLayout.tsx @@ -10,7 +10,6 @@ const SidenavPageHeading = ({ children }: { children: ReactNode }) => { { label: "Overview", path: "/components/sidenav" }, { label: "Code", path: "/components/sidenav/code" }, ]; - // TODO: UPDATE DESCRIPTION WHEN OVERVIEW IS ADDED return ( diff --git a/apps/website/screens/components/sidenav/code/SidenavCodePage.tsx b/apps/website/screens/components/sidenav/code/SidenavCodePage.tsx index 683c1de0a..9237e9723 100644 --- a/apps/website/screens/components/sidenav/code/SidenavCodePage.tsx +++ b/apps/website/screens/components/sidenav/code/SidenavCodePage.tsx @@ -2,6 +2,7 @@ import DocFooter from "@/common/DocFooter"; import QuickNavContainer from "@/common/QuickNavContainer"; import Code, { ExtendedTableCode, TableCode } from "@/common/Code"; import { DxcFlex, DxcTable } from "@dxc-technology/halstack-react"; +import StatusBadge from "@/common/StatusBadge"; const brandingTypeString = `{ logo?: Logo; @@ -15,11 +16,9 @@ const logoTypeString = `{ src: string; }`; -const commonItemTypeString = `{ - badge?: ReactElement; +const commonItemTypeString = `badge?: ReactElement; icon?: string | SVG; - label: string; -}`; + label: string;`; const itemTypeString = `{ ${commonItemTypeString} @@ -52,7 +51,12 @@ const sections = [ - bottomContent + + + + bottomContent + + React.ReactNode @@ -60,7 +64,12 @@ const sections = [ - - branding + + + + branding + + {"Branding | ReactNode"}

      @@ -76,7 +85,12 @@ const sections = [ - - defaultExpanded + + + + defaultExpanded + + boolean @@ -84,7 +98,12 @@ const sections = [ - - displayGroupLines + + + + displayGroupLines + + boolean @@ -92,7 +111,12 @@ const sections = [ - - expanded + + + + expanded + + boolean @@ -103,7 +127,12 @@ const sections = [ - - navItems + + + + navItems + + {"(Item | GroupItem)[] | Section[]"}

      @@ -126,7 +155,12 @@ const sections = [ - - onExpandedChange + + + + onExpandedChange + + {"(value: boolean) => void"} @@ -134,7 +168,12 @@ const sections = [ - - topContent + + + + topContent + + React.ReactNode diff --git a/apps/website/screens/components/table/code/TableCodePage.tsx b/apps/website/screens/components/table/code/TableCodePage.tsx index b27bbca9f..31ffa0165 100644 --- a/apps/website/screens/components/table/code/TableCodePage.tsx +++ b/apps/website/screens/components/table/code/TableCodePage.tsx @@ -62,12 +62,7 @@ const sections = [ - - - - - mode - - + mode 'default' | 'reduced' @@ -75,10 +70,10 @@ const sections = [ The available table modes:

      • - default: Default table size. + default: Default table size.
      • - reduced: More compact table with less spacing for high density information. + reduced: More compact table with less spacing for high density information.
      diff --git a/apps/website/screens/components/text-input/code/TextInputCodePage.tsx b/apps/website/screens/components/text-input/code/TextInputCodePage.tsx index 22604f369..c1f38ad2e 100644 --- a/apps/website/screens/components/text-input/code/TextInputCodePage.tsx +++ b/apps/website/screens/components/text-input/code/TextInputCodePage.tsx @@ -313,11 +313,12 @@ const sections = [ These are the options to be displayed as suggestions. It can be either an array or a function:
      • - Array: List of options that will be filtered by the user's input. + Array: List of options that will be filtered by the user's input.
      • - Function: This function will be called when the user changes the value. It will receive the new - value as a parameter and should return a promise that resolves to an array with the filtered options. + Function: This function will be called when the user changes the value. It will + receive the new value as a parameter and should return a promise that resolves to an array with the + filtered options.
      diff --git a/apps/website/screens/components/textarea/code/TextareaCodePage.tsx b/apps/website/screens/components/textarea/code/TextareaCodePage.tsx index 23b54e240..d00e56ed5 100644 --- a/apps/website/screens/components/textarea/code/TextareaCodePage.tsx +++ b/apps/website/screens/components/textarea/code/TextareaCodePage.tsx @@ -271,13 +271,13 @@ const sections = [ Defines the textarea's ability to resize vertically. It can be:
      • - 'auto': The textarea grows or shrinks automatically in order to fit the content. + 'auto': The textarea grows or shrinks automatically in order to fit the content.
      • - 'manual': The height of the textarea is enabled to be manually modified. + 'manual': The height of the textarea is enabled to be manually modified.
      • - 'none': The textarea has a fixed height and can't be modified. + 'none': The textarea has a fixed height and can't be modified.
      diff --git a/apps/website/screens/components/toast/code/ToastCodePage.tsx b/apps/website/screens/components/toast/code/ToastCodePage.tsx index 6fc9a8a0b..845adae1c 100644 --- a/apps/website/screens/components/toast/code/ToastCodePage.tsx +++ b/apps/website/screens/components/toast/code/ToastCodePage.tsx @@ -42,7 +42,7 @@ const sections = [
      - ReactNode + React.ReactNode Tree of components from which the useToast hook can be triggered. diff --git a/apps/website/screens/components/wizard/code/WizardCodePage.tsx b/apps/website/screens/components/wizard/code/WizardCodePage.tsx index 0410a95c8..36620704a 100644 --- a/apps/website/screens/components/wizard/code/WizardCodePage.tsx +++ b/apps/website/screens/components/wizard/code/WizardCodePage.tsx @@ -98,23 +98,23 @@ const sections = [ An array of objects representing the steps. Each of them has the following properties:
      • - label: Step label. + label: Step label.
      • - description: Description that will be placed next to the step. + description: Description that will be placed next to the step.
      • - icon:{" "} + icon:{" "} Material Symbol {" "} name or SVG element used as the icon displayed in the step.
      • - disabled: If true, the step will be disabled. + disabled: If true, the step will be disabled.
      • - valid: Whether the step is valid or not. + valid: Whether the step is valid or not.
      diff --git a/apps/website/screens/foundations/tokens/AliasTokenList.tsx b/apps/website/screens/foundations/tokens/AliasTokenList.tsx new file mode 100644 index 000000000..f7c16a6bd --- /dev/null +++ b/apps/website/screens/foundations/tokens/AliasTokenList.tsx @@ -0,0 +1,68 @@ +import DocFooter from "@/common/DocFooter"; +import PageHeading from "@/common/PageHeading"; +import DxcQuickNavContainer from "@/common/QuickNavContainer"; +import { DxcFlex, DxcHeading } from "@dxc-technology/halstack-react"; +import TokensTable from "./tables/TokensTable"; + +const sections = [ + { + title: "Border", + subSections: [ + { title: "Radius", content: }, + { title: "Style", content: }, + { title: "Width", content: }, + ], + }, + { + title: "Color", + subSections: [ + { title: "Border", content: }, + { title: "Background", content: }, + { title: "Shadow", content: }, + { title: "Text", content: }, + ], + }, + { + title: "Dimensions", + subSections: [ + { title: "Height", content: }, + { + title: "Shadow", + content: , + }, + { title: "Spacing", content: }, + ], + }, + { + title: "Typography", + subSections: [ + { title: "Body", content: }, + { + title: "Heading", + content: , + }, + { title: "Helper text", content: }, + { title: "Label", content: }, + { + title: "Link", + content: , + }, + { title: "Title", content: }, + { title: "Font family", content: }, + ], + }, +]; + +const TokensPage = () => ( + + + + + + + + + +); + +export default TokensPage; diff --git a/apps/website/screens/foundations/tokens/CoreTokenList.tsx b/apps/website/screens/foundations/tokens/CoreTokenList.tsx new file mode 100644 index 000000000..54c94f3c8 --- /dev/null +++ b/apps/website/screens/foundations/tokens/CoreTokenList.tsx @@ -0,0 +1,105 @@ +import DocFooter from "@/common/DocFooter"; +import PageHeading from "@/common/PageHeading"; +import DxcQuickNavContainer from "@/common/QuickNavContainer"; +import { DxcFlex, DxcHeading } from "@dxc-technology/halstack-react"; +import TokensTable from "./tables/TokensTable"; + +const sections = [ + { + title: "Colors", + content: ( + <> + <> + {/* Color Tokens */} + + + + + + + + + + + + + + + + + + + + + + + <> + {/* Dimensions Tokens */} + + + + <> + {/* Font Tokens */} + + + + + + + + + + + <> + {/* Border Tokens */} + + + + + ), + subSections: [ + { title: "Absolute", content: }, + { title: "Primary", content: }, + { title: "Secondary", content: }, + { title: "Tertiary", content: }, + { title: "Neutral", content: }, + { title: "Semantic 01", content: }, + { title: "Semantic 02", content: }, + { title: "Semantic 03", content: }, + { title: "Semantic 04", content: }, + { title: "Alpha", content: }, + ], + }, + { title: "Dimensions", content: }, + { + title: "Font", + content: , + subSections: [ + { + title: "Font size", + content: , + }, + { title: "Font weight", content: }, + { title: "Font family", content: }, + { title: "Font style", content: }, + ], + }, + { + title: "Border", + content: , + }, +]; + +const TokensPage = () => ( + + + + + + + + + +); + +export default TokensPage; diff --git a/apps/website/screens/foundations/tokens/TokensPage.tsx b/apps/website/screens/foundations/tokens/TokensPage.tsx index 8da050af9..bede23b01 100644 --- a/apps/website/screens/foundations/tokens/TokensPage.tsx +++ b/apps/website/screens/foundations/tokens/TokensPage.tsx @@ -6,21 +6,6 @@ import DxcQuickNavContainer from "@/common/QuickNavContainer"; import { DxcAlert, DxcBulletedList, DxcFlex, DxcHeading, DxcLink, DxcParagraph } from "@dxc-technology/halstack-react"; import Link from "next/link"; import componentTokens from "./images/component_tokens.gif"; -import { - AbsoluteTokens, - AlphaTokens, - NeutralTokens, - PrimaryTokens, - SecondaryTokens, - Semantic01Tokens, - Semantic02Tokens, - Semantic03Tokens, - Semantic04Tokens, - TertiaryTokens, -} from "./tables/CoreColorTokens"; -import DimensionsTokens from "./tables/CoreDimensionsTokens"; -import { FontFamilyTokens, FontSizesTokens, FontStylesTokens, FontWeightTokens } from "./tables/CoreFontTokens"; -import BorderTokens from "./tables/CoreBorderTokens"; const sections = [ { @@ -58,7 +43,7 @@ const sections = [ When Halstack was first established, its token structure followed a two-tier model:{" "} primitive tokens (the raw foundational values) and component tokens (styles - appliedWIP at the component level.) The intermediate alias layer — commonly used to connect + applied at the component level.) The intermediate alias layer — commonly used to connect foundations to components — was missing. @@ -315,55 +300,22 @@ const sections = [ The first layer (composed of core tokens) can be customized when using the opinionated theming approach. - Below is the list of available core tokens: + You can view the{" "} + + list of available core tokens + + . - <> - {/* Color Tokens */} - - - - - - - - - - - - - - - - - - - - - - - <> - {/* Dimensions Tokens */} - - - - <> - {/* Font Tokens */} - - - - - - - - - - - <> - {/* Border Tokens */} - - - - The component layer is still under development. + + The second layer (composed of alias tokens) can be used to replace raw values such as colors, paddings, + sizes, etc. Alias tokens act as an intermediate mapping between the low-level core values and the visual + roles used by components. You can view the{" "} + + list of available alias tokens + + . + + The third layer (component tokens) is still under development. ), }, @@ -379,7 +331,7 @@ const TokensPage = () => ( - + ); diff --git a/apps/website/screens/foundations/tokens/tables/CoreBorderTokens.tsx b/apps/website/screens/foundations/tokens/tables/CoreBorderTokens.tsx deleted file mode 100644 index a74df3ac3..000000000 --- a/apps/website/screens/foundations/tokens/tables/CoreBorderTokens.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { TableCode } from "@/common/Code"; -import { DxcTable } from "@dxc-technology/halstack-react"; - -const BorderTokens = () => ( - - - - Token - Default value - - - - - - --line-style-dashed - - dashed - - - - --line-style-solid - - solid - - - -); - -export default BorderTokens; diff --git a/apps/website/screens/foundations/tokens/tables/CoreColorTokens.tsx b/apps/website/screens/foundations/tokens/tables/CoreColorTokens.tsx deleted file mode 100644 index e1bca0110..000000000 --- a/apps/website/screens/foundations/tokens/tables/CoreColorTokens.tsx +++ /dev/null @@ -1,678 +0,0 @@ -import { TableCode } from "@/common/Code"; -import { DxcTable } from "@dxc-technology/halstack-react"; - -export const AbsoluteTokens = () => ( - - - - Token - Default value - - - - - - --color-absolutes-black - - #000000 - - - - --color-absolutes-white - - #ffffff - - - -); - -export const AlphaTokens = () => ( - - - - Token - Default value - - - - - - --color-alpha-100-a - - #ebebeb1a - - - - --color-alpha-200-a - - #dedede33 - - - - --color-alpha-300-a - - #d1d1d14d - - - - --color-alpha-400-a - - #b5b5b566 - - - - --color-alpha-500-a - - #9a9a9a80 - - - - --color-alpha-600-a - - #79797999 - - - - --color-alpha-700-a - - #5b5b5bb2 - - - - --color-alpha-800-a - - #494949cc - - - - --color-alpha-900-a - - #333333e5 - - - -); - -export const PrimaryTokens = () => ( - - - - Token - Default value - - - - - - --color-primary-50 - - #fcfbfe - - - - --color-primary-100 - - #f0e8fa - - - - --color-primary-200 - - #e7d9f6 - - - - --color-primary-300 - - #ddc9f3 - - - - --color-primary-400 - - #c8a7eb - - - - --color-primary-500 - - #b487e4 - - - - --color-primary-600 - - #9363c8 - - - - --color-primary-700 - - #6f4b97 - - - - --color-primary-800 - - #5a3c7a - - - - --color-primary-900 - - #3e2a55 - - - -); - -export const SecondaryTokens = () => ( - - - - Token - Default value - - - - - - --color-secondary-50 - - #f8fcff - - - - --color-secondary-100 - - #d9efff - - - - --color-secondary-200 - - #bce3ff - - - - --color-secondary-300 - - #a0d7ff - - - - --color-secondary-400 - - #61bdff - - - - --color-secondary-500 - - #30a1f1 - - - - --color-secondary-600 - - #267fbf - - - - --color-secondary-700 - - #1d6091 - - - - --color-secondary-800 - - #174e74 - - - - --color-secondary-900 - - #103651 - - - -); - -export const TertiaryTokens = () => ( - - - - Token - Default value - - - - - - --color-tertiary-50 - - #fefbef - - - - --color-tertiary-100 - - #fcedae - - - - --color-tertiary-200 - - #f9de6e - - - - --color-tertiary-300 - - #f5cd2b - - - - --color-tertiary-400 - - #d4b226 - - - - --color-tertiary-500 - - #b6981f - - - - --color-tertiary-600 - - #8f7818 - - - - --color-tertiary-700 - - #6c5a12 - - - - --color-tertiary-800 - - #57490f - - - - --color-tertiary-900 - - #3d3309 - - - -); - -export const NeutralTokens = () => ( - - - - Token - Default value - - - - - - --color-neutral-50 - - #fbfbfb - - - - --color-neutral-100 - - #ebebeb - - - - --color-neutral-200 - - #dedede - - - - --color-neutral-300 - - #d1d1d1 - - - - --color-neutral-400 - - #b5b5b5 - - - - --color-neutral-500 - - #9a9a9a - - - - --color-neutral-600 - - #797979 - - - - --color-neutral-700 - - #5b5b5b - - - - --color-neutral-800 - - #494949 - - - - --color-neutral-900 - - #333333 - - - -); - -export const Semantic01Tokens = () => ( - - - - Token - Default value - - - - - - --color-semantic01-50 - - #f8fcff - - - - --color-semantic01-100 - - #d9efff - - - - --color-semantic01-200 - - #bce3ff - - - - --color-semantic01-300 - - #a0d7ff - - - - --color-semantic01-400 - - #61bdff - - - - --color-semantic01-500 - - #30a1f1 - - - - --color-semantic01-600 - - #267fbf - - - - --color-semantic01-700 - - #1d6091 - - - - --color-semantic01-800 - - #174e74 - - - - --color-semantic01-900 - - #103651 - - - -); - -export const Semantic02Tokens = () => ( - - - - Token - Default value - - - - - - --color-semantic02-50 - - #f3fcf5 - - - - --color-semantic02-100 - - #d1f5db - - - - --color-semantic02-200 - - #acecbe - - - - --color-semantic02-300 - - #87e3a0 - - - - --color-semantic02-400 - - #53cb75 - - - - --color-semantic02-500 - - #47ae64 - - - - --color-semantic02-600 - - #39884f - - - - --color-semantic02-700 - - #2a673b - - - - --color-semantic02-800 - - #225230 - - - - --color-semantic02-900 - - #183921 - - - -); - -export const Semantic03Tokens = () => ( - - - - Token - Default value - - - - - - --color-semantic03-50 - - #fffbf6 - - - - --color-semantic03-100 - - #fde9d2 - - - - --color-semantic03-200 - - #fbd9b3 - - - - --color-semantic03-300 - - #f9c78f - - - - --color-semantic03-400 - - #f5a344 - - - - --color-semantic03-500 - - #d58a35 - - - - --color-semantic03-600 - - #a76d2b - - - - --color-semantic03-700 - - #7f5121 - - - - --color-semantic03-800 - - #66421a - - - - --color-semantic03-900 - - #3d3309 - - - -); - -export const Semantic04Tokens = () => ( - - - - Token - Default value - - - - - - --color-semantic04-50 - - #fff7f6 - - - - --color-semantic04-100 - - #ffe6e4 - - - - --color-semantic04-200 - - #ffd3d0 - - - - --color-semantic04-300 - - #ffc1bd - - - - --color-semantic04-400 - - #ff9896 - - - - --color-semantic04-500 - - #ff696f - - - - --color-semantic04-600 - - #e33248 - - - - --color-semantic04-700 - - #a92c37 - - - - --color-semantic04-800 - - #87262d - - - - --color-semantic04-900 - - #5b1f21 - - - -); diff --git a/apps/website/screens/foundations/tokens/tables/CoreDimensionsTokens.tsx b/apps/website/screens/foundations/tokens/tables/CoreDimensionsTokens.tsx deleted file mode 100644 index 350b7e4ec..000000000 --- a/apps/website/screens/foundations/tokens/tables/CoreDimensionsTokens.tsx +++ /dev/null @@ -1,137 +0,0 @@ -import { TableCode } from "@/common/Code"; -import { DxcTable } from "@dxc-technology/halstack-react"; - -const DimensionsTokens = () => ( - - - - Token - Default value - - - - - - --dimensions-0 - - 0px - - - - --dimensions-1 - - 1px - - - - --dimensions-2 - - 2px - - - - --dimensions-4 - - 4px - - - - --dimensions-8 - - 8px - - - - --dimensions-12 - - 12px - - - - --dimensions-16 - - 16px - - - - --dimensions-20 - - 20px - - - - --dimensions-24 - - 24px - - - - --dimensions-28 - - 28px - - - - --dimensions-32 - - 32px - - - - --dimensions-36 - - 36px - - - - --dimensions-40 - - 40px - - - - --dimensions-44 - - 44px - - - - --dimensions-48 - - 48px - - - - --dimensions-56 - - 56px - - - - --dimensions-64 - - 64px - - - - --dimensions-72 - - 72px - - - - --dimensions-80 - - 80px - - - - --dimensions-96 - - 96px - - - -); - -export default DimensionsTokens; diff --git a/apps/website/screens/foundations/tokens/tables/CoreFontTokens.tsx b/apps/website/screens/foundations/tokens/tables/CoreFontTokens.tsx deleted file mode 100644 index 2f9033e80..000000000 --- a/apps/website/screens/foundations/tokens/tables/CoreFontTokens.tsx +++ /dev/null @@ -1,162 +0,0 @@ -import { TableCode } from "@/common/Code"; -import { DxcTable } from "@dxc-technology/halstack-react"; - -export const FontSizesTokens = () => ( - - - - Token - Default value - - - - - - --font-size-12 - - 12px - - - - --font-size-14 - - 14px - - - - --font-size-16 - - 16px - - - - --font-size-18 - - 18px - - - - --font-size-20 - - 20px - - - - --font-size-24 - - 24px - - - - --font-size-32 - - 32px - - - - --font-size-40 - - 40px - - - - --font-size-48 - - 48px - - - - --font-size-60 - - 60px - - - -); - -export const FontWeightTokens = () => ( - - - - Token - Default value - - - - - - --font-weight-light - - 300 - - - - --font-weight-regular - - 400 - - - - --font-weight-semibold - - 600 - - - - --font-weight-bold - - 700 - - - -); - -export const FontFamilyTokens = () => ( - - - - Token - Default value - - - - - - --font-family-mono - - Source Code Pro, mono - - - - --font-family-sans - - Open Sans, sans-serif - - - -); - -export const FontStylesTokens = () => ( - - - - Token - Default value - - - - - - --font-style-lightitalic - - light italic - - - - --font-style-normal - - normal - - - -); diff --git a/apps/website/screens/foundations/tokens/tables/TokensTable.tsx b/apps/website/screens/foundations/tokens/tables/TokensTable.tsx new file mode 100644 index 000000000..968632bf5 --- /dev/null +++ b/apps/website/screens/foundations/tokens/tables/TokensTable.tsx @@ -0,0 +1,27 @@ +import { TableCode } from "@/common/Code"; +import { DxcTable } from "@dxc-technology/halstack-react"; +import { aliasTokens, coreTokens } from "../../../../../../packages/lib/src/styles/tokens"; +import getTokensByCategory from "./utils/mapCategory"; + +const TokensTable = ({ categories, type }: { categories: string[]; type: "alias" | "core" }) => ( + + + + Token + Default value + + + + {getTokensByCategory(type === "alias" ? aliasTokens : coreTokens, categories).map(([token, value]) => ( + + + {token} + + {type === "alias" ? {value} : value} + + ))} + + +); + +export default TokensTable; diff --git a/apps/website/screens/foundations/tokens/tables/utils/mapCategory.ts b/apps/website/screens/foundations/tokens/tables/utils/mapCategory.ts new file mode 100644 index 000000000..9f51ae687 --- /dev/null +++ b/apps/website/screens/foundations/tokens/tables/utils/mapCategory.ts @@ -0,0 +1,4 @@ +const getTokensByCategory = (tokens: Record, categories: string[]) => + Object.entries(tokens).filter(([token]) => categories.some((category) => token.startsWith(`--${category}`))); + +export default getTokensByCategory; diff --git a/apps/website/screens/migration/Components16MigrationPage.tsx b/apps/website/screens/migration/Components16MigrationPage.tsx new file mode 100644 index 000000000..0328f88f3 --- /dev/null +++ b/apps/website/screens/migration/Components16MigrationPage.tsx @@ -0,0 +1,374 @@ +import { DxcFlex, DxcParagraph, DxcHeading, DxcTable, DxcLink, DxcBulletedList } from "@dxc-technology/halstack-react"; +import QuickNavContainer from "@/common/QuickNavContainer"; +import DocFooter from "@/common/DocFooter"; +import PageHeading from "@/common/PageHeading"; +import Code, { ExtendedTableCode } from "@/common/Code"; +import Link from "next/link"; + +const sections = [ + { + title: "Introduction", + content: ( + + Version 16.0.0 introduces major breaking changes, including redesigned components, API updates, and + the removal of deprecated elements. This guide details the main differences and how to migrate components from{" "} + 15.x.x to 16.0.0. + + ), + }, + { + title: "Added components", + content: ( + <> + The following component is now available to be used in your applications: + + + + Component + Features + + + + + Avatar + + Visual element used to identify users, teams, or entities across the interface. It helps create a + recognizable and consistent user experience by visually representing people or objects through images, + icons, or initials. + + + + + + For more information about its usage and features, refer to{" "} + + its documentation + + + + ), + }, + { + title: "Modified components", + content: ( + + Several components were redesigned and now have a different API or behavior. See below for details. + + ), + subSections: [ + { + title: "ApplicationLayout", + content: ( + + The ApplicationLayout component and its compound components have been redesigned. The new API + focuses on improved flexibility, better responsiveness, and easier customization. The header{" "} + prop is no longer required, however it is highly encouraged to have either a Sidenav or a{" "} + Header in your application. The following sections will explain the changes in more depth. + + ), + subSections: [ + { + title: "ApplicationLayout.Header", + content: ( + <> + + The Header component has been redesigned. The new API provides a simpler and more + flexible approach: + + + + + Version + Description + + + + + + v15 (old) + + + The header was configured using props like underlined,content, and{" "} + responsiveContent. Dropdowns were rendered using DxcHeader.Dropdown. + + + + + v16 + + + The new header uses logo and appTitle for the branding,{" "} + navItems for navigation links (with optional nested groups),{" "} + sideContent for side elements, and responsiveBottomContent for + mobile-specific content. + + + + + + When migrating, move your old content and dropdowns into the new logo,{" "} + appTitle and navItems props. Replace responsiveContent with{" "} + responsiveBottomContent and sideContent based on the desired positioning.{" "} + sideContent can receive a flag parameter that depends on responsiveness. + + + For further information regarding the new API, please refer to{" "} + + updated documentation + + + + ), + }, + { + title: "ApplicationLayout.Sidenav", + content: ( + <> + + The Sidenav component has also changed from a compound component structure to a + declarative navItems prop. This new API also features changes that improve the + responsiveness and flexibility of the component. + + + + + Version + Description + + + + + + v15 (old) + + + DxcSidenav.Section,DxcSidenav.Group, and DxcSidenav.Link{" "} + defined the structure and links. + + + + + v16 + + +

      + The navItems prop accepts an array of Item and + GroupItem objects. Each GroupItem has the following structure: +

      + {`{ + badge?: ReactElement; + icon?: string | SVG; + label: string; + items: (Item)[]; +}`} +

      + Each Item has the following structure: +

      + {`{ + badge?: ReactElement; + icon?: string | SVG; + label: string; + onSelect?: () => void; + selected?: boolean; +}`} + + + +
      + + These are the main changes but there are some new additional props that have been added in this + version. + + + When migrating:{" "} + + + Flatten your old Title, Section, Group, and + Link structure into a single items array following the new typing. + + + Move your old logo/app title into the new logo and appTitle props. + + + Include topContent and bottomContent as needed for further interaction + and handle the expanded state for responsive layouts with defaultExpanded for + uncontrolled behavior or expanded and onExpandedChange for controlled + behavior + + + + + ), + }, + // TODO: CHECK PELAYO PR FOR THE NEW FOOTER API + { + title: "ApplicationLayout.Footer", + content: ( + + The Footer component no longer accepts children. It now provides two different props,{" "} + leftContent and rightContent, for placing custom elements in their respective + areas. In reduced mode, the footer will no longer display custom content on the right side, + instead it will display the copyright statement. A new logo prop has also been added to be + able to support custom branding. + + ), + }, + ], + }, + { + title: "Badge", + content: ( + + Due to the recent token updates, we have aligned the color prop with a semantic color approach. + The available values are now 'primary', 'secondary', 'tertiary', + 'success', 'info', 'neutral', 'warning', and + 'error', replacing the previous functional options ('grey', 'blue',{" "} + 'green', 'orange', 'red','yellow', 'purple' + ). + + ), + }, + { + title: "DataGrid", + content: ( + + + This component + {" "} + has exited the experimental phase and is now fully supported, featuring new functionalities like on-demand + loading (thanks to the childrenTrigger prop), possibility to have rows expanded by default and + the possibility to render any page by default. To know more about these new features, please refer to the + updated documentation. + + ), + }, + { + title: "Heading", + content: ( + + The weight options have been refactored, from 'light' | 'normal' | 'bold' to{" "} + 'default' | 'regular' | 'light'. Additionally, a heading level 6 is now supported. + + ), + }, + { + title: "Slider", + content: ( + + tabIndex prop has been removed. The prop was not working as we intended, so in the meantime we + decided to remove it. We believe that, at some point, the component will need to set this prop. + + ), + }, + { + title: "Tabs", + content: ( + + The Tabs component no longer supports the legacy API. A more flexible approach using a Compound + Component Pattern is now used instead to maintain a higher consistency with our existing{" "} + NavTabs and make the API much simpler. Additionally, a few improvements have been made to + enhance responsiveness and controlled behavior. Please refer to the + + updated documentation + {" "} + for more details. + + ), + }, + { + title: "ToggleGroup", + content: ( + + The ToggleGroup component API has been updated, including the possibility to have a custom + orientation (horizontal or vertical) and a redesign of the way options are structured. Please refer to the + + updated documentation + {" "} + for more details. + + ), + }, + ], + }, + { + title: "Removed components", + content: ( + <> + + The following components are no longer available and must be replaced or removed from your application: + + + + + Component + Action + + + + + Tag + + Removed completely. Replace with Badge, a Chip or StatusLight{" "} + based on the context. + + + + + + The following table describes which component to use depending on the use case: + + + + + Replacement + Recommended use case + + + + + + Badge + + + Use when you need to display a compact piece of information such as a count, short label, or status + indicator inside or near another component (e.g., notification count, "New", "Beta"). + + + + + Chip + + + Use for interactive labels or items representing filters, selections, or categories that users can + select, deselect, or remove. + + + + + StatusLight + + + Use for simple, non-interactive visual indicators of state or system status (e.g., success, warning, + error, inactive). + + + + + + ), + }, +]; + +const Components16MigrationPage = () => ( + + + + + + + + + +); + +export default Components16MigrationPage; diff --git a/apps/website/screens/migration/EmotionMigrationPage.tsx b/apps/website/screens/migration/EmotionMigrationPage.tsx new file mode 100644 index 000000000..41eeaead9 --- /dev/null +++ b/apps/website/screens/migration/EmotionMigrationPage.tsx @@ -0,0 +1,274 @@ +import { DxcFlex, DxcParagraph, DxcHeading, DxcTable, DxcLink } from "@dxc-technology/halstack-react"; +import QuickNavContainer from "@/common/QuickNavContainer"; +import DocFooter from "@/common/DocFooter"; +import PageHeading from "@/common/PageHeading"; +import Code from "@/common/Code"; +import Link from "next/link"; +import CodeBlock from "@/common/CodeBlock"; + +const sections = [ + { + title: "Overview", + content: ( + + As part of the version 16.0.0 release, Halstack React now uses emotion as its internal + styling engine. Previous versions relied on styled-components. This change improves performance, + reduces bundle size, and aligns with the rest of the Halstack ecosystem. This page explains the required steps + if your application relied on styled-components specific features, theme injections, or style + overrides. If any topic is not covered here, please refer to the{" "} + + official Emotion documentation + + . + + ), + }, + { + title: "What has changed", + content: ( + + + + Area + styled-components + emotion + + + + + Primary styling API + + styled factory from styled-components + + + @emotion/styled + + + + CSS prop + Not available by default + + Available natively{" "} + + CSS prop + + + + + SSR insertion + + ServerStyleSheet + + + @emotion/server (extractCritical) + + + + Theme object + SC ThemeProvider + Emotion ThemeProvider + + + + ), + }, + { + title: "Impact on adopters", + content: ( + <> + Applications may need adjustments in the following areas: +
        +
      • + Local components using styled-components. +
      • +
      • + Server-side rendering setups relying on ServerStyleSheet. +
      • +
      • Build setups using the Babel plugin for styled-components.
      • +
      + + ), + }, + { + title: "Updating styled components to emotion", + subSections: [ + { + title: "Installation", + content: ( + <> + + As stated in the{" "} + + Installation Page + + , the following packages must be added to your project: + + {`npm i @emotion/react @emotion/styled`} + While the following package must be removed from it: + {`npm un styled-components`} + + ), + }, + { + title: "Styled usage", + content: ( + <> + + Replace imports from styled-components with @emotion/styled: + + Previous version: + import styled from "styled-components"; + New version: + import styled from "@emotion/styled"; + + The API of both works in the same way, so this should be the only required change. For further + information, please refer to the{" "} + + official documentation + + + + ), + }, + { + title: "Animations and keyframes", + content: ( + <> + + Replace keyframes from styled-components with the one provided by Emotion. + + Previous version: + {`import { keyframes } from "styled-components";`} + New version: + {`import { keyframes } from "@emotion/react";`} + + ), + }, + { + title: "Theming", + content: ( + <> + + Theme context must now be provided using Emotion's ThemeProvider: + + Previous version: + {`import { ThemeProvider } from "styled-components";`} + New version: + {`import { ThemeProvider } from "@emotion/react";`} + + Emotion and styled-components have mostly compatible theming APIs, but theme propagation differs in some + edge cases. In Emotion, deeply nested styled components always use the nearest + ThemeProvider without needing additional wrappers. + + + If your application relied on implicit theme merging or multiple nested theme layers from + styled-components, verify that the theme structure is still correct after migrating. + + + ), + }, + { + title: "CSS prop", + content: ( + <> + + Emotion supports the css prop natively. This prop can be used to apply styles directly to any + component without needing to create a styled wrapper. For more information please refer to the{" "} + + official documentation + + + + ), + }, + { + title: "SSR configuration", + content: ( + <> + + If your app uses SSR, replace ServerStyleSheet with Emotion's server utilities: + + Previous version: + {`import { ServerStyleSheet } from "styled-components";`} + New version: + {`import createEmotionServer from "@emotion/server/create-instance"; +import { cache } from "@emotion/css"; // or emotion-cache if configured +const { extractCritical } = createEmotionServer(cache);`} + + ), + }, + ], + }, + { + title: "Global styles", + content: ( + <> + + If your application used createGlobalStyle from styled-components, it must be + replaced with Emotion's Global component. + + Previous version: + + {`import { createGlobalStyle } from "styled-components"; + +const GlobalStyles = createGlobalStyle\` + body { + margin: 0; + } +\`;`} + + New version: + + {`import { Global, css } from "@emotion/react"; + +const GlobalStyles = ( + +);`} + + + ), + }, + { + title: "Removing styled-components from your build", + content: ( + <> + + styled-components is no longer required by Halstack React. You should make sure to remove: + +
        +
      • + styled-components from package.json +
      • +
      • + Babel plugin (babel-plugin-styled-components) +
      • +
      • Any styled-components-specific webpack or SSR setup
      • +
      + + ), + }, +]; + +const EmotionMigrationPage = () => ( + + + + + + + + + +); + +export default EmotionMigrationPage; diff --git a/apps/website/screens/migration/TokensMigrationPage.tsx b/apps/website/screens/migration/TokensMigrationPage.tsx new file mode 100644 index 000000000..a4c80f11c --- /dev/null +++ b/apps/website/screens/migration/TokensMigrationPage.tsx @@ -0,0 +1,281 @@ +import { DxcFlex, DxcParagraph, DxcHeading, DxcTable, DxcLink } from "@dxc-technology/halstack-react"; +import QuickNavContainer from "@/common/QuickNavContainer"; +import DocFooter from "@/common/DocFooter"; +import PageHeading from "@/common/PageHeading"; +import Code from "@/common/Code"; +import CodeBlock from "@/common/CodeBlock"; +import Link from "next/link"; + +const sections = [ + { + title: "Overview", + content: ( + + Halstack 16 introduces a new token-based theming system composed of core and alias{" "} + tokens. In Halstack 15, theming relied on a JSON-based opinionatedTheme /{" "} + advancedTheme object passed to the application wrapper. This migration page explains how to + transition from the old theme object to the new CSS-token architecture. + + ), + }, + { + title: "What has changed", + content: ( + + + + Area + Halstack 15 + Halstack 16 + + + + + Theming mechanism + Theme object (JSON) passed to provider + CSS variables (core + alias tokens) + + + Customization + opinionatedTheme / advancedTheme + Override core tokens (safe) and component tokens (advanced, upcoming) + + + Runtime updates + ThemeProvider re-renders components + CSS vars update instantly without rerenders + + + Naming consistency + No token taxonomy, per-component styles + Core → Alias → Component (3-layer architecture) + + + + ), + }, + { + title: "Impact on adopters", + content: ( + <> + Applications may need adjustments in the following areas: +
        +
      • + Removal of old theme shape (advancedTheme / opinionatedTheme). +
      • +
      • Migrating color, spacing, and typography overrides to CSS tokens.
      • +
      • Replacing any custom component overrides that referenced theme object values.
      • +
      • Updating global styles to rely on CSS variables instead of hardcoded values.
      • +
      + + ), + }, + { + title: "New token architecture", + subSections: [ + { + title: "Core tokens", + content: ( + <> + + Core tokens define the raw, non-contextual values of the design system. They map directly to CSS + variables. You can find a list with all the core tokens in{" "} + + this page + + . + + + ), + }, + { + title: "Alias tokens", + content: ( + <> + + Alias tokens map raw core values to semantic meanings such as background, foreground, or border tokens. + They provide a shared vocabulary across components. You can find a list with all the alias tokens in{" "} + + this page + + . + + + ), + }, + { + title: "Component tokens (upcoming)", + content: ( + <> + + Component tokens will be introduced progressively. They will reference alias tokens and control + component-level styling. + + + ), + }, + ], + }, + { + title: "Migrating from the old theming strategy", + subSections: [ + { + title: "Style overrides", + content: ( + <> + Old JSON-based color overrides must be replaced by CSS variable assignments. + Previous version: + {`const customTheme = { + button: { + "baseColor": "#2b470b", + "primaryFontColor": "#ffffff", + } +} +// ... +return ( + + + +);`} + New version: + + {`const opinionatedTheme = { + "--color-primary-700": "#2b470b", + "--color-absolutes-white": "#ffffff", +} +// ... +return ( + + + +);`} + + + This can be applied to colors, fonts, spacings and borders. However, keep in mind that, for now, only core + tokens can be overwritten and they affect all the components which are wrapped within the{" "} + HalstackProvider. + + + ), + }, + { + title: "Apply themes dynamically", + content: ( + <> + + To support dynamic theme switching (for example, toggling between light and dark mode), you can store the + theme object in a useState hook and update it in response to user actions. When the state + changes, the + HalstackProvider receives the updated CSS variables and the UI updates instantly without + rerendering components manually. + + + + {`const App = () => { + // Light palette example + const lightPalette = { + "--color-primary-50": "#d3f0b4", + "--color-primary-100": "#a2df5e", + "--color-primary-200": "#77c81f", + "--color-primary-300": "#68ad1b", + "--color-primary-400": "#579317", + "--color-primary-500": "#487813", + "--color-primary-600": "#39600f", + "--color-primary-700": "#2b470b", + "--color-primary-800": "#1c2f07", + "--color-primary-900": "#0d1503", + + "--color-secondary-50": "#fff9d6", + "--color-secondary-100": "#ffed99", + "--color-secondary-200": "#ffe066", + "--color-secondary-300": "#e6c84d", + "--color-secondary-400": "#ccad33", + "--color-secondary-500": "#b39426", + "--color-secondary-600": "#8f741f", + "--color-secondary-700": "#6b5517", + "--color-secondary-800": "#47370f", + "--color-secondary-900": "#241b08", + }; + + // Dark palette example + const darkPalette = { + "--color-primary-50": "#ffd6e7", + "--color-primary-100": "#ff99c2", + "--color-primary-200": "#ff66a3", + "--color-primary-300": "#e05584", + "--color-primary-400": "#c5446d", + "--color-primary-500": "#a83659", + "--color-primary-600": "#872b47", + "--color-primary-700": "#661f35", + "--color-primary-800": "#441423", + "--color-primary-900": "#220a12", + + "--color-secondary-50": "#f3e6db", + "--color-secondary-100": "#e2c7a9", + "--color-secondary-200": "#d1a577", + "--color-secondary-300": "#b88252", + "--color-secondary-400": "#99673f", + "--color-secondary-500": "#7a5232", + "--color-secondary-600": "#5c3f26", + "--color-secondary-700": "#3e2b19", + "--color-secondary-800": "#21170d", + "--color-secondary-900": "#100b06", + }; + + const [theme, setTheme] = useState("light"); + + const toggleTheme = () => { + setTheme((prev) => { + const newTheme = prev === "light" ? "dark" : "light"; + console.log("Toggling theme", newTheme); + return newTheme; + }); + }; + + return ( + + + + ); +};`} + + + Any component wrapped by HalstackProvider will immediately reflect the new token values. + + + ), + }, + ], + }, + { + title: "Removing legacy theming APIs", + content: ( + <> + Ensure you remove: +
        +
      • + All usage of the old opinionatedTheme and advancedTheme. +
      • +
      • + Theme props passed to DxcApplication or similar wrappers. +
      • +
      • Any custom wrappers relying on the old theme shape.
      • +
      + + ), + }, +]; + +const TokensMigrationPage = () => ( + + + + + + + + + +); + +export default TokensMigrationPage; diff --git a/apps/website/screens/utilities/halstack-provider/HalstackProviderPage.tsx b/apps/website/screens/utilities/halstack-provider/HalstackProviderPage.tsx index 789ab0e77..b47a212d4 100644 --- a/apps/website/screens/utilities/halstack-provider/HalstackProviderPage.tsx +++ b/apps/website/screens/utilities/halstack-provider/HalstackProviderPage.tsx @@ -2,6 +2,7 @@ import DocFooter from "@/common/DocFooter"; import Example from "@/common/example/Example"; import QuickNavContainer from "@/common/QuickNavContainer"; import customTranslations from "./examples/customTranslations"; +import customThemes from "./examples/customThemes"; import { DxcFlex, DxcParagraph, @@ -15,6 +16,7 @@ import { import Link from "next/link"; import PageHeading from "@/common/PageHeading"; import Code, { TableCode } from "@/common/Code"; +import StatusBadge from "@/common/StatusBadge"; const sections = [ { @@ -38,6 +40,19 @@ const sections = [ Object with a given structure, specified below, for defining translations. - + + + + + opinionatedTheme + + + + OpinionatedTheme + + Object with a given structure, specified below, for defining the opinionated theme. + - + ), @@ -80,6 +95,23 @@ const sections = [ ), }, + { + title: "Theming", + content: ( + <> + You can apply the opinionated theming strategy to customize the components. + + Below is an example of customizing the colours of a DxcButton: + + + + We create a lightPalette and darkPalette objects with as many CSS variables as we + want and their respective values. Then we pass one of the objects based on the state of the theme{" "} + to the Halstack Provider, which wraps our components, through its opinionatedTheme property. + + + ), + }, ]; const HalstackProviderPage = () => ( diff --git a/apps/website/screens/utilities/halstack-provider/examples/customThemes.tsx b/apps/website/screens/utilities/halstack-provider/examples/customThemes.tsx new file mode 100644 index 000000000..7e38c5eeb --- /dev/null +++ b/apps/website/screens/utilities/halstack-provider/examples/customThemes.tsx @@ -0,0 +1,78 @@ +import { HalstackProvider, DxcButton } from "@dxc-technology/halstack-react"; +import { useState } from "react"; + +const code = `() => { + // Light palette example + const lightPalette = { + "--color-primary-50": "#d3f0b4", + "--color-primary-100": "#a2df5e", + "--color-primary-200": "#77c81f", + "--color-primary-300": "#68ad1b", + "--color-primary-400": "#579317", + "--color-primary-500": "#487813", + "--color-primary-600": "#39600f", + "--color-primary-700": "#2b470b", + "--color-primary-800": "#1c2f07", + "--color-primary-900": "#0d1503", + + "--color-secondary-50": "#fff9d6", + "--color-secondary-100": "#ffed99", + "--color-secondary-200": "#ffe066", + "--color-secondary-300": "#e6c84d", + "--color-secondary-400": "#ccad33", + "--color-secondary-500": "#b39426", + "--color-secondary-600": "#8f741f", + "--color-secondary-700": "#6b5517", + "--color-secondary-800": "#47370f", + "--color-secondary-900": "#241b08", + }; + + // Dark palette example + const darkPalette = { + "--color-primary-50": "#ffd6e7", + "--color-primary-100": "#ff99c2", + "--color-primary-200": "#ff66a3", + "--color-primary-300": "#e05584", + "--color-primary-400": "#c5446d", + "--color-primary-500": "#a83659", + "--color-primary-600": "#872b47", + "--color-primary-700": "#661f35", + "--color-primary-800": "#441423", + "--color-primary-900": "#220a12", + + "--color-secondary-50": "#f3e6db", + "--color-secondary-100": "#e2c7a9", + "--color-secondary-200": "#d1a577", + "--color-secondary-300": "#b88252", + "--color-secondary-400": "#99673f", + "--color-secondary-500": "#7a5232", + "--color-secondary-600": "#5c3f26", + "--color-secondary-700": "#3e2b19", + "--color-secondary-800": "#21170d", + "--color-secondary-900": "#100b06", + }; + + const [theme, setTheme] = useState("light"); + + const toggleTheme = () => { + setTheme((prev) => { + const newTheme = prev === "light" ? "dark" : "light"; + console.log("Toggling theme", newTheme); + return newTheme; + }); + }; + + return ( + + + + ); +}`; + +const scope = { + DxcButton, + HalstackProvider, + useState, +}; + +export default { code, scope }; diff --git a/packages/lib/src/base-menu/GroupItem.tsx b/packages/lib/src/base-menu/GroupItem.tsx index e72c73bf4..d5a742288 100644 --- a/packages/lib/src/base-menu/GroupItem.tsx +++ b/packages/lib/src/base-menu/GroupItem.tsx @@ -29,7 +29,6 @@ const GroupItem = ({ items, ...props }: GroupItemProps) => { : } onClick={() => toggleOpen()} selected={groupSelected && !isOpen} diff --git a/packages/lib/src/base-menu/ItemAction.tsx b/packages/lib/src/base-menu/ItemAction.tsx index 5d0546b26..c07b662ff 100644 --- a/packages/lib/src/base-menu/ItemAction.tsx +++ b/packages/lib/src/base-menu/ItemAction.tsx @@ -91,8 +91,9 @@ const ItemAction = memo( handleTextMouseEnter, getWrapper, } = useItemAction(props); - const { depthLevel, selected, href, label, icon, collapseIcon, "aria-pressed": ariaPressed, ...rest } = props; - + const { depthLevel, selected, href, label, icon, collapseIcon, ...rest } = props; + const ariaPressed = !href ? !!selected : undefined; + const ariaSelected = href ? !!selected : undefined; return getWrapper(