Skip to content

Commit 6baff22

Browse files
Use theme-aware variables (#79)
- Updates CSS files to use theme-aware variables - Added `theme-token` and `design-token` helpers to keep naming consistent across project - Updates token name usage to use dot notation to be consistent with how they're defined in the tokens project and theme configuration - Updates CSS files to use token helpers - Added `dev` scripts that automatically rebuild on changes Given that we have different token types now, this change tries to make it easier to work with tokens. Tokens can be one of either (a) design token; (b) theme token; (c) component token. This maps to the original plan of global, alias, and component tokens in our ADR -> design token (global), theme token (alias), and component token. Design tokens are any tokens in our `-tokens` project, theme tokens are ones defined in our theme in `-react`, component tokens are tokens created in our component CSS module files.
1 parent 75faca5 commit 6baff22

35 files changed

+626
-256
lines changed

.changeset/large-cows-destroy.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"@easypost/easy-ui-tokens": patch
3+
"@easypost/easy-ui-icons": patch
4+
"@easypost/easy-ui": patch
5+
---
6+
7+
Use theme-aware variables
8+
9+
With theming setup, update CSS modules and relevant places in JS components with tokens that are theme-aware.

.storybook/theme.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@ import tokens from "../easy-ui-tokens/dist/js/tokens";
44
export const gridCellSize = 8;
55

66
export const backgrounds = {
7-
dark: tokens["color-gray-800"],
8-
light: tokens["color-gray-000"],
7+
dark: tokens["color.gray.800"],
8+
light: tokens["color.gray.000"],
99
};
1010

1111
const colors = {
1212
background: backgrounds.light,
13-
primary: tokens["color-blue-500"],
14-
secondary: tokens["color-blue-500"],
15-
border: tokens["color-gray-200"],
16-
surface: tokens["color-white"],
17-
text: tokens["color-gray-700"],
18-
textMuted: tokens["color-gray-400"],
13+
primary: tokens["color.blue.500"],
14+
secondary: tokens["color.blue.500"],
15+
border: tokens["color.gray.200"],
16+
surface: tokens["color.white"],
17+
text: tokens["color.gray.700"],
18+
textMuted: tokens["color.gray.400"],
1919
};
2020

2121
export const theme = create({
@@ -30,7 +30,7 @@ export const theme = create({
3030
appBg: colors.background,
3131
appContentBg: colors.background,
3232
appBorderColor: colors.border,
33-
appBorderRadius: tokens["shape-border-radius-base"],
33+
appBorderRadius: tokens["shape.border_radius.base"],
3434

3535
// Main colors
3636
colorPrimary: colors.primary,
@@ -51,5 +51,5 @@ export const theme = create({
5151
inputBg: colors.background,
5252
inputBorder: colors.border,
5353
inputTextColor: colors.text,
54-
inputBorderRadius: tokens["shape-border-radius-base"],
54+
inputBorderRadius: tokens["shape.border_radius.base"],
5555
});

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ easy-ui/
3737
| `npm run changes:status` | Retrieves status of changesets |
3838
| `npm run changes:version` | Versions the current changesets |
3939
| `npm run clean` | Removes temp directories from workspaces |
40+
| `npm run dev` | Builds Easy UI on file changes |
4041
| `npm run lint` | Lints Easy UI |
4142
| `npm run format` | Formats files with prettier |
4243
| `npm run start:storybook` | Starts Storybook for dev |

easy-ui-icons/README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,11 @@ import svgFile from "@easypost/easy-ui-icons/svg/Info.svg";
6969

7070
### Commands
7171

72-
| Command | Runs |
73-
| :-------------- | :----------------------- |
74-
| `npm run clean` | Removes temp directories |
75-
| `npm run build` | Builds the icons project |
72+
| Command | Runs |
73+
| :-------------- | :--------------------------------------- |
74+
| `npm run build` | Builds the icons project |
75+
| `npm run clean` | Removes temp directories |
76+
| `npm run dev` | Builds the icons project on file changes |
7677

7778
### Adding an icon
7879

easy-ui-icons/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
},
1919
"scripts": {
2020
"build": "vite build --config ./vite.config.ts",
21-
"clean": "rm -rf .turbo dist node_modules"
21+
"clean": "rm -rf .turbo dist node_modules",
22+
"dev": "vite build --config ./vite.config.ts --watch"
2223
},
2324
"devDependencies": {
2425
"@material-symbols/svg-300": "^0.5.5",

easy-ui-react/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"build:js": "vite build",
2222
"build:types": "tsc --build",
2323
"clean": "rm -rf node_modules dist .turbo",
24+
"dev": "npm run --prefix .. start:storybook",
2425
"lint": "run-p lint:*",
2526
"lint:js": "eslint src --ext .ts,.tsx",
2627
"lint:styles": "stylelint 'src/**/*.{css,scss}'",

easy-ui-react/src/Button/Button.module.scss

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
.variantFilled {
3737
@include Button.variantFilled;
38-
padding: var(--ezui-space-1-5) var(--ezui-space-2);
38+
padding: design-token("space.1.5") design-token("space.2");
3939
}
4040

4141
.variantOutlined {
@@ -48,8 +48,10 @@
4848

4949
.variantOutlined,
5050
.variantLink {
51-
padding: calc(#{var(--ezui-space-1-5)} - #{var(--ezui-shape-border-width-1)})
52-
calc(#{var(--ezui-space-2)} - #{var(--ezui-shape-border-width-1)});
51+
padding: calc(
52+
#{design-token("space.1.5")} - #{design-token("shape.border_width.1")}
53+
)
54+
calc(#{design-token("space.2")} - #{design-token("shape.border_width.1")});
5355
}
5456

5557
.sizeMd {
@@ -61,12 +63,14 @@
6163
}
6264

6365
.sizeSm.variantFilled {
64-
padding: var(--ezui-space-1);
66+
padding: design-token("space.1");
6567
}
6668

6769
.sizeSm.variantOutlined,
6870
.sizeSm.variantLink {
69-
padding: calc(#{var(--ezui-space-1)} - #{var(--ezui-shape-border-width-1)});
71+
padding: calc(
72+
#{design-token("space.1")} - #{design-token("shape.border_width.1")}
73+
);
7074
}
7175

7276
.block {
@@ -75,9 +79,9 @@
7579
}
7680

7781
.iconAtStart {
78-
margin-left: var(--ezui-space-1);
82+
margin-left: design-token("space.1");
7983
}
8084

8185
.iconAtEnd {
82-
margin-right: var(--ezui-space-1);
86+
margin-right: design-token("space.1");
8387
}

easy-ui-react/src/Button/_mixins.scss

Lines changed: 72 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
@import "../styles/common";
2+
13
@mixin base {
24
display: inline-flex;
35
align-items: center;
46
justify-content: center;
5-
border-radius: var(--ezui-shape-border-radius-base);
7+
border-radius: design-token("shape.border_radius.base");
68
cursor: pointer;
79

810
&:focus {
9-
box-shadow: var(--ezui-shadow-button);
11+
box-shadow: theme-token("shadow.button");
1012
outline: none;
1113
}
1214

@@ -17,144 +19,152 @@
1719

1820
@mixin variantFilled {
1921
border: 0;
20-
background-color: var(--ezui-c-button-resting-color);
21-
color: var(--ezui-c-button-filled-font-color);
22+
background-color: component-token("button", "resting.color");
23+
color: component-token("button", "filled.font.color");
2224

2325
&:focus {
24-
background-color: var(--ezui-c-button-hover-focus-color);
26+
background-color: component-token("button", "hover.focus.color");
2527
}
2628

2729
&:disabled {
28-
color: var(--ezui-color-white);
29-
background-color: var(--ezui-color-gray-200);
30+
color: theme-token("color.text.inverse");
31+
background-color: theme-token("color.background.disabled");
3032
}
3133

3234
&:link {
3335
text-decoration: none;
3436
}
3537

3638
&:not(:disabled):active {
37-
color: var(--ezui-c-button-filled-active-font-color);
38-
background-color: var(--ezui-c-button-active-color);
39+
color: component-token("button", "filled.active.font.color");
40+
background-color: component-token("button", "active.color");
3941
&:focus {
4042
box-shadow: none;
4143
}
4244
}
4345

4446
&:hover:not(:disabled):not(:active) {
45-
background-color: var(--ezui-c-button-hover-focus-color);
47+
background-color: component-token("button", "hover.focus.color");
4648
}
4749
}
4850

4951
@mixin variantOutlined {
5052
background-color: transparent;
51-
border: var(--ezui-shape-border-width-1) solid
52-
var(--ezui-c-button-resting-color);
53-
color: var(--ezui-c-button-resting-color);
53+
border: design-token("shape.border_width.1") solid
54+
component-token("button", "resting.color");
55+
color: component-token("button", "resting.color");
5456

5557
&:focus {
56-
border: var(--ezui-shape-border-width-1) solid
57-
var(--ezui-c-button-hover-focus-color);
58-
color: var(--ezui-c-button-hover-focus-color);
58+
border: design-token("shape.border_width.1") solid
59+
component-token("button", "hover.focus.color");
60+
color: component-token("button", "hover.focus.color");
5961
}
6062

6163
&:disabled {
62-
color: var(--ezui-color-gray-300);
63-
border: var(--ezui-shape-border-width-1) solid var(--ezui-color-gray-300);
64+
color: theme-token("color.text.disabled");
65+
border: design-token("shape.border_width.1") solid
66+
theme-token("color.border.disabled");
6467
}
6568

6669
&:link {
6770
text-decoration: none;
6871
}
6972

7073
&:active:not(:disabled) {
71-
color: var(--ezui-c-button-active-color);
72-
border: var(--ezui-shape-border-width-1) solid
73-
var(--ezui-c-button-active-color);
74+
color: component-token("button", "active.color");
75+
border: design-token("shape.border_width.1") solid
76+
component-token("button", "active.color");
7477
&:focus {
7578
box-shadow: none;
7679
}
7780
}
7881

7982
&:hover:not(:disabled):not(:active) {
80-
border: var(--ezui-shape-border-width-1) solid
81-
var(--ezui-c-button-hover-focus-color);
82-
color: var(--ezui-c-button-hover-focus-color);
83+
border: design-token("shape.border_width.1") solid
84+
component-token("button", "hover.focus.color");
85+
color: component-token("button", "hover.focus.color");
8386
}
8487
}
8588

8689
@mixin variantLink {
87-
color: var(--ezui-c-button-resting-color);
90+
color: component-token("button", "resting.color");
8891
background-color: transparent;
89-
border: var(--ezui-shape-border-width-1) solid transparent;
92+
border: design-token("shape.border_width.1") solid transparent;
9093
text-decoration: underline;
9194

9295
&:focus {
93-
border: var(--ezui-shape-border-width-1) solid
94-
var(--ezui-c-button-hover-focus-color);
96+
border: design-token("shape.border_width.1") solid
97+
component-token("button", "hover.focus.color");
9598
}
9699

97100
&:disabled {
98-
color: var(--ezui-color-gray-300);
101+
color: theme-token("color.text.disabled");
99102
}
100103

101104
&:active:not(:disabled) {
102-
color: var(--ezui-c-button-active-color);
105+
color: component-token("button", "active.color");
103106
}
104107

105108
&:hover:not(:disabled):not(:active) {
106-
color: var(--ezui-c-button-hover-focus-color);
109+
color: component-token("button", "hover.focus.color");
107110
}
108111
}
109112

113+
// prettier-ignore
110114
@mixin colorPrimary {
111-
--ezui-c-button-filled-font-color: var(--ezui-color-white);
112-
--ezui-c-button-filled-active-font-color: var(--ezui-color-white);
113-
--ezui-c-button-resting-color: var(--ezui-color-blue-500);
114-
--ezui-c-button-hover-focus-color: var(--ezui-color-blue-600);
115-
--ezui-c-button-active-color: var(--ezui-color-blue-700);
115+
@include component-token("button", "filled.font.color", theme-token("color.text.inverse"));
116+
@include component-token("button", "filled.active.font.color", theme-token("color.text.inverse"));
117+
@include component-token("button", "resting.color", theme-token("color.background.primary"));
118+
@include component-token("button", "hover.focus.color", theme-token("color.background.primary.hovered"));
119+
@include component-token("button", "active.color", theme-token("color.background.primary.pressed"));
116120
}
117121

122+
// prettier-ignore
118123
@mixin colorSecondary {
119-
--ezui-c-button-filled-font-color: var(--ezui-color-white);
120-
--ezui-c-button-filled-active-font-color: var(--ezui-color-white);
121-
--ezui-c-button-resting-color: var(--ezui-color-purple-500);
122-
--ezui-c-button-hover-focus-color: var(--ezui-color-purple-800);
123-
--ezui-c-button-active-color: var(--ezui-color-purple-700);
124+
@include component-token("button", "filled.font.color", theme-token("color.text.inverse"));
125+
@include component-token("button", "filled.active.font.color", theme-token("color.text.inverse"));
126+
@include component-token("button", "resting.color", theme-token("color.background.secondary"));
127+
@include component-token("button", "hover.focus.color", theme-token("color.background.secondary.hovered"));
128+
@include component-token("button", "active.color", theme-token("color.background.secondary.pressed"));
124129
}
125130

131+
// prettier-ignore
126132
@mixin colorSuccess {
127-
--ezui-c-button-filled-font-color: var(--ezui-color-blue-800);
128-
--ezui-c-button-filled-active-font-color: var(--ezui-color-white);
129-
--ezui-c-button-resting-color: var(--ezui-color-green-500);
130-
--ezui-c-button-hover-focus-color: var(--ezui-color-green-600);
131-
--ezui-c-button-active-color: var(--ezui-color-green-700);
133+
@include component-token("button", "filled.font.color", theme-token("color.text.success.inverse"));
134+
@include component-token("button", "filled.active.font.color", theme-token("color.text.success.inverse.pressed"));
135+
@include component-token("button", "resting.color", theme-token("color.background.success"));
136+
@include component-token("button", "hover.focus.color", theme-token("color.background.success.hovered"));
137+
@include component-token("button", "active.color", theme-token("color.background.success.pressed"));
132138
}
133139

140+
// prettier-ignore
134141
@mixin colorWarning {
135-
--ezui-c-button-filled-font-color: var(--ezui-color-blue-800);
136-
--ezui-c-button-filled-active-font-color: var(--ezui-color-blue-800);
137-
--ezui-c-button-resting-color: var(--ezui-color-red-500);
138-
--ezui-c-button-hover-focus-color: var(--ezui-color-red-600);
139-
--ezui-c-button-active-color: var(--ezui-color-red-700);
142+
@include component-token("button", "filled.font.color",theme-token("color.text.danger.inverse"));
143+
@include component-token("button", "filled.active.font.color",theme-token("color.text.danger.inverse.pressed"));
144+
@include component-token("button", "resting.color",theme-token("color.background.danger"));
145+
@include component-token("button", "hover.focus.color",theme-token("color.background.danger.hovered"));
146+
@include component-token("button", "active.color",theme-token("color.background.danger.pressed"));
140147
}
141148

149+
// prettier-ignore
142150
@mixin colorNeutral {
143-
--ezui-c-button-filled-font-color: var(--ezui-color-white);
144-
--ezui-c-button-filled-active-font-color: var(--ezui-color-white);
145-
--ezui-c-button-resting-color: var(--ezui-color-blue-800);
146-
--ezui-c-button-hover-focus-color: var(--ezui-color-black);
147-
--ezui-c-button-active-color: var(--ezui-color-blue-700);
151+
@include component-token("button", "filled.font.color", theme-token("color.text.inverse"));
152+
@include component-token("button", "filled.active.font.color", theme-token("color.text.inverse"));
153+
@include component-token("button", "resting.color", theme-token("color.background.neutral"));
154+
@include component-token("button", "hover.focus.color", theme-token("color.background.neutral.hovered"));
155+
@include component-token("button", "active.color", theme-token("color.background.neutral.pressed"));
148156
}
149157

158+
// prettier-ignore
150159
@mixin colorSupport {
151-
--ezui-c-button-resting-color: var(--ezui-color-blue-800);
152-
--ezui-c-button-hover-focus-color: var(--ezui-color-black);
153-
--ezui-c-button-active-color: var(--ezui-color-gray-700);
160+
@include component-token("button", "resting.color", theme-token("color.border.support"));
161+
@include component-token("button", "hover.focus.color", theme-token("color.border.support.hovered"));
162+
@include component-token("button", "active.color", theme-token("color.border.support.pressed"));
154163
}
155164

165+
// prettier-ignore
156166
@mixin colorInverse {
157-
--ezui-c-button-resting-color: var(--ezui-color-white);
158-
--ezui-c-button-hover-focus-color: var(--ezui-color-gray-100);
159-
--ezui-c-button-active-color: var(--ezui-color-gray-200);
167+
@include component-token("button", "resting.color", theme-token("color.border.inverse"));
168+
@include component-token("button", "hover.focus.color", theme-token("color.border.inverse.hovered"));
169+
@include component-token("button", "active.color", theme-token("color.border.inverse.pressed"));
160170
}

0 commit comments

Comments
 (0)