Release Token Tools 0.2.0
Verify / verify (push) Canceled after 0s

This commit is contained in:
2026-09-02 12:38:34 +02:00
parent 8fd5210cb8
commit c305f3da43
22 changed files with 777 additions and 109 deletions
+49 -16
View File
@@ -44,7 +44,7 @@ const EXAMPLE = `{
}
}`;
type ExportFormat = "w3c" | "css" | "sass" | "android" | "swift";
type ExportFormat = "dtcg" | "css" | "sass" | "android" | "swift";
export function Workbench() {
const [draft, setDraft] = useState(EXAMPLE);
@@ -55,6 +55,7 @@ export function Workbench() {
[documentText],
);
const [theme, setTheme] = useState("light");
const [mode, setMode] = useState("default");
const [setName, setSetName] = useState("core");
const [selectedPath, setSelectedPath] = useState<string | null>(
"color.brand",
@@ -66,16 +67,16 @@ export function Workbench() {
const [format, setFormat] = useState<ExportFormat>("css");
const [filter, setFilter] = useState("");
const inputRef = useRef<HTMLInputElement>(null);
const activeTheme = document.themes[theme]
? theme
: (Object.keys(document.themes)[0] ?? "default");
const activeMode = document.modes[activeTheme]?.[mode]
? mode
: (Object.keys(document.modes[activeTheme] ?? {})[0] ?? "default");
const resolution = useMemo(
() =>
resolveTheme(
document,
document.themes[theme]
? theme
: (Object.keys(document.themes)[0] ?? "default"),
),
[document, theme],
() => resolveTheme(document, activeTheme, activeMode),
[document, activeTheme, activeMode],
);
const exported = useMemo(
() => exportTokens(format, resolution.tokens),
@@ -96,6 +97,7 @@ export function Workbench() {
? setName
: (Object.keys(parsed.sets)[0] ?? "default");
setTheme(nextTheme);
setMode(Object.keys(parsed.modes[nextTheme] ?? {})[0] ?? "default");
setSetName(nextSet);
setSelectedPath(null);
setParseError("");
@@ -231,6 +233,7 @@ export function Workbench() {
ref={inputRef}
className="sr-only"
type="file"
aria-label="Open design token JSON file"
accept="application/json,.json"
onChange={(event) => void importDocument(event.target.files?.[0])}
/>
@@ -336,9 +339,17 @@ export function Workbench() {
{[
"color",
"dimension",
"duration",
"number",
"string",
"boolean",
"fontFamily",
"fontWeight",
"cubicBezier",
"strokeStyle",
"border",
"transition",
"gradient",
"typography",
"shadow",
"unknown",
@@ -389,20 +400,42 @@ export function Workbench() {
<label className="inline-label">
Theme
<select
value={
document.themes[theme] ? theme : Object.keys(document.themes)[0]
}
onChange={(event) => setTheme(event.target.value)}
value={activeTheme}
onChange={(event) => {
const nextTheme = event.target.value;
setTheme(nextTheme);
setMode(
Object.keys(document.modes[nextTheme] ?? {})[0] ?? "default",
);
}}
>
{Object.keys(document.themes).map((name) => (
<option key={name}>{name}</option>
))}
</select>
</label>
<label className="inline-label">
Mode
<select
value={activeMode}
onChange={(event) => setMode(event.target.value)}
>
{Object.keys(document.modes[activeTheme] ?? { default: [] }).map(
(name) => (
<option key={name}>{name}</option>
),
)}
</select>
</label>
</div>
<p className="muted">
Sets: {(document.themes[theme] ?? []).join(" → ") || "none"}. Later
sets override matching paths.
Sets:{" "}
{(
document.modes[activeTheme]?.[activeMode] ??
document.themes[activeTheme] ??
[]
).join(" → ") || "none"}
. Later sets override matching paths.
</p>
{resolution.diagnostics.length > 0 ? (
<ul className="diagnostics">
@@ -460,7 +493,7 @@ export function Workbench() {
setFormat(event.target.value as ExportFormat)
}
>
<option value="w3c">W3C-style JSON</option>
<option value="dtcg">DTCG JSON</option>
<option value="css">CSS variables</option>
<option value="sass">Sass variables</option>
<option value="android">Android XML</option>