diff --git a/lib/.storybook/components/ExampleContainer.tsx b/lib/.storybook/components/ExampleContainer.tsx
index 06327682a..ed873a6df 100644
--- a/lib/.storybook/components/ExampleContainer.tsx
+++ b/lib/.storybook/components/ExampleContainer.tsx
@@ -1,9 +1,19 @@
import React from "react";
import styled from "styled-components";
+type PseudoStates =
+ | "pseudo-active"
+ | "pseudo-focus"
+ | "pseudo-focus-visible"
+ | "pseudo-focus-within"
+ | "pseudo-hover"
+ | "pseudo-link"
+ | "pseudo-target"
+ | "pseudo-visited";
+
type Props = {
children?: React.ReactNode;
- pseudoState?: string;
+ pseudoState?: PseudoStates;
expanded?: boolean;
};
diff --git a/lib/package-lock.json b/lib/package-lock.json
index d60c670ed..4a06dc308 100644
--- a/lib/package-lock.json
+++ b/lib/package-lock.json
@@ -36,6 +36,8 @@
"@testing-library/react": "^13.0.0",
"@testing-library/user-event": "^13.0.0",
"@types/color": "^3.0.3",
+ "@types/jest": "^29.5.12",
+ "@types/jest-axe": "^3.5.9",
"@types/react": "^18.0.18",
"@types/styled-components": "5.1.29",
"@types/uuid": "^9.0.6",
@@ -9364,6 +9366,61 @@
"@types/istanbul-lib-report": "*"
}
},
+ "node_modules/@types/jest": {
+ "version": "29.5.12",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz",
+ "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==",
+ "dev": true,
+ "dependencies": {
+ "expect": "^29.0.0",
+ "pretty-format": "^29.0.0"
+ }
+ },
+ "node_modules/@types/jest-axe": {
+ "version": "3.5.9",
+ "resolved": "https://registry.npmjs.org/@types/jest-axe/-/jest-axe-3.5.9.tgz",
+ "integrity": "sha512-z98CzR0yVDalCEuhGXXO4/zN4HHuSebAukXDjTLJyjEAgoUf1H1i+sr7SUB/mz8CRS/03/XChsx0dcLjHkndoQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/jest": "*",
+ "axe-core": "^3.5.5"
+ }
+ },
+ "node_modules/@types/jest-axe/node_modules/axe-core": {
+ "version": "3.5.6",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-3.5.6.tgz",
+ "integrity": "sha512-LEUDjgmdJoA3LqklSTwKYqkjcZ4HKc4ddIYGSAiSkr46NTjzg2L9RNB+lekO9P7Dlpa87+hBtzc2Fzn/+GUWMQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@types/jest/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@types/jest/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
"node_modules/@types/jsdom": {
"version": "20.0.1",
"resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz",
diff --git a/lib/package.json b/lib/package.json
index 371263a22..ae93c9645 100644
--- a/lib/package.json
+++ b/lib/package.json
@@ -56,6 +56,8 @@
"@testing-library/react": "^13.0.0",
"@testing-library/user-event": "^13.0.0",
"@types/color": "^3.0.3",
+ "@types/jest": "^29.5.12",
+ "@types/jest-axe": "^3.5.9",
"@types/react": "^18.0.18",
"@types/styled-components": "5.1.29",
"@types/uuid": "^9.0.6",
diff --git a/lib/src/breadcrumbs/Breadcrumbs.accessibility.test.tsx b/lib/src/breadcrumbs/Breadcrumbs.accessibility.test.tsx
new file mode 100644
index 000000000..98d82bb63
--- /dev/null
+++ b/lib/src/breadcrumbs/Breadcrumbs.accessibility.test.tsx
@@ -0,0 +1,51 @@
+import React from "react";
+import { render } from "@testing-library/react";
+import { axe } from "../../test/accessibility/axe-helper.js";
+import DxcBreadcrumbs from "./Breadcrumbs";
+import { disabledRules as rules } from "../../test/accessibility/rules/specific/breadcrumbs/disabledRules.js";
+
+const disabledRules = {
+ rules: rules.reduce((rulesObj, rule) => {
+ rulesObj[rule] = { enabled: false };
+ return rulesObj;
+ }, {}),
+};
+
+const items = [
+ {
+ label: "Home",
+ href: "/",
+ },
+ {
+ label: "User Menu",
+ href: "",
+ },
+ {
+ label: "Preferences",
+ href: "",
+ },
+ {
+ label: "Dark Mode",
+ href: "",
+ },
+];
+
+describe("Breadcrumbs component accessibility tests", () => {
+ it("Should not have basic accessibility issues", async () => {
+ const { container } = render();
+ const results = await axe(container, disabledRules);
+ expect(results).toHaveNoViolations();
+ });
+ it("Should not have basic accessibility issues when collapsed", async () => {
+ const { container } = render();
+ const results = await axe(container, disabledRules);
+ expect(results).toHaveNoViolations();
+ });
+ it("Should not have basic accessibility issues without root", async () => {
+ const { container } = render(
+
+ );
+ const results = await axe(container, disabledRules);
+ expect(results).toHaveNoViolations();
+ });
+});
diff --git a/lib/src/breadcrumbs/Breadcrumbs.stories.tsx b/lib/src/breadcrumbs/Breadcrumbs.stories.tsx
new file mode 100644
index 000000000..31187d644
--- /dev/null
+++ b/lib/src/breadcrumbs/Breadcrumbs.stories.tsx
@@ -0,0 +1,194 @@
+import React from "react";
+import Title from "../../.storybook/components/Title";
+import ExampleContainer from "../../.storybook/components/ExampleContainer";
+import DxcBreadcrumbs from "./Breadcrumbs";
+import DxcContainer from "../container/Container";
+import { HalstackProvider } from "../HalstackContext";
+import { userEvent, within } from "@storybook/testing-library";
+import { disabledRules } from "../../test/accessibility/rules/specific/breadcrumbs/disabledRules";
+import preview from "../../.storybook/preview";
+
+export default {
+ title: "Breadcrumbs",
+ component: DxcBreadcrumbs,
+ parameters: {
+ a11y: {
+ config: {
+ rules: [
+ ...disabledRules.map((ruleId) => ({ id: ruleId, enabled: false })),
+ ...preview?.parameters?.a11y?.config?.rules,
+ ],
+ },
+ },
+ },
+};
+
+const items = [
+ {
+ label: "Home",
+ href: "/",
+ },
+ {
+ label: "User Menu",
+ href: "",
+ },
+ {
+ label: "Preferences",
+ href: "",
+ },
+ {
+ label: "Customization",
+ href: "",
+ },
+ {
+ label: "Dark Mode",
+ href: "",
+ },
+];
+
+const Breadcrumbs = () => (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+);
+
+export const Chromatic = Breadcrumbs.bind({});
+Chromatic.play = async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const dropdowns = canvas.getAllByRole("button");
+ await userEvent.click(dropdowns[2]);
+};
diff --git a/lib/src/breadcrumbs/Breadcrumbs.test.tsx b/lib/src/breadcrumbs/Breadcrumbs.test.tsx
new file mode 100644
index 000000000..199a62069
--- /dev/null
+++ b/lib/src/breadcrumbs/Breadcrumbs.test.tsx
@@ -0,0 +1,97 @@
+import React from "react";
+import { render } from "@testing-library/react";
+import DxcBreadcrumbs from "./Breadcrumbs";
+import userEvent from "@testing-library/user-event";
+
+global.ResizeObserver = class ResizeObserver {
+ observe() {}
+ unobserve() {}
+ disconnect() {}
+};
+
+const items = [
+ {
+ label: "Home",
+ href: "/",
+ },
+ {
+ label: "User Menu",
+ href: "",
+ },
+ {
+ label: "Preferences",
+ href: "",
+ },
+ {
+ label: "Dark Mode",
+ href: "",
+ },
+];
+
+describe("Breadcrumbs component tests", () => {
+ test("Renders with correct aria accessibility attributes", () => {
+ const { getByText, getByRole } = render();
+ const breadcrumbs = getByRole("navigation");
+ expect(breadcrumbs.getAttribute("aria-label")).toBe("example");
+ expect(getByText("Dark Mode").parentElement.getAttribute("aria-current")).toBe("page");
+ });
+ test("Collapsed variant renders all the items inside the dropdown menu except the root and the current page", async () => {
+ const { queryByText, getByText, getByRole } = render();
+ const dropdown = getByRole("button");
+ expect(queryByText("User Menu")).toBeFalsy();
+ expect(queryByText("Preferences")).toBeFalsy();
+ await userEvent.click(dropdown);
+ expect(getByText("User Menu")).toBeTruthy();
+ expect(getByText("Preferences")).toBeTruthy();
+ });
+ test("Collapsed variant, with show root set to false, renders all the items inside the dropdown menu except the current page", async () => {
+ const { queryByText, getByText, getByRole } = render(
+
+ );
+ const dropdown = getByRole("button");
+ expect(queryByText("Home")).toBeFalsy();
+ expect(queryByText("User Menu")).toBeFalsy();
+ expect(queryByText("Preferences")).toBeFalsy();
+ await userEvent.click(dropdown);
+ expect(getByText("Home")).toBeTruthy();
+ expect(getByText("User Menu")).toBeTruthy();
+ expect(getByText("Preferences")).toBeTruthy();
+ });
+ test("If itemsBeforeCollapse value is below two, ignores it and renders a collapsed variant", async () => {
+ const { getByText, getByRole } = render();
+ expect(getByText("Home")).toBeTruthy();
+ expect(getByRole("button")).toBeTruthy();
+ expect(getByText("Dark Mode")).toBeTruthy();
+ });
+ test("The onClick prop from an item is properly called", () => {
+ const onItemClick = jest.fn();
+ const { getByText } = render(
+
+ );
+ userEvent.click(getByText("Home"));
+ expect(onItemClick).toHaveBeenCalledWith("/home");
+ });
+ test("The onClick prop from an item is properly called (collapsed)", async () => {
+ const onItemClick = jest.fn();
+ const { getByText, getByRole } = render(
+
+ );
+ await userEvent.click(getByRole("button"));
+ await userEvent.click(getByText("Preferences"));
+ expect(onItemClick).toHaveBeenCalledWith("/");
+ });
+});
diff --git a/lib/src/breadcrumbs/Breadcrumbs.tsx b/lib/src/breadcrumbs/Breadcrumbs.tsx
new file mode 100644
index 000000000..82eea9eac
--- /dev/null
+++ b/lib/src/breadcrumbs/Breadcrumbs.tsx
@@ -0,0 +1,85 @@
+import React, { useCallback } from "react";
+import styled from "styled-components";
+import BreadcrumbsProps from "./types";
+import DxcDropdown from "../dropdown/Dropdown";
+import { HalstackProvider } from "../HalstackContext";
+import dropdownTheme from "./dropdownTheme";
+import CoreTokens from "../common/coreTokens";
+import DxcIcon from "../icon/Icon";
+import Item from "./Item";
+import DxcFlex from "../flex/Flex";
+
+const DxcBreadcrumbs = ({
+ ariaLabel = "Breadcrumbs",
+ items,
+ itemsBeforeCollapse = 4,
+ onItemClick,
+ showRoot = true,
+}: BreadcrumbsProps) => {
+ const handleOnSelectOption = useCallback(
+ (href: string) => {
+ if (onItemClick) onItemClick(href);
+ else window.location.href = href;
+ },
+ [items]
+ );
+
+ return (
+
+ );
+};
+
+const OrderedList = styled.ol`
+ margin: ${CoreTokens.spacing_0};
+ padding-left: ${CoreTokens.spacing_0};
+ display: flex;
+ align-items: center;
+ gap: ${CoreTokens.spacing_12};
+ list-style-type: none;
+
+ > li:not(:first-child) {
+ > a,
+ > span {
+ margin-left: ${CoreTokens.spacing_12};
+ }
+ &::before {
+ margin: ${CoreTokens.spacing_0} ${CoreTokens.spacing_2};
+ transform: rotate(15deg);
+ border-right: ${CoreTokens.border_width_1} solid ${CoreTokens.color_grey_500};
+ height: 1rem;
+ content: "";
+ }
+ }
+`;
+
+export default DxcBreadcrumbs;
diff --git a/lib/src/breadcrumbs/Item.tsx b/lib/src/breadcrumbs/Item.tsx
new file mode 100644
index 000000000..f608967fa
--- /dev/null
+++ b/lib/src/breadcrumbs/Item.tsx
@@ -0,0 +1,78 @@
+import React from "react";
+import styled from "styled-components";
+import CoreTokens from "../common/coreTokens";
+import { ItemPropsType } from "./types";
+import { useRef } from "react";
+
+const Item = ({ isCurrentPage = false, href, label, onClick }: ItemPropsType) => {
+ const currentItemRef = useRef(null);
+
+ const handleOnMouseEnter = (event: React.MouseEvent) => {
+ const labelContainer = event.currentTarget;
+ const optionElement = currentItemRef?.current;
+ if (optionElement.title === "" && labelContainer.scrollWidth > labelContainer.clientWidth)
+ optionElement.title = label;
+ };
+
+ const handleOnClick = (event: React.MouseEvent) => {
+ if (onClick) {
+ event.preventDefault();
+ onClick(href);
+ }
+ };
+
+ return (
+
+ {isCurrentPage ? (
+
+ {label}
+
+ ) : (
+
+ {label}
+
+ )}
+
+ );
+};
+
+const ListItem = styled.li<{ isCurrentPage?: ItemPropsType["isCurrentPage"] }>`
+ display: flex;
+ align-items: center;
+ font-family: ${CoreTokens.type_sans};
+ font-size: ${CoreTokens.type_scale_02};
+ color: ${CoreTokens.color_black};
+ ${({ isCurrentPage }) => isCurrentPage && "overflow: hidden;"}
+`;
+
+const CurrentPage = styled.span`
+ font-weight: ${CoreTokens.type_semibold};
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ cursor: default;
+`;
+
+const Link = styled.a`
+ border-radius: ${CoreTokens.border_radius_small};
+ padding: ${CoreTokens.spacing_0} ${CoreTokens.spacing_2};
+ display: inline-flex;
+ align-items: center;
+ height: 24px;
+ color: ${CoreTokens.color_black};
+ text-decoration: ${CoreTokens.type_no_line};
+ cursor: pointer;
+
+ &:focus {
+ outline: ${CoreTokens.border_width_2} solid ${CoreTokens.color_blue_600};
+ }
+`;
+
+const Text = styled.span`
+ border: ${CoreTokens.border_width_1} solid ${CoreTokens.color_transparent};
+ &:hover {
+ border-bottom-color: ${CoreTokens.color_black};
+ }
+`;
+
+export default Item;
diff --git a/lib/src/breadcrumbs/dropdownTheme.ts b/lib/src/breadcrumbs/dropdownTheme.ts
new file mode 100644
index 000000000..5fe908d28
--- /dev/null
+++ b/lib/src/breadcrumbs/dropdownTheme.ts
@@ -0,0 +1,57 @@
+import CoreTokens from "../common/coreTokens";
+
+export default {
+ dropdown: {
+ // Breadcrumbs tokens
+ buttonIconSize: CoreTokens.spacing_16,
+ buttonPaddingTop: CoreTokens.spacing_4,
+ buttonPaddingBottom: CoreTokens.spacing_4,
+ buttonPaddingLeft: CoreTokens.spacing_4,
+ buttonPaddingRight: CoreTokens.spacing_4,
+ buttonHeight: "24px",
+ buttonBorderRadius: "2px",
+ buttonBorderColor: CoreTokens.color_transparent,
+ optionFontSize: "14px",
+ optionPaddingTop: CoreTokens.spacing_0,
+ optionPaddingBottom: CoreTokens.spacing_0,
+ optionPaddingLeft: CoreTokens.spacing_16,
+ optionPaddingRight: CoreTokens.spacing_16,
+
+ // Dropdown tokens
+ buttonBackgroundColor: CoreTokens.color_white,
+ hoverButtonBackgroundColor: CoreTokens.color_grey_100,
+ activeButtonBackgroundColor: CoreTokens.color_grey_300,
+ buttonFontFamily: CoreTokens.type_sans,
+ buttonFontSize: CoreTokens.type_scale_03,
+ buttonFontStyle: CoreTokens.type_normal,
+ buttonFontWeight: CoreTokens.type_regular,
+ buttonFontColor: CoreTokens.color_black,
+ buttonIconSpacing: "10px",
+ buttonIconColor: CoreTokens.color_black,
+ buttonBorderStyle: CoreTokens.border_none,
+ buttonBorderThickness: CoreTokens.border_width_0,
+ disabledColor: CoreTokens.color_grey_500,
+ disabledButtonBackgroundColor: CoreTokens.color_transparent,
+ disabledButtonBorderColor: CoreTokens.color_transparent,
+ optionBackgroundColor: CoreTokens.color_white,
+ hoverOptionBackgroundColor: CoreTokens.color_grey_100,
+ activeOptionBackgroundColor: CoreTokens.color_grey_300,
+ optionFontFamily: CoreTokens.type_sans,
+ optionFontStyle: CoreTokens.type_normal,
+ optionFontWeight: CoreTokens.type_regular,
+ optionFontColor: CoreTokens.color_black,
+ optionIconSize: "20px",
+ optionIconSpacing: "10px",
+ optionIconColor: CoreTokens.color_black,
+ caretIconSize: "24px",
+ caretIconColor: CoreTokens.color_black,
+ caretIconSpacing: "12px",
+ borderRadius: "4px",
+ borderStyle: CoreTokens.border_none,
+ borderThickness: CoreTokens.border_width_0,
+ borderColor: CoreTokens.color_transparent,
+ scrollBarThumbColor: CoreTokens.color_grey_700,
+ scrollBarTrackColor: CoreTokens.color_grey_300,
+ focusColor: CoreTokens.color_blue_600,
+ },
+};
diff --git a/lib/src/breadcrumbs/types.ts b/lib/src/breadcrumbs/types.ts
new file mode 100644
index 000000000..5748cc0ac
--- /dev/null
+++ b/lib/src/breadcrumbs/types.ts
@@ -0,0 +1,18 @@
+type Item = {
+ href?: string;
+ label: string;
+};
+type Props = {
+ ariaLabel?: string;
+ items: Array- ;
+ itemsBeforeCollapse?: number;
+ onItemClick?: (href: string) => void;
+ showRoot?: boolean;
+};
+
+export type ItemPropsType = Item & {
+ isCurrentPage?: boolean;
+ onClick?: (href: string) => void;
+};
+
+export default Props;
diff --git a/lib/src/common/coreTokens.ts b/lib/src/common/coreTokens.ts
index b145250d9..750720805 100644
--- a/lib/src/common/coreTokens.ts
+++ b/lib/src/common/coreTokens.ts
@@ -109,10 +109,10 @@ export const getCoreColorToken = (key: CoreColorTokens) => CoreColorTokens[key];
export type CoreColorTokens = keyof typeof CoreColorTokens;
/**
- * Halstack Spacing Principles
+ * Halstack Spacing Values
* @link https://developer.dxc.com/halstack/next/principles/spacing/
*/
-const SpacingTokens = {
+const CoreSpacingTokens = {
spacing_0: "0rem",
spacing_2: "0.125rem",
spacing_4: "0.25rem",
@@ -132,7 +132,7 @@ const SpacingTokens = {
const CoreTokens = {
...CoreColorTokens,
- ...SpacingTokens,
+ ...CoreSpacingTokens,
inherit: "inherit",
diff --git a/lib/src/common/variables.ts b/lib/src/common/variables.ts
index 231d87804..fd745a7d3 100644
--- a/lib/src/common/variables.ts
+++ b/lib/src/common/variables.ts
@@ -14,18 +14,18 @@ export const componentTokens = {
assistiveTextFontColor: CoreTokens.color_grey_700,
disabledAssistiveTextFontColor: CoreTokens.color_grey_500,
assistiveTextMinWidth: "100px",
- assistiveTextPaddingRight: "24px",
- assistiveTextPaddingLeft: "0px",
+ assistiveTextPaddingRight: CoreTokens.spacing_24,
+ assistiveTextPaddingLeft: CoreTokens.spacing_0,
titleLabelFontFamily: CoreTokens.type_sans,
titleLabelFontSize: CoreTokens.type_scale_03,
titleLabelFontWeight: CoreTokens.type_regular,
titleLabelFontStyle: CoreTokens.type_normal,
titleLabelFontColor: CoreTokens.color_black,
disabledTitleLabelFontColor: CoreTokens.color_grey_500,
- titleLabelPaddingTop: "0px",
- titleLabelPaddingBottom: "0px",
- titleLabelPaddingLeft: "0px",
- titleLabelPaddingRight: "16px",
+ titleLabelPaddingTop: CoreTokens.spacing_0,
+ titleLabelPaddingBottom: CoreTokens.spacing_0,
+ titleLabelPaddingLeft: CoreTokens.spacing_0,
+ titleLabelPaddingRight: CoreTokens.spacing_16,
focusBorderColor: CoreTokens.color_blue_600,
focusBorderStyle: CoreTokens.border_solid,
focusBorderThickness: "2px",
@@ -37,8 +37,8 @@ export const componentTokens = {
iconColor: CoreTokens.color_purple_700,
disabledIconColor: CoreTokens.color_grey_500,
iconSize: "24px",
- iconMarginLeft: "0px",
- iconMarginRight: "12px",
+ iconMarginLeft: CoreTokens.spacing_0,
+ iconMarginRight: CoreTokens.spacing_12,
accordionGroupSeparatorBorderColor: CoreTokens.color_grey_200_a,
accordionGroupSeparatorBorderThickness: "1px",
accordionGroupSeparatorBorderRadius: "0px",
@@ -51,17 +51,17 @@ export const componentTokens = {
titleFontStyle: CoreTokens.type_normal,
titleFontWeight: CoreTokens.type_bold,
titleTextTransform: CoreTokens.type_uppercase,
- titlePaddingRight: "0px",
- titlePaddingLeft: "0px",
+ titlePaddingRight: CoreTokens.spacing_0,
+ titlePaddingLeft: CoreTokens.spacing_0,
inlineTextFontFamily: CoreTokens.type_sans,
inlineTextFontColor: CoreTokens.color_black,
inlineTextFontSize: CoreTokens.type_scale_01,
inlineTextFontStyle: CoreTokens.type_normal,
inlineTextFontWeight: CoreTokens.type_regular,
- inlineTextPaddingLeft: "0px",
- inlineTextPaddingRight: "0px",
- contentPaddingLeft: "0px",
- contentPaddingRight: "0px",
+ inlineTextPaddingLeft: CoreTokens.spacing_0,
+ inlineTextPaddingRight: CoreTokens.spacing_0,
+ contentPaddingLeft: CoreTokens.spacing_0,
+ contentPaddingRight: CoreTokens.spacing_0,
contentPaddingTop: "20px",
contentPaddingBottom: "30px",
borderRadius: "4px",
@@ -72,8 +72,8 @@ export const componentTokens = {
warningBorderColor: CoreTokens.color_yellow_700,
errorBorderColor: CoreTokens.color_red_700,
iconSize: "24px",
- iconPaddingLeft: "0px",
- iconPaddingRight: "0px",
+ iconPaddingLeft: CoreTokens.spacing_0,
+ iconPaddingRight: CoreTokens.spacing_0,
infoIconColor: CoreTokens.color_blue_800,
successIconColor: CoreTokens.color_green_700,
warningIconColor: CoreTokens.color_yellow_700,
@@ -115,7 +115,7 @@ export const componentTokens = {
bulletIconWidth: "1.5rem",
bulletHeight: "5px",
bulletWidth: "5px",
- bulletMarginRight: "0.5rem",
+ bulletMarginRight: CoreTokens.spacing_8,
},
button: {
labelFontLineHeight: CoreTokens.type_leading_normal,
@@ -189,7 +189,7 @@ export const componentTokens = {
fontColor: CoreTokens.color_black,
disabledFontColor: CoreTokens.color_grey_500,
focusColor: CoreTokens.color_blue_600,
- checkLabelSpacing: "8px",
+ checkLabelSpacing: CoreTokens.spacing_8,
},
chip: {
backgroundColor: CoreTokens.color_grey_200,
@@ -204,12 +204,12 @@ export const componentTokens = {
borderRadius: "80px",
borderThickness: CoreTokens.border_width_0,
borderStyle: CoreTokens.border_solid,
- contentPaddingLeft: "16px",
- contentPaddingRight: "16px",
- contentPaddingTop: "0px",
- contentPaddingBottom: "0px",
+ contentPaddingLeft: CoreTokens.spacing_16,
+ contentPaddingRight: CoreTokens.spacing_16,
+ contentPaddingTop: CoreTokens.spacing_0,
+ contentPaddingBottom: CoreTokens.spacing_0,
iconSize: "24px",
- iconSpacing: "8px",
+ iconSpacing: CoreTokens.spacing_8,
iconColor: CoreTokens.color_grey_800,
hoverIconColor: CoreTokens.color_grey_900,
activeIconColor: CoreTokens.color_black,
@@ -279,10 +279,10 @@ export const componentTokens = {
buttonIconSize: "20px",
buttonIconSpacing: "10px",
buttonIconColor: CoreTokens.color_black,
- buttonPaddingTop: "0px",
- buttonPaddingBottom: "0px",
- buttonPaddingLeft: "16px",
- buttonPaddingRight: "16px",
+ buttonPaddingTop: CoreTokens.spacing_0,
+ buttonPaddingBottom: CoreTokens.spacing_0,
+ buttonPaddingLeft: CoreTokens.spacing_16,
+ buttonPaddingRight: CoreTokens.spacing_16,
buttonHeight: "40px",
buttonBorderRadius: "4px",
buttonBorderStyle: CoreTokens.border_none,
@@ -291,7 +291,6 @@ export const componentTokens = {
disabledColor: CoreTokens.color_grey_500,
disabledButtonBackgroundColor: CoreTokens.color_transparent,
disabledButtonBorderColor: CoreTokens.color_transparent,
- disabledBorderColor: CoreTokens.color_transparent,
optionBackgroundColor: CoreTokens.color_white,
hoverOptionBackgroundColor: CoreTokens.color_grey_100,
activeOptionBackgroundColor: CoreTokens.color_grey_300,
@@ -305,11 +304,11 @@ export const componentTokens = {
optionIconColor: CoreTokens.color_black,
optionPaddingTop: "6px",
optionPaddingBottom: "6px",
- optionPaddingLeft: "16px",
- optionPaddingRight: "16px",
+ optionPaddingLeft: CoreTokens.spacing_16,
+ optionPaddingRight: CoreTokens.spacing_16,
caretIconSize: "24px",
caretIconColor: CoreTokens.color_black,
- caretIconSpacing: "12px",
+ caretIconSpacing: CoreTokens.spacing_12,
borderRadius: "4px",
borderStyle: CoreTokens.border_none,
borderThickness: CoreTokens.border_width_0,
@@ -331,7 +330,6 @@ export const componentTokens = {
focusDropBorderColor: CoreTokens.color_blue_600,
disabledDropBorderColor: CoreTokens.color_grey_500,
dragoverDropBackgroundColor: CoreTokens.color_blue_50,
- activeFileItemIconBackgrounColor: CoreTokens.color_grey_300,
errorFileItemBorderColor: CoreTokens.color_red_700,
errorFileItemBackgroundColor: CoreTokens.color_red_50,
errorFilePreviewBackgroundColor: CoreTokens.color_red_200,
@@ -377,7 +375,7 @@ export const componentTokens = {
bottomLinksDividerColor: CoreTokens.color_blue_600,
bottomLinksDividerThickness: "1px",
bottomLinksDividerStyle: CoreTokens.border_solid,
- bottomLinksDividerSpacing: "8px",
+ bottomLinksDividerSpacing: CoreTokens.spacing_8,
bottomLinksFontFamily: CoreTokens.type_sans,
bottomLinksFontSize: CoreTokens.type_scale_01,
bottomLinksFontStyle: CoreTokens.type_normal,
@@ -393,7 +391,7 @@ export const componentTokens = {
logoHeight: "32px",
logoWidth: "auto",
socialLinksSize: "24px",
- socialLinksGutter: "16px",
+ socialLinksGutter: CoreTokens.spacing_16,
socialLinksColor: CoreTokens.color_white,
},
header: {
@@ -419,10 +417,10 @@ export const componentTokens = {
overlayColor: CoreTokens.color_grey_800_a,
overlayOpacity: "0.7",
overlayZindex: "1600",
- paddingTop: "0px",
- paddingBottom: "0px",
- paddingRight: "24px",
- paddingLeft: "24px",
+ paddingTop: CoreTokens.spacing_0,
+ paddingBottom: CoreTokens.spacing_0,
+ paddingRight: CoreTokens.spacing_24,
+ paddingLeft: CoreTokens.spacing_24,
underlinedColor: CoreTokens.color_black,
underlinedThickness: "2px",
underlinedStyle: CoreTokens.border_solid,
@@ -480,8 +478,8 @@ export const componentTokens = {
fontStyle: CoreTokens.type_normal,
fontWeight: CoreTokens.type_regular,
iconSize: "16px",
- iconSpacing: "4px",
- underlineSpacing: "0px",
+ iconSpacing: CoreTokens.spacing_4,
+ underlineSpacing: CoreTokens.spacing_0,
underlineStyle: CoreTokens.border_solid,
underlineThickness: "1px",
disabledFontColor: CoreTokens.color_grey_500,
@@ -520,20 +518,20 @@ export const componentTokens = {
fontStyle: CoreTokens.type_normal,
fontWeight: CoreTokens.type_regular,
fontTextTransform: "none",
- verticalPadding: "0.75rem",
- horizontalPadding: "2rem",
- marginRight: "40px",
+ verticalPadding: CoreTokens.spacing_12,
+ horizontalPadding: CoreTokens.spacing_32,
+ marginRight: CoreTokens.spacing_40,
marginLeft: "20px",
- itemsPerPageSelectorMarginLeft: "0px",
- itemsPerPageSelectorMarginRight: "0.5rem",
+ itemsPerPageSelectorMarginLeft: CoreTokens.spacing_0,
+ itemsPerPageSelectorMarginRight: CoreTokens.spacing_8,
pageSelectorMarginRight: "30px",
- pageSelectorMarginLeft: "0px",
- totalItemsContainerMarginRight: "2.5rem",
- totalItemsContainerMarginLeft: "0px",
+ pageSelectorMarginLeft: CoreTokens.spacing_0,
+ totalItemsContainerMarginRight: CoreTokens.spacing_40,
+ totalItemsContainerMarginLeft: CoreTokens.spacing_0,
},
paragraph: {
- fontColor: CoreTokens.color_black,
display: "block",
+ fontColor: CoreTokens.color_black,
fontSize: CoreTokens.type_scale_03,
fontWeight: CoreTokens.type_regular,
},
@@ -719,10 +717,10 @@ export const componentTokens = {
linkFontTextTransform: "none",
linkFontLetterSpacing: CoreTokens.type_spacing_wide_01,
linkTextDecoration: CoreTokens.type_no_line,
- linkMarginTop: "4px",
- linkMarginBottom: "4px",
- linkMarginRight: "16px",
- linkMarginLeft: "16px",
+ linkMarginTop: CoreTokens.spacing_4,
+ linkMarginBottom: CoreTokens.spacing_4,
+ linkMarginRight: CoreTokens.spacing_16,
+ linkMarginLeft: CoreTokens.spacing_16,
linkFocusColor: CoreTokens.color_blue_600,
scrollBarThumbColor: CoreTokens.color_grey_200_a,
scrollBarTrackColor: CoreTokens.color_transparent,
@@ -836,7 +834,7 @@ export const componentTokens = {
thumbShift: "1.25rem",
trackHeight: "12px",
trackWidth: "36px",
- spaceBetweenLabelSwitch: "8px",
+ spaceBetweenLabelSwitch: CoreTokens.spacing_8,
},
table: {
rowSeparatorThickness: "1px",
@@ -849,8 +847,8 @@ export const componentTokens = {
dataFontWeight: CoreTokens.type_regular,
dataFontColor: CoreTokens.color_black,
dataFontTextTransform: "none",
- dataPaddingTop: "16px",
- dataPaddingBottom: "16px",
+ dataPaddingTop: CoreTokens.spacing_16,
+ dataPaddingBottom: CoreTokens.spacing_16,
dataPaddingRight: "20px",
dataPaddingLeft: "20px",
dataPaddingTopReduced: CoreTokens.spacing_8,
@@ -871,8 +869,8 @@ export const componentTokens = {
headerFontWeight: CoreTokens.type_regular,
headerFontColor: CoreTokens.color_white,
headerFontTextTransform: "none",
- headerPaddingTop: "16px",
- headerPaddingBottom: "16px",
+ headerPaddingTop: CoreTokens.spacing_16,
+ headerPaddingBottom: CoreTokens.spacing_16,
headerPaddingRight: "20px",
headerPaddingLeft: "20px",
headerPaddingTopReduced: CoreTokens.spacing_8,
@@ -926,10 +924,10 @@ export const componentTokens = {
fontSize: CoreTokens.type_scale_02,
fontStyle: CoreTokens.type_normal,
fontWeight: CoreTokens.type_regular,
- labelPaddingTop: "0px",
- labelPaddingBottom: "0px",
- labelPaddingLeft: "16px",
- labelPaddingRight: "16px",
+ labelPaddingTop: CoreTokens.spacing_0,
+ labelPaddingBottom: CoreTokens.spacing_0,
+ labelPaddingLeft: CoreTokens.spacing_16,
+ labelPaddingRight: CoreTokens.spacing_16,
height: "40px",
iconColor: CoreTokens.color_white,
iconSectionWidth: "40px",
@@ -1297,13 +1295,13 @@ export type OpinionatedTheme = {
};
export const spaces = {
- xxsmall: "6px",
- xsmall: "16px",
- small: "24px",
- medium: "36px",
- large: "48px",
- xlarge: "64px",
- xxlarge: "100px",
+ xxsmall: CoreTokens.spacing_4,
+ xsmall: CoreTokens.spacing_8,
+ small: CoreTokens.spacing_12,
+ medium: CoreTokens.spacing_16,
+ large: CoreTokens.spacing_24,
+ xlarge: CoreTokens.spacing_32,
+ xxlarge: CoreTokens.spacing_48,
};
export const responsiveSizes = {
diff --git a/lib/src/main.ts b/lib/src/main.ts
index 39f9a446e..53e8538d3 100644
--- a/lib/src/main.ts
+++ b/lib/src/main.ts
@@ -45,6 +45,7 @@ import DxcBadge from "./badge/Badge";
import DxcStatusLight from "./status-light/StatusLight";
import DxcContextualMenu from "./contextual-menu/ContextualMenu";
import DxcDivider from "./divider/Divider";
+import DxcBreadcrumbs from "./breadcrumbs/Breadcrumbs";
import HalstackContext, { HalstackProvider, HalstackLanguageContext } from "./HalstackContext";
@@ -99,4 +100,5 @@ export {
DxcStatusLight,
DxcContextualMenu,
DxcDivider,
+ DxcBreadcrumbs,
};
diff --git a/lib/test/accessibility/rules/specific/breadcrumbs/disabledRules.js b/lib/test/accessibility/rules/specific/breadcrumbs/disabledRules.js
new file mode 100644
index 000000000..c37ae007f
--- /dev/null
+++ b/lib/test/accessibility/rules/specific/breadcrumbs/disabledRules.js
@@ -0,0 +1,8 @@
+/**
+ * Array of accessibility rule IDs to be disabled in both Jest and Storybook for the breadcrumbs component.
+ *
+ */
+export const disabledRules = [
+ // Disable landmark unique valid rule to prevent errors from having multiple nav in the same page (that can happen in testing environments)
+ "landmark-unique",
+];
diff --git a/website/screens/common/themes/advanced-theme.json b/website/screens/common/themes/advanced-theme.json
index e98de9124..e78c54a09 100644
--- a/website/screens/common/themes/advanced-theme.json
+++ b/website/screens/common/themes/advanced-theme.json
@@ -323,7 +323,6 @@
"focusDropBorderColor": "#0095ff",
"disabledDropBorderColor": "#999999",
"dragoverDropBackgroundColor": "#f5fbff",
- "activeFileItemIconBackgrounColor": "#cccccc",
"errorFileItemBorderColor": "#d0011b",
"errorFileItemBackgroundColor": "#fff5f6",
"errorFilePreviewBackgroundColor": "#ffccd3",
diff --git a/website/screens/components/link/code/examples/nextLink.ts b/website/screens/components/link/code/examples/nextLink.ts
index b67f514f8..48b41b6a5 100644
--- a/website/screens/components/link/code/examples/nextLink.ts
+++ b/website/screens/components/link/code/examples/nextLink.ts
@@ -3,18 +3,20 @@ import Link from "next/link";
import React from "react";
const code = `() => {
- const CustomLink = React.forwardRef(({ onClick, href, children, ...other }, ref) => {
- return (
-
- {children}
-
- );
- });
+ const CustomLink = React.forwardRef(
+ ({ onClick, href, children, ...other }, ref) => {
+ return (
+
+ {children}
+
+ );
+ }
+ );
return (
This is a text with a
- next link
+ next
{" "}
link.
diff --git a/website/screens/theme-generator/themes/schemas/advanced.schema.json b/website/screens/theme-generator/themes/schemas/advanced.schema.json
index c9c297488..559b518f0 100644
--- a/website/screens/theme-generator/themes/schemas/advanced.schema.json
+++ b/website/screens/theme-generator/themes/schemas/advanced.schema.json
@@ -323,7 +323,6 @@
"focusDropBorderColor": "color",
"disabledDropBorderColor": "color",
"dragoverDropBackgroundColor": "color",
- "activeFileItemIconBackgrounColor": "color",
"errorFileItemBorderColor": "color",
"errorFileItemBackgroundColor": "color",
"errorFilePreviewBackgroundColor": "color",