Summary
Adopt Spectrum 2 across drago-toolkit so internal tools and author-facing surfaces share Adobe’s current design language: updated tokens, typography, iconography, accessibility defaults, and (where appropriate) Spectrum Web Components (SWC).
References
Current state (baseline)
| Surface |
Stack |
Design today |
tools/inventory/ |
Lit 3, light DOM, ~1.1k lines custom CSS |
Hand-rolled Spectrum 1–style CSS variables on ema-inventory; custom tab shell modeled on React Spectrum ARIA |
tools/eds-migration/ |
Lit (planned/parallel pattern) |
Duplicated hand-rolled Spectrum-style tokens on ema-eds-migration |
tools/scheduler/ |
Lit, shadow DOM |
Ad-hoc light-dark() colors, not aligned to Spectrum |
Site blocks / styles/styles.css |
Helix blocks, Montserrat |
README documents spacing/emphasis/button tokens (XS–XXL, accent/primary, gray scales) — not Spectrum 2 |
| Build |
esbuild bundles deps/lit only |
No @spectrum-web-components/* dependencies yet |
Implication: Inventory is the best pilot (already Spectrum-minded, largest UI). Site blocks are a separate, later track to avoid blocking tool work.
Goals
- Single source of truth for color, type, spacing, radius, and focus rings via official Spectrum 2 token CSS (
tokens-v2).
- Consistent components for repeated patterns (Button, TextField, Tabs, Table, Progress, Dialog) via SWC where bundle size allows.
- Accessibility by default — keyboard models, focus visibility,
prefers-reduced-motion, contrast-ready light/dark.
- Incremental migration — no big-bang rewrite; inventory proves the pattern, then eds-migration and scheduler.
Non-goals (initial pass)
- Rebuilding every Helix block in SWC in one release.
- Introducing React / React Spectrum (repo is Lit + vanilla).
- Custom fork of Spectrum tokens.
Recommended technical approach
Option A — Tokens only (smallest diff)
Import @spectrum-web-components/styles tokens-v2 + typography.css; map existing BEM classes to token variables; drop duplicated hex values in inventory.css / eds-migration.css.
Option B — Tokens + sp-theme + selective SWC (recommended)
- Wrap tool roots in
<sp-theme system="spectrum-two" scale="medium" color="light"> (and dark variant behind a toggle or prefers-color-scheme).
- Import token CSS as documented for Spectrum 2.
- Replace high-churn primitives incrementally:
sp-button, sp-textfield, sp-tabs / sp-tab-panel, sp-table, sp-progress-circle, sp-toast (for copy feedback).
- Keep domain-specific UI (sitemap tree, DA repo browser, compare columns) as custom markup styled with tokens until a SWC pattern exists.
Option C — Full SWC everywhere
Highest consistency, largest bundle and import-graph cost — not recommended for Helix-delivered author pages without a dedicated bundle strategy.
Decision: Target Option B for tools/*; evaluate Option A only for blocks/ until performance budget is defined.
Implementation phases
Phase 0 — Discovery & standards (1–2 days)
Phase 1 — Shared Spectrum 2 foundation (3–5 days)
Acceptance: A minimal demo page shows sp-theme system="spectrum-two" with one sp-button and token-driven background/text.
Phase 2 — Inventory pilot (1–2 weeks)
Highest value; already references React Spectrum tab behavior in comments.
Acceptance: Inventory matches Spectrum 2 look on light theme; no duplicated legacy token hex in inventory.css; axe/keyboard smoke test documented.
Phase 3 — Other tools (1 week)
Phase 4 — Theming, motion, accessibility (3–5 days)
Phase 5 — Author site / blocks (optional, separate epic)
Dependency & delivery constraints
| Constraint |
Mitigation |
| Helix “buildless” delivery |
Bundle SWC + lit into deps/ via esbuild; tools import from /deps/... like existing Lit pattern |
| Package version skew |
Single locked version for all @spectrum-web-components/* in package.json |
| Light DOM in inventory |
Test SWC components with createRenderRoot() { return this; }; fall back to token-only if shadow styles break |
| CSS lint scope |
Add tools/**/*.css to lint:css script |
| Security |
No user input in dynamic import() paths; pin SWC versions; run npm audit on SWC adds |
Suggested work breakdown (issues / PRs)
- chore(spectrum): add SWC deps, shared token CSS, esbuild bundle, README
- feat(inventory): sp-theme wrapper + token migration (CSS-only PR)
- feat(inventory): replace buttons/inputs with SWC
- feat(inventory): tabs + alerts/toast
- feat(eds-migration): align to shared spectrum foundation
- feat(scheduler): align to shared spectrum foundation
- feat(spectrum): dark mode + reduced motion
- docs: design system decision record + screenshots
Risks & open questions
- Bundle size: How much SWC is acceptable on DA-hosted tool URLs? Measure before migrating all primitives.
- Light DOM + SWC: Confirm styling works without shadow DOM; may require
sp-theme as ancestor in document, not inside component render root.
- Brand vs Spectrum: Site uses Montserrat — do tools use Spectrum typography exclusively while marketing pages keep brand fonts?
- Express vs Spectrum 2: SWC also supports
express system — confirm product choice is spectrum-two only.
Success criteria
Test plan
Summary
Adopt Spectrum 2 across drago-toolkit so internal tools and author-facing surfaces share Adobe’s current design language: updated tokens, typography, iconography, accessibility defaults, and (where appropriate) Spectrum Web Components (SWC).
References
tokens-v2): https://opensource.adobe.com/spectrum-web-components/tools/styles/sp-theme(system="spectrum-two"): https://opensource.adobe.com/spectrum-web-components/tools/theme/api/Current state (baseline)
tools/inventory/ema-inventory; custom tab shell modeled on React Spectrum ARIAtools/eds-migration/ema-eds-migrationtools/scheduler/light-dark()colors, not aligned to Spectrumstyles/styles.cssesbuildbundlesdeps/litonly@spectrum-web-components/*dependencies yetImplication: Inventory is the best pilot (already Spectrum-minded, largest UI). Site blocks are a separate, later track to avoid blocking tool work.
Goals
tokens-v2).prefers-reduced-motion, contrast-ready light/dark.Non-goals (initial pass)
Recommended technical approach
Option A — Tokens only (smallest diff)
Import
@spectrum-web-components/stylestokens-v2+typography.css; map existing BEM classes to token variables; drop duplicated hex values ininventory.css/eds-migration.css.Option B — Tokens +
sp-theme+ selective SWC (recommended)<sp-theme system="spectrum-two" scale="medium" color="light">(and dark variant behind a toggle orprefers-color-scheme).sp-button,sp-textfield,sp-tabs/sp-tab-panel,sp-table,sp-progress-circle,sp-toast(for copy feedback).Option C — Full SWC everywhere
Highest consistency, largest bundle and import-graph cost — not recommended for Helix-delivered author pages without a dedicated bundle strategy.
Decision: Target Option B for
tools/*; evaluate Option A only forblocks/until performance budget is defined.Implementation phases
Phase 0 — Discovery & standards (1–2 days)
tools/inventory/inventory.js(buttons, inputs, tabs, tables, pills, panels, trees).@spectrum-web-components/*packages same semver (required by SWC).npm run lint:cssto includetools/**/*.css.sp-themeusage).Phase 1 — Shared Spectrum 2 foundation (3–5 days)
@spectrum-web-components/styles,@spectrum-web-components/theme(and component packages as needed).deps/spectrum/(orstyles/spectrum/) entry that imports:sp-*modules fromnode_modules.tools/shared/spectrum-theme.jshelper that registerssp-themeonce.Acceptance: A minimal demo page shows
sp-theme system="spectrum-two"with onesp-buttonand token-driven background/text.Phase 2 — Inventory pilot (1–2 weeks)
Highest value; already references React Spectrum tab behavior in comments.
ema-inventorycontent insp-theme(light DOM can remain if CSS targetsema-inventory sp-button— verify SWC style penetration).--spectrum-gray-*/--spectrum-blue-*blocks ininventory.csswithtokens-v2variables; delete duplicate hex definitions.sp-tabs+sp-tab+sp-tab-panelOR keep custom tab markup but style exclusively with S2 tab tokens.ema-inv__btn, primary/compact) →sp-buttonvariants (accent,secondary,quiet).sp-textfield/sp-pickerwhere applicable.sp-inline-alertor toast pattern.ema-inv__analysis-tablewithsp-tableor token-based table styles from SWC.role="tree") still passes manual a11y check.Acceptance: Inventory matches Spectrum 2 look on light theme; no duplicated legacy token hex in
inventory.css; axe/keyboard smoke test documented.Phase 3 — Other tools (1 week)
tools/eds-migration/: reuse shared theme + tokens; remove duplicated CSS variables.tools/scheduler/: adoptsp-theme+ tokens; replacelight-dark()ad hoc palette.tools/quick-edit/,tools/sidekick/: align if they expose UI chrome.Phase 4 — Theming, motion, accessibility (3–5 days)
color="dark"onsp-theme+tokens-v2/dark-vars.css; respectprefers-color-scheme.mediumvslargefor touch-heavy views.prefers-reduced-motion: gate animations (copy banner, loading states) per Spectrum 2 motion guidance.--spectrum-focus-ring-coloroverrides unless required.Phase 5 — Author site / blocks (optional, separate epic)
blocks/heroorblocks/card) before repo-wide block migration.Dependency & delivery constraints
deps/via esbuild; tools import from/deps/...like existing Lit pattern@spectrum-web-components/*inpackage.jsoncreateRenderRoot() { return this; }; fall back to token-only if shadow styles breaktools/**/*.csstolint:cssscriptimport()paths; pin SWC versions; runnpm auditon SWC addsSuggested work breakdown (issues / PRs)
Risks & open questions
sp-themeas ancestor in document, not inside component render root.expresssystem — confirm product choice isspectrum-twoonly.Success criteria
sp-theme system="spectrum-two"documented and used in all Lit tools.Test plan
npm run lintpasses with expanded CSS scope