diff --git a/.storybook/global.css b/.storybook/global.css
index 507ac625e..254477a08 100644
--- a/.storybook/global.css
+++ b/.storybook/global.css
@@ -6,6 +6,7 @@
font-family: 'Noto Sans JP', sans-serif;
font-optical-sizing: auto;
font-style: normal;
+ background-color: var(--charcoal-color-background-default);
}
#storybook-docs pre {
diff --git a/.storybook/theme-decorator.tsx b/.storybook/theme-decorator.tsx
index c66ed63b9..7fefc65a4 100644
--- a/.storybook/theme-decorator.tsx
+++ b/.storybook/theme-decorator.tsx
@@ -1,8 +1,12 @@
-import { useLayoutEffect } from 'react'
+import React, { useLayoutEffect } from 'react'
import { ThemeProvider } from 'styled-components'
import { useDarkMode } from 'storybook-dark-mode'
import { light, dark } from '@charcoal-ui/theme'
-import { TokenInjector, themeSelector, themeSetter } from '@charcoal-ui/styled'
+import { themeSetter } from '@charcoal-ui/styled'
+
+import '../packages/theme/src/css/_variables_dark.css'
+import '../packages/theme/src/css/_variables_light.css'
+import '../packages/react/src/index.css'
const setter = themeSetter()
@@ -20,14 +24,6 @@ const Theme = ({ children }) => {
return (
{children}
-
)
}
diff --git a/packages/react/docs/v4.0.0.mdx b/packages/react/docs/v4.0.0.mdx
index 5110a2ae2..27862ce49 100644
--- a/packages/react/docs/v4.0.0.mdx
+++ b/packages/react/docs/v4.0.0.mdx
@@ -100,3 +100,146 @@ After
- `input`要素の`props`を継承するように変更しました。
- 文字数の計算ロジックを`getCount`プロパティで上書きできるように変更しました。
+
+## 新トークン移行
+
+新トークンへの移行時に旧トークンも引き続き利用したい場合は、以下のマイグレーション用 CSS を適用してください。特定のカラーだけを新トークンに変更したい場合は、該当するカラーを上書きすることができます。
+
+```css
+:root {
+ --charcoal-background1: var(--charcoal-color-background-default);
+ --charcoal-background1-hover: var(--charcoal-color-background-hover);
+ --charcoal-background1-press: var(--charcoal-color-background-press);
+
+ --charcoal-background2: var(--charcoal-color-background-secondary-default);
+ --charcoal-background2-hover: var(
+ --charcoal-color-background-secondary-hover
+ );
+ --charcoal-background2-press: var(
+ --charcoal-color-background-secondary-press
+ );
+
+ --charcoal-surface1: var(--charcoal-color-container-default);
+ --charcoal-surface1-hover: var(--charcoal-color-container-hover);
+ --charcoal-surface1-press: var(--charcoal-color-container-press);
+
+ --charcoal-surface2: var(--charcoal-color-container-tertiary-default);
+ --charcoal-surface2-hover: var(--charcoal-color-container-tertiary-hover);
+ --charcoal-surface2-press: var(--charcoal-color-container-tertiary-press);
+
+ --charcoal-surface3: var(--charcoal-color-container-secondary-default);
+ --charcoal-surface3-hover: var(--charcoal-color-container-secondary-hover);
+ --charcoal-surface3-press: var(--charcoal-color-container-secondary-press);
+
+ --charcoal-surface4: var(--charcoal-color-container-neutral-default);
+ --charcoal-surface4-hover: var(--charcoal-color-container-neutral-hover);
+ --charcoal-surface4-press: var(--charcoal-color-container-neutral-press);
+
+ /* 対応無し */
+ --charcoal-surface5: ;
+ --charcoal-surface5-hover: ;
+ --charcoal-surface5-press: ;
+
+ --charcoal-surface6: var(--charcoal-color-container-hud-default);
+ --charcoal-surface6-hover: var(--charcoal-color-container-hud-hover);
+ --charcoal-surface6-press: var(--charcoal-color-container-hud-press);
+
+ --charcoal-surface7: var(--charcoal-color-container-tertiary-default);
+ --charcoal-surface7-hover: var(--charcoal-color-container-tertiary-hover);
+ --charcoal-surface7-press: var(--charcoal-color-container-tertiary-press);
+
+ --charcoal-surface8: var(--charcoal-color-container-hud-default);
+ --charcoal-surface8-hover: var(--charcoal-color-container-hud-hover);
+ --charcoal-surface8-press: var(--charcoal-color-container-hud-press);
+
+ --charcoal-surface9: var(--charcoal-color-container-default);
+ --charcoal-surface9-hover: var(--charcoal-color-container-hover);
+ --charcoal-surface9-press: var(--charcoal-color-container-press);
+
+ /* 対応無し */
+ --charcoal-surface10: ;
+ --charcoal-surface10-hover: ;
+ --charcoal-surface10-press: ;
+
+ /* charcoal 内では brand が使用されていたが、figma の導入ガイドには primary が記載されていたので両方記述 */
+ --charcoal-primary: var(--charcoal-color-container-primary-default);
+ --charcoal-primary-hover: var(--charcoal-color-container-primary-hover);
+ --charcoal-primary-press: var(--charcoal-color-container-primary-press);
+
+ --charcoal-brand: var(--charcoal-color-container-primary-default);
+ --charcoal-brand-hover: var(--charcoal-color-container-primary-hover);
+ --charcoal-brand-press: var(--charcoal-color-container-primary-press);
+
+ --charcoal-link1: var(--charcoal-color-text-info-default);
+ --charcoal-link1-hover: var(--charcoal-color-text-info-hover);
+ --charcoal-link1-press: var(--charcoal-color-text-info-press);
+
+ /* 対応無し */
+ --charcoal-link2: ;
+ --charcoal-link2-hover: ;
+ --charcoal-link2-press: ;
+
+ --charcoal-transparent: rgba(0, 0, 0, 0);
+ --charcoal-transparent-hover: var(--charcoal-color-container-hover-a);
+ --charcoal-transparent-press: var(--charcoal-color-container-press-a);
+
+ --charcoal-border: var(--charcoal-color-border-default);
+ --charcoal-border-hover: var(--charcoal-color-border-hover);
+ --charcoal-border-press: var(--charcoal-color-border-press);
+ --charcoal-border-default: var(--charcoal-border);
+ --charcoal-border-default-hover: var(--charcoal-border-hover);
+ --charcoal-border-default-press: var(--charcoal-border-press);
+
+ --charcoal-text1: var(--charcoal-color-text-default);
+ --charcoal-text1-hover: var(--charcoal-color-text-hover);
+ --charcoal-text1-press: var(--charcoal-color-text-press);
+
+ --charcoal-text2: var(--charcoal-color-text-secondary-default);
+ --charcoal-text2-hover: var(--charcoal-color-text-secondary-hover);
+ --charcoal-text2-press: var(--charcoal-color-text-secondary-press);
+
+ --charcoal-text3: var(--charcoal-color-text-tertiary-default);
+ --charcoal-text3-hover: var(--charcoal-color-text-tertiary-hover);
+ --charcoal-text3-press: var(--charcoal-color-text-tertiary-press);
+
+ --charcoal-text4: var(--charcoal-color-text-tertiary-default);
+ --charcoal-text4-hover: var(--charcoal-color-text-tertiary-hover);
+ --charcoal-text4-press: var(--charcoal-color-text-tertiary-press);
+
+ --charcoal-text5: var(--charcoal-color-text-on-primary-default);
+ --charcoal-text5-hover: var(--charcoal-color-text-on-primary-hover);
+ --charcoal-text5-press: var(--charcoal-color-text-on-primary-press);
+
+ --charcoal-warning: var(--charcoal-color-container-negative-default);
+ --charcoal-warning-hover: var(--charcoal-color-container-negative-hover);
+ --charcoal-warning-press: var(--charcoal-color-container-negative-press);
+
+ --charcoal-success: var(--charcoal-color-container-positive-default);
+ --charcoal-success-hover: var(--charcoal-color-container-positive-hover);
+ --charcoal-success-press: var(--charcoal-color-container-positive-press);
+}
+```
+
+### カラーの上書き
+
+ライトモードの場合は `:root`、ダークモードの場合は `:root[data-theme='dark']` セレクターに対応しています。`@charcoal-react/dist/index.css` の後に記述することで、トークンを上書きできます。
+
+#### ライトモード
+
+**例**: ブランドカラーを変更する場合
+
+```css
+:root {
+ --charcoal-color-container-primary-default: #0096fa;
+}
+```
+
+#### ダークモード
+
+**例**: ブランドカラーを変更する場合
+
+```css
+:root[data-theme='dark'] {
+ --charcoal-color-container-primary-default: #0096fa;
+}
+```
diff --git a/packages/react/src/components/Button/index.css b/packages/react/src/components/Button/index.css
index 9f179b7c9..70bb644b2 100644
--- a/packages/react/src/components/Button/index.css
+++ b/packages/react/src/components/Button/index.css
@@ -24,94 +24,102 @@
font-size: 14px;
line-height: 22px;
font-weight: bold;
- color: var(--charcoal-text2);
- background-color: var(--charcoal-surface3);
+ color: var(--charcoal-color-text-secondary-default);
+ background-color: var(--charcoal-color-container-secondary-default);
transition: 0.2s color, 0.2s background-color, 0.2s box-shadow;
height: 40px;
}
.charcoal-button:disabled {
cursor: default;
- opacity: 0.32;
+ color: var(--charcoal-color-text-disable);
+ background-color: var(--charcoal-color-container-disable);
}
.charcoal-button:not(:disabled):focus-visible {
outline: none;
- box-shadow: 0 0 0 4px rgba(0, 150, 250, 0.32);
+ box-shadow: var(--charcoal-color-custom-focus-effect);
}
.charcoal-button:not(:disabled):hover {
- color: var(--charcoal-text2-hover);
- background-color: var(--charcoal-surface3-hover);
+ color: var(--charcoal-color-text-secondary-hover);
+ background-color: var(--charcoal-color-container-secondary-hover);
}
.charcoal-button:not(:disabled):active,
.charcoal-button[data-active='true'] {
- color: var(--charcoal-text2-press);
- background-color: var(--charcoal-surface3-press);
+ color: var(--charcoal-color-text-secondary-press);
+ background-color: var(--charcoal-color-container-secondary-press);
}
.charcoal-button[data-variant='Primary'] {
- color: var(--charcoal-text5);
- background-color: var(--charcoal-brand);
+ color: var(--charcoal-color-text-on-primary-default);
+ background-color: var(--charcoal-color-container-primary-default);
}
.charcoal-button[data-variant='Primary']:hover:not(:disabled) {
- color: var(--charcoal-text5-hover);
- background-color: var(--charcoal-brand-hover);
+ color: var(--charcoal-color-text-on-primary-hover);
+ background-color: var(--charcoal-color-container-primary-hover);
}
.charcoal-button[data-variant='Primary']:active:not(:disabled),
.charcoal-button[data-variant='Primary'][data-active='true'] {
- color: var(--charcoal-text5-press);
- background-color: var(--charcoal-brand-press);
+ color: var(--charcoal-color-text-on-primary-press);
+ background-color: var(--charcoal-color-container-primary-press);
}
.charcoal-button[data-variant='Overlay'] {
- color: var(--charcoal-text5);
- background-color: var(--charcoal-surface4);
+ color: var(--charcoal-color-text-on-on-img-default);
+ background-color: var(--charcoal-color-container-on-img-default);
}
.charcoal-button[data-variant='Overlay']:hover:not(:disabled) {
- color: var(--charcoal-text5-hover);
- background-color: var(--charcoal-surface4-hover);
+ color: var(--charcoal-color-text-on-on-img-hover);
+ background-color: var(--charcoal-color-container-on-img-hover);
}
.charcoal-button[data-variant='Overlay']:active:not(:disabled),
.charcoal-button[data-variant='Overlay'][data-active='true'] {
- color: var(--charcoal-text5-press);
- background-color: var(--charcoal-surface4-press);
+ color: var(--charcoal-color-text-on-on-img-press);
+ background-color: var(--charcoal-color-container-on-img-press);
}
+/*
+ * HUD 要素ではないが、以下の理由で HUD を色として利用する。
+ * 1. UI パッケージであるがゆえにデザインを大幅に変えたくない
+ * a. このコンポーネントデザインは改善できると思っている
+ * 2. この要素を説明するための Applied Token が存在しないため、例外的に Component Token という位置づけを追加することになる
+ * 改善するとなくなる要素のために新しく Token を追加することは避けたいので、今回は最も近しい Applied Token の HUD を利用することにした。
+ */
.charcoal-button[data-variant='Navigation'] {
- color: var(--charcoal-text5);
- background-color: var(--charcoal-surface6);
+ color: var(--charcoal-color-text-on-hud-default);
+ background-color: var(--charcoal-color-container-hud-default);
}
.charcoal-button[data-variant='Navigation']:hover:not(:disabled) {
- color: var(--charcoal-text5-hover);
- background-color: var(--charcoal-surface6-hover);
+ color: var(--charcoal-color-text-on-primary-hover);
+ background-color: var(--charcoal-color-container-hud-hover);
}
.charcoal-button[data-variant='Navigation']:active:not(:disabled),
.charcoal-button[data-variant='Navigation'][data-active='true'] {
- color: var(--charcoal-text5-press);
- background-color: var(--charcoal-surface6-press);
+ color: var(--charcoal-color-text-on-primary-press);
+ background-color: var(--charcoal-color-container-hud-press);
}
.charcoal-button[data-variant='Danger'] {
- color: var(--charcoal-text5);
- background-color: var(--charcoal-assertive);
+ color: var(--charcoal-color-text-on-negative-default);
+ background-color: var(--charcoal-color-container-negative-default);
}
.charcoal-button[data-variant='Danger']:hover:not(:disabled) {
- color: var(--charcoal-text5-hover);
- background-color: var(--charcoal-assertive-hover);
+ color: var(--charcoal-color-text-on-negative-hover);
+ background-color: var(--charcoal-color-container-negative-hover);
}
.charcoal-button[data-variant='Danger']:active:not(:disabled),
.charcoal-button[data-variant='Danger'][data-active='true'] {
- color: var(--charcoal-text5-press);
- background-color: var(--charcoal-assertive-press);
+ color: var(--charcoal-color-text-on-negative-press);
+ background-color: var(--charcoal-color-container-negative-press);
}
.charcoal-button[data-size='S'] {
diff --git a/packages/react/src/components/Checkbox/CheckboxInput/__snapshots__/index.story.storyshot b/packages/react/src/components/Checkbox/CheckboxInput/__snapshots__/index.story.storyshot
index 8381e06f0..ceab6a029 100644
--- a/packages/react/src/components/Checkbox/CheckboxInput/__snapshots__/index.story.storyshot
+++ b/packages/react/src/components/Checkbox/CheckboxInput/__snapshots__/index.story.storyshot
@@ -60,7 +60,7 @@ exports[`Storybook Tests > react/internals/CheckboxInput > Rounded 1`] = `
= {
const [checked, setChecked] = useState(false)
return (
diff --git a/packages/react/src/components/Checkbox/index.css b/packages/react/src/components/Checkbox/index.css
index f9d9b5c18..674650fcd 100644
--- a/packages/react/src/components/Checkbox/index.css
+++ b/packages/react/src/components/Checkbox/index.css
@@ -3,19 +3,16 @@
cursor: pointer;
display: flex;
gap: 4px;
+ color: var(--charcoal-color-text-secondary-default);
}
.charcoal-checkbox__label[aria-disabled='true'] {
cursor: default;
- opacity: 0.32;
-}
-
-.charcoal-checkbox__label[aria-disabled='true'] > input {
- opacity: 1;
+ color: var(--charcoal-color-text-disable);
}
.charcoal-checkbox__label_div {
- color: var(--charcoal-text2);
+ color: inherit;
font-size: 14px;
line-height: 20px;
}
diff --git a/packages/react/src/components/DropdownSelector/DropdownMenuItem/index.css b/packages/react/src/components/DropdownSelector/DropdownMenuItem/index.css
index 6c3c8f3d6..3f0aabf79 100644
--- a/packages/react/src/components/DropdownSelector/DropdownMenuItem/index.css
+++ b/packages/react/src/components/DropdownSelector/DropdownMenuItem/index.css
@@ -1,7 +1,7 @@
.charcoal-dropdown-selector-menu-item {
font-size: 14px;
line-height: 22px;
- color: var(--charcoal-text2);
+ color: var(--charcoal-color-text-secondary-default);
padding: 9px 0;
display: flex;
@@ -15,6 +15,6 @@
}
.charcoal-dropdown-selector-menu-item-icon {
- color: var(--charcoal-text2);
+ color: var(--charcoal-color-text-secondary-default);
padding-right: 4px;
}
diff --git a/packages/react/src/components/DropdownSelector/ListItem/index.css b/packages/react/src/components/DropdownSelector/ListItem/index.css
index 4fabf12bb..348140cf7 100644
--- a/packages/react/src/components/DropdownSelector/ListItem/index.css
+++ b/packages/react/src/components/DropdownSelector/ListItem/index.css
@@ -15,10 +15,11 @@
.charcoal-list-item:not([aria-disabled='true']):hover,
.charcoal-list-item:not([aria-disabled='true']):focus,
.charcoal-list-item:not([aria-disabled='true']):focus-within {
- background-color: var(--charcoal-surface3);
+ background-color: var(--charcoal-color-container-secondary-default);
}
.charcoal-list-item[aria-disabled='true'] {
- opacity: 0.32;
cursor: default;
+ color: var(--charcoal-color-text-disable);
+ background-color: var(--charcoal-color-container-disable);
}
diff --git a/packages/react/src/components/DropdownSelector/MenuItemGroup/index.css b/packages/react/src/components/DropdownSelector/MenuItemGroup/index.css
index a34d43442..13976a592 100644
--- a/packages/react/src/components/DropdownSelector/MenuItemGroup/index.css
+++ b/packages/react/src/components/DropdownSelector/MenuItemGroup/index.css
@@ -4,7 +4,7 @@
.charcoal-menu-item-group > span {
display: block;
- color: var(--charcoal-text3);
+ color: var(--charcoal-color-text-tertiary-default);
font-size: 12px;
font-weight: bold;
padding: 12px 0 8px 16px;
diff --git a/packages/react/src/components/DropdownSelector/Popover/index.css b/packages/react/src/components/DropdownSelector/Popover/index.css
index e8fc9d795..87bb66a1f 100644
--- a/packages/react/src/components/DropdownSelector/Popover/index.css
+++ b/packages/react/src/components/DropdownSelector/Popover/index.css
@@ -3,8 +3,8 @@
list-style: none;
overflow: auto;
max-height: inherit;
- background-color: var(--charcoal-background1);
- border: solid 1px var(--charcoal-border-default);
+ background-color: var(--charcoal-color-background-default);
+ border: solid 1px var(--charcoal-color-border-default);
border-radius: 8px;
padding-top: 8px;
padding-bottom: 8px;
diff --git a/packages/react/src/components/DropdownSelector/index.css b/packages/react/src/components/DropdownSelector/index.css
index 0a0fc9298..fc3448953 100644
--- a/packages/react/src/components/DropdownSelector/index.css
+++ b/packages/react/src/components/DropdownSelector/index.css
@@ -7,7 +7,8 @@
.charcoal-dropdown-selector-root[aria-disabled='true'] {
cursor: default;
- opacity: 0.32;
+ color: var(--charcoal-color-text-disable);
+ background-color: var(--charcoal-color-container-disable);
}
.charcoal-dropdown-selector-button {
@@ -25,7 +26,7 @@
padding-right: 8px;
padding-left: 8px;
- background-color: var(--charcoal-surface3);
+ background-color: var(--charcoal-color-container-secondary-default);
border-radius: 4px;
transition: 0.2s box-shadow, 0.2s background-color;
@@ -37,20 +38,20 @@
.charcoal-dropdown-selector-button:not(:disabled):focus {
outline: none;
- box-shadow: 0 0 0 4px rgba(0, 150, 250, 0.32);
+ box-shadow: var(--charcoal-color-custom-focus-effect);
}
.charcoal-dropdown-selector-button:not(:disabled):focus-visible {
- box-shadow: 0 0 0 4px rgba(0, 150, 250, 0.32);
+ box-shadow: var(--charcoal-color-custom-focus-effect);
}
.charcoal-dropdown-selector-button:not(:disabled)[data-active='true'],
.charcoal-dropdown-selector-button:not(:disabled):active {
- background-color: var(--charcoal-surface3-press);
+ background-color: var(--charcoal-color-container-secondary-press);
}
.charcoal-dropdown-selector-button:not(:disabled):hover {
- background-color: var(--charcoal-surface3-hover);
+ background-color: var(--charcoal-color-container-secondary-hover);
}
.charcoal-dropdown-selector-button:not(:disabled):focus:not(:focus-visible) {
@@ -61,7 +62,7 @@
.charcoal-dropdown-selector-button:not(
:disabled
)[aria-invalid='true']:focus:not(:focus-visible) {
- box-shadow: 0 0 0 4px rgba(255, 43, 0, 0.32);
+ box-shadow: var(--charcoal-color-custom-error-effect);
}
.charcoal-ui-dropdown-selector-text {
@@ -69,16 +70,16 @@
font-size: 14px;
line-height: 22px;
display: flow-root;
- color: var(--charcoal-text2);
+ color: var(--charcoal-color-text-secondary-default);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.charcoal-ui-dropdown-selector-text[data-placeholder='true'] {
- color: var(--charcoal-text3);
+ color: var(--charcoal-color-text-placeholder-default);
}
.charcoal-ui-dropdown-selector-icon {
- color: var(--charcoal-text2);
+ color: var(--charcoal-color-text-secondary-default);
}
diff --git a/packages/react/src/components/FieldLabel/index.css b/packages/react/src/components/FieldLabel/index.css
index bc141b8c6..28f7631fd 100644
--- a/packages/react/src/components/FieldLabel/index.css
+++ b/packages/react/src/components/FieldLabel/index.css
@@ -3,21 +3,21 @@
line-height: 22px;
font-weight: bold;
display: flow-root;
- color: var(--charcoal-text1);
+ color: var(--charcoal-color-text-default);
}
.charcoal-field-label-required-text {
font-size: 14px;
line-height: 22px;
display: flow-root;
- color: var(--charcoal-text2);
+ color: var(--charcoal-color-text-secondary-default);
}
.charcoal-field-label-sub-label {
font-size: 14px;
line-height: 22px;
display: flow-root;
- color: var(--charcoal-text3);
+ color: var(--charcoal-color-text-tertiary-default);
transition: 0.2s color, 0.2s box-shadow;
}
diff --git a/packages/react/src/components/IconButton/index.css b/packages/react/src/components/IconButton/index.css
index 5d8a88eee..a6e0b5ed0 100644
--- a/packages/react/src/components/IconButton/index.css
+++ b/packages/react/src/components/IconButton/index.css
@@ -26,7 +26,8 @@
.charcoal-icon-button:disabled,
.charcoal-icon-button[aria-disabled]:not([aria-disabled='false']) {
cursor: default;
- opacity: 0.32;
+ color: var(--charcoal-color-text-disable);
+ background-color: var(--charcoal-color-container-disable);
}
.charcoal-icon-button:focus {
outline: none;
@@ -50,65 +51,65 @@
}
.charcoal-icon-button[data-variant='Default'] {
- color: var(--charcoal-text3);
- background-color: var(--charcoal-transparent);
+ color: var(--charcoal-color-text-tertiary-default);
+ background-color: rgba(0, 0, 0, 0);
}
.charcoal-icon-button[data-variant='Default'][data-active='true']:not(
:disabled
):not([aria-disabled]),
.charcoal-icon-button[data-variant='Default'][data-active='true'][aria-disabled='false'] {
- color: var(--charcoal-text3-press);
- background-color: var(--charcoal-transparent-press);
+ color: var(--charcoal-color-text-tertiary-press);
+ background-color: var(--charcoal-color-container-press-a);
}
.charcoal-icon-button[data-variant='Default'][data-active='false']:not(
:disabled
):not([aria-disabled]):hover,
.charcoal-icon-button[data-variant='Default'][data-active='false'][aria-disabled='false']:hover {
- color: var(--charcoal-text3-hover);
- background-color: var(--charcoal-transparent-hover);
+ color: var(--charcoal-color-text-tertiary-hover);
+ background-color: var(--charcoal-color-container-hover-a);
}
.charcoal-icon-button[data-variant='Default'][data-active='false']:not(
:disabled
):not([aria-disabled]):active,
.charcoal-icon-button[data-variant='Default'][data-active='false'][aria-disabled='false']:active {
- color: var(--charcoal-text3-press);
- background-color: var(--charcoal-transparent-press);
+ color: var(--charcoal-color-text-tertiary-press);
+ background-color: var(--charcoal-color-container-press-a);
}
.charcoal-icon-button[data-variant='Overlay'] {
- color: var(--charcoal-text5);
- background-color: var(--charcoal-surface4);
+ color: var(--charcoal-color-text-on-primary-default);
+ background-color: var(--charcoal-color-container-on-img-default);
}
.charcoal-icon-button[data-variant='Overlay'][data-active='true']:not(
:disabled
):not([aria-disabled]),
.charcoal-icon-button[data-variant='Overlay'][data-active='true'][aria-disabled='false'] {
- color: var(--charcoal-text5-press);
- background-color: var(--charcoal-surface4-press);
+ color: var(--charcoal-color-text-on-primary-press);
+ background-color: var(--charcoal-color-container-on-img-press);
}
.charcoal-icon-button[data-variant='Overlay'][data-active='false']:not(
:disabled
):not([aria-disabled]):hover,
.charcoal-icon-button[data-variant='Overlay'][data-active='false'][aria-disabled='false']:hover {
- color: var(--charcoal-text5-hover);
- background-color: var(--charcoal-surface4-hover);
+ color: var(--charcoal-color-text-on-primary-hover);
+ background-color: var(--charcoal-color-container-on-img-hover);
}
.charcoal-icon-button[data-variant='Overlay'][data-active='false']:not(
:disabled
):not([aria-disabled]):active,
.charcoal-icon-button[data-variant='Overlay'][data-active='false'][aria-disabled='false']:active {
- color: var(--charcoal-text5-press);
- background-color: var(--charcoal-surface4-press);
+ color: var(--charcoal-color-text-on-primary-press);
+ background-color: var(--charcoal-color-container-on-img-press);
}
.charcoal-icon-button:not(:disabled):not([aria-disabled]):focus,
.charcoal-icon-button[aria-disabled='false']:focus {
outline: none;
- box-shadow: 0 0 0 4px rgba(0, 150, 250, 0.32);
+ box-shadow: var(--charcoal-color-custom-focus-effect);
}
.charcoal-icon-button:not(:disabled):not([aria-disabled]):focus-visible,
.charcoal-icon-button[aria-disabled='false']:focus-visible {
- box-shadow: 0 0 0 4px rgba(0, 150, 250, 0.32);
+ box-shadow: var(--charcoal-color-custom-focus-effect);
}
.charcoal-icon-button:not(:disabled):not([aria-disabled]):focus:not(
:focus-visible
diff --git a/packages/react/src/components/LoadingSpinner/index.css b/packages/react/src/components/LoadingSpinner/index.css
index 3a7fe69b7..c9e99c6a6 100644
--- a/packages/react/src/components/LoadingSpinner/index.css
+++ b/packages/react/src/components/LoadingSpinner/index.css
@@ -1,4 +1,7 @@
.charcoal-loading-spinner {
+ --charcoal-loading-spinner-size: 48px;
+ --charcoal-loading-spinner-padding: 16px;
+
box-sizing: content-box;
margin: auto;
padding: var(--charcoal-loading-spinner-padding);
@@ -7,11 +10,10 @@
width: var(--charcoal-loading-spinner-size);
height: var(--charcoal-loading-spinner-size);
opacity: 0.84;
- color: var(--charcoal-text4);
- background-color: var(--charcoal-background1);
+ background-color: var(--charcoal-color-background-default);
}
.charcoal-loading-spinner[data-transparent='true'] {
- background-color: var(--charcoal-transparent);
+ background-color: rgba(0, 0, 0, 0);
}
@keyframes charcoal-loading-spinner-icon-scale-out {
diff --git a/packages/react/src/components/Modal/Dialog/index.css b/packages/react/src/components/Modal/Dialog/index.css
index 03de6c2ad..66444f48c 100644
--- a/packages/react/src/components/Modal/Dialog/index.css
+++ b/packages/react/src/components/Modal/Dialog/index.css
@@ -4,7 +4,7 @@
height: fit-content;
width: 440px;
- background-color: var(--charcoal-surface1);
+ background-color: var(--charcoal-color-container-default);
border-radius: 24px;
}
diff --git a/packages/react/src/components/Modal/ModalPlumbing.css b/packages/react/src/components/Modal/ModalPlumbing.css
index 3b5ff3853..389ac16da 100644
--- a/packages/react/src/components/Modal/ModalPlumbing.css
+++ b/packages/react/src/components/Modal/ModalPlumbing.css
@@ -13,7 +13,7 @@
}
.charcoal-modal-header-title {
- color: var(--charcoal-text1);
+ color: var(--charcoal-color-text-default);
font-size: 16px;
line-height: 24px;
font-weight: bold;
diff --git a/packages/react/src/components/Modal/__snapshots__/index.story.storyshot b/packages/react/src/components/Modal/__snapshots__/index.story.storyshot
index ed6c01d77..8115c99cf 100644
--- a/packages/react/src/components/Modal/__snapshots__/index.story.storyshot
+++ b/packages/react/src/components/Modal/__snapshots__/index.story.storyshot
@@ -66,7 +66,7 @@ exports[`Storybook Tests > react/Modal > BackgroundScroll 1`] = `
react/Modal > BackgroundScroll 1`] = `
data-invalid={false}
>
react/Modal > BackgroundScroll 1`] = `
data-invalid={false}
>
react/Modal > BottomSheet 1`] = `
react/Modal > Default 1`] = `
react/Modal > Default 1`] = `
data-invalid={false}
>
react/Modal > Default 1`] = `
data-invalid={false}
>
react/Modal > FullBottomSheet 1`] = `
react/Modal > FullBottomSheet 1`] = `
data-invalid={false}
>
react/Modal > FullBottomSheet 1`] = `
data-invalid={false}
>
react/Modal > NotDismmissableStory 1`] = `
, 'style'>) => {
fontSize: 14,
lineHeight: '22px',
padding: '0 16px',
- color: 'var(--charcoal-text2)',
+ color: 'var(--charcoal-color-text-secondary-default)',
}}
{...props}
/>
diff --git a/packages/react/src/components/Radio/RadioInput/index.css b/packages/react/src/components/Radio/RadioInput/index.css
index 71d62dea9..238c51d92 100644
--- a/packages/react/src/components/Radio/RadioInput/index.css
+++ b/packages/react/src/components/Radio/RadioInput/index.css
@@ -10,12 +10,12 @@
height: 20px;
cursor: pointer;
border-radius: 999999px;
- background-color: var(--charcoal-surface1);
+ background-color: var(--charcoal-color-container-default);
transition: 0.2s background-color, 0.2s box-shadow;
}
.charcoal-radio-input:checked {
- background-color: var(--charcoal-brand);
+ background-color: var(--charcoal-color-container-primary-default);
}
.charcoal-radio-input:checked::after {
@@ -24,7 +24,7 @@
width: 8px;
height: 8px;
pointer-events: none;
- background-color: var(--charcoal-text5);
+ background-color: var(--charcoal-color-text-on-primary-default);
border-radius: 999999px;
transition: 0.2s background-color, 0.2s box-shadow;
}
@@ -32,7 +32,7 @@
.charcoal-radio-input:not(:checked) {
border-width: 2px;
border-style: solid;
- border-color: var(--charcoal-text3);
+ border-color: var(--charcoal-color-text-tertiary-default);
}
.charcoal-radio-input:disabled {
@@ -40,20 +40,20 @@
}
.charcoal-radio-input:not(:disabled):hover {
- background-color: var(--charcoal-surface1-hover);
+ background-color: var(--charcoal-color-container-hover);
}
.charcoal-radio-input:not(:disabled):active {
- background-color: var(--charcoal-surface1-press);
+ background-color: var(--charcoal-color-container-press);
}
.charcoal-radio-input:not(:disabled):focus {
outline: none;
- box-shadow: 0 0 0 4px rgba(0, 150, 250, 0.32);
+ box-shadow: var(--charcoal-color-custom-focus-effect);
}
.charcoal-radio-input:not(:disabled):focus-visible {
- box-shadow: 0 0 0 4px rgba(0, 150, 250, 0.32);
+ box-shadow: var(--charcoal-color-custom-focus-effect);
}
.charcoal-radio-input:not(:disabled):focus:not(:focus-visible) {
@@ -62,21 +62,21 @@
.charcoal-radio-input:not(:disabled)[aria-invalid='true'],
.charcoal-radio-input:not(:disabled)[aria-invalid='true']:focus {
- box-shadow: 0 0 0 4px rgba(255, 43, 0, 0.32);
+ box-shadow: var(--charcoal-color-custom-error-effect);
}
.charcoal-radio-input:checked:not(:disabled):hover {
- background-color: var(--charcoal-brand-hover);
+ background-color: var(--charcoal-color-container-primary-hover);
}
.charcoal-radio-input:checked:not(:disabled):hover::after {
- background-color: var(--charcoal-text5-hover);
+ background-color: var(--charcoal-color-text-on-primary-hover);
}
.charcoal-radio-input:checked:not(:disabled):active {
- background-color: var(--charcoal-brand-press);
+ background-color: var(--charcoal-color-container-primary-press);
}
.charcoal-radio-input:checked:not(:disabled):active::after {
- background-color: var(--charcoal-text5-press);
+ background-color: var(--charcoal-color-text-on-primary-press);
}
diff --git a/packages/react/src/components/Radio/index.css b/packages/react/src/components/Radio/index.css
index 67e33bc19..22e9a901e 100644
--- a/packages/react/src/components/Radio/index.css
+++ b/packages/react/src/components/Radio/index.css
@@ -7,12 +7,13 @@
}
.charcoal-radio__label[aria-disabled]:not([aria-disabled='false']) {
- opacity: 0.32;
cursor: default;
+ color: var(--charcoal-color-text-disable);
+ background-color: var(--charcoal-color-container-disable);
}
.charcoal-radio__label_div {
font-size: 14px;
line-height: 22px;
- color: var(--charcoal-text2);
+ color: var(--charcoal-color-text-secondary-default);
}
diff --git a/packages/react/src/components/SegmentedControl/index.css b/packages/react/src/components/SegmentedControl/index.css
index 8d15b67c1..d4fcdf9be 100644
--- a/packages/react/src/components/SegmentedControl/index.css
+++ b/packages/react/src/components/SegmentedControl/index.css
@@ -2,7 +2,7 @@
display: inline-flex;
align-items: center;
- background-color: var(--charcoal-surface3);
+ background-color: var(--charcoal-color-container-secondary-default);
border-radius: 16px;
}
@@ -16,7 +16,7 @@
padding-right: 16px;
padding-left: 16px;
border-radius: 16px;
- color: var(--charcoal-text2);
+ color: var(--charcoal-color-text-secondary-default);
font-size: 14px;
line-height: 22px;
@@ -26,12 +26,13 @@
[aria-disabled='false']
) {
cursor: default;
- opacity: 0.32;
+ color: var(--charcoal-color-text-disable);
+ background-color: var(--charcoal-color-container-disable);
}
.charcoal-segmented-control-radio__label[data-checked='true'] {
- background-color: var(--charcoal-brand);
- color: var(--charcoal-text5);
+ background-color: var(--charcoal-color-container-primary-default);
+ color: var(--charcoal-color-text-on-primary-default);
}
.charcoal-segmented-control-radio__input {
diff --git a/packages/react/src/components/Switch/SwitchInput/index.css b/packages/react/src/components/Switch/SwitchInput/index.css
index fe53283ab..2bc29d57c 100644
--- a/packages/react/src/components/Switch/SwitchInput/index.css
+++ b/packages/react/src/components/Switch/SwitchInput/index.css
@@ -14,13 +14,14 @@
border-radius: 16px;
height: 16px;
margin: 0;
- background-color: var(--charcoal-text4);
+ background-color: var(--charcoal-color-container-neutral-default);
}
.charcoal-switch-input:disabled,
.charcoal-switch-input[readonly] {
- opacity: 0.32;
cursor: default;
+ color: var(--charcoal-color-text-disable);
+ background-color: var(--charcoal-color-container-disable);
}
.charcoal-switch-input::after {
@@ -34,7 +35,7 @@
transform: translateX(0);
transition: transform 0.2s;
border-radius: 1024px;
- background-color: var(--charcoal-text5);
+ background-color: var(--charcoal-color-text-on-primary-default);
}
.charcoal-switch-input:checked::after {
@@ -43,40 +44,40 @@
}
.charcoal-switch-input:checked {
- background-color: var(--charcoal-brand);
+ background-color: var(--charcoal-color-container-primary-default);
}
.charcoal-switch-input:not(:disabled):hover {
- background-color: var(--charcoal-text4-hover);
+ background-color: var(--charcoal-color-container-neutral-hover);
}
.charcoal-switch-input:not(:disabled):active {
- background-color: var(--charcoal-text4-press);
+ background-color: var(--charcoal-color-container-neutral-press);
}
.charcoal-switch-input:not(:disabled):focus {
outline: none;
- box-shadow: 0 0 0 4px rgba(0, 150, 250, 0.32);
+ box-shadow: var(--charcoal-color-custom-focus-effect);
}
.charcoal-switch-input:not(:disabled):focus-visible {
- box-shadow: 0 0 0 4px rgba(0, 150, 250, 0.32);
+ box-shadow: var(--charcoal-color-custom-focus-effect);
}
.charcoal-switch-input:not(:disabled):focus:not(:focus-visible) {
box-shadow: none;
}
.charcoal-switch-input:not(:disabled)::after:hover {
- background-color: var(--charcoal-text5-hover);
+ background-color: var(--charcoal-color-text-on-primary-hover);
}
.charcoal-switch-input:not(:disabled)::after:active {
- background-color: var(--charcoal-text5-press);
+ background-color: var(--charcoal-color-text-on-primary-press);
}
.charcoal-switch-input:not(:disabled):checked:hover {
- background-color: var(--charcoal-brand-hover);
+ background-color: var(--charcoal-color-container-primary-hover);
}
.charcoal-switch-input:not(:disabled):checked:active {
- background-color: var(--charcoal-brand-press);
+ background-color: var(--charcoal-color-container-primary-press);
}
diff --git a/packages/react/src/components/Switch/index.css b/packages/react/src/components/Switch/index.css
index 75ecd4aea..e9f307a4e 100644
--- a/packages/react/src/components/Switch/index.css
+++ b/packages/react/src/components/Switch/index.css
@@ -8,8 +8,9 @@
}
.charcoal-switch__label[aria-disabled='true'] {
- opacity: 0.32;
cursor: default;
+ color: var(--charcoal-color-text-disable);
+ background-color: var(--charcoal-color-container-disable);
}
.charcoal-switch__label[aria-disabled='true'] > input {
@@ -19,5 +20,5 @@
.charcoal-switch__label_div {
font-size: 14px;
line-height: 22px;
- color: var(--charcoal-text2);
+ color: var(--charcoal-color-text-secondary-default);
}
diff --git a/packages/react/src/components/TagItem/__snapshots__/index.story.storyshot b/packages/react/src/components/TagItem/__snapshots__/index.story.storyshot
index 67de955bb..cd353af4b 100644
--- a/packages/react/src/components/TagItem/__snapshots__/index.story.storyshot
+++ b/packages/react/src/components/TagItem/__snapshots__/index.story.storyshot
@@ -44,7 +44,7 @@ exports[`Storybook Tests > react/TagItem > BGColor 1`] = `
data-state="default"
style={
Object {
- "--charcoal-tag-item-bg": "var(--charcoal-brand)",
+ "--charcoal-tag-item-bg": "var(---charcoal-color-container-primary-default)",
}
}
>
diff --git a/packages/react/src/components/TagItem/index.css b/packages/react/src/components/TagItem/index.css
index d5fbb20fa..34b8aa251 100644
--- a/packages/react/src/components/TagItem/index.css
+++ b/packages/react/src/components/TagItem/index.css
@@ -1,8 +1,9 @@
.charcoal-tag-item {
- --charcoal-tag-item-color: var(--charcoal-text5);
+ --charcoal-tag-item-color: var(--charcoal-color-text-on-primary-default);
--charcoal-tag-item-size: 40px;
--charcoal-tag-item-padding-left: 24px;
--charcoal-tag-item-padding-right: 24px;
+ --charcoal-tag-item-bg: ;
isolation: isolate;
position: relative;
@@ -43,7 +44,7 @@
--charcoal-tag-item-padding-right: 16px;
}
.charcoal-tag-item[data-state='inactive'] {
- --charcoal-tag-item-color: var(--charcoal-text2);
+ --charcoal-tag-item-color: var(--charcoal-color-text-secondary-default);
}
.charcoal-tag-item[data-state='active'] {
--charcoal-tag-item-padding-left: 16px;
@@ -52,18 +53,19 @@
.charcoal-tag-item:disabled,
.charcoal-tag-item[aria-disabled]:not([aria-disabled='false']) {
- opacity: 0.32;
cursor: default;
+ color: var(--charcoal-color-text-disable);
+ background-color: var(--charcoal-color-container-disable);
}
.charcoal-tag-item:not(:disabled):not([aria-disabled]):focus-visible,
.charcoal-tag-item[aria-disabled='false']:focus-visible {
outline: none;
- box-shadow: 0 0 0 4px rgba(0, 150, 250, 0.32);
+ box-shadow: var(--charcoal-color-custom-focus-effect);
}
.charcoal-tag-item:not(:disabled):not([aria-disabled]):focus,
.charcoal-tag-item[aria-disabled='false']:focus {
outline: none;
- box-shadow: 0 0 0 4px rgba(0, 150, 250, 0.32);
+ box-shadow: var(--charcoal-color-custom-focus-effect);
}
.charcoal-tag-item:not(:disabled):not([aria-disabled]):focus:not(
:focus-visible
@@ -77,7 +79,7 @@
}
.charcoal-tag-item__bg[data-bg-variant='image'] {
- background-color: var(--charcoal-surface4);
+ background-color: var(--charcoal-color-container-on-img-default);
}
.charcoal-tag-item__bg[data-bg-variant='image']::before {
@@ -95,7 +97,7 @@
}
.charcoal-tag-item__bg[data-state='inactive'] {
- background-color: var(--charcoal-surface3);
+ background-color: var(--charcoal-color-container-secondary-default);
}
.charcoal-tag-item__label {
diff --git a/packages/react/src/components/TagItem/index.story.tsx b/packages/react/src/components/TagItem/index.story.tsx
index 57a72fb79..7a5dc96a8 100644
--- a/packages/react/src/components/TagItem/index.story.tsx
+++ b/packages/react/src/components/TagItem/index.story.tsx
@@ -26,7 +26,12 @@ export const TranslatedLabel: StoryObj
= {
export const BGColor: StoryObj = {
render: function Render() {
- return
+ return (
+
+ )
},
}
diff --git a/packages/react/src/components/TextArea/__snapshots__/TextArea.story.storyshot b/packages/react/src/components/TextArea/__snapshots__/TextArea.story.storyshot
index 5bb4ba65c..91f68ab9f 100644
--- a/packages/react/src/components/TextArea/__snapshots__/TextArea.story.storyshot
+++ b/packages/react/src/components/TextArea/__snapshots__/TextArea.story.storyshot
@@ -49,6 +49,7 @@ exports[`Storybook Tests > react/TextArea > AssistiveText 1`] = `
>
react/TextField > AssistiveText 1`] = `
>
react/TextField > Default 1`] = `
data-invalid={false}
>
react/TextField > Disabled 1`] = `
data-invalid={false}
>
react/TextField > Invalid 1`] = `
>
react/TextField > Label 1`] = `
data-invalid={false}
>
react/TextField > Number 1`] = `
data-invalid={false}
>
react/TextField > Placeholder 1`] = `
data-invalid={false}
>
react/TextField > Prefix 1`] = `
style={
Object {
"alignItems": "center",
- "color": "var(--charcoal-text3)",
+ "color": "var(--charcoal-color-text-tertiary-default)",
"display": "flex",
}
}
@@ -534,6 +542,7 @@ exports[`Storybook Tests > react/TextField > Prefix 1`] = `
react/TextField > ReadOnly 1`] = `
data-invalid={false}
>
react/TextField > RequiredText 1`] = `
data-invalid={false}
>
react/TextField > ShowCount 1`] = `
data-invalid={false}
>
react/TextField > SubLabel 1`] = `
data-invalid={false}
>
(
aria-describedby={showAssistiveText ? describedbyId : undefined}
aria-invalid={invalid}
aria-labelledby={labelledbyId}
+ aria-disabled={props['aria-disabled'] ?? disabled}
id={inputId}
data-invalid={invalid === true}
maxLength={maxLength}
diff --git a/packages/react/src/css-variables.test.tsx b/packages/react/src/css-variables.test.tsx
new file mode 100644
index 000000000..f33dbdf37
--- /dev/null
+++ b/packages/react/src/css-variables.test.tsx
@@ -0,0 +1,56 @@
+import glob from 'glob'
+import { readFile } from 'fs/promises'
+import path, { join } from 'path'
+
+const dir = path.resolve(__dirname, 'components')
+
+const extractVariables = (cssContent: string): string[] => {
+ const variablePattern = /--[\w-]+(?=:)/g
+ return cssContent.match(variablePattern) ?? []
+}
+const extractUsedVariables = (cssContent: string): string[] => {
+ const usedVariablePattern = /var\((--[\w-]+)\)/g
+ const matches = []
+ let match
+ while ((match = usedVariablePattern.exec(cssContent)) !== null) {
+ matches.push(match[1])
+ }
+ return matches
+}
+
+const variablesSet = new Set
()
+const variableFiles = [
+ join(__dirname, './index.css'),
+ ...glob.sync(join(__dirname, '../../theme/src/css/*.css')),
+]
+
+for (const file of variableFiles) {
+ const content = await readFile(file, 'utf-8')
+ const variables = extractVariables(content)
+ for (const variable of variables) {
+ variablesSet.add(variable)
+ }
+}
+
+describe('CSS Variables Check', () => {
+ const cssFiles = glob.sync(`${dir}/**/*.css`)
+
+ describe.each(cssFiles)('Check file: %s', async (file) => {
+ const content = await readFile(file, 'utf-8')
+ const usedVariables = extractUsedVariables(content)
+ const definedVariables = new Set(extractVariables(content))
+
+ it('should not empty', () => {
+ expect(content).not.toBe('')
+ })
+
+ it.each(usedVariables)(
+ 'should contain all used variables in %s',
+ (variable) => {
+ const contained =
+ variablesSet.has(variable) || definedVariables.has(variable)
+ expect(contained).toBeTruthy()
+ }
+ )
+ })
+})
diff --git a/packages/react/src/index.css b/packages/react/src/index.css
new file mode 100644
index 000000000..1130a14fa
--- /dev/null
+++ b/packages/react/src/index.css
@@ -0,0 +1,5 @@
+:root {
+ /* charcoal custom css variables */
+ --charcoal-color-custom-focus-effect: 0 0 0 4px rgba(0, 150, 250, 0.32);
+ --charcoal-color-custom-error-effect: 0 0 0 4px rgba(255, 43, 0, 0.32);
+}
diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts
index 630885c27..715889c03 100644
--- a/packages/react/src/index.ts
+++ b/packages/react/src/index.ts
@@ -1,3 +1,5 @@
+import './index.css'
+
export { SSRProvider } from './core/SSRProvider'
export { OverlayProvider } from './core/OverlayProvider'
export {
diff --git a/packages/theme/package.json b/packages/theme/package.json
index 8cadc2ba1..948d428cc 100644
--- a/packages/theme/package.json
+++ b/packages/theme/package.json
@@ -5,10 +5,20 @@
"main": "./dist/index.cjs.js",
"module": "./dist/index.esm.js",
"exports": {
- "types": "./dist/index.d.ts",
- "require": "./dist/index.cjs.js",
- "import": "./dist/index.esm.js",
- "default": "./dist/index.esm.js"
+ ".": {
+ "types": "./dist/index.d.ts",
+ "require": "./dist/index.cjs.js",
+ "import": "./dist/index.esm.js",
+ "default": "./dist/index.esm.js"
+ },
+ "./dark.css": {
+ "require": "./dist/css/_variables_dark.css",
+ "import": "./dist/css/_variables_dark.css"
+ },
+ "./light.css": {
+ "require": "./dist/css/_variables_light.css",
+ "import": "./dist/css/_variables_light.css"
+ }
},
"types": "./dist/index.d.ts",
"sideEffects": [