Skip to content

feat(theme): token-ize component surfaces for dark mode and re-skin#315

Closed
itsprade wants to merge 15 commits into
feat/theme-foundationfrom
feat/theme-component-surfaces
Closed

feat(theme): token-ize component surfaces for dark mode and re-skin#315
itsprade wants to merge 15 commits into
feat/theme-foundationfrom
feat/theme-component-surfaces

Conversation

@itsprade

Copy link
Copy Markdown
Contributor

Summary

The final layer of the theming work: replaces hardcoded color literals in components with semantic tokens, so every surface adapts correctly across light/dark mode and any brand palette introduced by the earlier PRs.

Stack: built on feat/theme-css-tokens (#314); targets that branch.

What changed

  • badge.tsxbg-green-500 / bg-yellow-500 / bg-blue-500 (and their /10 subtle + dot variants) → status-completed / status-attention / status-neutral tokens.
  • select.tsx, combobox.tsx, autocomplete.tsx — trigger / input / chip surfaces move from a fixed bg-background to bg-transparent dark:bg-input/30, giving a subtle control fill that reads well on every palette in dark mode without going too dark.
  • dialog.tsx, sheet.tsx — panel surface bg-backgroundbg-card (the backdrop bg-black/50 is intentionally left as-is — correct in both modes).
  • tabs.tsx — active tab uses bg-primary/10 text-primary; the capsule track uses bg-background dark:bg-input/30 with no border (was a bg-background track that became a black hole on dark cards).
  • csv-importer/CsvImporter.tsxtext-yellow-600 / bg-yellow-50 / border-yellow-500status-attention tokens; text-emerald-600status-completed.
  • 9 snapshots updated to match.

Verification

  • pnpm --filter @tailor-platform/app-shell type-check — clean.
  • pnpm --filter @tailor-platform/app-shell lint — 0 warnings, 0 errors.
  • pnpm --filter @tailor-platform/app-shell test1119 passed.
  • build — green.

🤖 Generated with Claude Code

IzumiSy and others added 14 commits June 4, 2026 11:34
…nt axis

- Add cream/bloom color palettes with CSS custom properties (theme.css)
- Shell gradient, font-axis CSS, squircle corners, autofill overrides (globals.css)
- Refactor ThemeProvider: Theme/ResolvedTheme/Font types, useFont hook, legacy ID migration, memoized context
- Add defaultTheme/defaultFont props to AppShell
- Export new types and hooks from package index
- Add ThemeProvider unit tests
- Add ThemeSwitcher dropdown menu with 5 color themes and 2 font options
- Extract useFont hook from theme-context for independent font state access
- Replace sidebar-layout's simple light/dark toggle with full ThemeSwitcher
- Add themeSwitcher prop to SidebarLayout for customization/hiding
- Export ThemeSwitcher and useFont from package index
- Add component tests for ThemeSwitcher
Extract token definitions and structural overrides into individual
files under src/assets/themes/ (light, dark, cream, bloom). Each
branded theme (cream/bloom) is now fully self-contained with its own
gradient, squircle, and transparency rules.

theme.css becomes a lightweight hub: @import directives + @theme inline
bridge. globals.css retains only theme-agnostic global rules.
- Add @fontsource-variable/geist and @fontsource-variable/inter as deps
- Add ./styles/fonts export in package.json pointing to dist/fonts.css
- Create src/assets/fonts.css importing fontsource packages
- Update globals.css font-axis comment to reference new subpath
- Update examples to import @tailor-platform/app-shell/styles/fonts
- Remove next/font/google usage in Next.js example in favor of fontsource
Merge font loading into globals.css so ThemeSwitcher font switching works
out of the box without extra imports. Browsers only download @font-face
resources when the font-family is actually applied to rendered text, so
bundling both Geist and Inter does not add network overhead for unused fonts.

- Import fontsource via src/assets/fonts.css (separation of concerns)
- globals.css imports fonts.css alongside theme.css
- Remove ./styles/fonts subpath export (no longer needed)
- Remove @tailor-platform/app-shell/styles/fonts from examples
- Add changeset
- Add scripts/generate-fonts.mjs to produce fonts.generated.css and
  copy woff2 files to src/assets/fonts/ from fontsource packages
- Remove fonts.css; globals.css no longer imports fonts directly
  (avoids Vite woff2 resolution warnings during build)
- Add appendFonts Vite plugin that appends fonts.generated.css to
  dist/app-shell.css in closeBundle hook (instant, no font generation)
- Committed generated assets so CI doesn't need to re-run generation
- Add generate:fonts script to package.json
Introduce two independent theming axes: mode (light/dark/system) as the
end-user accessibility preference via useMode, and palette/theme
(default/cream/bloom) as a developer configuration via useTheme. Mode is
persisted; palette is prop-driven. The <html> element carries mode as the
.light/.dark class and palette as data-theme. The font axis is untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Merge light.css and dark.css into a single default.css holding both the
light :root block and the .dark override. Organize every theme block
(default, cream, bloom) into tiers: BRAND (primary/secondary + foregrounds,
shell-gradient — the only re-skin knobs), DERIVED (accent/ring/sidebar-*
via color-mix on var(--primary)), SYSTEM (neutral surfaces, accessibility-
locked), and STATUS (semantic, fixed). Give cream and bloom dark variants
that inherit default's status colors. Decouple the shell gradient from
--background via a dedicated --shell-gradient-base token.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Base automatically changed from feat/theme-css-tokens to feat/theme-mode-axis June 15, 2026 02:21
Replace hardcoded colors with semantic tokens so components adapt to mode
and brand changes. Badge success/warning/info map to status-completed/
attention/neutral. Form controls (select/combobox/autocomplete) use
bg-transparent dark:bg-input/30; dialog/sheet panels use bg-card. Tabs
selection uses bg-primary/10 text-primary and the capsule track uses
bg-background dark:bg-input/30 with no border. CsvImporter yellow/emerald
highlights map to status-attention/completed. Snapshots updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@IzumiSy IzumiSy force-pushed the feat/theme-component-surfaces branch from 01375ca to 58d7fa2 Compare June 15, 2026 02:22
@IzumiSy IzumiSy force-pushed the feat/theme-mode-axis branch from 90ed214 to a812837 Compare June 15, 2026 02:23
Base automatically changed from feat/theme-mode-axis to feat/theme-foundation June 15, 2026 02:56
@IzumiSy IzumiSy force-pushed the feat/theme-foundation branch from dd07167 to a6b3da5 Compare June 15, 2026 04:04
@IzumiSy

IzumiSy commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Superseded by #319

@IzumiSy IzumiSy closed this Jun 17, 2026
@IzumiSy IzumiSy deleted the feat/theme-component-surfaces branch June 17, 2026 03:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants