═══════════════════════════════════════════════════════════════════════ TODO #6 — size-limit budgets in CI ═══════════════════════════════════════════════════════════════════════ Adds .size-limit.cjs with budgets for 6 pilot @bytelyst/* packages, plus a Gitea Actions workflow (.gitea/workflows/size-limit.yml) that fails the build on any regression. Current measurements vs budget (all comfortably under): @bytelyst/api-client 793 B / 8 KB @bytelyst/auth-client 1.97 KB / 8 KB @bytelyst/celebrations 236 B / 6 KB @bytelyst/quick-actions 122 B / 6 KB @bytelyst/react-auth 2.71 KB / 10 KB @bytelyst/dashboard-shell 3.96 KB / 30 KB Scripts: pnpm size — measure + assert against budgets pnpm size:why — explain top contributors Deps: size-limit@^12.1.0, @size-limit/preset-small-lib@^12.1.0. Pilot scope (this commit): 6 packages. Full @bytelyst/* rollout is incremental — each entry added separately. ═══════════════════════════════════════════════════════════════════════ TODO #5 — Storybook canonical pattern ═══════════════════════════════════════════════════════════════════════ Discovery: @bytelyst/ui already has Storybook 8 with the @bytelyst/ addon-a11y addon configured and 5 .stories.tsx files. This commit: - Documents that setup as the canonical template (docs/STORYBOOK_TEMPLATE.md) including the .storybook/main.ts, preview.ts, package.json scripts, and an example story. - Catalogs which of the 8 visual @bytelyst/* packages need Storybook added (1/8 done — @bytelyst/ui). - Per docs/ROADMAP_2026_DECISIONS.md §9, hosting target is self-hosted Gitea Pages (no Chromatic). Full rollout to the other 7 packages stays open as incremental work. ═══════════════════════════════════════════════════════════════════════ TODO #4 — DTCG v3 token migration RFC ═══════════════════════════════════════════════════════════════════════ This is too large to land in a single commit. Drafted RFC instead: docs/rfc/0001-dtcg-v3-token-migration.md The RFC proposes a 4-PR sequence: PR 1 — Add converter + dual-emit (byte-identical assertion) PR 2 — Flip source of truth to DTCG JSON PR 3 — Introduce the component tier PR 4 — Multi-theme via DTCG token sets Estimate: 2 person-weeks total. Backward compatibility: --ml-* and --bl-* names preserved through all 4 PRs. Status: Draft, awaiting reviewers. Refs: learning_ai_uxui_web/docs/ROADMAP_2026.md §10 TODOs #4, #5, #6
178 lines
6.2 KiB
Markdown
178 lines
6.2 KiB
Markdown
# RFC 0001 — Migrate `@bytelyst/design-tokens` to DTCG v3
|
||
|
||
| Status | Draft |
|
||
| --------- | ---------------- |
|
||
| Author | Cascade |
|
||
| Created | 2026-05-27 |
|
||
| Tracks | ROADMAP TODO #4 |
|
||
| Reviewers | _to be assigned_ |
|
||
|
||
## Summary
|
||
|
||
Migrate `packages/design-tokens/tokens/bytelyst.tokens.json` from the
|
||
current bespoke schema to the **W3C Design Tokens Community Group
|
||
(DTCG) Format Module v3**. Re-emit all generated outputs
|
||
(CSS / TS / Kotlin / Swift / per-product CSS) from the new schema with
|
||
**no observable change to runtime CSS variable names**.
|
||
|
||
## Motivation
|
||
|
||
1. **Designer tooling.** Figma-Tokens (now "Tokens Studio") and
|
||
Specify both speak DTCG natively. Today designers cannot round-trip
|
||
tokens with engineering — the JSON schema is bespoke.
|
||
2. **Long-term portability.** DTCG is becoming the lingua franca of
|
||
design systems (Adobe Spectrum, Salesforce Lightning, GitHub Primer
|
||
are all migrating).
|
||
3. **Three-tier semantics.** DTCG `$type` + reference syntax (`{path}`)
|
||
gives us a clean way to express the **reference → semantic →
|
||
component** layering documented in
|
||
`learning_ai_uxui_web/docs/ROADMAP_2026.md` §3.
|
||
|
||
## Current schema (excerpt)
|
||
|
||
```json
|
||
{
|
||
"meta": { "name": "ByteLyst Design Tokens", "version": "1.1.0" },
|
||
"color": {
|
||
"palette": { "neutral": { "0": "#FFFFFF", "50": "#F6F8FC", ... } },
|
||
"semantic": {
|
||
"dark": { "bgCanvas": "#06070A", ... },
|
||
"light": { "bgCanvas": "#F8F9FC", ... }
|
||
}
|
||
},
|
||
"spacing": { "0": 0, "1": 4, "2": 8, ... },
|
||
"radius": { "xs": 4, "sm": 6, ... },
|
||
"typography": { "fontSize": { "xs": 12, ... } },
|
||
...
|
||
}
|
||
```
|
||
|
||
## Proposed DTCG v3 schema (excerpt)
|
||
|
||
```json
|
||
{
|
||
"$description": "ByteLyst design tokens — DTCG v3",
|
||
"$schema": "https://design-tokens.github.io/community-group/format/",
|
||
|
||
"color": {
|
||
"neutral": {
|
||
"0": { "$value": "#FFFFFF", "$type": "color" },
|
||
"50": { "$value": "#F6F8FC", "$type": "color" },
|
||
"950": { "$value": "#06070A", "$type": "color" }
|
||
},
|
||
"brand": {
|
||
"blue": { "$value": "#5A8CFF", "$type": "color" },
|
||
"coral": { "$value": "#FF6E6E", "$type": "color" }
|
||
},
|
||
"semantic": {
|
||
"bgCanvas": {
|
||
"$value": "{color.neutral.950}",
|
||
"$type": "color",
|
||
"$description": "Page background — dark"
|
||
}
|
||
}
|
||
},
|
||
|
||
"spacing": {
|
||
"1": { "$value": "4px", "$type": "dimension" },
|
||
"2": { "$value": "8px", "$type": "dimension" }
|
||
},
|
||
|
||
"radius": {
|
||
"xs": { "$value": "4px", "$type": "dimension" }
|
||
},
|
||
|
||
"component": {
|
||
"button": {
|
||
"padding-x": { "$value": "{spacing.4}", "$type": "dimension" },
|
||
"bg": { "$value": "{color.semantic.accent}", "$type": "color" }
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### Key changes
|
||
|
||
| Aspect | Today | DTCG v3 |
|
||
| -------------- | ------------------------ | ------------------------------------- |
|
||
| Value wrapper | bare value | `{ "$value": ..., "$type": ... }` |
|
||
| Type metadata | inferred from JS path | explicit `$type` |
|
||
| References | manual JS lookup | `{path.to.token}` syntax |
|
||
| Light/dark | parallel sibling objects | DTCG **token sets** (per-theme files) |
|
||
| Documentation | none | `$description` per token |
|
||
| Component tier | doesn't exist | new top-level `component` group |
|
||
|
||
## Implementation plan
|
||
|
||
The migration is split into **4 PRs** to keep each one reviewable.
|
||
|
||
### PR 1 — Add converter + dual-emit (no behaviour change)
|
||
|
||
- Add `scripts/convert-legacy-to-dtcg.ts` that reads the bespoke JSON
|
||
and emits `bytelyst.tokens.dtcg.json`.
|
||
- Modify `scripts/generate.ts` to accept either schema and produce
|
||
byte-identical output.
|
||
- Add a vitest case asserting the two emitters produce identical CSS
|
||
byte-for-byte.
|
||
|
||
### PR 2 — Flip source of truth to DTCG JSON
|
||
|
||
- Delete the legacy JSON.
|
||
- Update Figma-Tokens plugin documentation + commit a `.tokens.config.json`
|
||
for round-trip.
|
||
|
||
### PR 3 — Introduce the component tier
|
||
|
||
- New `component.*` group in the DTCG JSON.
|
||
- Generator emits new `--bl-{component}-{slot}` variables.
|
||
- Audit existing hardcoded values in `@bytelyst/ui` and replace with
|
||
the new component tokens.
|
||
|
||
### PR 4 — Multi-theme via DTCG token sets
|
||
|
||
- Split the single JSON into:
|
||
- `tokens/global.tokens.json` (reference + semantic core)
|
||
- `tokens/themes/dark.tokens.json` (light/dark overrides)
|
||
- `tokens/themes/light.tokens.json`
|
||
- `tokens/brands/lysnrai.tokens.json` (brand-layer overrides — Wave 7)
|
||
- Generator composes per-output set.
|
||
|
||
## Backward compatibility
|
||
|
||
- All existing `--ml-*` and `--bl-*` CSS variable names are preserved.
|
||
- All TS/Kotlin/Swift exported identifiers preserved.
|
||
- Consumer apps require zero changes through PRs 1–3.
|
||
- PR 4 introduces multi-set composition but the **default** still
|
||
produces the same `tokens.css`.
|
||
|
||
## Risks
|
||
|
||
| Risk | Severity | Mitigation |
|
||
| ------------------------------------------------ | -------- | ------------------------------------- |
|
||
| Generator divergence between schemas during PR 1 | High | Byte-identical assertion test |
|
||
| Figma-Tokens plugin version churn | Med | Pin plugin version in docs/THEMING.md |
|
||
| Designer learning curve | Med | One-pager + paired migration session |
|
||
| Reference cycles in DTCG (`{a}` → `{b}` → `{a}`) | Low | Generator validates DAG before emit |
|
||
|
||
## Alternatives considered
|
||
|
||
- **Style Dictionary** — Amazon's tool. Heavier, more opinionated.
|
||
Rejected: we already have a working generator; switching tools is a
|
||
larger change than switching schemas.
|
||
- **Stay on bespoke JSON** — Rejected: blocks designer round-trip
|
||
and locks us out of the ecosystem.
|
||
|
||
## Estimate
|
||
|
||
~1 person-week for PRs 1–3, +1 pw for PR 4 = **2 pw total**.
|
||
|
||
## Open questions
|
||
|
||
- Do we adopt the DTCG **2024 candidate** or wait for the **2026
|
||
final**? Candidate is stable enough; recommend candidate now,
|
||
re-verify when final.
|
||
- Where do per-product brand layers live — separate packages
|
||
(`@bytelyst/brand-lysnrai`) or subpaths
|
||
(`@bytelyst/design-tokens/brands/lysnrai`)? Recommend subpaths
|
||
pre-Wave 7, separate packages from Wave 7.
|