Dark mode: fix highlight text + add theme preference setting#94
Dark mode: fix highlight text + add theme preference setting#94HamptonMakes merged 5 commits intomainfrom
Conversation
The <mark> element used for anchor highlights has a browser-default color: black, making highlighted/commented text unreadable in dark mode. Adding color: inherit to .anchor-highlight ensures the text color follows the page theme instead of the browser default. Amp-Thread-ID: https://ampcode.com/threads/T-019dac90-a21f-721a-96de-81ec6c0ec184 Co-authored-by: Amp <amp@ampcode.com>
Adds a user-facing Appearance section to Settings with three theme options: System (follows device), Light, and Dark. Theme switches instantly via a Stimulus controller that sets data-theme on <html> and persists the preference to the user's metadata JSON column. CSS changes: - Media query dark tokens now target :root:not([data-theme]) so they only apply when no explicit theme is set - Added :root[data-theme="dark"] with the same dark tokens for forced dark mode regardless of system preference - Added :root[data-theme="light"] to force light mode - Added .theme-option component styles for the settings UI Backend: - User model: theme_preference getter/setter backed by metadata JSON - Settings controller: PATCH /settings/theme endpoint - Routes: added theme route in settings namespace Frontend: - Stimulus theme_controller.js: instant DOM update + async PATCH - Layout: conditional data-theme attribute + dynamic color-scheme meta Amp-Thread-ID: https://ampcode.com/threads/T-019dac90-a21f-721a-96de-81ec6c0ec184 Co-authored-by: Amp <amp@ampcode.com>
Replace the large card-based radio buttons with a sleek inline segmented control: monitor icon for System, sun for Light, moon for Dark. Uses a settings-row layout pattern for clean label/control alignment. Amp-Thread-ID: https://ampcode.com/threads/T-019dac90-a21f-721a-96de-81ec6c0ec184 Co-authored-by: Amp <amp@ampcode.com>
Wrap the segmented control in a card so it reads as its own settings section rather than a floating header element. Bump button padding from xs/sm to sm/md for better touch targets. Amp-Thread-ID: https://ampcode.com/threads/T-019dac90-a21f-721a-96de-81ec6c0ec184 Co-authored-by: Amp <amp@ampcode.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 56bec22c11
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| def theme_preference=(value) | ||
| self.metadata ||= {} | ||
| self.metadata["theme_preference"] = value |
There was a problem hiding this comment.
Persist theme outside auth-synced metadata
Saving theme_preference inside metadata will be clobbered in common host setups because authenticate_coplan_user! reassigns attrs[:metadata] on every request (and the integration guide’s example returns metadata: {}). In that flow, a user can select Dark, but the next request overwrites metadata and resets to System, so the new setting is not actually persistent. This preference needs to live in a field that is not rewritten by auth sync (or merge preserved keys before assignment).
Useful? React with 👍 / 👎.
|
Good catch! The Fixed by extracting a See commit 56bec22 → fixed in the next push. |
The authenticate_coplan_user! method was using assign_attributes with the full :metadata key from the auth callback, which would overwrite user-set preferences like theme_preference on every request. Extract sync_user_attrs helper that merges incoming metadata into the existing hash, preserving keys the user has set independently. Amp-Thread-ID: https://ampcode.com/threads/T-019dac90-a21f-721a-96de-81ec6c0ec184 Co-authored-by: Amp <amp@ampcode.com>
Changes
1. Fix comment highlight text color in dark mode
The
<mark>element used for inline comment highlights has a browser-defaultcolor: black. Addedcolor: inheritto.anchor-highlightso highlighted text is readable in dark mode.2. Add theme preference setting (System / Light / Dark)
New Appearance section on the Settings page with three instant-switching options:
Theme switches instantly via Stimulus — no page reload. Preference is persisted to the user's
metadataJSON column.How it works
@media (prefers-color-scheme: dark)now targets:root:not([data-theme])so it only applies for "System" mode.:root[data-theme="dark"]and:root[data-theme="light"]handle forced overrides.theme_controllersetsdata-themeon<html>for instant transition, updates thecolor-schememeta tag, and PATCHes/settings/themeto persist.User#theme_preferencegetter/setter backed bymetadataJSON.PATCH /settings/themeendpoint validates against allowed values.Files changed
engine/app/assets/stylesheets/coplan/application.csscolor: inheriton highlights, forced theme selectors, theme option stylesengine/app/models/coplan/user.rbTHEME_PREFERENCES, getter/setterengine/config/routes.rbpatch "theme"routeengine/app/controllers/coplan/settings/settings_controller.rbupdate_themeactionengine/app/views/coplan/settings/settings/index.html.erbengine/app/views/layouts/coplan/application.html.erbdata-theme+color-schememetaengine/app/javascript/controllers/coplan/theme_controller.jsAll 687 specs pass.