Skip to content

Define design system and align codebase styling #1952

Description

@kmcginnes

Problem Statement

Graph Explorer's styling has accumulated legacy debt: a tailwind.config.ts that's redundant with Tailwind v4 CSS-native capabilities, ~18 legacy color token aliases used in 117 places across 64 files, orphaned dark mode fragments, shadcn compatibility aliases, and direct palette scale references that bypass the semantic token layer. There is no documented design system — contributors (human and agent) have no authoritative reference for which tokens to use, leading to further drift.

Solution

Eliminate the legacy styling debt, migrate all components to canonical semantic tokens, and produce a docs/agents/design.md that defines the design system. The result is a single CSS file (index.css) as the source of truth for all theme values, utilities, and color semantics — no JS config, no parallel vocabularies, no undocumented conventions.

User Stories

  1. As a contributor modifying UI, I want a single authoritative design system document, so that I know which tokens are correct without reverse-engineering CSS.
  2. As a contributor, I want all styling defined in CSS (no JS config file), so that the build is simpler and I don't need to check two places for theme values.
  3. As a contributor, I want legacy color aliases deleted, so that I'm not confused by two names for the same value.
  4. As a contributor, I want semantic tokens to be the strongly-preferred way to express color, so that future dark mode support doesn't require auditing individual components.
  5. As a contributor using shadcn components, I want shadcn compatibility tokens inlined and removed, so that there's one vocabulary for everyone.
  6. As a future implementer of dark mode, I want semantic tokens structured to support CSS light-dark() remapping, so that adding dark mode is a variable reassignment rather than a component-by-component rewrite.
  7. As a contributor reviewing a PR, I want batch-by-token commits during migration, so that I can see how each legacy token maps to its semantic replacement and whether the semantic layer has gaps.
  8. As a contributor, I want custom plugin utilities migrated to Tailwind v4 @utility syntax, so that no JS plugin code remains.
  9. As a contributor, I want the gray palette documented as zinc-values-under-the-gray-name, so that I understand the one non-obvious remapping.
  10. As a contributor, I want direct palette scale references in components to be exceptional and documented, not the norm, so that I default to semantic tokens.
  11. As a contributor, I want orphaned dark mode fragments removed, so that incomplete code doesn't suggest dark mode is partially implemented.
  12. As a contributor, I want docs/agents/tailwind.md merged into the new design doc, so that there's one styling reference, not two.

Implementation Decisions

  • Delete tailwind.config.ts entirely. All values move to CSS-native declarations:

    • Font families, font weights, z-index, keyframes, animations, logo-gradient, maxWidth.paragraph@theme block in index.css
    • aria.invalid and data.open/closed extensions → dropped (native in Tailwind v4 as aria-invalid:, data-open:, data-closed:)
    • Plugin utilities (content-auto, content-hidden, content-visible, intrinsic-size-*) → @utility blocks in index.css
  • Semantic token names stay as-is. The existing token vocabulary (foreground, muted-foreground, primary, primary-foreground, etc.) is preserved. No renames. Documentation clarifies semantics for the naming system that's already in place.

  • Legacy alias section (lines 116–148 of index.css) is deleted after all 117 usages are migrated to canonical tokens. Migration is intent-based (choose the correct semantic token by the component's purpose) rather than mechanical (blind find-and-replace of the alias target).

  • shadcn compat tokens (destructive, popover, popover-foreground, accent, accent-foreground) inlined. The handful of shadcn-origin components (DropdownMenu, AlertDialog, Dialog) are rewritten to use canonical tokens (danger, background, foreground, primary-subtle, primary-foreground). Compat aliases deleted.

  • Orphaned dark mode removed. The @custom-variant dark declaration and 4 dark: usages across Field, DropdownMenu, Checkbox, CollapsibleSidebar are stripped. Dark mode is an intended future goal using light-dark() on semantic tokens.

  • Gray-is-zinc is documented. Tailwind's neutral scales (slate, zinc, neutral, stone) are removed; gray-* is redefined with zinc's oklch values. This is the single neutral palette. Documented, not renamed.

  • Direct palette scale references (brand-*, gray-* in components) are migrated to semantic tokens where a semantic intent exists. Palette scales remain available for genuine one-offs (e.g. logo-gradient) — preference, not prohibition.

  • Migration batched by token. Each legacy token gets its own commit (or small set of commits) to surface any poorly-defined semantic tokens that need refinement. Insights update the draft design doc.

  • Execution order:

    1. Draft design.md
    2. Delete tailwind.config.ts (migrate to CSS)
    3. Strip orphaned dark mode
    4. Inline shadcn compat tokens
    5. Migrate legacy aliases (by token)
    6. Eliminate direct palette references
    7. Finalize design.md, delete tailwind.md, update AGENTS.md
  • design.md at docs/agents/design.md, referenced from AGENTS.md Conventions section. Absorbs tailwind.md content. Covers: token vocabulary and semantics, palette structure, gray-is-zinc, semantic-first preference with palette as legal one-off, dark mode future posture, Tailwind v4 conventions (prefer data attributes, responsive directives, v4 syntax).

Testing Decisions

  • This is a zero-behavior-change refactor — no new features, no logic changes. The test seam is the existing build pipeline:

    • pnpm checks must pass (types + lint + format) after every step
    • pnpm test must pass after every step
    • Tailwind's JIT compilation catches references to removed tokens as missing classes at build time — a broken reference becomes invisible (no error, no output), so visual verification via the running app is necessary after each major batch
  • No new automated tests needed. The codebase has no class-name snapshot tests and no visual regression test suite. The validation is that the app builds, renders, and looks the same. Each commit should be buildable and visually verifiable independently.

  • If any step reveals a semantic token gap (a usage that doesn't map cleanly to any existing token), the token is added to @theme, the draft design.md is updated, and a comment is left in the migration commit noting the addition.

Related Issues

Out of Scope

  • Dark mode implementation (future, uses light-dark() on the token layer defined here)
  • Token renames or naming model changes (surface/on pattern, -fg suffix, etc. — deferred)
  • Custom spacing, radius, shadow, or typography token layers (Tailwind defaults are adequate)
  • Component library extraction or design system package
  • Storybook or visual regression testing infrastructure
  • Any user-facing behavior change

Further Notes

  • The vite.config.ts reference to tailwind.config.ts (as a dep for HMR) should be removed when the config file is deleted.
  • The @config "../tailwind.config.ts" directive in index.css should be removed when the config is deleted.
  • The 9 usages of custom plugin utilities (content-auto, content-hidden, content-visible, intrinsic-size-*) should be verified to still work after migrating from JS plugin to @utility — they're used for virtualized list performance.

Important

Internal only — this issue is maintained by the core team and is not accepting external contributions.

Metadata

Metadata

Assignees

Labels

internalSignals that the team will work on this issue internally.ready-for-agentfully specified, ready for an AFK agent

Type

Fields

No fields configured for Task.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions