feat(theme): token-ize component surfaces for dark mode and re-skin#315
Closed
itsprade wants to merge 15 commits into
Closed
feat(theme): token-ize component surfaces for dark mode and re-skin#315itsprade wants to merge 15 commits into
itsprade wants to merge 15 commits into
Conversation
…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
…rdcode storage keys, add system reactivity
- 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>
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>
01375ca to
58d7fa2
Compare
90ed214 to
a812837
Compare
dd07167 to
a6b3da5
Compare
Contributor
|
Superseded by #319 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.tsx—bg-green-500/bg-yellow-500/bg-blue-500(and their/10subtle + dot variants) →status-completed/status-attention/status-neutraltokens.select.tsx,combobox.tsx,autocomplete.tsx— trigger / input / chip surfaces move from a fixedbg-backgroundtobg-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 surfacebg-background→bg-card(the backdropbg-black/50is intentionally left as-is — correct in both modes).tabs.tsx— active tab usesbg-primary/10 text-primary; the capsule track usesbg-background dark:bg-input/30with no border (was abg-backgroundtrack that became a black hole on dark cards).csv-importer/CsvImporter.tsx—text-yellow-600/bg-yellow-50/border-yellow-500→status-attentiontokens;text-emerald-600→status-completed.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 test— 1119 passed.build— green.🤖 Generated with Claude Code