diff --git a/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-ic-theme-inherit-dark.png b/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-ic-theme-inherit-dark.png
new file mode 100755
index 0000000000..321346fee4
Binary files /dev/null and b/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-ic-theme-inherit-dark.png differ
diff --git a/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-ic-theme-inherit-light.png b/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-ic-theme-inherit-light.png
new file mode 100755
index 0000000000..6ba5984f34
Binary files /dev/null and b/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-ic-theme-inherit-light.png differ
diff --git a/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-ic-theme-light-with-components-within-ic-theme.png b/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-ic-theme-light-with-components-within-ic-theme.png
new file mode 100755
index 0000000000..846d35d0a5
Binary files /dev/null and b/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-ic-theme-light-with-components-within-ic-theme.png differ
diff --git a/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-ic-theme-light-with-dark-mode-component-overrides.png b/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-ic-theme-light-with-dark-mode-component-overrides.png
new file mode 100755
index 0000000000..18018781e0
Binary files /dev/null and b/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-ic-theme-light-with-dark-mode-component-overrides.png differ
diff --git a/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-ic-theme-system-light.png b/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-ic-theme-system-light.png
new file mode 100755
index 0000000000..18018781e0
Binary files /dev/null and b/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-ic-theme-system-light.png differ
diff --git a/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-sunrise-brand.png b/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-sunrise-brand.png
new file mode 100755
index 0000000000..76481137ac
Binary files /dev/null and b/packages/react/cypress-image-diff-screenshots/baseline/IcTheme.cy.tsx-sunrise-brand.png differ
diff --git a/packages/react/src/component-tests/IcTheme/IcTheme.cy.tsx b/packages/react/src/component-tests/IcTheme/IcTheme.cy.tsx
new file mode 100644
index 0000000000..ecf5441b10
--- /dev/null
+++ b/packages/react/src/component-tests/IcTheme/IcTheme.cy.tsx
@@ -0,0 +1,203 @@
+/* eslint-disable react/jsx-no-bind */
+///
+
+import { mount } from "cypress/react";
+import React from "react";
+import {
+ ComponentsWithInheritThemeProp,
+ SwitchBrand,
+ ThemeWithComponentThemeProps,
+ ThemeWithComponentWithinSeparateIcTheme,
+} from "./IcThemeTestData";
+import {
+ HAVE_ATTR,
+ HAVE_BEEN_CALLED_ONCE,
+ HAVE_BEEN_CALLED_WITH,
+} from "../utils/constants";
+import { setThresholdBasedOnEnv } from "../../../cypress/utils/helpers";
+
+const THEME_SELECTOR = "ic-theme";
+const DEFAULT_TEST_THRESHOLD = 0.048;
+
+describe("IcTheme end-to-end and visual regression tests", () => {
+ beforeEach(() => {
+ cy.injectAxe();
+ cy.viewport(1440, 900);
+ });
+
+ afterEach(() => {
+ cy.task("generateReport");
+ });
+
+ it("should render in light mode when IcTheme theme is set to light with components with theme prop set to dark rendered in dark mode", () => {
+ mount(
+
+ );
+
+ cy.checkHydrated(THEME_SELECTOR);
+
+ cy.checkA11yWithWait();
+ cy.compareSnapshot({
+ name: "ic-theme-light-with-dark-mode-component-overrides",
+ testThreshold: setThresholdBasedOnEnv(DEFAULT_TEST_THRESHOLD + 0.031),
+ });
+ });
+
+ it("should render in light mode when IcTheme theme is set to light with components within another IcTheme component with theme set to dark rendered in dark mode", () => {
+ mount(
+
+ );
+
+ cy.checkHydrated(THEME_SELECTOR);
+
+ cy.checkA11yWithWait();
+ cy.compareSnapshot({
+ name: "ic-theme-light-with-components-within-ic-theme",
+ testThreshold: setThresholdBasedOnEnv(DEFAULT_TEST_THRESHOLD + 0.03),
+ });
+ });
+
+ it.skip("should render according to dark mode system settings when IcTheme theme is set to system", () => {
+ cy.wrap(
+ Cypress.automation("remote:debugger:protocol", {
+ command: "Emulation.setEmulatedMedia",
+ params: {
+ features: [
+ {
+ name: "prefers-color-scheme",
+ value: "dark",
+ },
+ ],
+ },
+ })
+ );
+
+ mount(
+
+ );
+
+ cy.checkHydrated(THEME_SELECTOR);
+
+ cy.checkA11yWithWait();
+ cy.compareSnapshot({
+ name: "ic-theme-system-dark",
+ testThreshold: setThresholdBasedOnEnv(DEFAULT_TEST_THRESHOLD + 0.03),
+ });
+ });
+
+ it("should render according to light mode system settings when IcTheme theme is set to system", () => {
+ cy.wrap(
+ Cypress.automation("remote:debugger:protocol", {
+ command: "Emulation.setEmulatedMedia",
+ params: {
+ features: [
+ {
+ name: "prefers-color-scheme",
+ value: "light",
+ },
+ ],
+ },
+ })
+ );
+
+ mount(
+
+ );
+
+ cy.checkHydrated(THEME_SELECTOR);
+
+ cy.checkA11yWithWait();
+ cy.compareSnapshot({
+ name: "ic-theme-system-light",
+ testThreshold: setThresholdBasedOnEnv(DEFAULT_TEST_THRESHOLD + 0.031),
+ });
+ });
+
+ it("should render components with IcTheme colour when theme prop is set to inherit - dark theme", () => {
+ mount(
+
+ );
+
+ cy.checkHydrated(THEME_SELECTOR);
+
+ cy.checkA11yWithWait();
+ cy.compareSnapshot({
+ name: "ic-theme-inherit-dark",
+ testThreshold: setThresholdBasedOnEnv(DEFAULT_TEST_THRESHOLD),
+ });
+ });
+
+ it("should render components with IcTheme colour when theme prop is set to inherit - light theme", () => {
+ mount(
+
+ );
+
+ cy.checkHydrated(THEME_SELECTOR);
+
+ cy.checkA11yWithWait();
+ cy.compareSnapshot({
+ name: "ic-theme-inherit-light",
+ testThreshold: setThresholdBasedOnEnv(DEFAULT_TEST_THRESHOLD + 0.004),
+ });
+ });
+
+ it("should switch brand colour", () => {
+ mount();
+
+ cy.checkHydrated(THEME_SELECTOR);
+ cy.spy(window.console, "log").as("spyWinConsoleLog");
+ cy.get(THEME_SELECTOR).invoke(
+ "on",
+ "brandChange",
+ cy.stub().as("brandChange")
+ );
+
+ cy.get(THEME_SELECTOR).should(
+ HAVE_ATTR,
+ "brand-color",
+ "rgb(255, 201, 60)"
+ );
+
+ cy.compareSnapshot({
+ name: "sunrise-brand",
+ testThreshold: setThresholdBasedOnEnv(DEFAULT_TEST_THRESHOLD + 0.022),
+ });
+
+ cy.get("ic-button").contains("Default theme").click();
+ cy.get(THEME_SELECTOR).should(HAVE_ATTR, "brand-color", "rgb(27, 60, 121)");
+ cy.get("@brandChange").should(HAVE_BEEN_CALLED_ONCE);
+ cy.get("@spyWinConsoleLog").should(HAVE_BEEN_CALLED_WITH, {
+ mode: "light",
+ color: {
+ r: 27,
+ g: 60,
+ b: 121,
+ a: 1,
+ },
+ });
+ });
+});
diff --git a/packages/react/src/component-tests/IcTheme/IcThemeTestData.tsx b/packages/react/src/component-tests/IcTheme/IcThemeTestData.tsx
new file mode 100644
index 0000000000..2b3f508897
--- /dev/null
+++ b/packages/react/src/component-tests/IcTheme/IcThemeTestData.tsx
@@ -0,0 +1,595 @@
+import React, { ReactElement, useState } from "react";
+import {
+ IcTheme,
+ IcTopNavigation,
+ IcSearchBar,
+ IcNavigationButton,
+ IcNavigationItem,
+ IcHero,
+ IcTextField,
+ IcButton,
+ IcLink,
+ IcSectionContainer,
+ IcCheckbox,
+ IcAlert,
+ IcTypography,
+ IcCardVertical,
+ IcFooter,
+ IcFooterLink,
+ IcSwitch,
+} from "../../components";
+import { SlottedSVG } from "../../react-component-lib/slottedSVG";
+
+export const ThemeWithComponentThemeProps = (args: {
+ color: "rgba(27, 60, 121, 1)";
+ theme: "light" | "dark" | "system";
+ backgroundColor: "white" | "black";
+}): ReactElement => {
+ return (
+ <>
+
+
+
+
+
+
+
+
+ alert("test")}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filter
+
+
+
+ See all
+
+
+ Help
+
+
+
+
+
+
+
+ Button
+
+
+
+ This is some text and
+ this is an inline link IcLink
+ within the text
+
+
+
+
+
+
+
+
+
+
+ The component theme prop should override the IcTheme theme prop
+
+
+
+
+
+ Get Started
+
+
+ Accessibility
+
+
+ Styles
+
+
+ Components
+
+
+ Patterns
+
+
+ Design toolkit
+
+
+ Slotted Button
+
+
+
+
+ >
+ );
+};
+
+export const ThemeWithComponentWithinSeparateIcTheme = (args: {
+ color: "rgba(27, 60, 121, 1)";
+ theme: "light" | "dark" | "system";
+ backgroundColor: "white" | "black";
+}): ReactElement => {
+ return (
+ <>
+
+
+
+
+
+
+
+
+ alert("test")}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filter
+
+
+
+ See all
+
+
+ Help
+
+
+
+
+
+
+
+ Button
+
+
+
+ This is some text and
+ this is an inline link IcLink
+ within the text
+
+
+
+
+
+
+ This content is in an IcTheme component with dark mode set
+
+
+
+
+
+
+
+
+
+ Get Started
+
+
+ Accessibility
+
+
+ Styles
+
+
+ Components
+
+
+ Patterns
+
+
+ Design toolkit
+
+
+ Slotted Button
+
+
+
+
+ >
+ );
+};
+
+export const ComponentsWithInheritThemeProp = (args: {
+ color: "rgba(27, 60, 121, 1)";
+ theme: "light" | "dark" | "system";
+ backgroundColor: "white" | "black";
+}): ReactElement => {
+ return (
+ <>
+
+
+
+
+
+
+
+
+ alert("test")}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Components will inherit their theme colour based on IcTheme when
+ theme="inherit"
+
+
+
+
+
+ >
+ );
+};
+
+export const SwitchBrand = () => {
+ const [color, setColour] = useState("rgb(255, 201, 60)");
+ const defaultButtonClickHandler = () => {
+ setColour("rgb(27, 60, 121)");
+ };
+ const differentButtonClickHandler = () => {
+ setColour("rgb(255, 201, 60)");
+ };
+ const handleBrandChange = (e: CustomEvent) => {
+ console.log(e.detail);
+ };
+ return (
+ <>
+
+
+ Default theme
+
+
+ Sunset theme
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filter
+
+
+
+ See all
+
+
+ Help
+
+
+
+
+ Get Started
+
+
+ Accessibility
+
+
+ Styles
+
+
+ Components
+
+
+ Patterns
+
+
+ Design toolkit
+
+
+
Slotted Button
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
diff --git a/packages/react/src/stories/ic-theme.stories.mdx b/packages/react/src/stories/ic-theme.stories.mdx
index dbdf539117..4a0274010e 100644
--- a/packages/react/src/stories/ic-theme.stories.mdx
+++ b/packages/react/src/stories/ic-theme.stories.mdx
@@ -105,11 +105,11 @@ export const Controlled = () => {
full-width
>
-
+ >
Filter
@@ -117,13 +117,13 @@ export const Controlled = () => {
See all
-
Help
-
+
{
This is some text and
- this is an inline link ic-link
+ this is an inline link ic-link
within the text
{
style={{
display: "flex",
alignItems: "center",
- gap: "var(--ic-space-sm);",
+ gap: "var(--ic-space-sm)",
}}
>
Slotted Button
@@ -269,11 +269,11 @@ export const defaultArgs = {
full-width
>
-
+ >
Filter
@@ -281,13 +281,13 @@ export const defaultArgs = {
See all
-
Help
-
+
This is some text and
- this is an inline link ic-link
+ this is an inline link ic-link
within the text
@@ -361,7 +361,7 @@ export const defaultArgs = {
style={{
display: "flex",
alignItems: "center",
- gap: "var(--ic-space-sm);",
+ gap: "var(--ic-space-sm)",
}}
>
Slotted Button