feat(theme): add design tokens and user theme hooks#31
Conversation
There was a problem hiding this comment.
Pull request overview
Introduces an initial design-token based theme system (light/dark + accent) and wires the app shell + home page to those tokens, with persisted per-user theme preferences stored on the users table.
Changes:
- Added CSS variable design tokens and selector-driven dark mode behavior for Tailwind v4 utilities.
- Applied token-based classes in the app shell and home page views, including per-user theme mode/accent overrides.
- Added a
theme_preferencesJSON column + model cast, plus feature tests covering default and authenticated theme behavior.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
resources/css/app.css |
Defines app color tokens as CSS variables, maps them to Tailwind theme colors, and configures dark mode via [data-theme=dark]. |
resources/views/components/layouts/app-shell.blade.php |
Reads user theme preferences, emits theme-related data attributes / CSS variables, and resolves system theme in the head script. |
resources/views/home.blade.php |
Updates UI classes to use the new token-based Tailwind colors. |
database/migrations/2026_04_10_052717_add_theme_preferences_to_users_table.php |
Adds persisted storage for user theme preferences. |
app/Models/User.php |
Makes theme_preferences mass-assignable and casts it to an array. |
tests/Feature/Shell/ThemePreferencesTest.php |
Adds feature coverage asserting default guest mode and authenticated user overrides. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| --app-text: oklch(0.24 0.01 212); | ||
| --app-muted: oklch(0.5 0.01 212); | ||
| --app-accent: #2d8f77; | ||
| --app-accent-soft: #d6f0e8; | ||
| --app-accent-strong: #1f6e5d; | ||
| } |
There was a problem hiding this comment.
User accent overrides only update --app-accent, but in the light theme --app-accent-soft and --app-accent-strong are hard-coded hex values. This means UI that uses bg-accent-soft/text-accent-strong won’t reflect the user’s chosen accent in light mode. Consider deriving the soft/strong tokens from var(--app-accent) in :root (similar to the dark theme) so the override applies consistently.
| <html | ||
| lang="{{ str_replace('_', '-', app()->getLocale()) }}" | ||
| class="h-full" | ||
| data-theme-mode="{{ $themeMode }}" | ||
| style="{{ $themeStyle }}" | ||
| > |
There was a problem hiding this comment.
Currently the theme is only applied via the inline script that sets data-theme. If JavaScript is disabled (or blocked by CSP), even an authenticated user with mode set to dark/light will render using the default :root tokens because the server never sets data-theme on the <html> element. Consider setting data-theme server-side when $themeMode is dark or light (and only rely on JS for the system case) so explicit user preferences work without JS.
Summary
Issue
Scope Check
Validation
Notes