Skip to content

Commit e34996a

Browse files
committed
WIP
1 parent 9743663 commit e34996a

File tree

2 files changed

+261
-2
lines changed

2 files changed

+261
-2
lines changed

src/main.ts

Lines changed: 228 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { generateRadixColors } from './generateRadixColors.js';
22
import { defineCustomElements } from '@utrecht/web-component-library-stencil/loader/index.js';
3+
import { toCssName, toCssValue, styleAttribute, setTokens } from './utils.js';
34
import '@utrecht/page-layout-css';
45
import '@utrecht/body-css';
56
import '@utrecht/root-css';
@@ -8,25 +9,233 @@ import './basis-theme.css';
89

910
defineCustomElements();
1011

12+
const primaryButton1 = {
13+
'utrecht.button.primary-action.background-color': '{basis.color.primary.interactive-1}',
14+
'utrecht.button.primary-action.border-color': '{basis.color.primary.border-2}',
15+
'utrecht.button.primary-action.color': '{basis.color.primary.text-2}',
16+
'utrecht.button.primary-action.hover.background-color': '{basis.color.primary.interactive-2}',
17+
'utrecht.button.primary-action.hover.border-color': '{basis.color.primary.border-3}',
18+
'utrecht.button.primary-action.hover.color': '{basis.color.primary.text-2}',
19+
'utrecht.button.primary-action.active.background-color': '{basis.color.primary.interactive-3}',
20+
'utrecht.button.primary-action.active.border-color': '{basis.color.primary.border-3}',
21+
'utrecht.button.primary-action.active.color': '{basis.color.primary.text-2}',
22+
};
23+
24+
const primaryButton2 = {
25+
...primaryButton1,
26+
'utrecht.button.primary-action.border-color': '{basis.color.transparent}',
27+
};
28+
29+
const primaryButton3 = {
30+
'utrecht.button.primary-action.background-color': '{basis.color.primary-inverse.interactive-1}',
31+
'utrecht.button.primary-action.border-color': '{basis.color.primary-inverse.border-2}',
32+
'utrecht.button.primary-action.color': '{basis.color.primary-inverse.text-2}',
33+
'utrecht.button.primary-action.hover.background-color': '{basis.color.primary-inverse.interactive-2}',
34+
'utrecht.button.primary-action.hover.border-color': '{basis.color.primary-inverse.border-3}',
35+
'utrecht.button.primary-action.hover.color': '{basis.color.primary-inverse.text-2}',
36+
'utrecht.button.primary-action.active.background-color': '{basis.color.primary-inverse.interactive-3}',
37+
'utrecht.button.primary-action.active.border-color': '{basis.color.primary-inverse.border-3}',
38+
'utrecht.button.primary-action.active.color': '{basis.color.primary-inverse.text-2}',
39+
};
40+
41+
const primaryButton4 = {
42+
...primaryButton3,
43+
'utrecht.button.primary-action.border-color': '{basis.color.transparent}',
44+
'utrecht.button.primary-action.hover.border-color': '{basis.color.transparent}',
45+
'utrecht.button.primary-action.active.border-color': '{basis.color.transparent}',
46+
};
47+
48+
const primaryButton5 = {
49+
...primaryButton1,
50+
'utrecht.button.primary-action.background-color': '{basis.color.transparent}',
51+
};
52+
53+
const primaryButton6 = {
54+
...primaryButton5,
55+
'utrecht.button.primary-action.background-color': '{basis.color.transparent}',
56+
'utrecht.button.primary-action.border-color': '{basis.color.transparent}',
57+
};
58+
59+
// const updateKeys = <T>(object: { [index: string]: T }, callback: (arg: string) => string) =>
60+
// Object.fromEntries(Object.entries(object).map(([key, value]) => [callback(key), value]));
61+
62+
const updateKeysValues = (object: { [index: string]: string }, callback: (arg: string) => string) =>
63+
Object.fromEntries(Object.entries(object).map(([key, value]) => [callback(key), callback(value)]));
64+
65+
const secondaryButton1 = updateKeysValues(primaryButton1, (arg: string) => arg.replace('primary', 'secondary'));
66+
const secondaryButton2 = updateKeysValues(primaryButton2, (arg: string) => arg.replace('primary', 'secondary'));
67+
const secondaryButton3 = updateKeysValues(primaryButton3, (arg: string) => arg.replace('primary', 'secondary'));
68+
const secondaryButton4 = updateKeysValues(primaryButton4, (arg: string) => arg.replace('primary', 'secondary'));
69+
70+
const subtleButton1 = updateKeysValues(primaryButton1, (arg: string) => arg.replace('primary-action', 'subtle'));
71+
const subtleButton2 = updateKeysValues(primaryButton2, (arg: string) => arg.replace('primary-action', 'subtle'));
72+
const subtleButton3 = updateKeysValues(primaryButton3, (arg: string) => arg.replace('primary-action', 'subtle'));
73+
const subtleButton4 = updateKeysValues(primaryButton4, (arg: string) => arg.replace('primary-action', 'subtle'));
74+
const subtleButton5 = updateKeysValues(primaryButton5, (arg: string) => arg.replace('primary-action', 'subtle'));
75+
const subtleButton6 = updateKeysValues(primaryButton6, (arg: string) => arg.replace('primary-action', 'subtle'));
76+
77+
const aaTargetSize = {
78+
'basis.pointer-target.min-block-size': '24px',
79+
'basis.pointer-target.min-inline-size': '24px',
80+
};
81+
const aaaTargetSize = {
82+
'basis.pointer-target.min-block-size': '44px',
83+
'basis.pointer-target.min-inline-size': '44px',
84+
};
85+
86+
const materialTargetSize = {
87+
'basis.pointer-target.min-block-size': '48px',
88+
'basis.pointer-target.min-inline-size': '48px',
89+
};
90+
91+
const buttonWithoutPadding = {
92+
'utrecht.button.padding-inline-start': '0',
93+
'utrecht.button.padding-inline-end': '0',
94+
'utrecht.button.padding-block-start': '0',
95+
'utrecht.button.padding-block-end': '0',
96+
};
97+
98+
const formControlPaddingBlockZero = {
99+
'basis.form-control.padding-block-start': '0',
100+
'basis.form-control.padding-block-end': '0',
101+
};
102+
const formControlPaddingBlockSmall = {
103+
'basis.form-control.padding-block-start': '{basis.space.block.sm}',
104+
'basis.form-control.padding-block-end': '{basis.space.block.sm}',
105+
};
106+
const formControlPaddingBlockMedium = {
107+
'basis.form-control.padding-block-start': '{basis.space.block.md}',
108+
'basis.form-control.padding-block-end': '{basis.space.block.md}',
109+
};
110+
const formControlPaddingBlockLarge = {
111+
'basis.form-control.padding-block-start': '{basis.space.block.lg}',
112+
'basis.form-control.padding-block-end': '{basis.space.block.lg}',
113+
};
114+
115+
const formControlPaddingInlineZero = {
116+
'basis.form-control.padding-inline-start': '0',
117+
'basis.form-control.padding-inline-end': '0',
118+
};
119+
const formControlPaddingInlineSmall = {
120+
'basis.form-control.padding-inline-start': '{basis.space.inline.sm}',
121+
'basis.form-control.padding-inline-end': '{basis.space.inline.sm}',
122+
};
123+
const formControlPaddingInlineMedium = {
124+
'basis.form-control.padding-inline-start': '{basis.space.inline.md}',
125+
'basis.form-control.padding-inline-end': '{basis.space.inline.md}',
126+
};
127+
const formControlPaddingInlineLarge = {
128+
'basis.form-control.padding-inline-start': '{basis.space.inline.lg}',
129+
'basis.form-control.padding-inline-end': '{basis.space.inline.lg}',
130+
};
131+
11132
document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
12133
<utrecht-page-header>
13134
<h1>Theme Builder</h1>
14135
</utrecht-page-header>
15136
<utrecht-page-body>
137+
<form>
16138
<div>
17139
<input type="color" oninput="handleColor(event.target, 'primary')" id="primary-input" value="#FF0000">
18-
<utrecht-button appearance="primary-action-button">Primary action</utrecht-button>
140+
<utrecht-button type="button" appearance="primary-action-button">Primary action</utrecht-button>
19141
</div>
20142
<div>
21143
<input type="color" oninput="handleColor(event.target, 'secondary')" id="secondary-input" value="#00FF00">
22-
<utrecht-button appearance="secondary-action-button">Secondary action</utrecht-button>
144+
<utrecht-button type="button" appearance="secondary-action-button">Secondary action</utrecht-button>
23145
</div>
24146
<div>
25147
<input type="color" oninput="handleColor(event.target, 'text')" id="text-input" value="#000000">
26148
<div>Text</div>
27149
</div>
28150
<div>
151+
<p>Form control border radius:</p>
152+
<utrecht-textbox></utrecht-textbox>
153+
<ul>
154+
<li><utrecht-button type="button" appearance="secondary-action-button" name="basis.form-control.border-radius" value="0" onclick="setToken(event.target)">Square corners</utrecht-button> (recommended)</li>
155+
<li><utrecht-button type="button" appearance="secondary-action-button" name="basis.form-control.border-radius" value="{basis.border-radius.sm}" onclick="setToken(event.target)">Small</utrecht-button></li>
156+
<li><utrecht-button type="button" appearance="secondary-action-button" name="basis.form-control.border-radius" value="{basis.border-radius.md}" onclick="setToken(event.target)">Medium</utrecht-button></li>
157+
<li><utrecht-button type="button" appearance="secondary-action-button" name="basis.form-control.border-radius" value="{basis.border-radius.lg}" onclick="setToken(event.target)">Large</utrecht-button></li>
158+
</ul>
159+
</div>
160+
<div>
161+
<figure>
162+
<div style="${styleAttribute(buttonWithoutPadding)}">
163+
<utrecht-textarea value="Ut quos illum eligendi. Et aut optio vitae. Reiciendis consectetur ipsam illo laborum rem id. Quo vel iure optio commodi veniam nihil. Quae ipsa non qui. Rem dolores nulla commodi ratione cum.
164+
Aut iste quam unde. Iure quidem et accusantium pariatur molestiae occaecati consequatur. Aut consectetur amet ea sint officia nesciunt ullam ut. Odio nulla rem neque et facere.
165+
Necessitatibus debitis eos expedita dolor. Quam laudantium qui officia est et eos. Sunt dolores voluptatibus nisi similique quae consequatur est.
166+
Repellendus assumenda eveniet qui. Ab eum et ut et odit quia. Voluptates rerum et qui sed aperiam totam veritatis quos."></utrecht-textarea>
167+
</div>
168+
<figcaption>Textarea without minimum pointer target size, demonstrating the padding needed for readability</figcaption>
169+
</figure>
170+
<p>Form control padding above and below:</p>
171+
<ul>
172+
<li><utrecht-button type="button" appearance="secondary-action-button" value='${JSON.stringify(formControlPaddingBlockZero)}' onclick="setTokens(event.target)">No padding</utrecht-button></li>
173+
<li><utrecht-button type="button" appearance="secondary-action-button" value='${JSON.stringify(formControlPaddingBlockSmall)}' onclick="setTokens(event.target)">Small</utrecht-button></li>
174+
<li><utrecht-button type="button" appearance="secondary-action-button" value='${JSON.stringify(formControlPaddingBlockMedium)}' onclick="setTokens(event.target)">Medium</utrecht-button> (recommended)</li>
175+
<li><utrecht-button type="button" appearance="secondary-action-button" value='${JSON.stringify(formControlPaddingBlockLarge)}' onclick="setTokens(event.target)">Large</utrecht-button></li>
176+
</ul>
177+
<p>Form control padding left and right:</p>
178+
<ul>
179+
<li><utrecht-button type="button" appearance="secondary-action-button" value='${JSON.stringify(formControlPaddingInlineZero)}' onclick="setTokens(event.target)">No padding</utrecht-button></li>
180+
<li><utrecht-button type="button" appearance="secondary-action-button" value='${JSON.stringify(formControlPaddingInlineSmall)}' onclick="setTokens(event.target)">Small</utrecht-button></li>
181+
<li><utrecht-button type="button" appearance="secondary-action-button" value='${JSON.stringify(formControlPaddingInlineMedium)}' onclick="setTokens(event.target)">Medium</utrecht-button> (recommended)</li>
182+
<li><utrecht-button type="button" appearance="secondary-action-button" value='${JSON.stringify(formControlPaddingInlineLarge)}' onclick="setTokens(event.target)">Large</utrecht-button></li>
183+
</ul>
184+
</div>
185+
<div>
186+
<p>Button border radius:</p>
187+
<utrecht-textbox></utrecht-textbox>
188+
<ul>
189+
<li><utrecht-button type="button" appearance="secondary-action-button" name="utrecht.button.border-radius" value="0" onclick="setToken(event.target)">Square corners</utrecht-button></li>
190+
<li><utrecht-button type="button" appearance="secondary-action-button" name="utrecht.button.border-radius" value=onclick="setToken(event.target)">Small</utrecht-button> (recommended)</li>
191+
<li><utrecht-button type="button" appearance="secondary-action-button" name="utrecht.button.border-radius" value="{basis.border-radius.md}" onclick="setToken(event.target)">Medium</utrecht-button></li>
192+
<li><utrecht-button type="button" appearance="secondary-action-button" name="utrecht.button.border-radius" value="{basis.border-radius.lg}" onclick="setToken(event.target)">Large</utrecht-button></li>
193+
</ul>
194+
</div>
195+
<div>
196+
<p>Primary button style:</p>
197+
<ul>
198+
<li><utrecht-button type="button" appearance="primary-action-button" value='${JSON.stringify(primaryButton1)}' onclick="setTokens(event.target)">Plain with border</utrecht-button></li>
199+
<li><utrecht-button type="button" appearance="primary-action-button" value='${JSON.stringify(primaryButton2)}' onclick="setTokens(event.target)">Plain without border</utrecht-button></li>
200+
<li><utrecht-button type="button" appearance="primary-action-button" value='${JSON.stringify(primaryButton3)}' onclick="setTokens(event.target)">Inverse with border</utrecht-button></li>
201+
<li><utrecht-button type="button" appearance="primary-action-button" value='${JSON.stringify(primaryButton4)}' onclick="setTokens(event.target)">Inverse without border</utrecht-button> (recommended)</li>
202+
</ul>
29203
</div>
204+
<div>
205+
<p>Secondary button style:</p>
206+
<ul>
207+
<li><utrecht-button type="button" appearance="secondary-action-button" value='${JSON.stringify(secondaryButton1)}' onclick="setTokens(event.target)">Plain with border</utrecht-button> (recommended)</li>
208+
<li><utrecht-button type="button" appearance="secondary-action-button" value='${JSON.stringify(secondaryButton2)}' onclick="setTokens(event.target)">Plain without border</utrecht-button></li>
209+
<li><utrecht-button type="button" appearance="secondary-action-button" value='${JSON.stringify(secondaryButton3)}' onclick="setTokens(event.target)">Inverse with border</utrecht-button></li>
210+
<li><utrecht-button type="button" appearance="secondary-action-button" value='${JSON.stringify(secondaryButton4)}' onclick="setTokens(event.target)">Inverse without border</utrecht-button></li>
211+
</ul>
212+
</div>
213+
<div>
214+
<p>Subtle button style:</p>
215+
<ul>
216+
<li><utrecht-button type="button" appearance="subtle-button" value='${JSON.stringify(subtleButton1)}' onclick="setTokens(event.target)">Plain with border</utrecht-button></li>
217+
<li><utrecht-button type="button" appearance="subtle-button" value='${JSON.stringify(subtleButton2)}' onclick="setTokens(event.target)">Plain without border</utrecht-button></li>
218+
<li><utrecht-button type="button" appearance="subtle-button" value='${JSON.stringify(subtleButton3)}' onclick="setTokens(event.target)">Inverse with border</utrecht-button></li>
219+
<li><utrecht-button type="button" appearance="subtle-button" value='${JSON.stringify(subtleButton4)}' onclick="setTokens(event.target)">Inverse without border</utrecht-button></li>
220+
<li><utrecht-button type="button" appearance="subtle-button" value='${JSON.stringify(subtleButton5)}' onclick="setTokens(event.target)">Transparent without border</utrecht-button></li>
221+
<li><utrecht-button type="button" appearance="subtle-button" value='${JSON.stringify(subtleButton6)}' onclick="setTokens(event.target)">Transparent with border</utrecht-button> (recommended)</li>
222+
</ul>
223+
</div>
224+
<div>
225+
<p>Minimum target size:</p>
226+
<figure>
227+
<div style="${styleAttribute(buttonWithoutPadding)}">
228+
<utrecht-button type="button"><span contentEditable="true">❤️</span></utrecht-button>
229+
</div>
230+
<figcaption>Button without padding, demonstrating the minimum pointer target size</figcaption>
231+
</figure>
232+
<ul>
233+
<li><utrecht-button type="button" appearance="secondary-button" value='${JSON.stringify(aaTargetSize)}' onclick="setTokens(event.target)">WCAG Level AA: 24px</utrecht-button></li>
234+
<li><utrecht-button type="button" appearance="secondary-button" value='${JSON.stringify(aaaTargetSize)}' onclick="setTokens(event.target)">WCAG Level AAA: 44px</utrecht-button> (recommended)</li>
235+
<li><utrecht-button type="button" appearance="secondary-button" value='${JSON.stringify(materialTargetSize)}' onclick="setTokens(event.target)">Material Design: 48px</utrecht-button></li>
236+
</ul>
237+
</div>
238+
</form>
30239
</utrecht-page-body>
31240
`;
32241

@@ -93,8 +302,25 @@ const handleColor = (target: HTMLInputElement, name: string) => {
93302
// setTheme(set(theme, tokenData.tokenRef, scaleTokens));
94303
};
95304

305+
const setToken = (input: HTMLButtonElement | HTMLInputElement) => {
306+
const tokenName = input.name;
307+
const tokenValue = input.value;
308+
309+
// Convert Design Token name to CSS custom property
310+
const cssName = toCssName(tokenName);
311+
312+
// Convert Design Token alias to CSS variable
313+
const cssValue = toCssValue(tokenValue);
314+
315+
console.log(cssName, cssValue);
316+
317+
document.documentElement.style.setProperty(cssName, cssValue);
318+
};
319+
96320
handleColor(document.getElementById('primary-input'), 'primary');
97321
handleColor(document.getElementById('secondary-input'), 'secondary');
98322
handleColor(document.getElementById('text-input'), 'text');
99323

100324
window['handleColor'] = handleColor;
325+
window['setToken'] = setToken;
326+
window['setTokens'] = setTokens;

src/utils.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Convert Design Token name to CSS custom property
2+
export const toCssName = (tokenName: string): string => `--${tokenName.replace(/\./g, '-')}`;
3+
4+
// Convert Design Token alias to CSS variable
5+
export const toCssValue = (tokenValue: string): string =>
6+
tokenValue.replace(/\{([^}]+)\}/, 'var(--$1)').replace(/\./g, '-');
7+
8+
export const toCssVariables = (tokens: { [index: string]: string }) =>
9+
Object.fromEntries(Object.entries(tokens).map(([name, value]) => [toCssName(name), toCssValue(value)]));
10+
11+
export const styleAttribute = (tokens: { [index: string]: string }) =>
12+
Object.entries(toCssVariables(tokens))
13+
.map(([name, value]) => `${name}: ${value}`)
14+
.join('; ');
15+
16+
export const setCssVariables = (cssVariables: { [index: string]: string }) => {
17+
Object.entries(cssVariables).forEach(([name, value]) => {
18+
document.documentElement.style.setProperty(name, value);
19+
});
20+
};
21+
22+
export const setTokens = (input: HTMLButtonElement | HTMLInputElement) => {
23+
const tokens = JSON.parse(input.value) as { [index: string]: string };
24+
25+
const cssVariables = Object.fromEntries(
26+
Object.entries(tokens).map(([name, value]) => [toCssName(name), toCssValue(value)]),
27+
);
28+
console.log(cssVariables);
29+
Object.entries(cssVariables).forEach(([name, value]) => {
30+
document.documentElement.style.setProperty(name, value);
31+
});
32+
setCssVariables(setCssVariables);
33+
};

0 commit comments

Comments
 (0)