Skip to content

Commit c4bedd5

Browse files
Add dynamic package, add setElementTheme and setElementVar (#25)
1 parent 1b57548 commit c4bedd5

File tree

27 files changed

+673
-108
lines changed

27 files changed

+673
-108
lines changed

.changeset/hungry-tigers-matter.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@vanilla-extract/css': minor
3+
---
4+
5+
The `createInlineTheme` function has now moved to the `@vanilla-extract/dynamic` package.
6+
7+
```diff
8+
-import { createInlineTheme } from '@vanilla-extract/css/createInlineTheme';
9+
+import { createInlineTheme } from '@vanilla-extract/dynamic';
10+
```

README.md

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ Basically, it’s [“CSS Modules](https://github.com/css-modules/css-modules)-i
3030

3131
🏃‍♂️   Optional runtime version for development and testing.
3232

33+
🙈   Optional API for dynamic runtime theming.
34+
3335
---
3436

3537
**Write your styles in `.css.ts` files.**
@@ -84,7 +86,6 @@ document.write(`
8486
- [mapToStyles](#maptostyles)
8587
- [createTheme](#createtheme)
8688
- [createGlobalTheme](#createglobaltheme)
87-
- [createInlineTheme](#createinlinetheme)
8889
- [createThemeVars](#createthemevars)
8990
- [assignVars](#assignvars)
9091
- [createVar](#createvar)
@@ -93,6 +94,10 @@ document.write(`
9394
- [globalFontFace](#globalfontface)
9495
- [keyframes](#keyframes)
9596
- [globalKeyframes](#globalkeyframes)
97+
- [Dynamic API](#dynamic-api)
98+
- [createInlineTheme](#createinlinetheme)
99+
- [setElementTheme](#setelementtheme)
100+
- [setElementVar](#setelementvar)
96101
- [Utility functions](#utility-functions)
97102
- [calc](#calc)
98103
- [Thanks](#thanks)
@@ -376,27 +381,6 @@ export const themeVars = createGlobalTheme(':root', {
376381

377382
> 💡 All theme variants must provide a value for every variable or it’s a type error.
378383
379-
### createInlineTheme
380-
381-
Generates a custom theme at runtime as an inline style object.
382-
383-
```ts
384-
import { createInlineTheme } from '@vanilla-extract/css/createInlineTheme';
385-
import { themeVars, exampleStyle } from './styles.css.ts';
386-
387-
const customTheme = createInlineTheme(themeVars, {
388-
small: '4px',
389-
medium: '8px',
390-
large: '16px'
391-
});
392-
393-
document.write(`
394-
<section style="${customTheme}">
395-
<h1 class="${exampleStyle}">Hello world!</h1>
396-
</section>
397-
`);
398-
```
399-
400384
### createThemeVars
401385

402386
Creates a collection of CSS Variables without coupling them to a specific theme variant.
@@ -439,7 +423,7 @@ export const themeB = createTheme(themeVars, {
439423

440424
### assignVars
441425

442-
Allows you to set an entire collection of CSS Variables anywhere within a style block.
426+
Assigns a collection of CSS Variables anywhere within a style block.
443427

444428
> 💡 This is useful for creating responsive themes since it can be used within `@media` blocks.
445429
@@ -597,6 +581,65 @@ export const animated = style({
597581
});
598582
```
599583

584+
## Dynamic API
585+
586+
We also provide a lightweight standalone package to support dynamic runtime theming.
587+
588+
```bash
589+
$ yarn add --dev @vanilla-extract/dynamic
590+
```
591+
592+
### createInlineTheme
593+
594+
Generates a custom theme at runtime as an inline style object.
595+
596+
```ts
597+
import { createInlineTheme } from '@vanilla-extract/dynamic';
598+
import { themeVars, exampleStyle } from './styles.css.ts';
599+
600+
const customTheme = createInlineTheme(themeVars, {
601+
small: '4px',
602+
medium: '8px',
603+
large: '16px'
604+
});
605+
606+
document.write(`
607+
<section style="${customTheme}">
608+
<h1 class="${exampleStyle}">Hello world!</h1>
609+
</section>
610+
`);
611+
```
612+
613+
### setElementTheme
614+
615+
Sets a collection of CSS Variables on an element.
616+
617+
```ts
618+
import { setElementTheme } from '@vanilla-extract/dynamic';
619+
import { themeVars } from './styles.css.ts';
620+
621+
const element = document.getElementById('myElement');
622+
setElementTheme(element, themeVars, {
623+
small: '4px',
624+
medium: '8px',
625+
large: '16px'
626+
});
627+
```
628+
629+
> 💡 All variables passed into this function must be assigned or it’s a type error.
630+
631+
### setElementVar
632+
633+
Sets a single var on an element.
634+
635+
```ts
636+
import { setElementVar } from '@vanilla-extract/dynamic';
637+
import { themeVars } from './styles.css.ts';
638+
639+
const element = document.getElementById('myElement');
640+
setElementVar(element, themeVars.color.brand, 'darksalmon');
641+
```
642+
600643
## Utility functions
601644

602645
We also provide a standalone package of optional utility functions to make it easier to work with CSS in TypeScript.

fixtures/themed/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"author": "SEEK",
77
"private": true,
88
"dependencies": {
9-
"@vanilla-extract/css": "0.1.0"
9+
"@vanilla-extract/css": "0.1.0",
10+
"@vanilla-extract/dynamic": "0.1.0"
1011
}
1112
}

fixtures/themed/src/index.ts

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { createInlineTheme } from '@vanilla-extract/css/createInlineTheme';
1+
import {
2+
createInlineTheme,
3+
setElementTheme,
4+
setElementVar,
5+
} from '@vanilla-extract/dynamic';
26

37
import { theme, altTheme, responsiveTheme, vars } from './themes.css';
48
import { button, container, opacity } from './styles.css';
@@ -47,6 +51,16 @@ function render() {
4751
}" class="${button.join(' ')} ${
4852
opacity['1/2']
4953
}">Inline theme button</button>
54+
<div>
55+
Dynamic vars
56+
<div id="${
57+
testNodes.dynamicVarsContainer
58+
}" class="${container}">
59+
<button id="${
60+
testNodes.dynamicVarsButton
61+
}" class="${button.join(
62+
' ',
63+
)}">Dynamic vars button</button>
5064
<div class="${responsiveTheme}">
5165
Responsive theme
5266
<div id="${
@@ -57,9 +71,12 @@ function render() {
5771
}" class="${button.join(
5872
' ',
5973
)}">Responsive theme button</button>
60-
</div>
61-
</div>
62-
</div>
74+
</div>
75+
</div>
76+
</div>
77+
</div>
78+
</div>
79+
</div>
6380
</div>
6481
</div>
6582
</div>
@@ -69,6 +86,32 @@ function render() {
6986
</div>
7087
</div>
7188
`;
89+
90+
const dynamicVarsContainer = document.getElementById(
91+
testNodes.dynamicVarsContainer,
92+
);
93+
94+
if (!dynamicVarsContainer) {
95+
throw new Error('Dynamic vars container not found.');
96+
}
97+
98+
setElementTheme(dynamicVarsContainer, vars, {
99+
colors: {
100+
backgroundColor: 'transparent',
101+
text: 'papayawhip',
102+
},
103+
space: {
104+
1: '5px',
105+
2: '10px',
106+
3: '15px',
107+
},
108+
});
109+
110+
setElementVar(
111+
dynamicVarsContainer,
112+
vars.colors.backgroundColor,
113+
'darksalmon',
114+
);
72115
}
73116

74117
render();

fixtures/themed/test-nodes.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
"nestedRootButton": "nestedRootButton",
99
"inlineThemeContainer": "inlineThemeContainer",
1010
"inlineThemeButton": "inlineThemeButton",
11+
"dynamicVarsContainer": "dynamicVarsContainer",
12+
"dynamicVarsButton": "dynamicVarsButton",
1113
"responsiveThemeContainer": "responsiveThemeContainer",
1214
"responsiveThemeButton": "responsiveThemeButton"
1315
}

packages/css/createInlineTheme/package.json

Lines changed: 0 additions & 9 deletions
This file was deleted.

packages/css/package.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,14 @@
1414
"index.ts",
1515
"adapter.ts",
1616
"transformCss.ts",
17-
"fileScope.ts",
18-
"createInlineTheme.ts"
17+
"fileScope.ts"
1918
]
2019
},
2120
"files": [
2221
"/dist",
2322
"/adapter",
2423
"/transformCss",
25-
"/fileScope",
26-
"/createInlineTheme"
24+
"/fileScope"
2725
],
2826
"repository": {
2927
"type": "git",
@@ -34,6 +32,7 @@
3432
"license": "MIT",
3533
"dependencies": {
3634
"@emotion/hash": "^0.8.0",
35+
"@vanilla-extract/private": "^0.1.0",
3736
"css-selector-parser": "^1.4.1",
3837
"cssesc": "^3.0.0",
3938
"csstype": "^3.0.7",

packages/css/src/theme.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import type { Contract, MapLeafNodes, ThemeVars, Tokens } from './types';
1+
import type { Contract, MapLeafNodes } from '@vanilla-extract/private';
2+
import type { ThemeVars, Tokens } from './types';
23
import { appendCss, registerClassName } from './adapter';
34
import { getFileScope } from './fileScope';
45
import { generateIdentifier } from './identifier';

packages/css/src/transformCss.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getVarName } from '@vanilla-extract/private';
12
import cssesc from 'cssesc';
23

34
import type {
@@ -234,15 +235,7 @@ class Stylesheet {
234235
}
235236

236237
return {
237-
...mapKeys(vars, (_value, key) => {
238-
const matches = key.match(/^var\((.*)\)$/);
239-
240-
if (matches) {
241-
return matches[1];
242-
}
243-
244-
return key;
245-
}),
238+
...mapKeys(vars, (_value, key) => getVarName(key)),
246239
...rest,
247240
};
248241
}

packages/css/src/types.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { Contract, MapLeafNodes } from '@vanilla-extract/private';
12
import type { PropertiesFallback, AtRule } from 'csstype';
23

34
import type { SimplePseudos } from './transformCss';
@@ -92,20 +93,10 @@ export interface Adapter {
9293
onEndFileScope: (fileScope: FileScope) => void;
9394
}
9495

95-
export type Contract = {
96-
[key: string]: string | null | Contract;
97-
};
98-
9996
export type Tokens = {
10097
[key: string]: string | Tokens;
10198
};
10299

103-
export type MapLeafNodes<Obj, LeafType> = {
104-
[Prop in keyof Obj]: Obj[Prop] extends Record<string | number, any>
105-
? MapLeafNodes<Obj[Prop], LeafType>
106-
: LeafType;
107-
};
108-
109100
export type ThemeVars<ThemeContract extends Contract> = MapLeafNodes<
110101
ThemeContract,
111102
string

0 commit comments

Comments
 (0)