Skip to content

Commit 2e7db8d

Browse files
committed
Fix example for contrast
1 parent 062a05a commit 2e7db8d

File tree

4 files changed

+92
-57
lines changed

4 files changed

+92
-57
lines changed

docs-intro/why-tokenscript.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,17 @@ variable lightBg: Color = #FFFFFF;
159159
variable lightText: Color = #000000;
160160

161161
// Auto-generate dark theme
162-
variable darkBg: Color = invert(lightBg);
163-
variable darkText: Color = invert(lightText);
162+
variable darkBg: Color.Srgb = invert(lightBg);
163+
variable darkText: Color = lightText;
164164

165165
// Ensure accessibility
166-
if (contrast(darkText, darkBg) < 4.5) [
167-
darkText = lighten(darkText, 20);
168-
]`}
166+
while (contrast(darkText, darkBg) < 65) [
167+
darkText = lighten(darkText, 10);
168+
]
169+
170+
return darkBg, darkText;
171+
`}
172+
169173
</TokenScriptCodeBlock>
170174

171175
### Responsive Spacing Scale

scripts/fetch-schemas.ts

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
/**
44
* Script to fetch TokenScript schemas at build time
5-
*
5+
*
66
* This script:
77
* 1. Fetches color and function schemas from the registry
88
* 2. Writes them to a generated TypeScript file
@@ -29,16 +29,16 @@ async function fetchSchemaRegistry(): Promise<SchemaInfo[]> {
2929
try {
3030
const controller = new AbortController();
3131
const timeout = setTimeout(() => controller.abort(), 10000);
32-
32+
3333
const response = await fetch('https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema?format=json', {
3434
signal: controller.signal
3535
});
3636
clearTimeout(timeout);
37-
37+
3838
if (!response.ok) {
3939
throw new Error(`Failed to fetch schema registry: ${response.statusText}`);
4040
}
41-
41+
4242
const data = await response.json() as SchemaRegistryResponse;
4343
return data.schemas || [];
4444
} catch (error) {
@@ -55,14 +55,14 @@ async function fetchSchema(slug: string): Promise<[string, any] | null> {
5555
const controller = new AbortController();
5656
const url = `https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/${slug}`;
5757
const timeout = setTimeout(() => controller.abort(), 10000);
58-
58+
5959
const response = await fetch(`${url}/latest?format=json`, { signal: controller.signal });
6060
clearTimeout(timeout);
61-
61+
6262
if (!response.ok) {
6363
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
6464
}
65-
65+
6666
const json = await response.json();
6767
return [url, json.content];
6868
} catch (error) {
@@ -76,15 +76,15 @@ async function fetchSchema(slug: string): Promise<[string, any] | null> {
7676
*/
7777
async function main(): Promise<void> {
7878
console.log('Fetching TokenScript schemas...\n');
79-
79+
8080
// Essential schemas needed for the docs
8181
const essentialColorSchemas = [
8282
'hsl-color',
8383
'srgb-color',
8484
'rgba-color',
8585
'oklch-color',
8686
];
87-
87+
8888
// Hardcoded CssColor schema (required for color conversions)
8989
const cssColorSchema = {
9090
"name": "CssColor",
@@ -238,7 +238,7 @@ async function main(): Promise<void> {
238238
}
239239
]
240240
};
241-
241+
242242
// Fetch essential color schemas
243243
const colorSchemasMap = new Map<string, any>();
244244
console.log('Fetching color schemas:');
@@ -250,14 +250,14 @@ async function main(): Promise<void> {
250250
console.log(` ✓ ${slug}`);
251251
}
252252
}
253-
253+
254254
// Add the hardcoded CssColor schema
255255
colorSchemasMap.set('https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/css-color/0/', cssColorSchema);
256256
console.log(' ✓ css-color (hardcoded)');
257-
257+
258258
// Function schemas for color manipulation
259259
const functionSchemasMap = new Map<string, any>();
260-
260+
261261
// Relative Darken function
262262
const relativeDarkenSchema = {
263263
"name": "Relative Darken",
@@ -277,16 +277,16 @@ async function main(): Promise<void> {
277277
},
278278
"script": {
279279
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
280-
"script": "variable input: List = {input};\nvariable baseColor: Color = input.get(0);\nvariable percentage: Number = input.get(1);\n\n// Convert to HSL for lightness manipulation\nvariable hslColor: Color.Hsl = baseColor.to.hsl();\n\n// Calculate new lightness (reduce by percentage)\nvariable currentLightness: Number = hslColor.l;\nvariable darkenAmount: Number = currentLightness * (percentage / 100);\nvariable newLightness: Number = currentLightness - darkenAmount;\n\n// Ensure lightness doesn't go below 0\nif (newLightness < 0) [\n newLightness = 0;\n]\n\n// Create and return the darkened color\nvariable darkenedColor: Color.Hsl = hsl(hslColor.h, hslColor.s, newLightness);\nreturn darkenedColor;"
280+
"script": "variable input: List = {input};\nvariable percentage: Number = input.get(1);\n\n// Convert to HSL for lightness manipulation\nvariable hslColor: Color.Hsl = input.get(0).to.hsl();\n\n// Calculate new lightness (reduce by percentage)\nvariable currentLightness: Number = hslColor.l;\nvariable darkenAmount: Number = currentLightness * (percentage / 100);\nvariable newLightness: Number = currentLightness - darkenAmount;\n\n// Ensure lightness doesn't go below 0\nif (newLightness < 0) [\n newLightness = 0;\n]\n\n// Create and return the darkened color\nvariable darkenedColor: Color.Hsl = hsl(hslColor.h, hslColor.s, newLightness);\nreturn darkenedColor;"
281281
},
282282
"keyword": "darken",
283283
"description": "Darkens a color by a relative percentage amount by reducing its lightness value.",
284284
"requirements": [
285285
"https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/hsl-color/0.0.1/",
286-
"https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/srgb-color/0.0.1/"
286+
"https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/srgb-color/0.1.0/"
287287
]
288288
};
289-
289+
290290
// Relative Lighten function
291291
const relativeLightenSchema = {
292292
"name": "Relative Lighten",
@@ -306,37 +306,54 @@ async function main(): Promise<void> {
306306
},
307307
"script": {
308308
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
309-
"script": "variable input: List = {input};\nvariable baseColor: Color = input.get(0);\nvariable percentage: Number = input.get(1);\n\n// Convert to HSL for lightness manipulation\nvariable hslColor: Color.Hsl = baseColor.to.hsl();\n\n// Calculate new lightness (increase by percentage)\nvariable currentLightness: Number = hslColor.l;\nvariable lightenAmount: Number = (100 - currentLightness) * (percentage / 100);\nvariable newLightness: Number = currentLightness + lightenAmount;\n\n// Ensure lightness doesn't go above 100\nif (newLightness > 100) [\n newLightness = 100;\n]\n\n// Create and return the lightened color\nvariable output: Color.Hsl;\noutput.h = hslColor.h;\noutput.s = hslColor.s;\noutput.l = newLightness;\nreturn output;"
309+
"script": "variable input: List = {input};\nvariable percentage: Number = input.get(1);\n\n// Convert to HSL for lightness manipulation\nvariable hslColor: Color.Hsl = input.get(0).to.hsl();\n\n// Calculate new lightness (increase by percentage)\nvariable currentLightness: Number = hslColor.l;\nvariable lightenAmount: Number = (100 - currentLightness) * (percentage / 100);\nvariable newLightness: Number = currentLightness + lightenAmount;\n\n// Ensure lightness doesn't go above 100\nif (newLightness > 100) [\n newLightness = 100;\n]\n\n// Create and return the lightened color\nvariable output: Color.Hsl;\noutput.h = hslColor.h;\noutput.s = hslColor.s;\noutput.l = newLightness;\nreturn output;"
310310
},
311311
"keyword": "lighten",
312312
"description": "Lightens a color by a relative percentage amount by increasing its lightness value.",
313313
"requirements": [
314314
"https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/hsl-color/0.0.1/",
315-
"https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/srgb-color/0.0.1/"
315+
"https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/schema/srgb-color/0.1.0/"
316316
]
317317
};
318-
318+
319319
functionSchemasMap.set('https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/function/relative-darken/0/', relativeDarkenSchema);
320320
functionSchemasMap.set('https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/function/relative-lighten/0/', relativeLightenSchema);
321+
321322
console.log('\nFunction schemas:');
322323
console.log(' ✓ relative-darken');
323324
console.log(' ✓ relative-lighten');
324-
325+
326+
// Fetch invert function schema
327+
const invertResult = await fetchSchema('invert');
328+
if (invertResult) {
329+
const [url, spec] = invertResult;
330+
functionSchemasMap.set(`${url}/0/`, spec);
331+
console.log(' ✓ invert');
332+
}
333+
334+
// Fetch contrast function schema
335+
const contrastResult = await fetchSchema('contrast');
336+
if (contrastResult) {
337+
const [url, spec] = contrastResult;
338+
functionSchemasMap.set(`${url}/0/`, spec);
339+
console.log(' ✓ contrast');
340+
}
341+
325342
// Generate TypeScript file content
326343
const fileContent = `// Auto-generated file - DO NOT EDIT
327344
// Generated at: ${new Date().toISOString()}
328345
// This file contains TokenScript schemas fetched at build time
329346
330347
export const COLOR_SCHEMAS = new Map<string, any>([
331348
${Array.from(colorSchemasMap.entries())
332-
.map(([url, spec]) => ` ['${url}', ${JSON.stringify(spec)}]`)
333-
.join(',\n')}
349+
.map(([url, spec]) => ` ['${url}', ${JSON.stringify(spec)}]`)
350+
.join(',\n')}
334351
]);
335352
336353
export const FUNCTION_SCHEMAS = new Map<string, any>([
337354
${Array.from(functionSchemasMap.entries())
338-
.map(([url, spec]) => ` ['${url}', ${JSON.stringify(spec)}]`)
339-
.join(',\n')}
355+
.map(([url, spec]) => ` ['${url}', ${JSON.stringify(spec)}]`)
356+
.join(',\n')}
340357
]);
341358
342359
export function getColorSchema(url: string): any | undefined {
@@ -347,20 +364,20 @@ export function getFunctionSchema(url: string): any | undefined {
347364
return FUNCTION_SCHEMAS.get(url);
348365
}
349366
`;
350-
367+
351368
// Write to file
352369
const fs = await import('fs');
353370
const path = await import('path');
354371
const outputDir = path.resolve(process.cwd(), 'src/lib');
355372
const outputPath = path.join(outputDir, 'schemas.generated.ts');
356-
373+
357374
// Ensure directory exists
358375
if (!fs.existsSync(outputDir)) {
359376
fs.mkdirSync(outputDir, { recursive: true });
360377
}
361-
378+
362379
fs.writeFileSync(outputPath, fileContent, 'utf-8');
363-
380+
364381
console.log(`\n✓ Schemas written to: ${outputPath}`);
365382
console.log(` Color schemas: ${colorSchemasMap.size}`);
366383
console.log(` Function schemas: ${functionSchemasMap.size}`);

src/hooks/useSchemas.ts

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,34 @@ const COLOR_SCHEMA_SLUGS = [
2222
'srgb-color',
2323
];
2424

25+
const FUNCTION_SCHEMA_SLUGS = [
26+
'invert',
27+
];
28+
29+
async function fetchSchemasBySlugs(slugs: string[]): Promise<Map<string, any>> {
30+
const schemas = new Map<string, any>();
31+
32+
for (const slug of slugs) {
33+
try {
34+
const url = `${SCHEMA_BASE_URL}/${slug}`;
35+
const response = await fetch(`${url}/latest?format=json`);
36+
37+
if (response.ok) {
38+
const data = await response.json();
39+
if (data.content) {
40+
// Use versioned URL as key
41+
const versionedUrl = `${url}/${data.version || '0'}/`;
42+
schemas.set(versionedUrl, data.content);
43+
}
44+
}
45+
} catch (err) {
46+
console.warn(`Failed to fetch schema ${slug}:`, err);
47+
}
48+
}
49+
50+
return schemas;
51+
}
52+
2553
export function useSchemas() {
2654
const [schemas, setSchemas] = useState<SchemaCache>(cache);
2755
const [loading, setLoading] = useState(!cache.loaded);
@@ -38,30 +66,14 @@ export function useSchemas() {
3866

3967
async function fetchSchemas() {
4068
try {
41-
const colorSchemas = new Map<string, any>();
42-
43-
// Fetch color schemas
44-
for (const slug of COLOR_SCHEMA_SLUGS) {
45-
try {
46-
const url = `${SCHEMA_BASE_URL}/${slug}`;
47-
const response = await fetch(`${url}/latest?format=json`);
48-
49-
if (response.ok) {
50-
const data = await response.json();
51-
if (data.content) {
52-
// Use versioned URL as key
53-
const versionedUrl = `${url}/${data.version || '0'}/`;
54-
colorSchemas.set(versionedUrl, data.content);
55-
}
56-
}
57-
} catch (err) {
58-
console.warn(`Failed to fetch schema ${slug}:`, err);
59-
}
60-
}
69+
const [colorSchemas, functionSchemas] = await Promise.all([
70+
fetchSchemasBySlugs(COLOR_SCHEMA_SLUGS),
71+
fetchSchemasBySlugs(FUNCTION_SCHEMA_SLUGS),
72+
]);
6173

6274
if (!cancelled) {
6375
cache.colorSchemas = colorSchemas;
64-
cache.functionSchemas = new Map(); // TODO: Add function schemas
76+
cache.functionSchemas = functionSchemas;
6577
cache.loaded = true;
6678

6779
setSchemas({ ...cache });

0 commit comments

Comments
 (0)