WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit d6bd388

Browse files
authored
feat: Extend ThemeBuilder with reference token processing (#126)
1 parent 60f8181 commit d6bd388

File tree

6 files changed

+151
-2
lines changed

6 files changed

+151
-2
lines changed

src/browser/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"compilerOptions": {
3-
"lib": ["es5", "es2015.collection", "dom"],
3+
"lib": ["es2017", "dom"],
44
"types": [],
55
"module": "esnext",
66
"moduleResolution": "node",

src/build/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,9 @@ export {
1313
Value,
1414
resolveTheme,
1515
resolveThemeWithPaths,
16+
ReferenceTokens,
17+
ColorReferenceTokens,
18+
ColorPaletteInput,
19+
ColorPaletteDefinition,
20+
PaletteStep,
1621
} from '../shared/theme';

src/shared/theme/__tests__/builder.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,26 @@ test('theme adds context', () => {
5555
},
5656
});
5757
});
58+
59+
test('theme adds reference tokens', () => {
60+
builder.addReferenceTokens({
61+
color: {
62+
neutral: { 900: '#242E3C' },
63+
warning: { 400: '#ff9900' },
64+
},
65+
});
66+
67+
const theme = builder.build();
68+
69+
expect(theme.referenceTokens).toMatchObject({
70+
color: {
71+
neutral: { 900: '#242E3C' },
72+
warning: { 400: '#ff9900' },
73+
},
74+
});
75+
76+
expect(theme.tokens).toMatchObject({
77+
colorNeutral900: '#242E3C',
78+
colorWarning400: '#ff9900',
79+
});
80+
});

src/shared/theme/builder.ts

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
3-
import { Theme, Context, Mode } from './interfaces';
3+
import {
4+
Theme,
5+
Context,
6+
Mode,
7+
ReferenceTokens,
8+
ColorReferenceTokens,
9+
ColorPaletteInput,
10+
PaletteStep,
11+
ColorPaletteDefinition,
12+
} from './interfaces';
413

514
export type TokenCategory<T extends string, V> = Record<T, V>;
615

@@ -46,7 +55,60 @@ export class ThemeBuilder {
4655
return this;
4756
}
4857

58+
addReferenceTokens(referenceTokens: ReferenceTokens): ThemeBuilder {
59+
this.theme.referenceTokens = referenceTokens;
60+
61+
// Process reference tokens and add generated tokens to theme
62+
if (referenceTokens.color) {
63+
const generatedTokens = this.processReferenceTokens(referenceTokens.color);
64+
this.theme.tokens = { ...this.theme.tokens, ...generatedTokens };
65+
}
66+
67+
return this;
68+
}
69+
4970
build(): Theme {
5071
return this.theme;
5172
}
73+
74+
private processReferenceTokens(colorTokens: ColorReferenceTokens): TokenCategory<string, string> {
75+
const generatedTokens: TokenCategory<string, string> = {};
76+
77+
Object.entries(colorTokens).forEach(([colorName, paletteInput]) => {
78+
const palette = this.processColorPaletteInput(paletteInput);
79+
80+
// Add generated palette tokens with naming convention: colorPrimary50, colorPrimary600, etc.
81+
Object.entries(palette).forEach(([step, value]) => {
82+
const tokenName = `color${this.capitalize(colorName)}${step}`;
83+
generatedTokens[tokenName] = value;
84+
});
85+
});
86+
87+
return generatedTokens;
88+
}
89+
90+
// Right now just validates steps, but will also handle seed token color generation in a future PR
91+
private processColorPaletteInput(input: ColorPaletteInput): ColorPaletteDefinition {
92+
const validSteps: number[] = [];
93+
// Add steps 50-1000 in increments of 50
94+
for (let i = 50; i <= 1000; i += 50) {
95+
validSteps.push(i);
96+
}
97+
98+
const result: ColorPaletteDefinition = {};
99+
100+
// Add explicit step values
101+
Object.entries(input).forEach(([step, value]) => {
102+
const numStep = Number(step);
103+
if (value && validSteps.includes(numStep)) {
104+
result[numStep as PaletteStep] = value;
105+
}
106+
});
107+
108+
return result;
109+
}
110+
111+
private capitalize(str: string): string {
112+
return str.charAt(0).toUpperCase() + str.slice(1);
113+
}
52114
}

src/shared/theme/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ export {
1111
GlobalValue,
1212
ModeValue,
1313
TypedModeValueOverride,
14+
ReferenceTokens,
15+
ColorReferenceTokens,
16+
ColorPaletteInput,
17+
ColorPaletteDefinition,
18+
PaletteStep,
1419
} from './interfaces';
1520
export { ThemeBuilder, TokenCategory } from './builder';
1621
export {

src/shared/theme/interfaces.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,62 @@ export interface Theme {
3535
modes: Record<string, Mode>;
3636
tokenModeMap: Record<string, string>;
3737
contexts: Record<string, Context>;
38+
referenceTokens?: ReferenceTokens;
3839
}
3940

41+
/**
42+
* Reference tokens enable seed-based palette generation and semantic token organization.
43+
*/
44+
export interface ReferenceTokens {
45+
color?: ColorReferenceTokens;
46+
}
47+
48+
export interface ColorReferenceTokens {
49+
primary?: ColorPaletteInput;
50+
neutral?: ColorPaletteInput;
51+
error?: ColorPaletteInput;
52+
success?: ColorPaletteInput;
53+
warning?: ColorPaletteInput;
54+
info?: ColorPaletteInput;
55+
}
56+
57+
/**
58+
* Color reference tokens organized by semantic color categories.
59+
* Each category is defined as a palette definition with explicit color values.
60+
*/
61+
export type ColorPaletteInput = ColorPaletteDefinition;
62+
63+
/**
64+
* Palette steps available across all color types. Different color categories
65+
* may use different subsets of these steps.
66+
*/
67+
export type PaletteStep =
68+
| 50
69+
| 100
70+
| 150
71+
| 200
72+
| 250
73+
| 300
74+
| 350
75+
| 400
76+
| 450
77+
| 500
78+
| 550
79+
| 600
80+
| 650
81+
| 700
82+
| 750
83+
| 800
84+
| 850
85+
| 900
86+
| 950
87+
| 1000;
88+
89+
/**
90+
* Color palette definition with explicit color values for palette steps.
91+
*/
92+
export type ColorPaletteDefinition = Partial<Record<PaletteStep, string>>;
93+
4094
type Tokens = Partial<Record<string, GlobalValue | TypedModeValueOverride>>;
4195

4296
export interface Override {

0 commit comments

Comments
 (0)