From 9b7f0a11267bd4c5be03ae690b11fb3502b2acfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rcio?= Date: Wed, 5 Aug 2026 16:34:41 +0200 Subject: [PATCH 1/4] [NO-JIRA] Add new design language color pilot --- design-tokens/tokens/component/dark.json | 30 + design-tokens/tokens/component/light.json | 35 + design-tokens/tokens/modes/dark.json | 255 ++++--- design-tokens/tokens/modes/light.json | 269 +++++-- src/components/buttons/ButtonStyles.tsx | 22 +- .../buttons/__tests__/Button-test.tsx | 2 +- .../SidebarNavigationBaseItem.tsx | 8 +- .../SidebarNavigationItemStyles.tsx | 8 +- src/components/table/TableStyles.tsx | 11 +- src/components/text-input/TextInputBase.tsx | 22 +- src/generated/design-tokens-dark.css | 244 +++++-- src/generated/design-tokens-light.css | 244 +++++-- src/generated/design-tokens-themed.json | 244 +++++-- .../__tests__/color-system-pilot-test.ts | 287 ++++++++ src/utils/design-tokens.ts | 18 +- .../ColorSystemPilot-stories.tsx | 685 ++++++++++++++++++ stories/playground/Issues-stories.tsx | 145 ++++ stories/playground/PlaygroundShell.tsx | 166 +++++ .../playground/PortfolioOverview-stories.tsx | 132 ++++ .../playground/ProjectSettings-stories.tsx | 126 ++++ 20 files changed, 2586 insertions(+), 367 deletions(-) create mode 100644 src/utils/__tests__/color-system-pilot-test.ts create mode 100644 stories/design-tokens/ColorSystemPilot-stories.tsx create mode 100644 stories/playground/Issues-stories.tsx create mode 100644 stories/playground/PlaygroundShell.tsx create mode 100644 stories/playground/PortfolioOverview-stories.tsx create mode 100644 stories/playground/ProjectSettings-stories.tsx diff --git a/design-tokens/tokens/component/dark.json b/design-tokens/tokens/component/dark.json index fa6e8d69a..fa108d678 100644 --- a/design-tokens/tokens/component/dark.json +++ b/design-tokens/tokens/component/dark.json @@ -1,5 +1,35 @@ { "echoes": { + "button": { + "colors": { + "background": { "default": { "$type": "color", "$value": "{echoes.color.background.action.neutral.default}" }, "hover": { "$type": "color", "$value": "{echoes.color.background.action.neutral.hover}" }, "active": { "$type": "color", "$value": "{echoes.color.background.action.neutral.active}" }, "disabled": { "$type": "color", "$value": "{echoes.color.surface.disabled}" } }, + "border": { "default": { "$type": "color", "$value": "{echoes.color.border.action.neutral}" } }, + "text": { "default": { "$type": "color", "$value": "{echoes.color.text.onAction}" }, "disabled": { "$type": "color", "$value": "{echoes.color.text.disabled}" } }, + "focus": { "$type": "color", "$value": "{echoes.color.focus.default}" } + } + }, + "input": { + "colors": { + "background": { "default": { "$type": "color", "$value": "{echoes.color.surface.default}" }, "hover": { "$type": "color", "$value": "{echoes.color.surface.hover}" }, "disabled": { "$type": "color", "$value": "{echoes.color.surface.disabled}" } }, + "border": { "default": { "$type": "color", "$value": "{echoes.color.border.bolder}" }, "focus": { "$type": "color", "$value": "{echoes.color.focus.default}" }, "disabled": { "$type": "color", "$value": "{echoes.color.border.bold}" } }, + "text": { "default": { "$type": "color", "$value": "{echoes.color.text.strong}" }, "placeholder": { "$type": "color", "$value": "{echoes.color.text.subtle}" }, "disabled": { "$type": "color", "$value": "{echoes.color.text.disabled}" } }, + "focus": { "$type": "color", "$value": "{echoes.color.focus.default}" } + } + }, + "navigation-item": { + "colors": { + "background": { "default": { "$type": "color", "$value": "{echoes.color.surface.default}" }, "hover": { "$type": "color", "$value": "{echoes.color.surface.hover}" }, "selected": { "$type": "color", "$value": "{echoes.color.background.selected.weak.default}" }, "selected-hover": { "$type": "color", "$value": "{echoes.color.background.selected.weak.hover}" } }, + "text": { "default": { "$type": "color", "$value": "{echoes.color.text.strong}" }, "selected": { "$type": "color", "$value": "{echoes.color.text.emphasis}" } }, + "icon": { "default": { "$type": "color", "$value": "{echoes.color.icon.subtle}" }, "selected": { "$type": "color", "$value": "{echoes.color.icon.selected}" } }, + "focus": { "$type": "color", "$value": "{echoes.color.focus.default}" } + } + }, + "issue-row": { + "colors": { + "background": { "default": { "$type": "color", "$value": "{echoes.color.surface.default}" }, "hover": { "$type": "color", "$value": "{echoes.color.surface.hover}" }, "selected": { "$type": "color", "$value": "{echoes.color.background.selected.weak.default}" }, "selected-hover": { "$type": "color", "$value": "{echoes.color.background.selected.weak.hover}" } }, + "border": { "$type": "color", "$value": "{echoes.color.border.weak}" } + } + }, "bottom-scroll": { "colors": { "shadow": { diff --git a/design-tokens/tokens/component/light.json b/design-tokens/tokens/component/light.json index 37cbf757f..5da105b6a 100644 --- a/design-tokens/tokens/component/light.json +++ b/design-tokens/tokens/component/light.json @@ -1,5 +1,40 @@ { "echoes": { + "button": { + "colors": { + "background": { + "default": { "$type": "color", "$value": "{echoes.color.background.action.neutral.default}" }, + "hover": { "$type": "color", "$value": "{echoes.color.background.action.neutral.hover}" }, + "active": { "$type": "color", "$value": "{echoes.color.background.action.neutral.active}" }, + "disabled": { "$type": "color", "$value": "{echoes.color.surface.disabled}" } + }, + "border": { "default": { "$type": "color", "$value": "{echoes.color.border.action.neutral}" } }, + "text": { "default": { "$type": "color", "$value": "{echoes.color.text.onAction}" }, "disabled": { "$type": "color", "$value": "{echoes.color.text.disabled}" } }, + "focus": { "$type": "color", "$value": "{echoes.color.focus.default}" } + } + }, + "input": { + "colors": { + "background": { "default": { "$type": "color", "$value": "{echoes.color.surface.default}" }, "hover": { "$type": "color", "$value": "{echoes.color.surface.hover}" }, "disabled": { "$type": "color", "$value": "{echoes.color.surface.disabled}" } }, + "border": { "default": { "$type": "color", "$value": "{echoes.color.border.bolder}" }, "focus": { "$type": "color", "$value": "{echoes.color.focus.default}" }, "disabled": { "$type": "color", "$value": "{echoes.color.border.bold}" } }, + "text": { "default": { "$type": "color", "$value": "{echoes.color.text.strong}" }, "placeholder": { "$type": "color", "$value": "{echoes.color.text.subtle}" }, "disabled": { "$type": "color", "$value": "{echoes.color.text.disabled}" } }, + "focus": { "$type": "color", "$value": "{echoes.color.focus.default}" } + } + }, + "navigation-item": { + "colors": { + "background": { "default": { "$type": "color", "$value": "{echoes.color.surface.default}" }, "hover": { "$type": "color", "$value": "{echoes.color.surface.hover}" }, "selected": { "$type": "color", "$value": "{echoes.color.background.selected.weak.default}" }, "selected-hover": { "$type": "color", "$value": "{echoes.color.background.selected.weak.hover}" } }, + "text": { "default": { "$type": "color", "$value": "{echoes.color.text.strong}" }, "selected": { "$type": "color", "$value": "{echoes.color.text.emphasis}" } }, + "icon": { "default": { "$type": "color", "$value": "{echoes.color.icon.subtle}" }, "selected": { "$type": "color", "$value": "{echoes.color.icon.selected}" } }, + "focus": { "$type": "color", "$value": "{echoes.color.focus.default}" } + } + }, + "issue-row": { + "colors": { + "background": { "default": { "$type": "color", "$value": "{echoes.color.surface.default}" }, "hover": { "$type": "color", "$value": "{echoes.color.surface.hover}" }, "selected": { "$type": "color", "$value": "{echoes.color.background.selected.weak.default}" }, "selected-hover": { "$type": "color", "$value": "{echoes.color.background.selected.weak.hover}" } }, + "border": { "$type": "color", "$value": "{echoes.color.border.weak}" } + } + }, "bottom-scroll": { "colors": { "shadow": { diff --git a/design-tokens/tokens/modes/dark.json b/design-tokens/tokens/modes/dark.json index 92c90af35..67e0ffcc8 100644 --- a/design-tokens/tokens/modes/dark.json +++ b/design-tokens/tokens/modes/dark.json @@ -1,6 +1,89 @@ { "echoes": { "color": { + "palette": { + "ui": { + "gray": { + "1": { "$type": "color", "$value": "#151515" }, "2": { "$type": "color", "$value": "#1A1A1A" }, "3": { "$type": "color", "$value": "#1F1F1F" }, "4": { "$type": "color", "$value": "#252525" }, + "5": { "$type": "color", "$value": "#2A2A2A" }, "6": { "$type": "color", "$value": "#363636" }, "7": { "$type": "color", "$value": "#464646" }, "8": { "$type": "color", "$value": "#5A5A5A" }, + "9": { "$type": "color", "$value": "#737373" }, "10": { "$type": "color", "$value": "#828282" }, "11": { "$type": "color", "$value": "#B8B8B8" }, "12": { "$type": "color", "$value": "#EEEEEE" } + }, + "gray-alpha": { + "1": { "$type": "color", "$value": "#FFFFFF05" }, "2": { "$type": "color", "$value": "#FFFFFF08" }, "3": { "$type": "color", "$value": "#FFFFFF0D" }, "4": { "$type": "color", "$value": "#FFFFFF14" }, + "5": { "$type": "color", "$value": "#FFFFFF1F" }, "6": { "$type": "color", "$value": "#FFFFFF2E" }, "7": { "$type": "color", "$value": "#FFFFFF3D" }, "8": { "$type": "color", "$value": "#FFFFFF52" }, + "9": { "$type": "color", "$value": "#FFFFFF70" }, "10": { "$type": "color", "$value": "#FFFFFF85" }, "11": { "$type": "color", "$value": "#FFFFFFB8" }, "12": { "$type": "color", "$value": "#FFFFFFEB" } + }, + "brand-blue": { + "1": { "$type": "color", "$value": "#0C1825" }, "2": { "$type": "color", "$value": "#0E1E30" }, "3": { "$type": "color", "$value": "#10243A" }, "4": { "$type": "color", "$value": "#122D47" }, + "5": { "$type": "color", "$value": "#153554" }, "6": { "$type": "color", "$value": "#1C4A70" }, "7": { "$type": "color", "$value": "#275F8F" }, "8": { "$type": "color", "$value": "#3D7FBA" }, + "9": { "$type": "color", "$value": "#6BA9F0" }, "10": { "$type": "color", "$value": "#82B8F3" }, "11": { "$type": "color", "$value": "#A9CDF7" }, "12": { "$type": "color", "$value": "#E7F2FD" } + }, + "success-green": { + "1": { "$type": "color", "$value": "#13190D" }, + "2": { "$type": "color", "$value": "#192111" }, + "3": { "$type": "color", "$value": "#1F2914" }, + "4": { "$type": "color", "$value": "#263318" }, + "5": { "$type": "color", "$value": "#2C3D1B" }, + "6": { "$type": "color", "$value": "#3A4F23" }, + "7": { "$type": "color", "$value": "#4B662D" }, + "8": { "$type": "color", "$value": "#68854A" }, + "9": { "$type": "color", "$value": "#7DBA1F" }, + "10": { "$type": "color", "$value": "#94C75A" }, + "11": { "$type": "color", "$value": "#B3D98D" }, + "12": { "$type": "color", "$value": "#E9F5DF" } + }, + "warning-yellow": { + "1": { "$type": "color", "$value": "#1C160D" }, + "2": { "$type": "color", "$value": "#241D11" }, + "3": { "$type": "color", "$value": "#2D2414" }, + "4": { "$type": "color", "$value": "#382C17" }, + "5": { "$type": "color", "$value": "#43341A" }, + "6": { "$type": "color", "$value": "#584422" }, + "7": { "$type": "color", "$value": "#71582C" }, + "8": { "$type": "color", "$value": "#907649" }, + "9": { "$type": "color", "$value": "#D3991E" }, + "10": { "$type": "color", "$value": "#DBAC59" }, + "11": { "$type": "color", "$value": "#E4C693" }, + "12": { "$type": "color", "$value": "#F5EFE7" } + }, + "danger-red": { + "1": { "$type": "color", "$value": "#26100D" }, + "2": { "$type": "color", "$value": "#311410" }, + "3": { "$type": "color", "$value": "#3D1813" }, + "4": { "$type": "color", "$value": "#4C1D17" }, + "5": { "$type": "color", "$value": "#5C211A" }, + "6": { "$type": "color", "$value": "#782A21" }, + "7": { "$type": "color", "$value": "#9A362B" }, + "8": { "$type": "color", "$value": "#BE5648" }, + "9": { "$type": "color", "$value": "#FB7664" }, + "10": { "$type": "color", "$value": "#EC9C90" }, + "11": { "$type": "color", "$value": "#E5C1BB" }, + "12": { "$type": "color", "$value": "#F5EEED" } + }, + "data-viz": { + "categorical": { + "1": { "$type": "color", "$value": "#78A7E5" }, + "2": { "$type": "color", "$value": "#E986B7" }, + "3": { "$type": "color", "$value": "#5CB8A7" }, + "4": { "$type": "color", "$value": "#9F6BEB" }, + "5": { "$type": "color", "$value": "#E89361" }, + "6": { "$type": "color", "$value": "#8AD8F1" }, + "7": { "$type": "color", "$value": "#F0A8E9" }, + "8": { "$type": "color", "$value": "#91DC63" } + }, + "severity": { + "blocker": { "$type": "color", "$value": "#D53A2C" }, + "high": { "$type": "color", "$value": "#E98475" }, + "medium": { "$type": "color", "$value": "#E39757" }, + "low": { "$type": "color", "$value": "#CDB761" }, + "info": { "$type": "color", "$value": "#78A7E5" } + }, + "placeholder": { + "default": { "$type": "color", "$value": "#828282" } + } + } + } + }, "background": { "neutral": { "subtle": { @@ -46,22 +129,45 @@ } } }, + "action": { + "neutral": { + "default": { + "$type": "color", + "$value": "{echoes.color.palette.ui.gray.2}", + "$description": "Near-black fill for high-contrast neutral actions" + }, + "hover": { + "$type": "color", + "$value": "{echoes.color.palette.ui.gray.6}", + "$description": "Hover fill for high-contrast neutral actions" + }, + "focus": { + "$type": "color", + "$value": "{echoes.color.palette.ui.gray.2}" + }, + "active": { + "$type": "color", + "$value": "{echoes.color.palette.ui.gray.7}", + "$description": "Active fill for high-contrast neutral actions" + } + } + }, "accent": { "default": { "$type": "color", - "$value": "{echoes.color.roles.primary.medium}" + "$value": "{echoes.color.background.action.neutral.default}" }, "hover": { "$type": "color", - "$value": "{echoes.color.palette.indigo.200}" + "$value": "{echoes.color.background.action.neutral.hover}" }, "focus": { "$type": "color", - "$value": "{echoes.color.roles.primary.medium}" + "$value": "{echoes.color.background.action.neutral.focus}" }, "active": { "$type": "color", - "$value": "{echoes.color.roles.primary.light}" + "$value": "{echoes.color.background.action.neutral.active}" }, "weak": { "default": { @@ -75,7 +181,7 @@ } }, "$type": "color", - "$value": "{echoes.color.roles.primary.strong}" + "$value": "{echoes.color.palette.ui.gray.11}" }, "hover": { "$extensions": { @@ -88,7 +194,7 @@ } }, "$type": "color", - "$value": "{echoes.color.roles.primary.strong}" + "$value": "{echoes.color.palette.ui.gray.11}" }, "focus": { "$extensions": { @@ -101,7 +207,7 @@ } }, "$type": "color", - "$value": "{echoes.color.roles.primary.strong}" + "$value": "{echoes.color.palette.ui.gray.11}" }, "active": { "$extensions": { @@ -114,7 +220,7 @@ } }, "$type": "color", - "$value": "{echoes.color.roles.primary.strong}" + "$value": "{echoes.color.palette.ui.gray.11}" } } }, @@ -415,57 +521,30 @@ "selected": { "weak": { "default": { - "$extensions": { - "studio.tokens": { - "modify": { - "type": "alpha", - "value": "0.2", - "space": "lch" - } - } - }, "$type": "color", - "$value": "{echoes.color.roles.primary.strong}" + "$value": "{echoes.color.palette.ui.brand-blue.3}" }, "hover": { - "$extensions": { - "studio.tokens": { - "modify": { - "type": "alpha", - "value": "0.3", - "space": "lch" - } - } - }, "$type": "color", - "$value": "{echoes.color.roles.primary.strong}" + "$value": "{echoes.color.palette.ui.brand-blue.4}" }, "pressed": { - "$extensions": { - "studio.tokens": { - "modify": { - "type": "alpha", - "value": "0.4", - "space": "lch" - } - } - }, "$type": "color", - "$value": "{echoes.color.roles.primary.strong}" + "$value": "{echoes.color.palette.ui.brand-blue.5}" } }, "bold": { "default": { "$type": "color", - "$value": "{echoes.color.palette.indigo.200}" + "$value": "{echoes.color.palette.ui.brand-blue.9}" }, "hover": { "$type": "color", - "$value": "{echoes.color.roles.primary.light}" + "$value": "{echoes.color.palette.ui.brand-blue.10}" }, "pressed": { "$type": "color", - "$value": "{echoes.color.roles.primary.lightest}" + "$value": "{echoes.color.palette.ui.brand-blue.11}" } } }, @@ -486,7 +565,7 @@ } }, "$type": "color", - "$value": "{echoes.color.roles.primary.strong}" + "$value": "{echoes.color.palette.ui.gray.11}" }, "active": { "$extensions": { @@ -499,7 +578,7 @@ } }, "$type": "color", - "$value": "{echoes.color.roles.primary.strong}" + "$value": "{echoes.color.palette.ui.gray.11}" }, "focus": { "$type": "color", @@ -574,7 +653,7 @@ } }, "$type": "color", - "$value": "{echoes.color.palette.purple.600}" + "$value": "{echoes.color.palette.ui.brand-blue.9}" }, "hover": { "$extensions": { @@ -587,7 +666,7 @@ } }, "$type": "color", - "$value": "{echoes.color.palette.purple.600}" + "$value": "{echoes.color.palette.ui.brand-blue.9}" }, "focus": { "$extensions": { @@ -600,7 +679,7 @@ } }, "$type": "color", - "$value": "{echoes.color.palette.purple.600}" + "$value": "{echoes.color.palette.ui.brand-blue.9}" }, "active": { "$extensions": { @@ -613,24 +692,24 @@ } }, "$type": "color", - "$value": "{echoes.color.palette.purple.600}" + "$value": "{echoes.color.palette.ui.brand-blue.9}" } }, "default": { "$type": "color", - "$value": "{echoes.color.palette.purple.400}" + "$value": "{echoes.color.palette.ui.brand-blue.9}" }, "hover": { "$type": "color", - "$value": "{echoes.color.roles.highlight.medium}" + "$value": "{echoes.color.palette.ui.brand-blue.10}" }, "focus": { "$type": "color", - "$value": "{echoes.color.palette.purple.400}" + "$value": "{echoes.color.palette.ui.brand-blue.9}" }, "active": { "$type": "color", - "$value": "{echoes.color.palette.purple.200}" + "$value": "{echoes.color.palette.ui.brand-blue.8}" } }, "favourite": { @@ -647,20 +726,20 @@ "surface": { "default": { "$type": "color", - "$value": "{echoes.color.palette.grey.600}" + "$value": "{echoes.color.palette.ui.gray.2}" }, "hover": { "$type": "color", - "$value": "{echoes.color.roles.neutral.bold}" + "$value": "{echoes.color.palette.ui.gray-alpha.3}" }, "active": { "$type": "color", - "$value": "{echoes.color.palette.grey.800}" + "$value": "{echoes.color.palette.ui.gray-alpha.5}" }, "canvas": { "default": { "$type": "color", - "$value": "{echoes.color.roles.neutral.bold}" + "$value": "{echoes.color.palette.ui.gray.1}" } }, "inverse": { @@ -683,7 +762,7 @@ }, "disabled": { "$type": "color", - "$value": "{echoes.color.roles.neutral.strong}" + "$value": "{echoes.color.palette.ui.gray.3}" } }, "overlays": { @@ -710,23 +789,28 @@ "text": { "strong": { "$type": "color", - "$value": "{echoes.color.palette.grey.25}" + "$value": "{echoes.color.palette.ui.gray.12}" }, "default": { "$type": "color", - "$value": "{echoes.color.roles.neutral.light}" + "$value": "{echoes.color.palette.ui.gray.11}" }, "subtle": { "$type": "color", - "$value": "{echoes.color.palette.grey.200}" + "$value": "{echoes.color.palette.ui.gray.11}" }, "disabled": { "$type": "color", - "$value": "{echoes.color.palette.grey.400}" + "$value": "{echoes.color.palette.ui.gray.9}" }, "onColor": { "$type": "color", - "$value": "{echoes.color.palette.grey.600}" + "$value": "{echoes.color.palette.ui.gray.2}" + }, + "onAction": { + "$type": "color", + "$value": "{echoes.color.palette.ui.gray.12}", + "$description": "Text and icon color on high-contrast neutral actions" }, "onColor-Inverse": { "$type": "color", @@ -738,11 +822,11 @@ }, "placeholder": { "$type": "color", - "$value": "{echoes.color.palette.grey.200}" + "$value": "{echoes.color.palette.ui.gray.11}" }, "accent": { "$type": "color", - "$value": "{echoes.color.roles.primary.medium}" + "$value": "{echoes.color.palette.ui.gray.12}" }, "info": { "$type": "color", @@ -758,39 +842,39 @@ }, "emphasis": { "$type": "color", - "$value": "{echoes.color.palette.purple.200}" + "$value": "{echoes.color.palette.ui.brand-blue.11}" }, "link": { "hover": { "$type": "color", - "$value": "{echoes.color.palette.indigo.200}" + "$value": "{echoes.color.palette.ui.gray.12}" } } }, "icon": { "bold": { "$type": "color", - "$value": "{echoes.color.palette.grey.25}" + "$value": "{echoes.color.palette.ui.gray.12}" }, "default": { "$type": "color", - "$value": "{echoes.color.roles.neutral.light}" + "$value": "{echoes.color.palette.ui.gray.11}" }, "subtle": { "$type": "color", - "$value": "{echoes.color.palette.grey.200}" + "$value": "{echoes.color.palette.ui.gray.11}" }, "disabled": { "$type": "color", - "$value": "{echoes.color.palette.grey.400}" + "$value": "{echoes.color.palette.ui.gray.9}" }, "placeholder": { "$type": "color", - "$value": "{echoes.color.palette.grey.200}" + "$value": "{echoes.color.palette.ui.gray.11}" }, "accent": { "$type": "color", - "$value": "{echoes.color.palette.indigo.200}" + "$value": "{echoes.color.palette.ui.gray.12}" }, "danger": { "$type": "color", @@ -810,7 +894,7 @@ }, "onColor": { "$type": "color", - "$value": "{echoes.color.palette.grey.600}" + "$value": "{echoes.color.palette.ui.gray.2}" }, "onColor-Inverse": { "$type": "color", @@ -818,38 +902,45 @@ }, "selected": { "$type": "color", - "$value": "{echoes.color.palette.indigo.200}" + "$value": "{echoes.color.palette.ui.brand-blue.10}" }, "emphasis": { "$type": "color", - "$value": "{echoes.color.palette.purple.200}" + "$value": "{echoes.color.palette.ui.brand-blue.11}" } }, "border": { "bolder": { "$type": "color", - "$value": "{echoes.color.palette.grey.200}" + "$value": "{echoes.color.palette.ui.gray.10}" }, "bold": { "$type": "color", - "$value": "{echoes.color.roles.neutral.medium}" + "$value": "{echoes.color.palette.ui.gray.7}" }, "weak": { "$type": "color", - "$value": "{echoes.color.palette.grey.400}" + "$value": "{echoes.color.palette.ui.gray.6}" }, "weaker": { "$type": "color", - "$value": "{echoes.color.roles.neutral.strong}" + "$value": "{echoes.color.palette.ui.gray.5}" }, "disabled": { "$type": "color", - "$value": "{echoes.color.palette.grey.400}" + "$value": "{echoes.color.palette.ui.gray.7}" }, "accent": { "default": { "$type": "color", - "$value": "{echoes.color.palette.indigo.200}" + "$value": "{echoes.color.palette.ui.gray.10}" + } + }, + "action": { + "neutral": { + "$type": "color", + "$value": "{echoes.color.palette.ui.gray.9}", + "$description": "Boundary color for near-black neutral actions on dark surfaces" } }, "danger": { @@ -936,7 +1027,7 @@ } }, "$type": "color", - "$value": "{echoes.color.palette.purple.600}" + "$value": "{echoes.color.palette.ui.brand-blue.7}" } } }, @@ -999,7 +1090,7 @@ "focus": { "default": { "$type": "color", - "$value": "{echoes.color.palette.indigo.200}" + "$value": "{echoes.color.palette.ui.gray.12}" } }, "charts": { diff --git a/design-tokens/tokens/modes/light.json b/design-tokens/tokens/modes/light.json index f68c8172c..10f41df2f 100644 --- a/design-tokens/tokens/modes/light.json +++ b/design-tokens/tokens/modes/light.json @@ -1,6 +1,116 @@ { "echoes": { "color": { + "palette": { + "ui": { + "gray": { + "1": { "$type": "color", "$value": "#FCFCFC" }, + "2": { "$type": "color", "$value": "#F8F8F8" }, + "3": { "$type": "color", "$value": "#F4F4F4" }, + "4": { "$type": "color", "$value": "#EFEFEF" }, + "5": { "$type": "color", "$value": "#E8E8E8" }, + "6": { "$type": "color", "$value": "#E0E0E0" }, + "7": { "$type": "color", "$value": "#D4D4D4" }, + "8": { "$type": "color", "$value": "#B8B8B8" }, + "9": { "$type": "color", "$value": "#5A5A5A" }, + "10": { "$type": "color", "$value": "#4A4A4A" }, + "11": { "$type": "color", "$value": "#3A3A3A" }, + "12": { "$type": "color", "$value": "#1A1A1A" } + }, + "gray-alpha": { + "1": { "$type": "color", "$value": "#00000003" }, + "2": { "$type": "color", "$value": "#00000005" }, + "3": { "$type": "color", "$value": "#00000008" }, + "4": { "$type": "color", "$value": "#0000000D" }, + "5": { "$type": "color", "$value": "#00000014" }, + "6": { "$type": "color", "$value": "#0000001F" }, + "7": { "$type": "color", "$value": "#0000002E" }, + "8": { "$type": "color", "$value": "#00000047" }, + "9": { "$type": "color", "$value": "#000000A6" }, + "10": { "$type": "color", "$value": "#000000B8" }, + "11": { "$type": "color", "$value": "#000000C7" }, + "12": { "$type": "color", "$value": "#000000E6" } + }, + "brand-blue": { + "1": { "$type": "color", "$value": "#F7FAFE" }, + "2": { "$type": "color", "$value": "#F2F7FD" }, + "3": { "$type": "color", "$value": "#E8F1FC" }, + "4": { "$type": "color", "$value": "#DCEBFA" }, + "5": { "$type": "color", "$value": "#C9E0F7" }, + "6": { "$type": "color", "$value": "#A9CDF2" }, + "7": { "$type": "color", "$value": "#78B2E9" }, + "8": { "$type": "color", "$value": "#4191DE" }, + "9": { "$type": "color", "$value": "#126ED3" }, + "10": { "$type": "color", "$value": "#0F61BD" }, + "11": { "$type": "color", "$value": "#0C51A0" }, + "12": { "$type": "color", "$value": "#082F5B" } + }, + "success-green": { + "1": { "$type": "color", "$value": "#F8FCF4" }, + "2": { "$type": "color", "$value": "#F0FAE6" }, + "3": { "$type": "color", "$value": "#DFF8C8" }, + "4": { "$type": "color", "$value": "#CEF3A9" }, + "5": { "$type": "color", "$value": "#C0E69B" }, + "6": { "$type": "color", "$value": "#AFD18D" }, + "7": { "$type": "color", "$value": "#94B474" }, + "8": { "$type": "color", "$value": "#759554" }, + "9": { "$type": "color", "$value": "#558112" }, + "10": { "$type": "color", "$value": "#4D6B29" }, + "11": { "$type": "color", "$value": "#43572D" }, + "12": { "$type": "color", "$value": "#293121" } + }, + "warning-yellow": { + "1": { "$type": "color", "$value": "#FCFAF7" }, + "2": { "$type": "color", "$value": "#FAF5ED" }, + "3": { "$type": "color", "$value": "#F7ECDB" }, + "4": { "$type": "color", "$value": "#F2E2C9" }, + "5": { "$type": "color", "$value": "#EAD4B2" }, + "6": { "$type": "color", "$value": "#DEBF8B" }, + "7": { "$type": "color", "$value": "#C0A373" }, + "8": { "$type": "color", "$value": "#A18453" }, + "9": { "$type": "color", "$value": "#926912" }, + "10": { "$type": "color", "$value": "#775B28" }, + "11": { "$type": "color", "$value": "#5F4D2D" }, + "12": { "$type": "color", "$value": "#342D21" } + }, + "danger-red": { + "1": { "$type": "color", "$value": "#FCF9F9" }, + "2": { "$type": "color", "$value": "#FAF4F3" }, + "3": { "$type": "color", "$value": "#F7EAE8" }, + "4": { "$type": "color", "$value": "#F2E0DD" }, + "5": { "$type": "color", "$value": "#EAD1CD" }, + "6": { "$type": "color", "$value": "#E0BAB3" }, + "7": { "$type": "color", "$value": "#D5958A" }, + "8": { "$type": "color", "$value": "#D46152" }, + "9": { "$type": "color", "$value": "#D11C11" }, + "10": { "$type": "color", "$value": "#A53327" }, + "11": { "$type": "color", "$value": "#7F352C" }, + "12": { "$type": "color", "$value": "#412521" } + }, + "data-viz": { + "categorical": { + "1": { "$type": "color", "$value": "#347BD0" }, + "2": { "$type": "color", "$value": "#D44194" }, + "3": { "$type": "color", "$value": "#388779" }, + "4": { "$type": "color", "$value": "#8838E0" }, + "5": { "$type": "color", "$value": "#C66F39" }, + "6": { "$type": "color", "$value": "#295A69" }, + "7": { "$type": "color", "$value": "#84307F" }, + "8": { "$type": "color", "$value": "#3D6127" } + }, + "severity": { + "blocker": { "$type": "color", "$value": "#5E221A" }, + "high": { "$type": "color", "$value": "#AE2E22" }, + "medium": { "$type": "color", "$value": "#A2642A" }, + "low": { "$type": "color", "$value": "#937F30" }, + "info": { "$type": "color", "$value": "#2E6FBD" } + }, + "placeholder": { + "default": { "$type": "color", "$value": "#737373" } + } + } + } + }, "background": { "neutral": { "subtle": { @@ -33,46 +143,69 @@ } } }, + "action": { + "neutral": { + "default": { + "$type": "color", + "$value": "{echoes.color.palette.ui.gray.12}", + "$description": "Near-black fill for high-contrast neutral actions" + }, + "hover": { + "$type": "color", + "$value": "{echoes.color.palette.ui.gray.11}", + "$description": "Hover fill for high-contrast neutral actions" + }, + "focus": { + "$type": "color", + "$value": "{echoes.color.palette.ui.gray.12}" + }, + "active": { + "$type": "color", + "$value": "{echoes.color.palette.ui.gray.10}", + "$description": "Active fill for high-contrast neutral actions" + } + } + }, "accent": { "default": { "$type": "color", - "$value": "{echoes.color.roles.primary.strong}", - "$description": "Used as the background color of components that reinforce our brand" + "$value": "{echoes.color.background.action.neutral.default}", + "$description": "Used as the background color of high-contrast neutral actions" }, "hover": { "$type": "color", - "$value": "{echoes.color.palette.indigo.600}", - "$description": "Hover state of components that reinforce our brand" + "$value": "{echoes.color.background.action.neutral.hover}", + "$description": "Hover state of high-contrast neutral actions" }, "focus": { "$type": "color", - "$value": "{echoes.color.roles.primary.strong}" + "$value": "{echoes.color.background.action.neutral.focus}" }, "active": { "$type": "color", - "$value": "{echoes.color.roles.primary.bold}", - "$description": "Active state of components that reinforce our brand" + "$value": "{echoes.color.background.action.neutral.active}", + "$description": "Active state of high-contrast neutral actions" }, "weak": { "default": { "$type": "color", - "$value": "{echoes.color.palette.indigo.25}", - "$description": "Used as the background color of components that reinforce our brand with less visual highlight" + "$value": "{echoes.color.palette.ui.gray.2}", + "$description": "Used as a subtle neutral background" }, "hover": { "$type": "color", - "$value": "{echoes.color.roles.primary.lightest}", - "$description": "Hover state of components that reinforce our brand with less visual highlight" + "$value": "{echoes.color.palette.ui.gray.3}", + "$description": "Hover state of a subtle neutral background" }, "active": { "$type": "color", - "$value": "{echoes.color.roles.primary.light}", - "$description": "Active state of components that reinforce our brand with less visual highlight" + "$value": "{echoes.color.palette.ui.gray.4}", + "$description": "Active state of a subtle neutral background" }, "focus": { "$type": "color", - "$value": "{echoes.color.roles.primary.lightest}", - "$description": "Focus state of components that reinforce our brand with less visual highlight" + "$value": "{echoes.color.palette.ui.gray.2}", + "$description": "Focus state of a subtle neutral background" } } }, @@ -280,34 +413,34 @@ "weak": { "default": { "$type": "color", - "$value": "{echoes.color.palette.indigo.25}", + "$value": "{echoes.color.palette.ui.brand-blue.3}", "$description": "Use it in backgrounds of components that have a selected state that need less visual highlight, like dropdown or selects" }, "hover": { "$type": "color", - "$value": "{echoes.color.roles.primary.lightest}", + "$value": "{echoes.color.palette.ui.brand-blue.4}", "$description": "Hover state of components that have a selected state that need less visual highlight, like dropdown or selects" }, "pressed": { "$type": "color", - "$value": "{echoes.color.roles.primary.light}", + "$value": "{echoes.color.palette.ui.brand-blue.5}", "$description": "Pressed state of components that have a selected state that need less visual highlight, like dropdown or selects" } }, "bold": { "default": { "$type": "color", - "$value": "{echoes.color.roles.primary.strong}", + "$value": "{echoes.color.palette.ui.brand-blue.9}", "$description": "Use it in backgrounds of components that have a selected state, like checkboxes or radios" }, "hover": { "$type": "color", - "$value": "{echoes.color.palette.indigo.600}", + "$value": "{echoes.color.palette.ui.brand-blue.10}", "$description": "Hover state of components that have a selected state, like checkboxes or radios" }, "pressed": { "$type": "color", - "$value": "{echoes.color.roles.primary.bold}", + "$value": "{echoes.color.palette.ui.brand-blue.11}", "$description": "Pressed state of components that have a selected state, like checkboxes or radios" } } @@ -320,11 +453,11 @@ }, "hover": { "$type": "color", - "$value": "{echoes.color.roles.primary.lightest}" + "$value": "{echoes.color.palette.ui.gray-alpha.3}" }, "active": { "$type": "color", - "$value": "{echoes.color.roles.primary.light}" + "$value": "{echoes.color.palette.ui.gray-alpha.5}" }, "focus": { "$type": "color", @@ -372,36 +505,36 @@ "weak": { "default": { "$type": "color", - "$value": "{echoes.color.roles.highlight.light}" + "$value": "{echoes.color.palette.ui.brand-blue.3}" }, "hover": { "$type": "color", - "$value": "{echoes.color.palette.purple.200}" + "$value": "{echoes.color.palette.ui.brand-blue.4}" }, "focus": { "$type": "color", - "$value": "{echoes.color.roles.highlight.light}" + "$value": "{echoes.color.palette.ui.brand-blue.3}" }, "active": { "$type": "color", - "$value": "{echoes.color.roles.highlight.medium}" + "$value": "{echoes.color.palette.ui.brand-blue.5}" } }, "default": { "$type": "color", - "$value": "{echoes.color.roles.highlight.bold}" + "$value": "{echoes.color.palette.ui.brand-blue.9}" }, "hover": { "$type": "color", - "$value": "{echoes.color.palette.purple.800}" + "$value": "{echoes.color.palette.ui.brand-blue.10}" }, "focus": { "$type": "color", - "$value": "{echoes.color.roles.highlight.bold}" + "$value": "{echoes.color.palette.ui.brand-blue.9}" }, "active": { "$type": "color", - "$value": "{echoes.color.roles.highlight.dark}" + "$value": "{echoes.color.palette.ui.brand-blue.11}" } }, "favourite": { @@ -418,23 +551,23 @@ "surface": { "default": { "$type": "color", - "$value": "{echoes.color.roles.support.white}", + "$value": "{echoes.color.palette.ui.gray.1}", "$description": "Go to color for surfaces.. eg: cards, modals, popovers, etc..." }, "hover": { "$type": "color", - "$value": "{echoes.color.palette.grey.40}", + "$value": "{echoes.color.palette.ui.gray-alpha.3}", "$description": "Hover color for bg-default" }, "active": { "$type": "color", - "$value": "{echoes.color.roles.neutral.light}", + "$value": "{echoes.color.palette.ui.gray-alpha.5}", "$description": "Active color for bg-default" }, "canvas": { "default": { "$type": "color", - "$value": "{echoes.color.palette.grey.25}", + "$value": "{echoes.color.palette.ui.gray.2}", "$description": "Use it as page background" } }, @@ -459,7 +592,7 @@ }, "disabled": { "$type": "color", - "$value": "{echoes.color.roles.neutral.lightest}", + "$value": "{echoes.color.palette.ui.gray.3}", "$description": "Use it as background for disabled components" } }, @@ -488,27 +621,32 @@ "text": { "strong": { "$type": "color", - "$value": "{echoes.color.roles.neutral.bold}" + "$value": "{echoes.color.palette.ui.gray.12}" }, "default": { "$type": "color", - "$value": "{echoes.color.roles.neutral.strong}" + "$value": "{echoes.color.palette.ui.gray.10}" }, "disabled": { "$type": "color", - "$value": "{echoes.color.roles.neutral.medium}" + "$value": "{echoes.color.palette.ui.gray.9}" }, "placeholder": { "$type": "color", - "$value": "{echoes.color.palette.grey.400}" + "$value": "{echoes.color.palette.ui.gray.10}" }, "subtle": { "$type": "color", - "$value": "{echoes.color.palette.grey.400}" + "$value": "{echoes.color.palette.ui.gray.10}" }, "onColor": { "$type": "color", - "$value": "{echoes.color.roles.support.white}" + "$value": "{echoes.color.palette.ui.gray.1}" + }, + "onAction": { + "$type": "color", + "$value": "{echoes.color.palette.ui.gray.1}", + "$description": "Text and icon color on high-contrast neutral actions" }, "onColor-Inverse": { "$type": "color", @@ -516,7 +654,7 @@ }, "accent": { "$type": "color", - "$value": "{echoes.color.roles.primary.strong}" + "$value": "{echoes.color.palette.ui.gray.12}" }, "danger": { "$type": "color", @@ -536,39 +674,39 @@ }, "emphasis": { "$type": "color", - "$value": "{echoes.color.palette.purple.800}" + "$value": "{echoes.color.palette.ui.brand-blue.11}" }, "link": { "hover": { "$type": "color", - "$value": "{echoes.color.palette.indigo.600}" + "$value": "{echoes.color.palette.ui.gray.11}" } } }, "icon": { "bold": { "$type": "color", - "$value": "{echoes.color.roles.neutral.bold}" + "$value": "{echoes.color.palette.ui.gray.12}" }, "default": { "$type": "color", - "$value": "{echoes.color.roles.neutral.strong}" + "$value": "{echoes.color.palette.ui.gray.10}" }, "subtle": { "$type": "color", - "$value": "{echoes.color.palette.grey.400}" + "$value": "{echoes.color.palette.ui.gray.10}" }, "disabled": { "$type": "color", - "$value": "{echoes.color.roles.neutral.medium}" + "$value": "{echoes.color.palette.ui.gray.9}" }, "placeholder": { "$type": "color", - "$value": "{echoes.color.palette.grey.400}" + "$value": "{echoes.color.palette.ui.gray.10}" }, "accent": { "$type": "color", - "$value": "{echoes.color.roles.primary.strong}" + "$value": "{echoes.color.palette.ui.gray.12}" }, "danger": { "$type": "color", @@ -588,7 +726,7 @@ }, "onColor": { "$type": "color", - "$value": "{echoes.color.roles.support.white}" + "$value": "{echoes.color.palette.ui.gray.1}" }, "onColor-Inverse": { "$type": "color", @@ -596,38 +734,45 @@ }, "selected": { "$type": "color", - "$value": "{echoes.color.roles.primary.strong}" + "$value": "{echoes.color.palette.ui.brand-blue.9}" }, "emphasis": { "$type": "color", - "$value": "{echoes.color.palette.purple.800}" + "$value": "{echoes.color.palette.ui.brand-blue.11}" } }, "border": { "bolder": { "$type": "color", - "$value": "{echoes.color.palette.grey.400}" + "$value": "{echoes.color.palette.ui.gray.9}" }, "bold": { "$type": "color", - "$value": "{echoes.color.palette.grey.200}" + "$value": "{echoes.color.palette.ui.gray.7}" }, "weak": { "$type": "color", - "$value": "{echoes.color.roles.neutral.light}" + "$value": "{echoes.color.palette.ui.gray.6}" }, "weaker": { "$type": "color", - "$value": "{echoes.color.roles.neutral.lightest}" + "$value": "{echoes.color.palette.ui.gray.5}" }, "disabled": { "$type": "color", - "$value": "{echoes.color.palette.grey.200}" + "$value": "{echoes.color.palette.ui.gray.7}" }, "accent": { "default": { "$type": "color", - "$value": "{echoes.color.roles.primary.strong}" + "$value": "{echoes.color.palette.ui.gray.12}" + } + }, + "action": { + "neutral": { + "$type": "color", + "$value": "{echoes.color.background.action.neutral.default}", + "$description": "Boundary color for high-contrast neutral actions" } }, "danger": { @@ -669,7 +814,7 @@ "emphasis": { "weak": { "$type": "color", - "$value": "{echoes.color.palette.purple.200}" + "$value": "{echoes.color.palette.ui.brand-blue.6}" } } }, @@ -732,7 +877,7 @@ "focus": { "default": { "$type": "color", - "$value": "{echoes.color.palette.indigo.600}" + "$value": "{echoes.color.palette.ui.gray.12}" } }, "charts": { diff --git a/src/components/buttons/ButtonStyles.tsx b/src/components/buttons/ButtonStyles.tsx index f9fd11da2..202a6c27f 100644 --- a/src/components/buttons/ButtonStyles.tsx +++ b/src/components/buttons/ButtonStyles.tsx @@ -55,7 +55,7 @@ export const ButtonStyled = styled.button` } &:focus-visible { - outline: ${cssVar('color-focus-default')} solid ${cssVar('focus-border-width-default')}; + outline: ${cssVar('button-colors-focus')} solid ${cssVar('focus-border-width-default')}; outline-offset: ${cssVar('focus-border-offset-default')}; } @@ -69,7 +69,7 @@ export const ButtonStyled = styled.button` &:disabled, &:disabled:has(:hover, :active, :focus, :focus-visible) { - color: ${cssVar('color-text-disabled')}; + color: ${cssVar('button-colors-text-disabled')}; background-color: var(--button-background-disabled); border: none; @@ -110,7 +110,7 @@ export const SpinnerButton = styled(SpinnerOverrideColor)` margin-right: ${cssVar('dimension-space-75')}; `; -export const BUTTON_VARIETY_STYLES = { +export const BUTTON_VARIETY_STYLES: Record> = { [ButtonVariety.Default]: { '--button-color': cssVar('color-text-default'), '--button-border': `${cssVar('color-border-bold')} solid ${cssVar('border-width-default')}`, @@ -134,14 +134,14 @@ export const BUTTON_VARIETY_STYLES = { '--spinner-track-color-override': cssVar('color-border-bold'), }, [ButtonVariety.Primary]: { - '--button-color': cssVar('color-text-on-color'), - '--button-border': 'none', - '--button-background': cssVar('color-background-accent-default'), - '--button-background-hover': cssVar('color-background-accent-hover'), - '--button-background-active': cssVar('color-background-accent-active'), - '--button-background-focus': cssVar('color-background-accent-focus'), - '--button-background-disabled': cssVar('color-surface-disabled'), - '--spinner-color-override': cssVar('color-icon-on-color'), + '--button-color': cssVar('button-colors-text-default'), + '--button-border': `${cssVar('button-colors-border-default')} solid ${cssVar('border-width-default')}`, + '--button-background': cssVar('button-colors-background-default'), + '--button-background-hover': cssVar('button-colors-background-hover'), + '--button-background-active': cssVar('button-colors-background-active'), + '--button-background-focus': cssVar('button-colors-background-default'), + '--button-background-disabled': cssVar('button-colors-background-disabled'), + '--spinner-color-override': cssVar('button-colors-text-default'), '--spinner-track-color-override': cssVar('color-border-bold'), }, [ButtonVariety.PrimaryGhost]: { diff --git a/src/components/buttons/__tests__/Button-test.tsx b/src/components/buttons/__tests__/Button-test.tsx index 3fa11ea78..98a832b04 100644 --- a/src/components/buttons/__tests__/Button-test.tsx +++ b/src/components/buttons/__tests__/Button-test.tsx @@ -67,7 +67,7 @@ describe('Button', () => { it.each([ [ButtonVariety.Default, cssVar('color-icon-default'), cssVar('color-border-bold')], [ButtonVariety.DefaultGhost, cssVar('color-icon-default'), cssVar('color-border-bold')], - [ButtonVariety.Primary, cssVar('color-icon-on-color'), cssVar('color-border-bold')], + [ButtonVariety.Primary, cssVar('button-colors-text-default'), cssVar('color-border-bold')], [ButtonVariety.Danger, cssVar('color-icon-on-color'), cssVar('color-background-danger-active')], ])('defines %s spinner arc and track sentiment tokens', (variety, spinnerColor, trackColor) => { expect(BUTTON_VARIETY_STYLES[variety]).toMatchObject({ diff --git a/src/components/layout/sidebar-navigation/SidebarNavigationBaseItem.tsx b/src/components/layout/sidebar-navigation/SidebarNavigationBaseItem.tsx index 8cdb04b21..027ea0143 100644 --- a/src/components/layout/sidebar-navigation/SidebarNavigationBaseItem.tsx +++ b/src/components/layout/sidebar-navigation/SidebarNavigationBaseItem.tsx @@ -103,12 +103,12 @@ const SidebarNavigationBaseItemLink = styled(NavLinkBase)` display: flex; visibility: visible; - background-color: ${cssVar('sidebar-navigation-item-colors-background-active')}; - color: ${cssVar('color-text-accent')}; + background-color: ${cssVar('navigation-item-colors-background-selected')}; + color: ${cssVar('navigation-item-colors-text-selected')}; font: ${cssVar('typography-text-default-semi-bold')}; &:hover { - background-color: ${cssVar('sidebar-navigation-item-colors-background-hover')}; + background-color: ${cssVar('navigation-item-colors-background-selected-hover')}; } } `; @@ -120,6 +120,6 @@ const sidebarNavigationBaseItemIconStyles = css` ${SidebarNavigationBaseItemLink}.active > &, ${SidebarNavigationBaseItemLink}:active > & { - color: ${cssVar('color-icon-accent')}; + color: ${cssVar('navigation-item-colors-icon-selected')}; } `; diff --git a/src/components/layout/sidebar-navigation/SidebarNavigationItemStyles.tsx b/src/components/layout/sidebar-navigation/SidebarNavigationItemStyles.tsx index 9db00a41e..d5816ea02 100644 --- a/src/components/layout/sidebar-navigation/SidebarNavigationItemStyles.tsx +++ b/src/components/layout/sidebar-navigation/SidebarNavigationItemStyles.tsx @@ -39,17 +39,17 @@ export const sidebarNavigationBaseItemStyles = css` flex-shrink: 0; - color: ${cssVar('color-text-default')}; + color: ${cssVar('navigation-item-colors-text-default')}; font: ${cssVar('typography-text-default-regular')}; cursor: pointer; &:hover { - background-color: ${cssVar('sidebar-navigation-item-colors-background-hover')}; + background-color: ${cssVar('navigation-item-colors-background-hover')}; } &:focus-visible { - outline: ${cssVar('color-focus-default')} solid ${cssVar('focus-border-width-default')}; + outline: ${cssVar('navigation-item-colors-focus')} solid ${cssVar('focus-border-width-default')}; outline-offset: ${cssVar('focus-border-offset-default')}; border-radius: ${cssVar('border-radius-400')}; } @@ -63,7 +63,7 @@ export const SidebarNavigationItemLabel = styled.span` SidebarNavigationItemLabel.displayName = 'SidebarNavigationItemLabel'; export const sidebarNavigationItemIconStyles = css` - color: ${cssVar('color-icon-subtle')}; + color: ${cssVar('navigation-item-colors-icon-default')}; font-size: ${cssVar('font-size-30')}; `; diff --git a/src/components/table/TableStyles.tsx b/src/components/table/TableStyles.tsx index 85eb1609b..85c0e960a 100644 --- a/src/components/table/TableStyles.tsx +++ b/src/components/table/TableStyles.tsx @@ -27,7 +27,7 @@ import { cssVar } from '~utils/design-tokens'; const TABLE_VARIETY_STYLES = { [TableVariety.Surface]: { '--table-header-background-color': cssVar('table-colors-background-header-default'), - border: `${cssVar('border-width-default')} solid ${cssVar('color-border-bold')}`, + border: `${cssVar('border-width-default')} solid ${cssVar('issue-row-colors-border')}`, 'border-collapse': 'separate', }, [TableVariety.Ghost]: { @@ -87,7 +87,7 @@ export const cellBaseStyle = css` font: ${cssVar('typography-text-default-regular')}; tbody & { - border-top: ${cssVar('border-width-default')} solid ${cssVar('color-border-weak')}; + border-top: ${cssVar('border-width-default')} solid ${cssVar('issue-row-colors-border')}; } .table-variety-surface thead tr:first-child &:first-child { @@ -111,17 +111,18 @@ export const StyledTableCell = styled.td` ${cellBaseStyle} justify-content: center; + background-color: ${cssVar('issue-row-colors-background-default')}; ${StyledTableRow}:hover:not(.selected) & { - background-color: ${cssVar('color-surface-hover')}; + background-color: ${cssVar('issue-row-colors-background-hover')}; } ${StyledTableRow}.selected & { - background-color: ${cssVar('color-background-selected-weak-default')}; + background-color: ${cssVar('issue-row-colors-background-selected')}; } ${StyledTableRow}:hover.selected & { - background-color: ${cssVar('color-background-selected-weak-hover')}; + background-color: ${cssVar('issue-row-colors-background-selected-hover')}; } `; StyledTableCell.displayName = 'StyledTableCell'; diff --git a/src/components/text-input/TextInputBase.tsx b/src/components/text-input/TextInputBase.tsx index e92b68e52..1deec0b03 100644 --- a/src/components/text-input/TextInputBase.tsx +++ b/src/components/text-input/TextInputBase.tsx @@ -50,9 +50,9 @@ export interface InputProps extends ValidationProps, FormFieldPropsSubset { } export const InputStyled = styled.input` - color: ${cssVar('color-text-default')}; - background-color: ${cssVar('form-control-colors-background-default')}; - border: ${cssVar('border-width-default')} solid ${cssVar('form-control-colors-border-default')}; + color: ${cssVar('input-colors-text-default')}; + background-color: ${cssVar('input-colors-background-default')}; + border: ${cssVar('border-width-default')} solid ${cssVar('input-colors-border-default')}; border-radius: ${cssVar('form-control-border-radius-default')}; font: ${cssVar('typography-text-default-regular')}; @@ -64,10 +64,10 @@ export const InputStyled = styled.input` padding: ${cssVar('dimension-space-100')} ${cssVar('dimension-space-150')}; &::placeholder { - color: ${cssVar('color-text-placeholder')}; + color: ${cssVar('input-colors-text-placeholder')}; } &:hover { - background-color: ${cssVar('form-control-colors-background-hover')}; + background-color: ${cssVar('input-colors-background-hover')}; } &[data-valid] { border-color: ${cssVar('color-border-success-default')}; @@ -92,20 +92,20 @@ export const InputStyled = styled.input` &:focus, &:focus-within, &:focus-visible { - border-color: ${cssVar('form-control-colors-border-focus')}; - outline: ${cssVar('color-focus-default')} solid ${cssVar('focus-border-width-default')}; + border-color: ${cssVar('input-colors-border-focus')}; + outline: ${cssVar('input-colors-focus')} solid ${cssVar('focus-border-width-default')}; } &:disabled, &:disabled:hover { - color: ${cssVar('color-text-disabled')}; - background-color: ${cssVar('color-surface-disabled')}; - border-color: ${cssVar('color-border-disabled')}; + color: ${cssVar('input-colors-text-disabled')}; + background-color: ${cssVar('input-colors-background-disabled')}; + border-color: ${cssVar('input-colors-border-disabled')}; outline: none; cursor: not-allowed; &::placeholder { - color: ${cssVar('color-text-disabled')}; + color: ${cssVar('input-colors-text-disabled')}; } } `; diff --git a/src/generated/design-tokens-dark.css b/src/generated/design-tokens-dark.css index 9eb833d09..5a35b16d6 100644 --- a/src/generated/design-tokens-dark.css +++ b/src/generated/design-tokens-dark.css @@ -21,19 +21,109 @@ */ html[data-echoes-theme='dark'], [data-echoes-theme='dark'] { + --echoes-color-palette-ui-gray-1: #151515; + --echoes-color-palette-ui-gray-2: #1a1a1a; + --echoes-color-palette-ui-gray-3: #1f1f1f; + --echoes-color-palette-ui-gray-4: #252525; + --echoes-color-palette-ui-gray-5: #2a2a2a; + --echoes-color-palette-ui-gray-6: #363636; + --echoes-color-palette-ui-gray-7: #464646; + --echoes-color-palette-ui-gray-8: #5a5a5a; + --echoes-color-palette-ui-gray-9: #737373; + --echoes-color-palette-ui-gray-10: #828282; + --echoes-color-palette-ui-gray-11: #b8b8b8; + --echoes-color-palette-ui-gray-12: #eeeeee; + --echoes-color-palette-ui-gray-alpha-1: #ffffff05; + --echoes-color-palette-ui-gray-alpha-2: #ffffff08; + --echoes-color-palette-ui-gray-alpha-3: #ffffff0d; + --echoes-color-palette-ui-gray-alpha-4: #ffffff14; + --echoes-color-palette-ui-gray-alpha-5: #ffffff1f; + --echoes-color-palette-ui-gray-alpha-6: #ffffff2e; + --echoes-color-palette-ui-gray-alpha-7: #ffffff3d; + --echoes-color-palette-ui-gray-alpha-8: #ffffff52; + --echoes-color-palette-ui-gray-alpha-9: #ffffff70; + --echoes-color-palette-ui-gray-alpha-10: #ffffff85; + --echoes-color-palette-ui-gray-alpha-11: #ffffffb8; + --echoes-color-palette-ui-gray-alpha-12: #ffffffeb; + --echoes-color-palette-ui-brand-blue-1: #0c1825; + --echoes-color-palette-ui-brand-blue-2: #0e1e30; + --echoes-color-palette-ui-brand-blue-3: #10243a; + --echoes-color-palette-ui-brand-blue-4: #122d47; + --echoes-color-palette-ui-brand-blue-5: #153554; + --echoes-color-palette-ui-brand-blue-6: #1c4a70; + --echoes-color-palette-ui-brand-blue-7: #275f8f; + --echoes-color-palette-ui-brand-blue-8: #3d7fba; + --echoes-color-palette-ui-brand-blue-9: #6ba9f0; + --echoes-color-palette-ui-brand-blue-10: #82b8f3; + --echoes-color-palette-ui-brand-blue-11: #a9cdf7; + --echoes-color-palette-ui-brand-blue-12: #e7f2fd; + --echoes-color-palette-ui-success-green-1: #13190d; + --echoes-color-palette-ui-success-green-2: #192111; + --echoes-color-palette-ui-success-green-3: #1f2914; + --echoes-color-palette-ui-success-green-4: #263318; + --echoes-color-palette-ui-success-green-5: #2c3d1b; + --echoes-color-palette-ui-success-green-6: #3a4f23; + --echoes-color-palette-ui-success-green-7: #4b662d; + --echoes-color-palette-ui-success-green-8: #68854a; + --echoes-color-palette-ui-success-green-9: #7dba1f; + --echoes-color-palette-ui-success-green-10: #94c75a; + --echoes-color-palette-ui-success-green-11: #b3d98d; + --echoes-color-palette-ui-success-green-12: #e9f5df; + --echoes-color-palette-ui-warning-yellow-1: #1c160d; + --echoes-color-palette-ui-warning-yellow-2: #241d11; + --echoes-color-palette-ui-warning-yellow-3: #2d2414; + --echoes-color-palette-ui-warning-yellow-4: #382c17; + --echoes-color-palette-ui-warning-yellow-5: #43341a; + --echoes-color-palette-ui-warning-yellow-6: #584422; + --echoes-color-palette-ui-warning-yellow-7: #71582c; + --echoes-color-palette-ui-warning-yellow-8: #907649; + --echoes-color-palette-ui-warning-yellow-9: #d3991e; + --echoes-color-palette-ui-warning-yellow-10: #dbac59; + --echoes-color-palette-ui-warning-yellow-11: #e4c693; + --echoes-color-palette-ui-warning-yellow-12: #f5efe7; + --echoes-color-palette-ui-danger-red-1: #26100d; + --echoes-color-palette-ui-danger-red-2: #311410; + --echoes-color-palette-ui-danger-red-3: #3d1813; + --echoes-color-palette-ui-danger-red-4: #4c1d17; + --echoes-color-palette-ui-danger-red-5: #5c211a; + --echoes-color-palette-ui-danger-red-6: #782a21; + --echoes-color-palette-ui-danger-red-7: #9a362b; + --echoes-color-palette-ui-danger-red-8: #be5648; + --echoes-color-palette-ui-danger-red-9: #fb7664; + --echoes-color-palette-ui-danger-red-10: #ec9c90; + --echoes-color-palette-ui-danger-red-11: #e5c1bb; + --echoes-color-palette-ui-danger-red-12: #f5eeed; + --echoes-color-palette-ui-data-viz-categorical-1: #78a7e5; + --echoes-color-palette-ui-data-viz-categorical-2: #e986b7; + --echoes-color-palette-ui-data-viz-categorical-3: #5cb8a7; + --echoes-color-palette-ui-data-viz-categorical-4: #9f6beb; + --echoes-color-palette-ui-data-viz-categorical-5: #e89361; + --echoes-color-palette-ui-data-viz-categorical-6: #8ad8f1; + --echoes-color-palette-ui-data-viz-categorical-7: #f0a8e9; + --echoes-color-palette-ui-data-viz-categorical-8: #91dc63; + --echoes-color-palette-ui-data-viz-severity-blocker: #d53a2c; + --echoes-color-palette-ui-data-viz-severity-high: #e98475; + --echoes-color-palette-ui-data-viz-severity-medium: #e39757; + --echoes-color-palette-ui-data-viz-severity-low: #cdb761; + --echoes-color-palette-ui-data-viz-severity-info: #78a7e5; + --echoes-color-palette-ui-data-viz-placeholder-default: #828282; --echoes-color-background-neutral-subtle-default: #3e4357; --echoes-color-background-neutral-subtle-hover: #3e4357cc; --echoes-color-background-neutral-subtle-focus: #3e4357; --echoes-color-background-neutral-subtle-active: #3e4357b3; --echoes-color-background-neutral-bolder-default: #637192; - --echoes-color-background-accent-default: #9fa9ed; - --echoes-color-background-accent-hover: #bdc6ff; - --echoes-color-background-accent-focus: #9fa9ed; - --echoes-color-background-accent-active: #d1d7fe; - --echoes-color-background-accent-weak-default: #5d6cd033; - --echoes-color-background-accent-weak-hover: #5d6cd04d; - --echoes-color-background-accent-weak-focus: #5d6cd033; - --echoes-color-background-accent-weak-active: #5d6cd066; + --echoes-color-background-action-neutral-default: #1a1a1a; /** Near-black fill for high-contrast neutral actions */ + --echoes-color-background-action-neutral-hover: #363636; /** Hover fill for high-contrast neutral actions */ + --echoes-color-background-action-neutral-focus: #1a1a1a; + --echoes-color-background-action-neutral-active: #464646; /** Active fill for high-contrast neutral actions */ + --echoes-color-background-accent-default: #1a1a1a; + --echoes-color-background-accent-hover: #363636; + --echoes-color-background-accent-focus: #1a1a1a; + --echoes-color-background-accent-active: #464646; + --echoes-color-background-accent-weak-default: #b8b8b833; + --echoes-color-background-accent-weak-hover: #b8b8b84d; + --echoes-color-background-accent-weak-focus: #b8b8b833; + --echoes-color-background-accent-weak-active: #b8b8b866; --echoes-color-background-warning-default: #fadc79; --echoes-color-background-warning-hover: #fce9a3; --echoes-color-background-warning-focus: #fadc79; @@ -67,15 +157,15 @@ html[data-echoes-theme='dark'], [data-echoes-theme='dark'] { --echoes-color-background-info-weak-focus: #8fcaea4d; --echoes-color-background-info-weak-active: #8fcaea1a; --echoes-color-background-utility-transparent: #00000000; - --echoes-color-background-selected-weak-default: #5d6cd033; - --echoes-color-background-selected-weak-hover: #5d6cd04d; - --echoes-color-background-selected-weak-pressed: #5d6cd066; - --echoes-color-background-selected-bold-default: #bdc6ff; - --echoes-color-background-selected-bold-hover: #d1d7fe; - --echoes-color-background-selected-bold-pressed: #e8ebff; + --echoes-color-background-selected-weak-default: #10243a; + --echoes-color-background-selected-weak-hover: #122d47; + --echoes-color-background-selected-weak-pressed: #153554; + --echoes-color-background-selected-bold-default: #6ba9f0; + --echoes-color-background-selected-bold-hover: #82b8f3; + --echoes-color-background-selected-bold-pressed: #a9cdf7; --echoes-color-background-ghost-accent-default: #00000000; - --echoes-color-background-ghost-accent-hover: #5d6cd033; - --echoes-color-background-ghost-accent-active: #5d6cd04d; + --echoes-color-background-ghost-accent-hover: #b8b8b833; + --echoes-color-background-ghost-accent-active: #b8b8b84d; --echoes-color-background-ghost-accent-focus: #00000000; --echoes-color-background-ghost-neutral-default: #00000000; --echoes-color-background-ghost-neutral-hover: #1d212f; @@ -85,61 +175,63 @@ html[data-echoes-theme='dark'], [data-echoes-theme='dark'] { --echoes-color-background-ghost-danger-hover: #5d1d1333; --echoes-color-background-ghost-danger-active: #5d1d134d; --echoes-color-background-ghost-danger-focus: #00000000; - --echoes-color-background-emphasis-weak-default: #b790f74d; - --echoes-color-background-emphasis-weak-hover: #b790f733; - --echoes-color-background-emphasis-weak-focus: #b790f74d; - --echoes-color-background-emphasis-weak-active: #b790f71a; - --echoes-color-background-emphasis-default: #d9c5ff; - --echoes-color-background-emphasis-hover: #e5d5ff; - --echoes-color-background-emphasis-focus: #d9c5ff; - --echoes-color-background-emphasis-active: #ede2ff; + --echoes-color-background-emphasis-weak-default: #6ba9f04d; + --echoes-color-background-emphasis-weak-hover: #6ba9f033; + --echoes-color-background-emphasis-weak-focus: #6ba9f04d; + --echoes-color-background-emphasis-weak-active: #6ba9f01a; + --echoes-color-background-emphasis-default: #6ba9f0; + --echoes-color-background-emphasis-hover: #82b8f3; + --echoes-color-background-emphasis-focus: #6ba9f0; + --echoes-color-background-emphasis-active: #3d7fba; --echoes-color-background-favourite-default: #fadc79; --echoes-color-background-favourite-hover: #fce9a3; - --echoes-color-surface-default: #2a2f40; - --echoes-color-surface-hover: #1d212f; - --echoes-color-surface-active: #12141d; - --echoes-color-surface-canvas-default: #1d212f; + --echoes-color-surface-default: #1a1a1a; + --echoes-color-surface-hover: #ffffff0d; + --echoes-color-surface-active: #ffffff1f; + --echoes-color-surface-canvas-default: #151515; --echoes-color-surface-inverse-default: #e1e6f3; --echoes-color-surface-inverse-hover: #eff2f9; --echoes-color-surface-inverse-focus: #e1e6f3; --echoes-color-surface-inverse-active: #f6f7fb; - --echoes-color-surface-disabled: #3e4357; + --echoes-color-surface-disabled: #1f1f1f; --echoes-color-overlays-back-drop-default: #08090c99; --echoes-color-overlays-disabled: #3e4357; - --echoes-color-text-strong: #fcfcfd; - --echoes-color-text-default: #e1e6f3; - --echoes-color-text-subtle: #c5cddf; - --echoes-color-text-disabled: #637192; - --echoes-color-text-on-color: #2a2f40; + --echoes-color-text-strong: #eeeeee; + --echoes-color-text-default: #b8b8b8; + --echoes-color-text-subtle: #b8b8b8; + --echoes-color-text-disabled: #737373; + --echoes-color-text-on-color: #1a1a1a; + --echoes-color-text-on-action: #eeeeee; /** Text and icon color on high-contrast neutral actions */ --echoes-color-text-on-color-inverse: #2a2f40; --echoes-color-text-danger: #fda29b; - --echoes-color-text-placeholder: #c5cddf; - --echoes-color-text-accent: #9fa9ed; + --echoes-color-text-placeholder: #b8b8b8; + --echoes-color-text-accent: #eeeeee; --echoes-color-text-info: #8fcaea; --echoes-color-text-success: #c4ea9e; --echoes-color-text-warning: #fef5d0; - --echoes-color-text-emphasis: #ede2ff; - --echoes-color-text-link-hover: #bdc6ff; - --echoes-color-icon-bold: #fcfcfd; - --echoes-color-icon-default: #e1e6f3; - --echoes-color-icon-subtle: #c5cddf; - --echoes-color-icon-disabled: #637192; - --echoes-color-icon-placeholder: #c5cddf; - --echoes-color-icon-accent: #bdc6ff; + --echoes-color-text-emphasis: #a9cdf7; + --echoes-color-text-link-hover: #eeeeee; + --echoes-color-icon-bold: #eeeeee; + --echoes-color-icon-default: #b8b8b8; + --echoes-color-icon-subtle: #b8b8b8; + --echoes-color-icon-disabled: #737373; + --echoes-color-icon-placeholder: #b8b8b8; + --echoes-color-icon-accent: #eeeeee; --echoes-color-icon-danger: #fda29b; --echoes-color-icon-warning: #fce9a3; --echoes-color-icon-success: #d4f2b7; --echoes-color-icon-info: #b8def1; - --echoes-color-icon-on-color: #2a2f40; + --echoes-color-icon-on-color: #1a1a1a; --echoes-color-icon-on-color-inverse: #2a2f40; - --echoes-color-icon-selected: #bdc6ff; - --echoes-color-icon-emphasis: #ede2ff; - --echoes-color-border-bolder: #c5cddf; - --echoes-color-border-bold: #a6adc2; - --echoes-color-border-weak: #637192; - --echoes-color-border-weaker: #3e4357; - --echoes-color-border-disabled: #637192; - --echoes-color-border-accent-default: #bdc6ff; + --echoes-color-icon-selected: #82b8f3; + --echoes-color-icon-emphasis: #a9cdf7; + --echoes-color-border-bolder: #828282; + --echoes-color-border-bold: #464646; + --echoes-color-border-weak: #363636; + --echoes-color-border-weaker: #2a2a2a; + --echoes-color-border-disabled: #464646; + --echoes-color-border-accent-default: #828282; + --echoes-color-border-action-neutral: #737373; /** Boundary color for near-black neutral actions on dark surfaces */ --echoes-color-border-danger-weak: #fda29b66; --echoes-color-border-danger-default: #fda29b; --echoes-color-border-none: #00000000; @@ -147,7 +239,7 @@ html[data-echoes-theme='dark'], [data-echoes-theme='dark'] { --echoes-color-border-success-default: #b3dd86; --echoes-color-border-warning-weak: #fadc7966; --echoes-color-border-info-weak: #8fcaea66; - --echoes-color-border-emphasis-weak: #b790f766; + --echoes-color-border-emphasis-weak: #275f8f66; --echoes-color-code-background-default: #3e4357; --echoes-color-code-background-highlight: #2a2f40; --echoes-color-code-border-default: #00000000; @@ -160,7 +252,7 @@ html[data-echoes-theme='dark'], [data-echoes-theme='dark'] { --echoes-color-code-text-string: #98c379; --echoes-color-code-text-keyword-subtle: #ababff; --echoes-color-code-text-preprocessing-directive: #78d779; - --echoes-color-focus-default: #bdc6ff; + --echoes-color-focus-default: #eeeeee; --echoes-color-charts-categorical-1: #3b82d4; --echoes-color-charts-categorical-2: #d74a78; --echoes-color-charts-categorical-3: #0f9383; @@ -180,12 +272,44 @@ html[data-echoes-theme='dark'], [data-echoes-theme='dark'] { --echoes-box-shadow-medium: inset 0 2px 15px -2px #08090c0f, 0 4px 15px -2px #08090c80; --echoes-box-shadow-large: 0 4px 6px -2px #08090c0d, 0 12px 20px -4px #08090c80; --echoes-box-shadow-x-large: 0 8px 8px -4px #08090c0a, 0 20px 30px -4px #08090c80; + --echoes-button-colors-background-default: #1a1a1a; + --echoes-button-colors-background-hover: #363636; + --echoes-button-colors-background-active: #464646; + --echoes-button-colors-background-disabled: #1f1f1f; + --echoes-button-colors-border-default: #737373; + --echoes-button-colors-text-default: #eeeeee; + --echoes-button-colors-text-disabled: #737373; + --echoes-button-colors-focus: #eeeeee; + --echoes-input-colors-background-default: #1a1a1a; + --echoes-input-colors-background-hover: #ffffff0d; + --echoes-input-colors-background-disabled: #1f1f1f; + --echoes-input-colors-border-default: #828282; + --echoes-input-colors-border-focus: #eeeeee; + --echoes-input-colors-border-disabled: #464646; + --echoes-input-colors-text-default: #eeeeee; + --echoes-input-colors-text-placeholder: #b8b8b8; + --echoes-input-colors-text-disabled: #737373; + --echoes-input-colors-focus: #eeeeee; + --echoes-navigation-item-colors-background-default: #1a1a1a; + --echoes-navigation-item-colors-background-hover: #ffffff0d; + --echoes-navigation-item-colors-background-selected: #10243a; + --echoes-navigation-item-colors-background-selected-hover: #122d47; + --echoes-navigation-item-colors-text-default: #eeeeee; + --echoes-navigation-item-colors-text-selected: #a9cdf7; + --echoes-navigation-item-colors-icon-default: #b8b8b8; + --echoes-navigation-item-colors-icon-selected: #82b8f3; + --echoes-navigation-item-colors-focus: #eeeeee; + --echoes-issue-row-colors-background-default: #1a1a1a; + --echoes-issue-row-colors-background-hover: #ffffff0d; + --echoes-issue-row-colors-background-selected: #10243a; + --echoes-issue-row-colors-background-selected-hover: #122d47; + --echoes-issue-row-colors-border: #363636; --echoes-bottom-scroll-colors-shadow-gradient: #ffffff33; - --echoes-form-control-colors-background-default: #2a2f40; - --echoes-form-control-colors-background-hover: #1d212f; - --echoes-form-control-colors-border-default: #c5cddf; - --echoes-form-control-colors-border-focus: #637192; - --echoes-form-control-colors-icon-default: #c5cddf; + --echoes-form-control-colors-background-default: #1a1a1a; + --echoes-form-control-colors-background-hover: #ffffff0d; + --echoes-form-control-colors-border-default: #828282; + --echoes-form-control-colors-border-focus: #363636; + --echoes-form-control-colors-icon-default: #b8b8b8; --echoes-logos-colors-text: #ffffff; --echoes-logos-colors-brand: #ffffff; --echoes-logos-colors-sonar-whale: #d3121d; diff --git a/src/generated/design-tokens-light.css b/src/generated/design-tokens-light.css index a20d52d56..dd83a3a94 100644 --- a/src/generated/design-tokens-light.css +++ b/src/generated/design-tokens-light.css @@ -21,19 +21,109 @@ */ :root, [data-echoes-theme='light'] { + --echoes-color-palette-ui-gray-1: #fcfcfc; + --echoes-color-palette-ui-gray-2: #f8f8f8; + --echoes-color-palette-ui-gray-3: #f4f4f4; + --echoes-color-palette-ui-gray-4: #efefef; + --echoes-color-palette-ui-gray-5: #e8e8e8; + --echoes-color-palette-ui-gray-6: #e0e0e0; + --echoes-color-palette-ui-gray-7: #d4d4d4; + --echoes-color-palette-ui-gray-8: #b8b8b8; + --echoes-color-palette-ui-gray-9: #5a5a5a; + --echoes-color-palette-ui-gray-10: #4a4a4a; + --echoes-color-palette-ui-gray-11: #3a3a3a; + --echoes-color-palette-ui-gray-12: #1a1a1a; + --echoes-color-palette-ui-gray-alpha-1: #00000003; + --echoes-color-palette-ui-gray-alpha-2: #00000005; + --echoes-color-palette-ui-gray-alpha-3: #00000008; + --echoes-color-palette-ui-gray-alpha-4: #0000000d; + --echoes-color-palette-ui-gray-alpha-5: #00000014; + --echoes-color-palette-ui-gray-alpha-6: #0000001f; + --echoes-color-palette-ui-gray-alpha-7: #0000002e; + --echoes-color-palette-ui-gray-alpha-8: #00000047; + --echoes-color-palette-ui-gray-alpha-9: #000000a6; + --echoes-color-palette-ui-gray-alpha-10: #000000b8; + --echoes-color-palette-ui-gray-alpha-11: #000000c7; + --echoes-color-palette-ui-gray-alpha-12: #000000e6; + --echoes-color-palette-ui-brand-blue-1: #f7fafe; + --echoes-color-palette-ui-brand-blue-2: #f2f7fd; + --echoes-color-palette-ui-brand-blue-3: #e8f1fc; + --echoes-color-palette-ui-brand-blue-4: #dcebfa; + --echoes-color-palette-ui-brand-blue-5: #c9e0f7; + --echoes-color-palette-ui-brand-blue-6: #a9cdf2; + --echoes-color-palette-ui-brand-blue-7: #78b2e9; + --echoes-color-palette-ui-brand-blue-8: #4191de; + --echoes-color-palette-ui-brand-blue-9: #126ed3; + --echoes-color-palette-ui-brand-blue-10: #0f61bd; + --echoes-color-palette-ui-brand-blue-11: #0c51a0; + --echoes-color-palette-ui-brand-blue-12: #082f5b; + --echoes-color-palette-ui-success-green-1: #f8fcf4; + --echoes-color-palette-ui-success-green-2: #f0fae6; + --echoes-color-palette-ui-success-green-3: #dff8c8; + --echoes-color-palette-ui-success-green-4: #cef3a9; + --echoes-color-palette-ui-success-green-5: #c0e69b; + --echoes-color-palette-ui-success-green-6: #afd18d; + --echoes-color-palette-ui-success-green-7: #94b474; + --echoes-color-palette-ui-success-green-8: #759554; + --echoes-color-palette-ui-success-green-9: #558112; + --echoes-color-palette-ui-success-green-10: #4d6b29; + --echoes-color-palette-ui-success-green-11: #43572d; + --echoes-color-palette-ui-success-green-12: #293121; + --echoes-color-palette-ui-warning-yellow-1: #fcfaf7; + --echoes-color-palette-ui-warning-yellow-2: #faf5ed; + --echoes-color-palette-ui-warning-yellow-3: #f7ecdb; + --echoes-color-palette-ui-warning-yellow-4: #f2e2c9; + --echoes-color-palette-ui-warning-yellow-5: #ead4b2; + --echoes-color-palette-ui-warning-yellow-6: #debf8b; + --echoes-color-palette-ui-warning-yellow-7: #c0a373; + --echoes-color-palette-ui-warning-yellow-8: #a18453; + --echoes-color-palette-ui-warning-yellow-9: #926912; + --echoes-color-palette-ui-warning-yellow-10: #775b28; + --echoes-color-palette-ui-warning-yellow-11: #5f4d2d; + --echoes-color-palette-ui-warning-yellow-12: #342d21; + --echoes-color-palette-ui-danger-red-1: #fcf9f9; + --echoes-color-palette-ui-danger-red-2: #faf4f3; + --echoes-color-palette-ui-danger-red-3: #f7eae8; + --echoes-color-palette-ui-danger-red-4: #f2e0dd; + --echoes-color-palette-ui-danger-red-5: #ead1cd; + --echoes-color-palette-ui-danger-red-6: #e0bab3; + --echoes-color-palette-ui-danger-red-7: #d5958a; + --echoes-color-palette-ui-danger-red-8: #d46152; + --echoes-color-palette-ui-danger-red-9: #d11c11; + --echoes-color-palette-ui-danger-red-10: #a53327; + --echoes-color-palette-ui-danger-red-11: #7f352c; + --echoes-color-palette-ui-danger-red-12: #412521; + --echoes-color-palette-ui-data-viz-categorical-1: #347bd0; + --echoes-color-palette-ui-data-viz-categorical-2: #d44194; + --echoes-color-palette-ui-data-viz-categorical-3: #388779; + --echoes-color-palette-ui-data-viz-categorical-4: #8838e0; + --echoes-color-palette-ui-data-viz-categorical-5: #c66f39; + --echoes-color-palette-ui-data-viz-categorical-6: #295a69; + --echoes-color-palette-ui-data-viz-categorical-7: #84307f; + --echoes-color-palette-ui-data-viz-categorical-8: #3d6127; + --echoes-color-palette-ui-data-viz-severity-blocker: #5e221a; + --echoes-color-palette-ui-data-viz-severity-high: #ae2e22; + --echoes-color-palette-ui-data-viz-severity-medium: #a2642a; + --echoes-color-palette-ui-data-viz-severity-low: #937f30; + --echoes-color-palette-ui-data-viz-severity-info: #2e6fbd; + --echoes-color-palette-ui-data-viz-placeholder-default: #737373; --echoes-color-background-neutral-subtle-default: #eff2f9; /** Use it in components with neutral sentiment */ --echoes-color-background-neutral-subtle-focus: #eff2f9; /** Use it in components with neutral sentiment */ --echoes-color-background-neutral-subtle-hover: #e1e6f3; /** Use it in components with neutral sentiment */ --echoes-color-background-neutral-subtle-active: #c5cddf; /** Use it in components with neutral sentiment */ --echoes-color-background-neutral-bolder-default: #e1e6f3; /** Use it in components with neutral sentiment that need a bolder highlight */ - --echoes-color-background-accent-default: #5d6cd0; /** Used as the background color of components that reinforce our brand */ - --echoes-color-background-accent-hover: #4b56bb; /** Hover state of components that reinforce our brand */ - --echoes-color-background-accent-focus: #5d6cd0; - --echoes-color-background-accent-active: #47518f; /** Active state of components that reinforce our brand */ - --echoes-color-background-accent-weak-default: #f4f6ff; /** Used as the background color of components that reinforce our brand with less visual highlight */ - --echoes-color-background-accent-weak-hover: #e8ebff; /** Hover state of components that reinforce our brand with less visual highlight */ - --echoes-color-background-accent-weak-active: #d1d7fe; /** Active state of components that reinforce our brand with less visual highlight */ - --echoes-color-background-accent-weak-focus: #e8ebff; /** Focus state of components that reinforce our brand with less visual highlight */ + --echoes-color-background-action-neutral-default: #1a1a1a; /** Near-black fill for high-contrast neutral actions */ + --echoes-color-background-action-neutral-hover: #3a3a3a; /** Hover fill for high-contrast neutral actions */ + --echoes-color-background-action-neutral-focus: #1a1a1a; + --echoes-color-background-action-neutral-active: #4a4a4a; /** Active fill for high-contrast neutral actions */ + --echoes-color-background-accent-default: #1a1a1a; /** Used as the background color of high-contrast neutral actions */ + --echoes-color-background-accent-hover: #3a3a3a; /** Hover state of high-contrast neutral actions */ + --echoes-color-background-accent-focus: #1a1a1a; + --echoes-color-background-accent-active: #4a4a4a; /** Active state of high-contrast neutral actions */ + --echoes-color-background-accent-weak-default: #f8f8f8; /** Used as a subtle neutral background */ + --echoes-color-background-accent-weak-hover: #f4f4f4; /** Hover state of a subtle neutral background */ + --echoes-color-background-accent-weak-active: #efefef; /** Active state of a subtle neutral background */ + --echoes-color-background-accent-weak-focus: #f8f8f8; /** Focus state of a subtle neutral background */ --echoes-color-background-warning-default: #f5b840; /** Use for backgrounds that communicate warning or caution */ --echoes-color-background-warning-hover: #e7ae3d; /** Use for backgrounds that communicate warning or caution */ --echoes-color-background-warning-focus: #f5b840; /** Use for backgrounds that communicate warning or caution */ @@ -67,15 +157,15 @@ --echoes-color-background-info-weak-focus: #f5fbff; /** Use for backgrounds that communicate information to the user, with less visual highlight */ --echoes-color-background-info-weak-active: #b8def1; /** Use for backgrounds that communicate information to the user, with less visual highlight */ --echoes-color-background-utility-transparent: #00000000; /** Use it when you need transparency in the background */ - --echoes-color-background-selected-weak-default: #f4f6ff; /** Use it in backgrounds of components that have a selected state that need less visual highlight, like dropdown or selects */ - --echoes-color-background-selected-weak-hover: #e8ebff; /** Hover state of components that have a selected state that need less visual highlight, like dropdown or selects */ - --echoes-color-background-selected-weak-pressed: #d1d7fe; /** Pressed state of components that have a selected state that need less visual highlight, like dropdown or selects */ - --echoes-color-background-selected-bold-default: #5d6cd0; /** Use it in backgrounds of components that have a selected state, like checkboxes or radios */ - --echoes-color-background-selected-bold-hover: #4b56bb; /** Hover state of components that have a selected state, like checkboxes or radios */ - --echoes-color-background-selected-bold-pressed: #47518f; /** Pressed state of components that have a selected state, like checkboxes or radios */ + --echoes-color-background-selected-weak-default: #e8f1fc; /** Use it in backgrounds of components that have a selected state that need less visual highlight, like dropdown or selects */ + --echoes-color-background-selected-weak-hover: #dcebfa; /** Hover state of components that have a selected state that need less visual highlight, like dropdown or selects */ + --echoes-color-background-selected-weak-pressed: #c9e0f7; /** Pressed state of components that have a selected state that need less visual highlight, like dropdown or selects */ + --echoes-color-background-selected-bold-default: #126ed3; /** Use it in backgrounds of components that have a selected state, like checkboxes or radios */ + --echoes-color-background-selected-bold-hover: #0f61bd; /** Hover state of components that have a selected state, like checkboxes or radios */ + --echoes-color-background-selected-bold-pressed: #0c51a0; /** Pressed state of components that have a selected state, like checkboxes or radios */ --echoes-color-background-ghost-accent-default: #00000000; - --echoes-color-background-ghost-accent-hover: #e8ebff; - --echoes-color-background-ghost-accent-active: #d1d7fe; + --echoes-color-background-ghost-accent-hover: #00000008; + --echoes-color-background-ghost-accent-active: #00000014; --echoes-color-background-ghost-accent-focus: #00000000; --echoes-color-background-ghost-neutral-default: #00000000; --echoes-color-background-ghost-neutral-hover: #eff2f9; @@ -85,61 +175,63 @@ --echoes-color-background-ghost-danger-hover: #fef3f2; --echoes-color-background-ghost-danger-active: #fee4e2; --echoes-color-background-ghost-danger-focus: #00000000; - --echoes-color-background-emphasis-weak-default: #f4eeff; - --echoes-color-background-emphasis-weak-hover: #ede2ff; - --echoes-color-background-emphasis-weak-focus: #f4eeff; - --echoes-color-background-emphasis-weak-active: #e5d5ff; - --echoes-color-background-emphasis-default: #883fdd; - --echoes-color-background-emphasis-hover: #7934c7; - --echoes-color-background-emphasis-focus: #883fdd; - --echoes-color-background-emphasis-active: #3f186b; + --echoes-color-background-emphasis-weak-default: #e8f1fc; + --echoes-color-background-emphasis-weak-hover: #dcebfa; + --echoes-color-background-emphasis-weak-focus: #e8f1fc; + --echoes-color-background-emphasis-weak-active: #c9e0f7; + --echoes-color-background-emphasis-default: #126ed3; + --echoes-color-background-emphasis-hover: #0f61bd; + --echoes-color-background-emphasis-focus: #126ed3; + --echoes-color-background-emphasis-active: #0c51a0; --echoes-color-background-favourite-default: #d19834; --echoes-color-background-favourite-hover: #ae7a29; - --echoes-color-surface-default: #ffffff; /** Go to color for surfaces.. eg: cards, modals, popovers, etc... */ - --echoes-color-surface-hover: #f6f7fb; /** Hover color for bg-default */ - --echoes-color-surface-active: #e1e6f3; /** Active color for bg-default */ - --echoes-color-surface-canvas-default: #fcfcfd; /** Use it as page background */ + --echoes-color-surface-default: #fcfcfc; /** Go to color for surfaces.. eg: cards, modals, popovers, etc... */ + --echoes-color-surface-hover: #00000008; /** Hover color for bg-default */ + --echoes-color-surface-active: #00000014; /** Active color for bg-default */ + --echoes-color-surface-canvas-default: #f8f8f8; /** Use it as page background */ --echoes-color-surface-inverse-default: #2a2f40; /** Inverse color for bgs, creates high contrast against bg-default and bg-page */ --echoes-color-surface-inverse-hover: #1d212f; --echoes-color-surface-inverse-focus: #2a2f40; --echoes-color-surface-inverse-active: #12141d; - --echoes-color-surface-disabled: #eff2f9; /** Use it as background for disabled components */ + --echoes-color-surface-disabled: #f4f4f4; /** Use it as background for disabled components */ --echoes-color-overlays-back-drop-default: #08090c73; --echoes-color-overlays-disabled: #eff2f9; /** Use it as background for disabled components */ - --echoes-color-text-strong: #1d212f; - --echoes-color-text-default: #3e4357; - --echoes-color-text-disabled: #a6adc2; - --echoes-color-text-placeholder: #637192; - --echoes-color-text-subtle: #637192; - --echoes-color-text-on-color: #ffffff; + --echoes-color-text-strong: #1a1a1a; + --echoes-color-text-default: #4a4a4a; + --echoes-color-text-disabled: #5a5a5a; + --echoes-color-text-placeholder: #4a4a4a; + --echoes-color-text-subtle: #4a4a4a; + --echoes-color-text-on-color: #fcfcfc; + --echoes-color-text-on-action: #fcfcfc; /** Text and icon color on high-contrast neutral actions */ --echoes-color-text-on-color-inverse: #3e4357; - --echoes-color-text-accent: #5d6cd0; + --echoes-color-text-accent: #1a1a1a; --echoes-color-text-danger: #b42318; --echoes-color-text-warning: #8c5e1e; --echoes-color-text-success: #537c17; --echoes-color-text-info: #316c92; - --echoes-color-text-emphasis: #7934c7; - --echoes-color-text-link-hover: #4b56bb; - --echoes-color-icon-bold: #1d212f; - --echoes-color-icon-default: #3e4357; - --echoes-color-icon-subtle: #637192; - --echoes-color-icon-disabled: #a6adc2; - --echoes-color-icon-placeholder: #637192; - --echoes-color-icon-accent: #5d6cd0; + --echoes-color-text-emphasis: #0c51a0; + --echoes-color-text-link-hover: #3a3a3a; + --echoes-color-icon-bold: #1a1a1a; + --echoes-color-icon-default: #4a4a4a; + --echoes-color-icon-subtle: #4a4a4a; + --echoes-color-icon-disabled: #5a5a5a; + --echoes-color-icon-placeholder: #4a4a4a; + --echoes-color-icon-accent: #1a1a1a; --echoes-color-icon-danger: #d92d20; --echoes-color-icon-warning: #ae7a29; --echoes-color-icon-success: #82b73c; --echoes-color-icon-info: #4595cb; - --echoes-color-icon-on-color: #ffffff; + --echoes-color-icon-on-color: #fcfcfc; --echoes-color-icon-on-color-inverse: #3e4357; - --echoes-color-icon-selected: #5d6cd0; - --echoes-color-icon-emphasis: #7934c7; - --echoes-color-border-bolder: #637192; - --echoes-color-border-bold: #c5cddf; - --echoes-color-border-weak: #e1e6f3; - --echoes-color-border-weaker: #eff2f9; - --echoes-color-border-disabled: #c5cddf; - --echoes-color-border-accent-default: #5d6cd0; + --echoes-color-icon-selected: #126ed3; + --echoes-color-icon-emphasis: #0c51a0; + --echoes-color-border-bolder: #5a5a5a; + --echoes-color-border-bold: #d4d4d4; + --echoes-color-border-weak: #e0e0e0; + --echoes-color-border-weaker: #e8e8e8; + --echoes-color-border-disabled: #d4d4d4; + --echoes-color-border-accent-default: #1a1a1a; + --echoes-color-border-action-neutral: #1a1a1a; /** Boundary color for high-contrast neutral actions */ --echoes-color-border-danger-weak: #fee4e2; --echoes-color-border-danger-default: #d92d20; --echoes-color-border-none: #00000000; @@ -147,7 +239,7 @@ --echoes-color-border-success-default: #75a92c; --echoes-color-border-warning-weak: #fef5d0; --echoes-color-border-info-weak: #e9f4fb; - --echoes-color-border-emphasis-weak: #ede2ff; + --echoes-color-border-emphasis-weak: #a9cdf2; --echoes-color-code-background-default: #fcfcfd; --echoes-color-code-background-highlight: #c5cddf; --echoes-color-code-border-default: #e1e6f3; @@ -160,7 +252,7 @@ --echoes-color-code-text-string: #247523; --echoes-color-code-text-keyword-subtle: #1e1ead; --echoes-color-code-text-preprocessing-directive: #347235; - --echoes-color-focus-default: #4b56bb; + --echoes-color-focus-default: #1a1a1a; --echoes-color-charts-categorical-1: #3b82d4; --echoes-color-charts-categorical-2: #d74a78; --echoes-color-charts-categorical-3: #0f9383; @@ -180,12 +272,44 @@ --echoes-box-shadow-medium: 0 2px 15px -2px #1d212f0f, 0 4px 8px -2px #1d212f1a; --echoes-box-shadow-large: 0 4px 6px -2px #1d212f0d, 0 12px 16px -4px #1d212f1a; --echoes-box-shadow-x-large: 0 8px 8px -4px #1d212f0a, 15px 20px 24px -4px #1d212f1a; + --echoes-button-colors-background-default: #1a1a1a; + --echoes-button-colors-background-hover: #3a3a3a; + --echoes-button-colors-background-active: #4a4a4a; + --echoes-button-colors-background-disabled: #f4f4f4; + --echoes-button-colors-border-default: #1a1a1a; + --echoes-button-colors-text-default: #fcfcfc; + --echoes-button-colors-text-disabled: #5a5a5a; + --echoes-button-colors-focus: #1a1a1a; + --echoes-input-colors-background-default: #fcfcfc; + --echoes-input-colors-background-hover: #00000008; + --echoes-input-colors-background-disabled: #f4f4f4; + --echoes-input-colors-border-default: #5a5a5a; + --echoes-input-colors-border-focus: #1a1a1a; + --echoes-input-colors-border-disabled: #d4d4d4; + --echoes-input-colors-text-default: #1a1a1a; + --echoes-input-colors-text-placeholder: #4a4a4a; + --echoes-input-colors-text-disabled: #5a5a5a; + --echoes-input-colors-focus: #1a1a1a; + --echoes-navigation-item-colors-background-default: #fcfcfc; + --echoes-navigation-item-colors-background-hover: #00000008; + --echoes-navigation-item-colors-background-selected: #e8f1fc; + --echoes-navigation-item-colors-background-selected-hover: #dcebfa; + --echoes-navigation-item-colors-text-default: #1a1a1a; + --echoes-navigation-item-colors-text-selected: #0c51a0; + --echoes-navigation-item-colors-icon-default: #4a4a4a; + --echoes-navigation-item-colors-icon-selected: #126ed3; + --echoes-navigation-item-colors-focus: #1a1a1a; + --echoes-issue-row-colors-background-default: #fcfcfc; + --echoes-issue-row-colors-background-hover: #00000008; + --echoes-issue-row-colors-background-selected: #e8f1fc; + --echoes-issue-row-colors-background-selected-hover: #dcebfa; + --echoes-issue-row-colors-border: #e0e0e0; --echoes-bottom-scroll-colors-shadow-gradient: #00000033; - --echoes-form-control-colors-background-default: #ffffff; - --echoes-form-control-colors-background-hover: #f6f7fb; - --echoes-form-control-colors-border-default: #637192; - --echoes-form-control-colors-border-focus: #e1e6f3; - --echoes-form-control-colors-icon-default: #637192; + --echoes-form-control-colors-background-default: #fcfcfc; + --echoes-form-control-colors-background-hover: #00000008; + --echoes-form-control-colors-border-default: #5a5a5a; + --echoes-form-control-colors-border-focus: #e0e0e0; + --echoes-form-control-colors-icon-default: #4a4a4a; --echoes-logos-colors-text: #290042; --echoes-logos-colors-brand: #126ed3; --echoes-logos-colors-sonar-whale: #d3121d; diff --git a/src/generated/design-tokens-themed.json b/src/generated/design-tokens-themed.json index eafe01885..1fa452f7d 100644 --- a/src/generated/design-tokens-themed.json +++ b/src/generated/design-tokens-themed.json @@ -1,17 +1,107 @@ { + "echoes-color-palette-ui-gray-1": "#fcfcfc", + "echoes-color-palette-ui-gray-2": "#f8f8f8", + "echoes-color-palette-ui-gray-3": "#f4f4f4", + "echoes-color-palette-ui-gray-4": "#efefef", + "echoes-color-palette-ui-gray-5": "#e8e8e8", + "echoes-color-palette-ui-gray-6": "#e0e0e0", + "echoes-color-palette-ui-gray-7": "#d4d4d4", + "echoes-color-palette-ui-gray-8": "#b8b8b8", + "echoes-color-palette-ui-gray-9": "#5a5a5a", + "echoes-color-palette-ui-gray-10": "#4a4a4a", + "echoes-color-palette-ui-gray-11": "#3a3a3a", + "echoes-color-palette-ui-gray-12": "#1a1a1a", + "echoes-color-palette-ui-gray-alpha-1": "#00000003", + "echoes-color-palette-ui-gray-alpha-2": "#00000005", + "echoes-color-palette-ui-gray-alpha-3": "#00000008", + "echoes-color-palette-ui-gray-alpha-4": "#0000000d", + "echoes-color-palette-ui-gray-alpha-5": "#00000014", + "echoes-color-palette-ui-gray-alpha-6": "#0000001f", + "echoes-color-palette-ui-gray-alpha-7": "#0000002e", + "echoes-color-palette-ui-gray-alpha-8": "#00000047", + "echoes-color-palette-ui-gray-alpha-9": "#000000a6", + "echoes-color-palette-ui-gray-alpha-10": "#000000b8", + "echoes-color-palette-ui-gray-alpha-11": "#000000c7", + "echoes-color-palette-ui-gray-alpha-12": "#000000e6", + "echoes-color-palette-ui-brand-blue-1": "#f7fafe", + "echoes-color-palette-ui-brand-blue-2": "#f2f7fd", + "echoes-color-palette-ui-brand-blue-3": "#e8f1fc", + "echoes-color-palette-ui-brand-blue-4": "#dcebfa", + "echoes-color-palette-ui-brand-blue-5": "#c9e0f7", + "echoes-color-palette-ui-brand-blue-6": "#a9cdf2", + "echoes-color-palette-ui-brand-blue-7": "#78b2e9", + "echoes-color-palette-ui-brand-blue-8": "#4191de", + "echoes-color-palette-ui-brand-blue-9": "#126ed3", + "echoes-color-palette-ui-brand-blue-10": "#0f61bd", + "echoes-color-palette-ui-brand-blue-11": "#0c51a0", + "echoes-color-palette-ui-brand-blue-12": "#082f5b", + "echoes-color-palette-ui-success-green-1": "#f8fcf4", + "echoes-color-palette-ui-success-green-2": "#f0fae6", + "echoes-color-palette-ui-success-green-3": "#dff8c8", + "echoes-color-palette-ui-success-green-4": "#cef3a9", + "echoes-color-palette-ui-success-green-5": "#c0e69b", + "echoes-color-palette-ui-success-green-6": "#afd18d", + "echoes-color-palette-ui-success-green-7": "#94b474", + "echoes-color-palette-ui-success-green-8": "#759554", + "echoes-color-palette-ui-success-green-9": "#558112", + "echoes-color-palette-ui-success-green-10": "#4d6b29", + "echoes-color-palette-ui-success-green-11": "#43572d", + "echoes-color-palette-ui-success-green-12": "#293121", + "echoes-color-palette-ui-warning-yellow-1": "#fcfaf7", + "echoes-color-palette-ui-warning-yellow-2": "#faf5ed", + "echoes-color-palette-ui-warning-yellow-3": "#f7ecdb", + "echoes-color-palette-ui-warning-yellow-4": "#f2e2c9", + "echoes-color-palette-ui-warning-yellow-5": "#ead4b2", + "echoes-color-palette-ui-warning-yellow-6": "#debf8b", + "echoes-color-palette-ui-warning-yellow-7": "#c0a373", + "echoes-color-palette-ui-warning-yellow-8": "#a18453", + "echoes-color-palette-ui-warning-yellow-9": "#926912", + "echoes-color-palette-ui-warning-yellow-10": "#775b28", + "echoes-color-palette-ui-warning-yellow-11": "#5f4d2d", + "echoes-color-palette-ui-warning-yellow-12": "#342d21", + "echoes-color-palette-ui-danger-red-1": "#fcf9f9", + "echoes-color-palette-ui-danger-red-2": "#faf4f3", + "echoes-color-palette-ui-danger-red-3": "#f7eae8", + "echoes-color-palette-ui-danger-red-4": "#f2e0dd", + "echoes-color-palette-ui-danger-red-5": "#ead1cd", + "echoes-color-palette-ui-danger-red-6": "#e0bab3", + "echoes-color-palette-ui-danger-red-7": "#d5958a", + "echoes-color-palette-ui-danger-red-8": "#d46152", + "echoes-color-palette-ui-danger-red-9": "#d11c11", + "echoes-color-palette-ui-danger-red-10": "#a53327", + "echoes-color-palette-ui-danger-red-11": "#7f352c", + "echoes-color-palette-ui-danger-red-12": "#412521", + "echoes-color-palette-ui-data-viz-categorical-1": "#347bd0", + "echoes-color-palette-ui-data-viz-categorical-2": "#d44194", + "echoes-color-palette-ui-data-viz-categorical-3": "#388779", + "echoes-color-palette-ui-data-viz-categorical-4": "#8838e0", + "echoes-color-palette-ui-data-viz-categorical-5": "#c66f39", + "echoes-color-palette-ui-data-viz-categorical-6": "#295a69", + "echoes-color-palette-ui-data-viz-categorical-7": "#84307f", + "echoes-color-palette-ui-data-viz-categorical-8": "#3d6127", + "echoes-color-palette-ui-data-viz-severity-blocker": "#5e221a", + "echoes-color-palette-ui-data-viz-severity-high": "#ae2e22", + "echoes-color-palette-ui-data-viz-severity-medium": "#a2642a", + "echoes-color-palette-ui-data-viz-severity-low": "#937f30", + "echoes-color-palette-ui-data-viz-severity-info": "#2e6fbd", + "echoes-color-palette-ui-data-viz-placeholder-default": "#737373", "echoes-color-background-neutral-subtle-default": "#eff2f9", "echoes-color-background-neutral-subtle-focus": "#eff2f9", "echoes-color-background-neutral-subtle-hover": "#e1e6f3", "echoes-color-background-neutral-subtle-active": "#c5cddf", "echoes-color-background-neutral-bolder-default": "#e1e6f3", - "echoes-color-background-accent-default": "#5d6cd0", - "echoes-color-background-accent-hover": "#4b56bb", - "echoes-color-background-accent-focus": "#5d6cd0", - "echoes-color-background-accent-active": "#47518f", - "echoes-color-background-accent-weak-default": "#f4f6ff", - "echoes-color-background-accent-weak-hover": "#e8ebff", - "echoes-color-background-accent-weak-active": "#d1d7fe", - "echoes-color-background-accent-weak-focus": "#e8ebff", + "echoes-color-background-action-neutral-default": "#1a1a1a", + "echoes-color-background-action-neutral-hover": "#3a3a3a", + "echoes-color-background-action-neutral-focus": "#1a1a1a", + "echoes-color-background-action-neutral-active": "#4a4a4a", + "echoes-color-background-accent-default": "#1a1a1a", + "echoes-color-background-accent-hover": "#3a3a3a", + "echoes-color-background-accent-focus": "#1a1a1a", + "echoes-color-background-accent-active": "#4a4a4a", + "echoes-color-background-accent-weak-default": "#f8f8f8", + "echoes-color-background-accent-weak-hover": "#f4f4f4", + "echoes-color-background-accent-weak-active": "#efefef", + "echoes-color-background-accent-weak-focus": "#f8f8f8", "echoes-color-background-warning-default": "#f5b840", "echoes-color-background-warning-hover": "#e7ae3d", "echoes-color-background-warning-focus": "#f5b840", @@ -45,15 +135,15 @@ "echoes-color-background-info-weak-focus": "#f5fbff", "echoes-color-background-info-weak-active": "#b8def1", "echoes-color-background-utility-transparent": "#00000000", - "echoes-color-background-selected-weak-default": "#f4f6ff", - "echoes-color-background-selected-weak-hover": "#e8ebff", - "echoes-color-background-selected-weak-pressed": "#d1d7fe", - "echoes-color-background-selected-bold-default": "#5d6cd0", - "echoes-color-background-selected-bold-hover": "#4b56bb", - "echoes-color-background-selected-bold-pressed": "#47518f", + "echoes-color-background-selected-weak-default": "#e8f1fc", + "echoes-color-background-selected-weak-hover": "#dcebfa", + "echoes-color-background-selected-weak-pressed": "#c9e0f7", + "echoes-color-background-selected-bold-default": "#126ed3", + "echoes-color-background-selected-bold-hover": "#0f61bd", + "echoes-color-background-selected-bold-pressed": "#0c51a0", "echoes-color-background-ghost-accent-default": "#00000000", - "echoes-color-background-ghost-accent-hover": "#e8ebff", - "echoes-color-background-ghost-accent-active": "#d1d7fe", + "echoes-color-background-ghost-accent-hover": "#00000008", + "echoes-color-background-ghost-accent-active": "#00000014", "echoes-color-background-ghost-accent-focus": "#00000000", "echoes-color-background-ghost-neutral-default": "#00000000", "echoes-color-background-ghost-neutral-hover": "#eff2f9", @@ -63,61 +153,63 @@ "echoes-color-background-ghost-danger-hover": "#fef3f2", "echoes-color-background-ghost-danger-active": "#fee4e2", "echoes-color-background-ghost-danger-focus": "#00000000", - "echoes-color-background-emphasis-weak-default": "#f4eeff", - "echoes-color-background-emphasis-weak-hover": "#ede2ff", - "echoes-color-background-emphasis-weak-focus": "#f4eeff", - "echoes-color-background-emphasis-weak-active": "#e5d5ff", - "echoes-color-background-emphasis-default": "#883fdd", - "echoes-color-background-emphasis-hover": "#7934c7", - "echoes-color-background-emphasis-focus": "#883fdd", - "echoes-color-background-emphasis-active": "#3f186b", + "echoes-color-background-emphasis-weak-default": "#e8f1fc", + "echoes-color-background-emphasis-weak-hover": "#dcebfa", + "echoes-color-background-emphasis-weak-focus": "#e8f1fc", + "echoes-color-background-emphasis-weak-active": "#c9e0f7", + "echoes-color-background-emphasis-default": "#126ed3", + "echoes-color-background-emphasis-hover": "#0f61bd", + "echoes-color-background-emphasis-focus": "#126ed3", + "echoes-color-background-emphasis-active": "#0c51a0", "echoes-color-background-favourite-default": "#d19834", "echoes-color-background-favourite-hover": "#ae7a29", - "echoes-color-surface-default": "#ffffff", - "echoes-color-surface-hover": "#f6f7fb", - "echoes-color-surface-active": "#e1e6f3", - "echoes-color-surface-canvas-default": "#fcfcfd", + "echoes-color-surface-default": "#fcfcfc", + "echoes-color-surface-hover": "#00000008", + "echoes-color-surface-active": "#00000014", + "echoes-color-surface-canvas-default": "#f8f8f8", "echoes-color-surface-inverse-default": "#2a2f40", "echoes-color-surface-inverse-hover": "#1d212f", "echoes-color-surface-inverse-focus": "#2a2f40", "echoes-color-surface-inverse-active": "#12141d", - "echoes-color-surface-disabled": "#eff2f9", + "echoes-color-surface-disabled": "#f4f4f4", "echoes-color-overlays-back-drop-default": "#08090c73", "echoes-color-overlays-disabled": "#eff2f9", - "echoes-color-text-strong": "#1d212f", - "echoes-color-text-default": "#3e4357", - "echoes-color-text-disabled": "#a6adc2", - "echoes-color-text-placeholder": "#637192", - "echoes-color-text-subtle": "#637192", - "echoes-color-text-on-color": "#ffffff", + "echoes-color-text-strong": "#1a1a1a", + "echoes-color-text-default": "#4a4a4a", + "echoes-color-text-disabled": "#5a5a5a", + "echoes-color-text-placeholder": "#4a4a4a", + "echoes-color-text-subtle": "#4a4a4a", + "echoes-color-text-on-color": "#fcfcfc", + "echoes-color-text-on-action": "#fcfcfc", "echoes-color-text-on-color-inverse": "#3e4357", - "echoes-color-text-accent": "#5d6cd0", + "echoes-color-text-accent": "#1a1a1a", "echoes-color-text-danger": "#b42318", "echoes-color-text-warning": "#8c5e1e", "echoes-color-text-success": "#537c17", "echoes-color-text-info": "#316c92", - "echoes-color-text-emphasis": "#7934c7", - "echoes-color-text-link-hover": "#4b56bb", - "echoes-color-icon-bold": "#1d212f", - "echoes-color-icon-default": "#3e4357", - "echoes-color-icon-subtle": "#637192", - "echoes-color-icon-disabled": "#a6adc2", - "echoes-color-icon-placeholder": "#637192", - "echoes-color-icon-accent": "#5d6cd0", + "echoes-color-text-emphasis": "#0c51a0", + "echoes-color-text-link-hover": "#3a3a3a", + "echoes-color-icon-bold": "#1a1a1a", + "echoes-color-icon-default": "#4a4a4a", + "echoes-color-icon-subtle": "#4a4a4a", + "echoes-color-icon-disabled": "#5a5a5a", + "echoes-color-icon-placeholder": "#4a4a4a", + "echoes-color-icon-accent": "#1a1a1a", "echoes-color-icon-danger": "#d92d20", "echoes-color-icon-warning": "#ae7a29", "echoes-color-icon-success": "#82b73c", "echoes-color-icon-info": "#4595cb", - "echoes-color-icon-on-color": "#ffffff", + "echoes-color-icon-on-color": "#fcfcfc", "echoes-color-icon-on-color-inverse": "#3e4357", - "echoes-color-icon-selected": "#5d6cd0", - "echoes-color-icon-emphasis": "#7934c7", - "echoes-color-border-bolder": "#637192", - "echoes-color-border-bold": "#c5cddf", - "echoes-color-border-weak": "#e1e6f3", - "echoes-color-border-weaker": "#eff2f9", - "echoes-color-border-disabled": "#c5cddf", - "echoes-color-border-accent-default": "#5d6cd0", + "echoes-color-icon-selected": "#126ed3", + "echoes-color-icon-emphasis": "#0c51a0", + "echoes-color-border-bolder": "#5a5a5a", + "echoes-color-border-bold": "#d4d4d4", + "echoes-color-border-weak": "#e0e0e0", + "echoes-color-border-weaker": "#e8e8e8", + "echoes-color-border-disabled": "#d4d4d4", + "echoes-color-border-accent-default": "#1a1a1a", + "echoes-color-border-action-neutral": "#1a1a1a", "echoes-color-border-danger-weak": "#fee4e2", "echoes-color-border-danger-default": "#d92d20", "echoes-color-border-none": "#00000000", @@ -125,7 +217,7 @@ "echoes-color-border-success-default": "#75a92c", "echoes-color-border-warning-weak": "#fef5d0", "echoes-color-border-info-weak": "#e9f4fb", - "echoes-color-border-emphasis-weak": "#ede2ff", + "echoes-color-border-emphasis-weak": "#a9cdf2", "echoes-color-code-background-default": "#fcfcfd", "echoes-color-code-background-highlight": "#c5cddf", "echoes-color-code-border-default": "#e1e6f3", @@ -138,7 +230,7 @@ "echoes-color-code-text-string": "#247523", "echoes-color-code-text-keyword-subtle": "#1e1ead", "echoes-color-code-text-preprocessing-directive": "#347235", - "echoes-color-focus-default": "#4b56bb", + "echoes-color-focus-default": "#1a1a1a", "echoes-color-charts-categorical-1": "#3b82d4", "echoes-color-charts-categorical-2": "#d74a78", "echoes-color-charts-categorical-3": "#0f9383", @@ -158,12 +250,44 @@ "echoes-box-shadow-medium": "0 2px 15px -2px #1d212f0f, 0 4px 8px -2px #1d212f1a", "echoes-box-shadow-large": "0 4px 6px -2px #1d212f0d, 0 12px 16px -4px #1d212f1a", "echoes-box-shadow-x-large": "0 8px 8px -4px #1d212f0a, 15px 20px 24px -4px #1d212f1a", + "echoes-button-colors-background-default": "#1a1a1a", + "echoes-button-colors-background-hover": "#3a3a3a", + "echoes-button-colors-background-active": "#4a4a4a", + "echoes-button-colors-background-disabled": "#f4f4f4", + "echoes-button-colors-border-default": "#1a1a1a", + "echoes-button-colors-text-default": "#fcfcfc", + "echoes-button-colors-text-disabled": "#5a5a5a", + "echoes-button-colors-focus": "#1a1a1a", + "echoes-input-colors-background-default": "#fcfcfc", + "echoes-input-colors-background-hover": "#00000008", + "echoes-input-colors-background-disabled": "#f4f4f4", + "echoes-input-colors-border-default": "#5a5a5a", + "echoes-input-colors-border-focus": "#1a1a1a", + "echoes-input-colors-border-disabled": "#d4d4d4", + "echoes-input-colors-text-default": "#1a1a1a", + "echoes-input-colors-text-placeholder": "#4a4a4a", + "echoes-input-colors-text-disabled": "#5a5a5a", + "echoes-input-colors-focus": "#1a1a1a", + "echoes-navigation-item-colors-background-default": "#fcfcfc", + "echoes-navigation-item-colors-background-hover": "#00000008", + "echoes-navigation-item-colors-background-selected": "#e8f1fc", + "echoes-navigation-item-colors-background-selected-hover": "#dcebfa", + "echoes-navigation-item-colors-text-default": "#1a1a1a", + "echoes-navigation-item-colors-text-selected": "#0c51a0", + "echoes-navigation-item-colors-icon-default": "#4a4a4a", + "echoes-navigation-item-colors-icon-selected": "#126ed3", + "echoes-navigation-item-colors-focus": "#1a1a1a", + "echoes-issue-row-colors-background-default": "#fcfcfc", + "echoes-issue-row-colors-background-hover": "#00000008", + "echoes-issue-row-colors-background-selected": "#e8f1fc", + "echoes-issue-row-colors-background-selected-hover": "#dcebfa", + "echoes-issue-row-colors-border": "#e0e0e0", "echoes-bottom-scroll-colors-shadow-gradient": "#00000033", - "echoes-form-control-colors-background-default": "#ffffff", - "echoes-form-control-colors-background-hover": "#f6f7fb", - "echoes-form-control-colors-border-default": "#637192", - "echoes-form-control-colors-border-focus": "#e1e6f3", - "echoes-form-control-colors-icon-default": "#637192", + "echoes-form-control-colors-background-default": "#fcfcfc", + "echoes-form-control-colors-background-hover": "#00000008", + "echoes-form-control-colors-border-default": "#5a5a5a", + "echoes-form-control-colors-border-focus": "#e0e0e0", + "echoes-form-control-colors-icon-default": "#4a4a4a", "echoes-logos-colors-text": "#290042", "echoes-logos-colors-brand": "#126ed3", "echoes-logos-colors-sonar-whale": "#d3121d", diff --git a/src/utils/__tests__/color-system-pilot-test.ts b/src/utils/__tests__/color-system-pilot-test.ts new file mode 100644 index 000000000..1afcef2cf --- /dev/null +++ b/src/utils/__tests__/color-system-pilot-test.ts @@ -0,0 +1,287 @@ +/* + * Echoes React + * Copyright (C) 2023-2025 SonarSource Sàrl + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { readFileSync } from 'node:fs'; + +const lightTheme = readFileSync('src/generated/design-tokens-light.css', 'utf8'); +const darkTheme = readFileSync('src/generated/design-tokens-dark.css', 'utf8'); + +function channelToLinear(channel: number) { + const normalized = channel / 255; + return normalized <= 0.04045 ? normalized / 12.92 : ((normalized + 0.055) / 1.055) ** 2.4; +} + +function luminance(hex: string) { + const channels = [1, 3, 5].map((index) => + channelToLinear(Number.parseInt(hex.slice(index, index + 2), 16)), + ); + return 0.2126 * channels[0] + 0.7152 * channels[1] + 0.0722 * channels[2]; +} + +function contrastRatio(foreground: string, background: string) { + const values = [luminance(foreground), luminance(background)].sort((a, b) => b - a); + return (values[0] + 0.05) / (values[1] + 0.05); +} + +function hexToOklch(hex: string) { + const [red, green, blue] = [1, 3, 5].map((index) => + channelToLinear(Number.parseInt(hex.slice(index, index + 2), 16)), + ); + const l = Math.cbrt(0.4122214708 * red + 0.5363325363 * green + 0.0514459929 * blue); + const m = Math.cbrt(0.2119034982 * red + 0.6806995451 * green + 0.1073969566 * blue); + const s = Math.cbrt(0.0883024619 * red + 0.2817188376 * green + 0.6299787005 * blue); + const lightness = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s; + const a = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s; + const b = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s; + const hue = (Math.atan2(b, a) * 180) / Math.PI; + + return { + chroma: Math.sqrt(a ** 2 + b ** 2), + hue: hue < 0 ? hue + 360 : hue, + lightness, + }; +} + +function hueSpread(hues: number[]) { + const sorted = [...hues].sort((a, b) => a - b); + const gaps = sorted.map((hue, index) => { + const next = sorted[(index + 1) % sorted.length]; + return index === sorted.length - 1 ? next + 360 - hue : next - hue; + }); + return 360 - Math.max(...gaps); +} + +function oklabDistance(first: string, second: string) { + const toLab = (hex: string) => { + const { chroma, hue, lightness } = hexToOklch(hex); + const hueInRadians = (hue * Math.PI) / 180; + return [lightness, chroma * Math.cos(hueInRadians), chroma * Math.sin(hueInRadians)]; + }; + const firstLab = toLab(first); + const secondLab = toLab(second); + + return Math.sqrt( + firstLab.reduce((sum, channel, index) => sum + (channel - secondLab[index]) ** 2, 0), + ); +} + +function token(css: string, name: string) { + const match = css.match(new RegExp(`--echoes-${name}: (#[0-9a-f]{6,8});`)); + if (!match) { + throw new Error(`Missing generated token: ${name}`); + } + return match[1]; +} + +describe.each([ + [ + 'light', + lightTheme, + { + actionActive: 'color-palette-ui-gray-10', + actionDefault: 'color-palette-ui-gray-12', + actionHover: 'color-palette-ui-gray-11', + actionText: 'color-palette-ui-gray-1', + buttonBorder: 'color-palette-ui-gray-12', + }, + ], + [ + 'dark', + darkTheme, + { + actionActive: 'color-palette-ui-gray-7', + actionDefault: 'color-palette-ui-gray-2', + actionHover: 'color-palette-ui-gray-6', + actionText: 'color-palette-ui-gray-12', + buttonBorder: 'color-palette-ui-gray-9', + }, + ], +])('12-step color pilot: %s theme', (themeName, theme, expected) => { + it('preserves every Gray Alpha step as eight-digit hexadecimal', () => { + for (let step = 1; step <= 12; step += 1) { + expect(token(theme, `color-palette-ui-gray-alpha-${step}`)).toMatch(/^#[0-9a-f]{8}$/); + } + }); + + it('keeps opaque scales monotonic in OKLCH lightness', () => { + for (const palette of ['gray', 'brand-blue', 'success-green', 'warning-yellow', 'danger-red']) { + const lightness = Array.from( + { length: 12 }, + (_, index) => + hexToOklch(token(theme, `color-palette-ui-${palette}-${index + 1}`)).lightness, + ); + + const isMonotonic = lightness.every( + (value, index) => + index === 0 || + (themeName === 'light' ? value < lightness[index - 1] : value > lightness[index - 1]), + ); + + expect(isMonotonic).toBe(true); + } + }); + + it('keeps Brand Blue hue-stable with peak chroma at step 9', () => { + const blue = Array.from({ length: 12 }, (_, index) => + hexToOklch(token(theme, `color-palette-ui-brand-blue-${index + 1}`)), + ); + + expect(hueSpread(blue.map(({ hue }) => hue))).toBeLessThanOrEqual(10); + expect( + blue.findIndex(({ chroma }) => chroma === Math.max(...blue.map((color) => color.chroma))), + ).toBe(8); + }); + + it('keeps sentiment hues stable with peak chroma at step 9', () => { + for (const palette of ['success-green', 'warning-yellow', 'danger-red']) { + const colors = Array.from({ length: 12 }, (_, index) => + hexToOklch(token(theme, `color-palette-ui-${palette}-${index + 1}`)), + ); + const visibleHues = colors.filter(({ chroma }) => chroma >= 0.01).map(({ hue }) => hue); + + expect(hueSpread(visibleHues)).toBeLessThanOrEqual(10); + expect( + colors.findIndex( + ({ chroma }) => chroma === Math.max(...colors.map((color) => color.chroma)), + ), + ).toBe(8); + expect( + contrastRatio( + token(theme, `color-palette-ui-${palette}-9`), + token(theme, 'color-surface-default'), + ), + ).toBeGreaterThanOrEqual(4.5); + } + }); + + it('keeps data visualization colors visible and distinguishable', () => { + const categorical = Array.from({ length: 8 }, (_, index) => + token(theme, `color-palette-ui-data-viz-categorical-${index + 1}`), + ); + const severity = ['blocker', 'high', 'medium', 'low', 'info'].map((level) => + token(theme, `color-palette-ui-data-viz-severity-${level}`), + ); + const canvas = token(theme, 'color-surface-canvas-default'); + + for (const color of [ + ...categorical, + ...severity, + token(theme, 'color-palette-ui-data-viz-placeholder-default'), + ]) { + expect(contrastRatio(color, canvas)).toBeGreaterThanOrEqual(3); + } + + const pairDistances = categorical.flatMap((color, index) => + categorical.slice(index + 1).map((otherColor) => oklabDistance(color, otherColor)), + ); + expect(Math.min(...pairDistances)).toBeGreaterThanOrEqual(0.08); + }); + + it('meets WCAG 2.2 AA for component text pairs', () => { + expect( + contrastRatio(token(theme, 'color-text-strong'), token(theme, 'color-surface-default')), + ).toBeGreaterThanOrEqual(4.5); + expect( + contrastRatio(token(theme, 'color-text-default'), token(theme, 'color-surface-default')), + ).toBeGreaterThanOrEqual(4.5); + expect( + contrastRatio( + token(theme, 'button-colors-text-default'), + token(theme, 'button-colors-background-default'), + ), + ).toBeGreaterThanOrEqual(4.5); + expect( + contrastRatio( + token(theme, 'navigation-item-colors-text-selected'), + token(theme, 'navigation-item-colors-background-selected'), + ), + ).toBeGreaterThanOrEqual(4.5); + }); + + it('meets 3:1 non-text and focus-indicator contrast', () => { + expect( + contrastRatio( + token(theme, 'input-colors-border-default'), + token(theme, 'input-colors-background-default'), + ), + ).toBeGreaterThanOrEqual(3); + expect( + contrastRatio( + token(theme, 'button-colors-border-default'), + token(theme, 'color-surface-default'), + ), + ).toBeGreaterThanOrEqual(3); + expect( + contrastRatio( + token(theme, 'button-colors-focus'), + token(theme, 'color-surface-canvas-default'), + ), + ).toBeGreaterThanOrEqual(3); + expect( + contrastRatio( + token(theme, 'navigation-item-colors-focus'), + token(theme, 'navigation-item-colors-background-selected'), + ), + ).toBeGreaterThanOrEqual(3); + }); + + it('resolves near-black neutral actions through semantic and component roles', () => { + expect(token(theme, 'color-background-action-neutral-default')).toBe( + token(theme, expected.actionDefault), + ); + expect(token(theme, 'color-background-action-neutral-hover')).toBe( + token(theme, expected.actionHover), + ); + expect(token(theme, 'color-background-action-neutral-active')).toBe( + token(theme, expected.actionActive), + ); + expect(token(theme, 'color-text-on-action')).toBe(token(theme, expected.actionText)); + expect(token(theme, 'color-border-action-neutral')).toBe(token(theme, expected.buttonBorder)); + + expect(token(theme, 'button-colors-background-default')).toBe( + token(theme, 'color-background-action-neutral-default'), + ); + expect(token(theme, 'button-colors-text-default')).toBe(token(theme, 'color-text-on-action')); + expect(token(theme, 'button-colors-border-default')).toBe( + token(theme, 'color-border-action-neutral'), + ); + + expect(token(theme, 'color-background-accent-default')).toBe( + token(theme, 'color-background-action-neutral-default'), + ); + }); + + it('keeps non-action accent roles neutral and reserves Brand Blue for emphasis', () => { + expect(token(theme, 'color-text-accent')).toBe(token(theme, 'color-palette-ui-gray-12')); + expect(token(theme, 'color-icon-accent')).toBe(token(theme, 'color-palette-ui-gray-12')); + expect(token(theme, 'color-focus-default')).toBe(token(theme, 'color-palette-ui-gray-12')); + + expect(token(theme, 'color-background-emphasis-default')).toBe( + token(theme, 'color-palette-ui-brand-blue-9'), + ); + expect(token(theme, 'color-text-emphasis')).toBe( + token(theme, 'color-palette-ui-brand-blue-11'), + ); + expect([ + token(theme, 'color-palette-ui-brand-blue-9'), + token(theme, 'color-palette-ui-brand-blue-10'), + ]).toContain(token(theme, 'color-icon-selected')); + }); +}); diff --git a/src/utils/design-tokens.ts b/src/utils/design-tokens.ts index 604d19a69..e647f9c15 100644 --- a/src/utils/design-tokens.ts +++ b/src/utils/design-tokens.ts @@ -23,8 +23,9 @@ import designTokensBase from '~generated/design-tokens-base.json'; import { DesignTokens, DesignTokensBase, WithoutEchoesPrefix } from '~types/design-tokens'; export type EchoesDesignTokens = WithoutEchoesPrefix; -export type EchoesCSSVarString = `var(--echoes-${EchoesDesignTokens})`; -export type EchoesCSSVarStringWithFallback = `var(--echoes-${EchoesDesignTokens}, ${string})`; +export type EchoesCSSVarString = `var(--echoes-${T})`; +export type EchoesCSSVarStringWithFallback = + `var(--echoes-${T}, ${string})`; /** * Type-safe helper function to create CSS variable references for echoes design tokens. @@ -54,12 +55,15 @@ export type EchoesCSSVarStringWithFallback = `var(--echoes-${EchoesDesignTokens} * }); * ``` */ -export function cssVar(token: EchoesDesignTokens): EchoesCSSVarString; -export function cssVar(token: EchoesDesignTokens, fallback: string): EchoesCSSVarStringWithFallback; -export function cssVar( - token: EchoesDesignTokens, +export function cssVar(token: T): EchoesCSSVarString; +export function cssVar( + token: T, + fallback: string, +): EchoesCSSVarStringWithFallback; +export function cssVar( + token: T, fallback?: string, -): EchoesCSSVarString | EchoesCSSVarStringWithFallback { +): EchoesCSSVarString | EchoesCSSVarStringWithFallback { const variableName = `--echoes-${token}` as const; return isStringDefined(fallback) ? `var(${variableName}, ${fallback})` : `var(${variableName})`; } diff --git a/stories/design-tokens/ColorSystemPilot-stories.tsx b/stories/design-tokens/ColorSystemPilot-stories.tsx new file mode 100644 index 000000000..85865528f --- /dev/null +++ b/stories/design-tokens/ColorSystemPilot-stories.tsx @@ -0,0 +1,685 @@ +/* + * Echoes React + * Copyright (C) 2023-2025 SonarSource Sàrl + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import styled from '@emotion/styled'; +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { Button, ButtonVariety, TextInput, Theme, ThemeProvider, cssVar } from '../../src'; + +const meta: Meta = { + title: 'Design Tokens/12-step color pilot', + parameters: { layout: 'fullscreen' }, +}; + +export default meta; + +type Story = StoryObj; + +const THEMES = [Theme.light, Theme.dark] as const; +const STATES = ['Default', 'Hover', 'Active', 'Focus', 'Selected', 'Disabled'] as const; +const ALPHA_BACKGROUNDS = [ + ['White', 'color-roles-support-white', 'color-roles-support-black'], + ['Neutral', 'color-palette-ui-gray-5', 'color-text-strong'], + ['Tinted', 'color-palette-ui-brand-blue-3', 'color-text-strong'], + ['Brand', 'color-palette-ui-brand-blue-9', 'color-text-on-color'], +] as const; +const PALETTE_ROLE_GUIDANCE = [ + { + palette: 'Chromatic', + step9: 'Solid accent', + step10: 'Hovered accent', + note: 'Use for brand and sentiment fills when the semantic role calls for color.', + }, + { + palette: 'Neutral', + step9: 'Mid-contrast fill', + step10: 'Hovered fill', + note: 'High-contrast neutral actions may use step 12 through semantic and component tokens.', + }, + { + palette: 'Alpha', + step9: 'Strong overlay', + step10: 'Stronger overlay', + note: 'Alpha values remain overlays whose result depends on the underlying surface.', + }, +] as const; + +const SENTIMENT_PALETTES = [ + { + label: 'Success green', + tokens: [ + 'color-palette-ui-success-green-1', + 'color-palette-ui-success-green-2', + 'color-palette-ui-success-green-3', + 'color-palette-ui-success-green-4', + 'color-palette-ui-success-green-5', + 'color-palette-ui-success-green-6', + 'color-palette-ui-success-green-7', + 'color-palette-ui-success-green-8', + 'color-palette-ui-success-green-9', + 'color-palette-ui-success-green-10', + 'color-palette-ui-success-green-11', + 'color-palette-ui-success-green-12', + ], + }, + { + label: 'Warning yellow', + tokens: [ + 'color-palette-ui-warning-yellow-1', + 'color-palette-ui-warning-yellow-2', + 'color-palette-ui-warning-yellow-3', + 'color-palette-ui-warning-yellow-4', + 'color-palette-ui-warning-yellow-5', + 'color-palette-ui-warning-yellow-6', + 'color-palette-ui-warning-yellow-7', + 'color-palette-ui-warning-yellow-8', + 'color-palette-ui-warning-yellow-9', + 'color-palette-ui-warning-yellow-10', + 'color-palette-ui-warning-yellow-11', + 'color-palette-ui-warning-yellow-12', + ], + }, + { + label: 'Danger red', + tokens: [ + 'color-palette-ui-danger-red-1', + 'color-palette-ui-danger-red-2', + 'color-palette-ui-danger-red-3', + 'color-palette-ui-danger-red-4', + 'color-palette-ui-danger-red-5', + 'color-palette-ui-danger-red-6', + 'color-palette-ui-danger-red-7', + 'color-palette-ui-danger-red-8', + 'color-palette-ui-danger-red-9', + 'color-palette-ui-danger-red-10', + 'color-palette-ui-danger-red-11', + 'color-palette-ui-danger-red-12', + ], + }, +] as const; + +const DATA_VIZ_CATEGORICAL = [ + 'color-palette-ui-data-viz-categorical-1', + 'color-palette-ui-data-viz-categorical-2', + 'color-palette-ui-data-viz-categorical-3', + 'color-palette-ui-data-viz-categorical-4', + 'color-palette-ui-data-viz-categorical-5', + 'color-palette-ui-data-viz-categorical-6', + 'color-palette-ui-data-viz-categorical-7', + 'color-palette-ui-data-viz-categorical-8', +] as const; + +const DATA_VIZ_SEVERITY = [ + ['Blocker', 'color-palette-ui-data-viz-severity-blocker'], + ['High', 'color-palette-ui-data-viz-severity-high'], + ['Medium', 'color-palette-ui-data-viz-severity-medium'], + ['Low', 'color-palette-ui-data-viz-severity-low'], + ['Info', 'color-palette-ui-data-viz-severity-info'], +] as const; + +function Workflow({ theme }: Readonly<{ theme: `${Theme}` }>) { + return ( + + + {theme} theme + + + acme-frontend + Overview + + Issues + + Measures + + +
+
+
+ New code issues + Review issues introduced by pull request #482. +
+ +
+ + + + + + + Issue + File + Status + + + + + Avoid duplicated string literals + src/api/client.ts + Open + + + Refactor this function to reduce complexity + src/auth/session.ts + Selected + + + Remove this unused import + src/App.tsx + Open + + + +
+
+ + Step 9 and 10 guidance + + Palette steps are landmarks, not component contracts. Buttons resolve through neutral + action semantics instead of binding directly to a numbered palette value. + + + {PALETTE_ROLE_GUIDANCE.map(({ note, palette, step10, step9 }) => ( + + {palette} + 9 · {step9} + 10 · {step10} + {note} + + ))} + + + Interaction states + + {STATES.map((state) => ( + + {state} + + ))} + + + Gray Alpha over representative surfaces + + {ALPHA_BACKGROUNDS.map(([label, token, foreground]) => ( + + {label} + + ))} + +
+
+ ); +} + +function SentimentAndDataVizProposal({ theme }: Readonly<{ theme: `${Theme}` }>) { + return ( + + + {theme} theme + + OKLCH-derived candidates. Existing sentiment semantics and chart tokens remain unchanged + until this proposal is approved. + + + Sentiment scales + + {SENTIMENT_PALETTES.map(({ label, tokens }) => ( + + {label} + + {tokens.map((token, index) => ( + + + {index + 1} + + ))} + + + ))} + + + Categorical data visualization + + + {DATA_VIZ_CATEGORICAL.map((token, index) => ( + + ))} + + + {DATA_VIZ_CATEGORICAL.map((token, index) => ( + + + Series {index + 1} + + ))} + + + + Severity data visualization + + {DATA_VIZ_SEVERITY.map(([label, token]) => ( + + + {label} + + ))} + + + Placeholder + + + + + ); +} + +export const WorkflowAndStates: Story = { + render: () => ( + + {THEMES.map((theme) => ( + + ))} + + ), +}; + +export const SentimentAndDataVisualization: Story = { + render: () => ( + + {THEMES.map((theme) => ( + + ))} + + ), +}; + +const Comparison = styled.div` + display: grid; + grid-template-columns: repeat(auto-fit, minmax(${cssVar('dimension-width-5000')}, 1fr)); + min-height: 100vh; +`; +Comparison.displayName = 'Comparison'; + +const ThemePanel = styled.section` + padding: ${cssVar('dimension-space-400')}; + color: ${cssVar('color-text-strong')}; + background: ${cssVar('color-surface-canvas-default')}; +`; +ThemePanel.displayName = 'ThemePanel'; + +const ThemeHeading = styled.h2` + margin: 0 0 ${cssVar('dimension-space-200')}; + font: ${cssVar('typography-heading-medium')}; + text-transform: capitalize; +`; +ThemeHeading.displayName = 'ThemeHeading'; + +const Workspace = styled.div` + display: grid; + grid-template-columns: ${cssVar('dimension-width-800')} 1fr; + overflow: hidden; + border: ${cssVar('border-width-default')} solid ${cssVar('color-border-bold')}; + border-radius: ${cssVar('border-radius-400')}; + background: ${cssVar('color-surface-default')}; +`; +Workspace.displayName = 'Workspace'; + +const Navigation = styled.nav` + display: flex; + flex-direction: column; + gap: ${cssVar('dimension-space-50')}; + padding: ${cssVar('dimension-space-150')}; + border-right: ${cssVar('border-width-default')} solid ${cssVar('color-border-weak')}; +`; +Navigation.displayName = 'Navigation'; + +const ProjectName = styled.strong` + margin-bottom: ${cssVar('dimension-space-100')}; + font: ${cssVar('typography-text-default-semi-bold')}; +`; +ProjectName.displayName = 'ProjectName'; + +const NavigationItem = styled.a` + padding: ${cssVar('dimension-space-100')}; + border-radius: ${cssVar('border-radius-400')}; + color: ${cssVar('navigation-item-colors-text-default')}; + font: ${cssVar('typography-text-default-regular')}; + text-decoration: none; + + &:hover { + background: ${cssVar('navigation-item-colors-background-hover')}; + } + + &[aria-current='page'] { + color: ${cssVar('navigation-item-colors-text-selected')}; + background: ${cssVar('navigation-item-colors-background-selected')}; + font: ${cssVar('typography-text-default-semi-bold')}; + } + + &:focus-visible { + outline: ${cssVar('focus-border-width-default')} solid ${cssVar('navigation-item-colors-focus')}; + outline-offset: ${cssVar('focus-border-offset-default')}; + } +`; +NavigationItem.displayName = 'NavigationItem'; + +const Main = styled.main` + display: flex; + flex-direction: column; + gap: ${cssVar('dimension-space-200')}; + padding: ${cssVar('dimension-space-300')}; +`; +Main.displayName = 'Main'; + +const Header = styled.header` + display: flex; + align-items: start; + justify-content: space-between; + gap: ${cssVar('dimension-space-200')}; +`; +Header.displayName = 'Header'; + +const Title = styled.h3` + margin: 0; + font: ${cssVar('typography-heading-small')}; +`; +Title.displayName = 'Title'; + +const SupportingText = styled.p` + margin: ${cssVar('dimension-space-50')} 0 0; + color: ${cssVar('color-text-default')}; + font: ${cssVar('typography-text-default-regular')}; +`; +SupportingText.displayName = 'SupportingText'; + +const IssueTable = styled.table` + border-collapse: collapse; + color: ${cssVar('color-text-strong')}; + font: ${cssVar('typography-text-default-regular')}; +`; +IssueTable.displayName = 'IssueTable'; + +const ColumnHeader = styled.th` + padding: ${cssVar('dimension-space-100')}; + border-bottom: ${cssVar('border-width-default')} solid ${cssVar('issue-row-colors-border')}; + text-align: left; +`; +ColumnHeader.displayName = 'ColumnHeader'; + +const IssueRow = styled.tr` + background: ${cssVar('issue-row-colors-background-default')}; + + &:hover { + background: ${cssVar('issue-row-colors-background-hover')}; + } + + &[data-selected='true'] { + background: ${cssVar('issue-row-colors-background-selected')}; + } +`; +IssueRow.displayName = 'IssueRow'; + +const Cell = styled.td` + padding: ${cssVar('dimension-space-100')}; + border-bottom: ${cssVar('border-width-default')} solid ${cssVar('issue-row-colors-border')}; +`; +Cell.displayName = 'Cell'; + +const SectionHeading = styled.h3` + margin: ${cssVar('dimension-space-300')} 0 ${cssVar('dimension-space-100')}; + font: ${cssVar('typography-heading-xsmall')}; +`; +SectionHeading.displayName = 'SectionHeading'; + +const GuidanceText = styled.p` + margin: 0 0 ${cssVar('dimension-space-150')}; + color: ${cssVar('color-text-default')}; + font: ${cssVar('typography-text-default-regular')}; +`; +GuidanceText.displayName = 'GuidanceText'; + +const GuidanceGrid = styled.div` + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: ${cssVar('dimension-space-100')}; +`; +GuidanceGrid.displayName = 'GuidanceGrid'; + +const GuidanceCard = styled.div` + display: flex; + flex-direction: column; + gap: ${cssVar('dimension-space-50')}; + padding: ${cssVar('dimension-space-150')}; + border: ${cssVar('border-width-default')} solid ${cssVar('color-border-weak')}; + border-radius: ${cssVar('border-radius-400')}; + background: ${cssVar('color-surface-default')}; +`; +GuidanceCard.displayName = 'GuidanceCard'; + +const GuidanceTitle = styled.strong` + font: ${cssVar('typography-text-default-semi-bold')}; +`; +GuidanceTitle.displayName = 'GuidanceTitle'; + +const GuidanceRole = styled.span` + color: ${cssVar('color-text-strong')}; + font: ${cssVar('typography-text-small-semi-bold')}; +`; +GuidanceRole.displayName = 'GuidanceRole'; + +const GuidanceNote = styled.span` + color: ${cssVar('color-text-default')}; + font: ${cssVar('typography-text-small-regular')}; +`; +GuidanceNote.displayName = 'GuidanceNote'; + +const StateGrid = styled.div` + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: ${cssVar('dimension-space-100')}; +`; +StateGrid.displayName = 'StateGrid'; + +const StateExample = styled.button` + padding: ${cssVar('dimension-space-100')}; + border: ${cssVar('border-width-default')} solid ${cssVar('button-colors-border-default')}; + border-radius: ${cssVar('border-radius-400')}; + color: ${cssVar('button-colors-text-default')}; + background: ${cssVar('button-colors-background-default')}; + font: ${cssVar('typography-others-label')}; + + &[data-state='hover'] { + background: ${cssVar('button-colors-background-hover')}; + } + &[data-state='active'] { + background: ${cssVar('button-colors-background-active')}; + } + &[data-state='focus'] { + outline: ${cssVar('focus-border-width-default')} solid ${cssVar('button-colors-focus')}; + outline-offset: ${cssVar('focus-border-offset-default')}; + } + &[data-state='selected'] { + color: ${cssVar('navigation-item-colors-text-selected')}; + background: ${cssVar('navigation-item-colors-background-selected')}; + } + &[data-state='disabled'] { + color: ${cssVar('button-colors-text-disabled')}; + background: ${cssVar('button-colors-background-disabled')}; + } +`; +StateExample.displayName = 'StateExample'; + +const AlphaGrid = styled.div` + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: ${cssVar('dimension-space-100')}; +`; +AlphaGrid.displayName = 'AlphaGrid'; + +const AlphaSurface = styled.div` + min-height: ${cssVar('dimension-height-1000')}; + padding: ${cssVar('dimension-space-100')}; + border: ${cssVar('border-width-default')} solid ${cssVar('color-border-bold')}; + border-radius: ${cssVar('border-radius-400')}; +`; +AlphaSurface.displayName = 'AlphaSurface'; + +const AlphaOverlay = styled.div` + display: flex; + align-items: center; + justify-content: center; + height: 100%; + background: ${cssVar('color-palette-ui-gray-alpha-6')}; + font: ${cssVar('typography-text-default-semi-bold')}; +`; +AlphaOverlay.displayName = 'AlphaOverlay'; + +const PaletteCollection = styled.div` + display: grid; + gap: ${cssVar('dimension-space-150')}; +`; +PaletteCollection.displayName = 'PaletteCollection'; + +const PaletteCard = styled.div` + display: grid; + gap: ${cssVar('dimension-space-100')}; + padding: ${cssVar('dimension-space-150')}; + border: ${cssVar('border-width-default')} solid ${cssVar('color-border-weak')}; + border-radius: ${cssVar('border-radius-400')}; + background: ${cssVar('color-surface-default')}; +`; +PaletteCard.displayName = 'PaletteCard'; + +const PaletteScale = styled.div` + display: grid; + grid-template-columns: repeat(12, minmax(0, 1fr)); + gap: ${cssVar('dimension-space-50')}; +`; +PaletteScale.displayName = 'PaletteScale'; + +const PaletteStep = styled.div` + display: grid; + gap: ${cssVar('dimension-space-50')}; +`; +PaletteStep.displayName = 'PaletteStep'; + +const PaletteSwatch = styled.div` + aspect-ratio: 1; + border: ${cssVar('border-width-default')} solid ${cssVar('color-border-weak')}; + border-radius: ${cssVar('border-radius-200')}; +`; +PaletteSwatch.displayName = 'PaletteSwatch'; + +const PaletteStepLabel = styled.span` + color: ${cssVar('color-text-default')}; + font: ${cssVar('typography-text-small-regular')}; + text-align: center; +`; +PaletteStepLabel.displayName = 'PaletteStepLabel'; + +const ChartCard = styled.div` + display: grid; + gap: ${cssVar('dimension-space-200')}; + padding: ${cssVar('dimension-space-200')}; + border: ${cssVar('border-width-default')} solid ${cssVar('color-border-weak')}; + border-radius: ${cssVar('border-radius-400')}; + background: ${cssVar('color-surface-default')}; +`; +ChartCard.displayName = 'ChartCard'; + +const ChartBars = styled.div` + display: grid; + grid-template-columns: repeat(8, 1fr); + align-items: end; + gap: ${cssVar('dimension-space-100')}; + height: calc(${cssVar('dimension-height-1000')} * 4); + padding: ${cssVar('dimension-space-100')}; + border-bottom: ${cssVar('border-width-default')} solid ${cssVar('color-border-bold')}; +`; +ChartBars.displayName = 'ChartBars'; + +const ChartBar = styled.div` + min-height: ${cssVar('dimension-height-200')}; + border-radius: ${cssVar('border-radius-200')} ${cssVar('border-radius-200')} 0 0; +`; +ChartBar.displayName = 'ChartBar'; + +const ChartLegend = styled.div` + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: ${cssVar('dimension-space-100')}; +`; +ChartLegend.displayName = 'ChartLegend'; + +const ChartLegendItem = styled.span` + display: flex; + align-items: center; + gap: ${cssVar('dimension-space-50')}; + color: ${cssVar('color-text-default')}; + font: ${cssVar('typography-text-small-regular')}; +`; +ChartLegendItem.displayName = 'ChartLegendItem'; + +const LegendSwatch = styled.span` + width: ${cssVar('dimension-width-100')}; + height: ${cssVar('dimension-height-100')}; + border-radius: ${cssVar('border-radius-full')}; +`; +LegendSwatch.displayName = 'LegendSwatch'; + +const SeverityGrid = styled.div` + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: ${cssVar('dimension-space-100')}; +`; +SeverityGrid.displayName = 'SeverityGrid'; + +const SeverityItem = styled.div` + display: flex; + align-items: center; + gap: ${cssVar('dimension-space-100')}; + padding: ${cssVar('dimension-space-150')}; + border: ${cssVar('border-width-default')} solid ${cssVar('color-border-weak')}; + border-radius: ${cssVar('border-radius-400')}; + color: ${cssVar('color-text-strong')}; + background: ${cssVar('color-surface-default')}; + font: ${cssVar('typography-text-default-semi-bold')}; +`; +SeverityItem.displayName = 'SeverityItem'; + +const SeveritySwatch = styled.span` + width: ${cssVar('dimension-width-300')}; + aspect-ratio: 1; + border-radius: ${cssVar('border-radius-200')}; +`; +SeveritySwatch.displayName = 'SeveritySwatch'; diff --git a/stories/playground/Issues-stories.tsx b/stories/playground/Issues-stories.tsx new file mode 100644 index 000000000..e3e42d1ef --- /dev/null +++ b/stories/playground/Issues-stories.tsx @@ -0,0 +1,145 @@ +/* + * Echoes React + * Copyright (C) 2023-2025 SonarSource Sàrl + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { useMemo, useState } from 'react'; +import { + Button, + ButtonVariety, + IconIssues, + IconMoreVertical, + IconOverview, + Pagination, + Table, + TableVariety, + Text, + TextInput, +} from '../../src'; +import { PlaygroundShell, PlaygroundStack, PlaygroundToolbar } from './PlaygroundShell'; + +const meta: Meta = { + title: 'Playground/Issues', + parameters: { layout: 'fullscreen' }, +}; + +export default meta; +type Story = StoryObj; + +const ISSUES = [ + { + file: 'src/auth/session.ts', + message: 'Refactor this function to reduce its Cognitive Complexity', + rule: 'typescript:S3776', + }, + { + file: 'src/api/client.ts', + message: 'Define a constant instead of duplicating this literal', + rule: 'typescript:S1192', + }, + { + file: 'src/components/Login.tsx', + message: 'Add an explicit type to this button', + rule: 'typescript:S6848', + }, + { file: 'src/App.tsx', message: 'Remove this unused import', rule: 'typescript:S1128' }, +] as const; + +export const Default: Story = { render: () => }; + +function IssuesPage() { + const [page, setPage] = useState(1); + const [query, setQuery] = useState(''); + const [selected, setSelected] = useState>({}); + const visibleIssues = useMemo( + () => + ISSUES.filter((issue) => + `${issue.message} ${issue.file}`.toLowerCase().includes(query.toLowerCase()), + ), + [query], + ); + + return ( + Refresh} + navigation={[ + { Icon: IconOverview, label: 'Overview', to: '/' }, + { Icon: IconIssues, label: 'Issues', to: '/issues' }, + ]} + productName="acme-frontend" + title="Issues"> + + + setQuery(event.target.value)} + placeholder="Search by message or file" + type="search" + value={query} + /> + {visibleIssues.length} issues on new code + + + + + + + + + + + + + + {visibleIssues.map((issue) => ( + + + setSelected((value) => ({ ...value, [issue.rule]: !value[issue.rule] })) + } + /> + + + Open + + + ))} + +
+ + + + + +
+
+ ); +} diff --git a/stories/playground/PlaygroundShell.tsx b/stories/playground/PlaygroundShell.tsx new file mode 100644 index 000000000..d8334f726 --- /dev/null +++ b/stories/playground/PlaygroundShell.tsx @@ -0,0 +1,166 @@ +/* + * Echoes React + * Copyright (C) 2023-2025 SonarSource Sàrl + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import styled from '@emotion/styled'; +import type { ComponentProps, ReactNode } from 'react'; +import { + DropdownMenu, + IconProject, + IconQuestionMark, + IconSearch, + Layout, + LogoSonarQubeServer, + cssVar, +} from '../../src'; + +interface NavigationItem { + Icon: NonNullable['Icon']>; + label: string; + to: string; +} + +interface PlaygroundShellProps { + actions?: ReactNode; + children: ReactNode; + navigation: NavigationItem[]; + productName: string; + title: string; +} + +export function PlaygroundShell({ + actions, + children, + navigation, + productName, + title, +}: Readonly) { + return ( + + + + + + + + } + name={productName} + /> + + {navigation.map(({ Icon, label, to }) => ( + + {label} + + ))} + + + + + + {actions} : undefined + } + title={{title}} + /> + {children} + + + + ); +} + +PlaygroundShell.displayName = 'PlaygroundShell'; + +function PlaygroundGlobalNavigation() { + return ( + + + + + + + Projects + Issues + Rules + + + + + + MM} + items={My account} + /> + + + ); +} + +PlaygroundGlobalNavigation.displayName = 'PlaygroundGlobalNavigation'; + +const ProjectAvatar = styled.div` + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + border-radius: ${cssVar('border-radius-400')}; + color: ${cssVar('navigation-item-colors-icon-selected')}; + background: ${cssVar('navigation-item-colors-background-selected')}; +`; +ProjectAvatar.displayName = 'ProjectAvatar'; + +const AccountAvatar = styled.span` + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + border-radius: ${cssVar('border-radius-full')}; + color: ${cssVar('color-text-on-color')}; + background: ${cssVar('color-background-accent-default')}; + font: ${cssVar('typography-text-small-semi-bold')}; +`; +AccountAvatar.displayName = 'AccountAvatar'; + +export const PlaygroundStack = styled.div` + display: flex; + flex-direction: column; + gap: ${cssVar('dimension-space-200')}; +`; +PlaygroundStack.displayName = 'PlaygroundStack'; + +export const PlaygroundToolbar = styled.div` + display: flex; + align-items: end; + justify-content: space-between; + gap: ${cssVar('dimension-space-150')}; + flex-wrap: wrap; +`; +PlaygroundToolbar.displayName = 'PlaygroundToolbar'; + +export const PlaygroundCardGrid = styled.div` + display: grid; + grid-template-columns: repeat(auto-fit, minmax(${cssVar('dimension-width-5000')}, 1fr)); + gap: ${cssVar('dimension-space-150')}; +`; +PlaygroundCardGrid.displayName = 'PlaygroundCardGrid'; diff --git a/stories/playground/PortfolioOverview-stories.tsx b/stories/playground/PortfolioOverview-stories.tsx new file mode 100644 index 000000000..dec63b669 --- /dev/null +++ b/stories/playground/PortfolioOverview-stories.tsx @@ -0,0 +1,132 @@ +/* + * Echoes React + * Copyright (C) 2023-2025 SonarSource Sàrl + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import styled from '@emotion/styled'; +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { + Button, + Card, + Heading, + IconOverview, + IconProject, + IconReports, + LinkStandalone, + Table, + TableVariety, + Text, + cssVar, +} from '../../src'; +import { PlaygroundCardGrid, PlaygroundShell, PlaygroundStack } from './PlaygroundShell'; + +const meta: Meta = { title: 'Playground/Portfolio Overview', parameters: { layout: 'fullscreen' } }; +export default meta; +type Story = StoryObj; + +export const Default: Story = { render: () => }; + +const PROJECTS = [ + { gate: 'Passed', name: 'acme-frontend', reliability: 'A', security: 'A' }, + { gate: 'Failed', name: 'payments-service', reliability: 'B', security: 'C' }, + { gate: 'Passed', name: 'identity-api', reliability: 'A', security: 'A' }, +] as const; + +function PortfolioOverviewPage() { + return ( + Add project} + navigation={[ + { Icon: IconOverview, label: 'Overview', to: '/' }, + { Icon: IconProject, label: 'Projects', to: '/projects' }, + { Icon: IconReports, label: 'Reports', to: '/reports' }, + ]} + productName="Business applications" + title="Commerce portfolio"> + + + Track release readiness across the services supporting the commerce experience. + + + + + + + + + View all projects} + title="Project health" + /> + + + + + + + + + + + + {PROJECTS.map((project) => ( + + + + {project.gate} + + + + + ))} + +
+
+
+
+
+ ); +} + +function SummaryCard({ label, value }: Readonly<{ label: string; value: string }>) { + return ( + + + + {label} + + {value} + + + + + ); +} + +SummaryCard.displayName = 'SummaryCard'; + +const Metric = styled.div` + display: flex; + flex-direction: column; + gap: ${cssVar('dimension-space-75')}; +`; +Metric.displayName = 'Metric'; diff --git a/stories/playground/ProjectSettings-stories.tsx b/stories/playground/ProjectSettings-stories.tsx new file mode 100644 index 000000000..033951e0e --- /dev/null +++ b/stories/playground/ProjectSettings-stories.tsx @@ -0,0 +1,126 @@ +/* + * Echoes React + * Copyright (C) 2023-2025 SonarSource Sàrl + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { useState } from 'react'; +import { + Button, + ButtonVariety, + Form, + FormFieldValidation, + IconGear, + IconKey, + IconPeople, + IconWebhook, + Select, + TextArea, + TextInput, +} from '../../src'; +import { PlaygroundShell } from './PlaygroundShell'; + +const meta: Meta = { title: 'Playground/Project Settings', parameters: { layout: 'fullscreen' } }; +export default meta; +type Story = StoryObj; + +export const Default: Story = { render: () => }; + +function ProjectSettingsPage() { + const [branch, setBranch] = useState('main'); + const [name, setName] = useState('acme-frontend'); + const [savedName, setSavedName] = useState(name); + const isNameInvalid = name.trim().length < 3; + + return ( + +
setName(savedName)} + onSubmit={(event) => { + event.preventDefault(); + if (!isNameInvalid) { + setSavedName(name); + } + }}> + + + setName(event.target.value)} + validation={isNameInvalid ? FormFieldValidation.Invalid : FormFieldValidation.None} + value={name} + /> + +