Skip to content

Commit 231124d

Browse files
authored
Merge c92a5b6 into aa776bd
2 parents aa776bd + c92a5b6 commit 231124d

File tree

17 files changed

+103
-50
lines changed

17 files changed

+103
-50
lines changed

.changeset/clean-ravens-happen.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@khanacademy/wonder-blocks-tokens": minor
3+
---
4+
5+
Export `border` and `sizing` as CSS variables. Map JS tokens to css var counterparts

__docs__/wonder-blocks-tabs/navigation-tabs.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ export const HeaderWithNavigationTabsExample: StoryComponentType = {
299299
navigationTabsRoot: {
300300
// set margin to negative value of header vertical spacing so
301301
// that selected indicator lines up with header border
302-
margin: `-${headerVerticalSpacing} 0`,
302+
margin: `calc(${headerVerticalSpacing} * -1) 0`,
303303
},
304304
});
305305
const [currentTab, setCurrentTab] = React.useState(0);

__docs__/wonder-blocks-tokens/tokens-border.mdx

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import TokenTable from "../components/token-table";
44

55
import Banner from "@khanacademy/wonder-blocks-banner";
66
import {View} from "@khanacademy/wonder-blocks-core";
7-
import * as tokens from "@khanacademy/wonder-blocks-tokens";
7+
import {border, color, sizing} from "@khanacademy/wonder-blocks-tokens";
88

99
<Meta title="Packages / Tokens / Border" />
1010

@@ -17,6 +17,10 @@ export const baseColumns = (kind) => [
1717
</code>
1818
),
1919
},
20+
{
21+
label: "CSS Variable",
22+
cell: (row) => <code>{row.css}</code>,
23+
},
2024
{
2125
label: "Value",
2226
cell: "value",
@@ -28,7 +32,7 @@ export const baseColumns = (kind) => [
2832
The `border` tokens are used to define the border properties of an element. The
2933
border tokens are broken down into two categories: `radius` and `width`.
3034

31-
<View style={{marginBottom: tokens.spacing.medium_16}}>
35+
<View style={{marginBottom: sizing.size_160}}>
3236
<Banner
3337
kind="info"
3438
text="We don't define border colors here, and instead we recommend you to rely on the `color` token primitives to build on top of that."
@@ -42,8 +46,8 @@ border tokens are broken down into two categories: `radius` and `width`.
4246
import {border} from "@khanacademy/wonder-blocks-tokens";
4347
const styles = {
4448
borderedContainer: {
45-
borderRadius: border.radius.small,
46-
borderWidth: border.width.small,
49+
borderRadius: border.radius.radius_040,
50+
borderWidth: border.width.thin,
4751
},
4852
};
4953
```
@@ -60,18 +64,18 @@ const styles = {
6064
cell: (row) => (
6165
<View
6266
style={{
63-
backgroundColor: tokens.color.purple,
67+
backgroundColor: color.purple,
6468
borderRadius: row.value,
65-
width: tokens.sizing.size_480,
66-
height: tokens.sizing.size_480,
69+
width: sizing.size_480,
70+
height: sizing.size_480,
6771
}}
6872
>
6973
&nbsp;
7074
</View>
7175
),
7276
},
7377
]}
74-
tokens={tokens.border.radius}
78+
tokens={border.radius}
7579
/>
7680

7781
### Width
@@ -84,16 +88,16 @@ const styles = {
8488
cell: (row) => (
8589
<View
8690
style={{
87-
borderColor: tokens.color.purple,
91+
borderColor: color.purple,
8892
borderWidth: row.value,
89-
width: tokens.sizing.size_480,
90-
height: tokens.sizing.size_480,
93+
width: sizing.size_480,
94+
height: sizing.size_480,
9195
}}
9296
>
9397
&nbsp;
9498
</View>
9599
),
96100
},
97101
]}
98-
tokens={tokens.border.width}
102+
tokens={border.width}
99103
/>

__docs__/wonder-blocks-tokens/tokens-sizing.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ const styles = {padding: sizing.size_160};
4141
label: "Token",
4242
cell: (row) => <code>sizing.{row.label}</code>,
4343
},
44+
{
45+
label: "CSS Variable",
46+
cell: (row) => <code>{row.css}</code>,
47+
},
4448
{
4549
label: "Base unit multiplier",
4650
cell: (row) => row.value.replace("rem", "x"),

packages/wonder-blocks-dropdown/src/components/select-opener.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ const _generateStyles = (placeholder: boolean, error: boolean) => {
279279
// TODO(WB-1868): Address outlineOffset to include hover and focus states
280280
const sharedOutlineStyling = {
281281
// Outline sits inside the border (inset)
282-
outlineOffset: `-${border.width.medium}`,
282+
outlineOffset: `calc(${border.width.medium} * -1)`,
283283
outlineStyle: "solid",
284284
outlineWidth: border.width.medium,
285285
};

packages/wonder-blocks-tabs/src/components/navigation-tab-item.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,10 @@ const styles = StyleSheet.create({
111111
listStyle: "none",
112112
display: "inline-flex",
113113
[":has(a:hover)" as any]: {
114-
boxShadow: `inset 0 -${sizing.size_020} 0 0 ${semanticColor.action.secondary.progressive.hover.foreground}`,
114+
boxShadow: `inset 0 calc(${sizing.size_020}*-1) 0 0 ${semanticColor.action.secondary.progressive.hover.foreground}`,
115115
},
116116
[":has(a:active)" as any]: {
117-
boxShadow: `inset 0 -${sizing.size_060} 0 0 ${semanticColor.action.secondary.progressive.press.foreground}`,
117+
boxShadow: `inset 0 calc(${sizing.size_060}*-1) 0 0 ${semanticColor.action.secondary.progressive.press.foreground}`,
118118
},
119119
paddingBlockStart: sizing.size_080,
120120
paddingBlockEnd: sizing.size_180,

packages/wonder-blocks-tokens/src/build/generate-css-variables.ts

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import ancesdir from "ancesdir";
55
import {THEME_DATA_ATTRIBUTE} from "@khanacademy/wonder-blocks-theming";
66
import {generateTokens} from "../internal/generate-tokens";
77

8-
const THEMES_DIR = "../theme/color";
8+
const THEMES_DIR = "../theme";
99

1010
/**
1111
* Process all themes in the theme directory.
@@ -14,22 +14,37 @@ const THEMES_DIR = "../theme/color";
1414
* the CSS variables for each theme.
1515
*/
1616
function processThemeCollection() {
17-
return fs.readdirSync(path.resolve(__dirname, THEMES_DIR)).map((file) => {
18-
// Remove the file extension
19-
const filename = file.split(".")[0];
20-
// eslint-disable-next-line @typescript-eslint/no-require-imports
21-
const {default: themeObject} = require(`${THEMES_DIR}/${filename}`);
17+
return (
18+
fs
19+
.readdirSync(path.resolve(__dirname, THEMES_DIR), {
20+
// Needed to determine whether the file is a directory or a
21+
// file.
22+
withFileTypes: true,
23+
})
24+
// Only include files that contain tokens
25+
.filter((file) => {
26+
return file.isFile() && file.name.endsWith(".ts");
27+
})
28+
.map((file) => {
29+
// Remove the file extension
30+
const filename = file.name.split(".")[0];
2231

23-
return {name: filename, tokens: generateTokens(themeObject)};
24-
});
32+
// eslint-disable-next-line @typescript-eslint/no-require-imports
33+
const {default: themeObject} = require(
34+
`${THEMES_DIR}/${filename}`,
35+
);
36+
37+
return {name: filename, tokens: generateTokens(themeObject)};
38+
})
39+
);
2540
}
2641

2742
/**
2843
* Generate the CSS selectors containing CSS variables for each theme.
2944
*/
3045
function generateCssVariablesDefinitions() {
3146
return processThemeCollection()
32-
.map((theme) => {
47+
.map((theme, index) => {
3348
const cssVariables = Object.entries(theme.tokens)
3449
.map(([key, value]) => `${key}: ${value};`)
3550
.join("");

packages/wonder-blocks-tokens/src/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
// primitive tokens
2-
import {border} from "./tokens/border";
32
import {color} from "./tokens/color";
43
import {font} from "./tokens/font";
5-
import {sizing} from "./tokens/sizing";
64
import {spacing} from "./tokens/spacing";
75

86
// media queries
97
import {breakpoint} from "./tokens/media-queries";
10-
// semantic tokens
11-
import {semanticColor} from "./tokens/semantic-color";
128

139
// utils
1410
import {mix, fade} from "./util/utils";
1511

12+
// theme
13+
import theme from "./tokens/theme";
14+
15+
const {border, semanticColor, sizing} = theme;
16+
1617
export {
1718
/**
1819
* Primitive tokens for the Wonder Blocks design system.

packages/wonder-blocks-tokens/src/internal/__test__/generate-tokens.test.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,37 @@ describe("generateTokens", () => {
44
it("should generate tokens", () => {
55
// Arrange
66
const obj = {
7-
primary: "red",
8-
secondary: "blue",
7+
semanticColor: {
8+
primary: "red",
9+
secondary: "blue",
10+
},
911
};
1012

1113
// Act
1214
const cssVars = generateTokens(obj);
1315

1416
// Assert
1517
expect(cssVars).toStrictEqual({
16-
"--wb-s-color-primary": "red",
17-
"--wb-s-color-secondary": "blue",
18+
"--wb-semanticColor-primary": "red",
19+
"--wb-semanticColor-secondary": "blue",
1820
});
1921
});
2022

2123
it("should not generate tokens in empty objects", () => {
2224
// Arrange
2325
const obj = {
24-
primary: {},
25-
secondary: "blue",
26+
semanticColor: {
27+
primary: {},
28+
secondary: "blue",
29+
},
2630
};
2731

2832
// Act
2933
const cssVars = generateTokens(obj);
3034

3135
// Assert
3236
expect(cssVars).toStrictEqual({
33-
"--wb-s-color-secondary": "blue",
37+
"--wb-semanticColor-secondary": "blue",
3438
});
3539
});
3640
});

packages/wonder-blocks-tokens/src/internal/generate-tokens.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {CSS_VAR_COLOR_PREFIX} from "../util/constants";
1+
import {CSS_VAR_PREFIX} from "../util/constants";
22
import {RecursivePartial} from "../util/types";
33

44
/**
@@ -11,7 +11,7 @@ export function generateTokens<T>(root: T): Record<string, string> {
1111
const tokens = {} as Record<string, string>;
1212
function generateCssVariables(
1313
obj: T | RecursivePartial<T>,
14-
prefix = CSS_VAR_COLOR_PREFIX,
14+
prefix = CSS_VAR_PREFIX,
1515
) {
1616
for (const key in obj as RecursivePartial<T>) {
1717
if (typeof obj[key] === "object") {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import {sizing} from "./primitive/sizing";
2+
import {semanticColor} from "./semantic/semantic-color";
3+
import {border} from "./primitive/border";
4+
5+
/**
6+
* NOTE: All the tokens included in this `theme` file will be automatically
7+
* mapped to CSS vars and included in
8+
* @khanacademy/wonder-blocks-tokens/styles.css.
9+
*
10+
* The css vars transformation is done in the `generate-css-variables.ts`
11+
* script. Used by `pnpm run dev` in the `@khanacademy/wonder-blocks-tokens`
12+
* package.
13+
*/
14+
export default {
15+
border,
16+
semanticColor,
17+
sizing,
18+
};

packages/wonder-blocks-tokens/src/tokens/border.ts renamed to packages/wonder-blocks-tokens/src/theme/primitive/border.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {sizing, remToPx} from "./sizing";
1+
import {remToPx, sizing} from "./sizing";
22

33
export const border = {
44
/**

packages/wonder-blocks-tokens/src/theme/color/default.ts renamed to packages/wonder-blocks-tokens/src/theme/semantic/semantic-color.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const border = {
77
inverse: color.white,
88
};
99

10-
export default {
10+
export const semanticColor = {
1111
/**
1212
* For buttons, links, and controls to communicate the presence and meaning
1313
* of interaction.

packages/wonder-blocks-tokens/src/tokens/semantic-color.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import {CSS_VAR_PREFIX} from "../util/constants";
2+
import {mapValuesToCssVars} from "../internal/map-values-to-css-vars";
3+
import themeDefault from "../theme/default";
4+
5+
export default mapValuesToCssVars(themeDefault, CSS_VAR_PREFIX);
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
/**
2-
* The prefix for all CSS variables that are semantic colors.
2+
* The prefix for all CSS variables that are converted from the original tokens.
33
*
44
* NOTE: The prefix uses the following structure:
5-
* --wb-<namespace>-<token_category>-
5+
* --wb-<namespace>-<token_category>-*
66
*
7-
* - namespace: The design token namespace (`s` for semantic tokens).
8-
* - token_category: The category of the design token (e.g. `color`, `size`).
7+
* - namespace: The design token namespace (`semanticColor`).
8+
* - token_category: The category of the design token (e.g. `border`, `sizing`).
9+
*
10+
* @see https://khanacademy.atlassian.net/wiki/spaces/WB/pages/3967287319/Component+tokens+structure
911
*/
10-
export const CSS_VAR_COLOR_PREFIX = "--wb-s-color-";
12+
export const CSS_VAR_PREFIX = "--wb-";

0 commit comments

Comments
 (0)