Skip to content

Commit 575e05f

Browse files
committed
WIP
1 parent 141ef44 commit 575e05f

12 files changed

Lines changed: 8477 additions & 7 deletions

public/design-tokens/onderzoek.amsterdam.nl.json

Lines changed: 545 additions & 0 deletions
Large diffs are not rendered by default.

public/design-tokens/purmerend.nl.json

Lines changed: 2483 additions & 0 deletions
Large diffs are not rendered by default.

public/design-tokens/rijksoverheid.nl.json

Lines changed: 1957 additions & 0 deletions
Large diffs are not rendered by default.

public/design-tokens/rotterdam.nl.json

Lines changed: 651 additions & 0 deletions
Large diffs are not rendered by default.

public/design-tokens/utrecht.nl.json

Lines changed: 2483 additions & 0 deletions
Large diffs are not rendered by default.

src/basis-theme-stylesheet.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,16 @@ class BasisThemeStylesheet extends HTMLElement {
1818
map: Map<string, FlatTokens>;
1919
parameters: URLSearchParams;
2020
variantsMap: VariantsMap;
21+
_eventHandler: (evt: Event) => void;
22+
_designTokenValueListeners: Set<Element>;
23+
_flatTokensCache: FlatTokens;
2124
constructor() {
2225
super();
2326

2427
const sheet = new CSSStyleSheet();
2528
this.sheet = sheet;
2629
this.map = new Map();
30+
this._flatTokensCache = {};
2731
sheet.replaceSync('');
2832
window.themeBuilder = this;
2933
this.parameters = new URLSearchParams();
@@ -69,16 +73,37 @@ class BasisThemeStylesheet extends HTMLElement {
6973
});
7074
}
7175
});
76+
77+
this._designTokenValueListeners = new Set();
78+
this._eventHandler = (evt) => this.handleRequestDesignTokenValue(evt);
7279
}
7380

7481
connectedCallback() {
7582
if (this.sheet) {
7683
this.ownerDocument.adoptedStyleSheets.push(this.sheet);
7784
}
85+
this.ownerDocument.addEventListener('subscribeDesignTokenValue', this._eventHandler, true);
86+
this.ownerDocument.addEventListener('unsubscribeDesignTokenValue', this._eventHandler, true);
7887
}
7988

8089
disconnectedCallback() {
8190
// TODO: Remove from adoptedStyleSheets
91+
this.ownerDocument.removeEventListener('subscribeDesignTokenValue', this._eventHandler, true);
92+
this.ownerDocument.removeEventListener('unsubscribeDesignTokenValue', this._eventHandler, true);
93+
}
94+
95+
handleRequestDesignTokenValue(evt: Event) {
96+
if (evt.type === 'subscribeDesignTokenValue' && evt.target instanceof Element) {
97+
this._designTokenValueListeners.add(evt.target);
98+
// Set initial value
99+
const tokenName = !!evt.target && (evt.target as unknown).name;
100+
if (typeof tokenName === 'string' && this._flatTokensCache.hasOwnProperty(tokenName)) {
101+
evt.target.value = this._flatTokensCache[tokenName];
102+
}
103+
}
104+
if (evt.type === 'unsubscribeDesignTokenValue' && evt.target instanceof Element) {
105+
this._designTokenValueListeners.delete(evt.target);
106+
}
82107
}
83108

84109
update() {
@@ -87,8 +112,23 @@ class BasisThemeStylesheet extends HTMLElement {
87112
.join(';\n');
88113

89114
let css = `.basis-theme {\n${properties}\n}`;
90-
115+
console.log(css);
91116
this.sheet?.replaceSync(css);
117+
118+
this._flatTokensCache = Array.from(this.map.values()).reduce((map, tokens) => ({ ...map, ...tokens }), {});
119+
120+
if (!this._designTokenValueListeners) {
121+
return;
122+
}
123+
for (let key in this._flatTokensCache) {
124+
const value = this._flatTokensCache[key];
125+
126+
this._designTokenValueListeners.forEach((el) => {
127+
if (el.name === key) {
128+
el.value = value;
129+
}
130+
});
131+
}
92132
}
93133

94134
toggleTokens(id: string, tokens: FlatTokens) {

src/color-preset-input.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
const requested = new Set<ExampleColorPresetInput>();
2+
3+
let animationFrame = -1;
4+
5+
const requestRender = (el: ExampleColorPresetInput) => {
6+
if (animationFrame === -1) {
7+
requested.add(el);
8+
requestAnimationFrame(renderThings);
9+
}
10+
};
11+
12+
const renderThings = () => {
13+
animationFrame = -1;
14+
for (let item of requested) {
15+
requested.delete(item);
16+
item.render();
17+
}
18+
};
19+
20+
export interface ColorOption {
21+
name: string;
22+
color: string;
23+
}
24+
25+
export class ExampleColorPresetInput extends HTMLElement {
26+
_name: string;
27+
_inverse: string;
28+
_value: string;
29+
_colors: ColorOption[];
30+
constructor() {
31+
super();
32+
this._name = this.getAttribute('name') || '';
33+
this._inverse = this.getAttribute('inverse') || '';
34+
this._value = this.getAttribute('value') || '';
35+
this._colors = [];
36+
}
37+
38+
connectedCallback() {
39+
this.render();
40+
}
41+
42+
set name(value: string) {
43+
this._name = value;
44+
requestRender(this);
45+
}
46+
47+
set value(value: string) {
48+
this._value = value;
49+
requestRender(this);
50+
}
51+
52+
set inverse(value: string) {
53+
this._inverse = value;
54+
requestRender(this);
55+
}
56+
57+
set colors(value: ColorOption[]) {
58+
this._colors = value;
59+
requestRender(this);
60+
}
61+
62+
renderHTML(name: string, inverseName: string, colors: ColorOption[]) {
63+
return `<details><summary>Show preset colors</summary><utrecht-button-group>${colors
64+
.map(
65+
({ name: colorName, color }) =>
66+
`<utrecht-button onclick='themeBuilder.handleColorInput(event.currentTarget, ${JSON.stringify(name)}, ${JSON.stringify(inverseName)})' value="${color}"${color === this._value ? ' pressed="true"' : ''}><utrecht-color-sample color="${color}"></utrecht-color-sample> ${colorName}</utrecht-button>`,
67+
)
68+
.join('\n')}</utrecht-button-group></details>`;
69+
}
70+
71+
render() {
72+
this.innerHTML = this.renderHTML(this._name, this._inverse, this._colors);
73+
}
74+
}
75+
76+
customElements.define('example-color-preset-input', ExampleColorPresetInput);

src/design-token-options.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,4 +783,50 @@ export const variants: VariantOptionGroup[] = [
783783
},
784784
],
785785
},
786+
{
787+
id: 'border-width-scale',
788+
variants: [
789+
{
790+
id: 'default-rem',
791+
flatTokens: {
792+
'basis.border-width.sm': '0.0625rem',
793+
'basis.border-width.md': '0.125rem',
794+
'basis.border-width.lg': '0.1875rem',
795+
'basis.border-width.xl': '0.25rem',
796+
},
797+
recommended: true,
798+
name: 'Default (root font size relative)',
799+
},
800+
{
801+
id: 'default-px',
802+
flatTokens: {
803+
'basis.border-width.sm': '1px',
804+
'basis.border-width.md': '2px',
805+
'basis.border-width.lg': '3px',
806+
'basis.border-width.xl': '4px',
807+
},
808+
name: 'Default (pixels)',
809+
},
810+
{
811+
id: 'heavy',
812+
flatTokens: {
813+
'basis.border-width.sm': '2px',
814+
'basis.border-width.md': '3px',
815+
'basis.border-width.lg': '5px',
816+
'basis.border-width.xl': '8px',
817+
},
818+
name: 'Heavy (pixels)',
819+
},
820+
{
821+
id: 'heavy-rem',
822+
flatTokens: {
823+
'basis.border-width.sm': '0.125rem',
824+
'basis.border-width.md': '0.1875rem',
825+
'basis.border-width.lg': '0.3125rem',
826+
'basis.border-width.xl': '0.5rem',
827+
},
828+
name: 'Heavy (root font size relative)',
829+
},
830+
],
831+
},
786832
];

src/example-border-width.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
export class ExampleBorderWidthSample extends HTMLElement {
2+
constructor() {
3+
super();
4+
const style = this.ownerDocument.createElement('style');
5+
style.textContent = `
6+
.example-border-width {
7+
border-color: currentColor;
8+
border-style: solid;
9+
border-width: var(--example-border-width);
10+
}
11+
.example-border-width--block {
12+
min-inline-size: 1em;
13+
border-block-end-width: 0;
14+
border-inline-start-width: 0;
15+
border-inline-end-width: 0;
16+
}
17+
18+
.example-border-width--inline {
19+
min-block-size: 1em;
20+
border-block-start-width: 0;
21+
border-block-end-width: 0;
22+
border-inline-end-width: 0;
23+
}`;
24+
const shadow = this.attachShadow({ mode: 'closed' });
25+
shadow.appendChild(style);
26+
const div = this.ownerDocument.createElement('div');
27+
div.classList.add('example-border-width');
28+
const orientation = this.getAttribute('orientation');
29+
div.classList.toggle('example-border-width--block', orientation === 'block');
30+
div.classList.toggle('example-border-width--inline', orientation === 'inline');
31+
div.appendChild(this.ownerDocument.createElement('slot'));
32+
shadow.appendChild(div);
33+
}
34+
}
35+
36+
customElements.define('example-border-width-sample', ExampleBorderWidthSample);

src/example-design-token-value.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
const requested = new Set<ExampleDesignTokenValue>();
2+
3+
let animationFrame = -1;
4+
5+
const requestRender = (el: ExampleDesignTokenValue) => {
6+
if (animationFrame === -1) {
7+
requested.add(el);
8+
requestAnimationFrame(renderThings);
9+
}
10+
};
11+
12+
const renderThings = () => {
13+
animationFrame = -1;
14+
for (let item of requested) {
15+
requested.delete(item);
16+
item.render();
17+
}
18+
};
19+
20+
export interface ColorOption {
21+
name: string;
22+
color: string;
23+
}
24+
25+
export class ExampleDesignTokenValue extends HTMLElement {
26+
_name: string;
27+
_value: string;
28+
29+
get name() {
30+
return this._name;
31+
}
32+
33+
constructor() {
34+
super();
35+
this._name = this.getAttribute('name') || '';
36+
this._value = this.getAttribute('value') || 'TODO';
37+
}
38+
39+
connectedCallback() {
40+
const evt = new CustomEvent('subscribeDesignTokenValue', { detail: { name: this._name } });
41+
this.dispatchEvent(evt);
42+
this.render();
43+
}
44+
disconnectedCallback() {
45+
const evt = new CustomEvent('unsubscribeDesignTokenValue', { detail: { name: this._name } });
46+
this.dispatchEvent(evt);
47+
}
48+
49+
set value(value: string) {
50+
this._value = value;
51+
requestRender(this);
52+
}
53+
54+
render() {
55+
this.innerHTML = `<utrecht-code>${this._value}</utrecht-code>`;
56+
}
57+
}
58+
59+
customElements.define('example-design-token-value', ExampleDesignTokenValue);

0 commit comments

Comments
 (0)