learning_ai_common_plat/docs/rfc/0001-dtcg-v3-token-migration.md
saravanakumardb1 ed5fb707ad ci(packages): close ROADMAP TODOs #5, #6 + draft RFC for #4
═══════════════════════════════════════════════════════════════════════
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
2026-05-27 11:49:21 -07:00

178 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 13.
- 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 13, +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.