Skip to content

feat: increase text and interactive elems contrast#2621

Open
alexdln wants to merge 9 commits into
npmx-dev:mainfrom
alexdln:feat/color-contrast
Open

feat: increase text and interactive elems contrast#2621
alexdln wants to merge 9 commits into
npmx-dev:mainfrom
alexdln:feat/color-contrast

Conversation

@alexdln

@alexdln alexdln commented Apr 24, 2026

Copy link
Copy Markdown
Member

🔗 Linked issue

Resolves #1510

🧭 Context

One of the issues with the a11y and a recurring topic with the community is poor text visibility. I've also experienced this myself. So, I'm trying to increase contrast. As usual, I did it quite carefully - changed the colors by 10% and added a new shade for the borders (I use it for inputs/selects and in the midtone for buttons [I think they need a redesign to make them more visible, not the borders])

I also added foreground shade select so that the user can choose the desired format, where the default contrast is slightly increased from the previous one and we can switch to the old one or to an even higher contrast one

image

@vercel

vercel Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Jul 6, 2026 12:53pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Jul 6, 2026 12:53pm
npmx-lunaria Ignored Ignored Jul 6, 2026 12:53pm

Request Review

@coderabbitai

coderabbitai Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 746b351e-ce4c-462c-b2bb-4d37326f1cf7

📥 Commits

Reviewing files that changed from the base of the PR and between 33ab9bf and f364d4e.

📒 Files selected for processing (1)
  • app/utils/prehydrate.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/utils/prehydrate.ts

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added support for foreground themes (contrast, standard, muted) and a new selector in Appearance settings.
    • Foreground themes are now configurable via the command palette.
  • Bug Fixes
    • Refined colour tokens for improved contrast across light and dark modes, including higher-contrast preferences.
    • Updated button, input, and select borders to use the elevated border styling.
  • Accessibility
    • Added accessibility checks for the foreground theme control.
    • Added hydration coverage for foreground theme persistence.

Walkthrough

This change adds a selectable foreground theme setting with muted, standard, and contrast modes. It wires the setting through theme tokens, persisted app state, prehydration, settings UI, command palette navigation, translations, and tests.

Changes

Foreground Theme Feature

Layer / File(s) Summary
Design system tokens and theme colours
app/assets/main.css, lunaria/styles.ts, uno.theme.ts, app/components/Button/Base.vue, app/components/Input/Base.vue, app/components/Select/Base.vue, app/components/VersionSelector.vue
CSS custom properties define foreground theme variants for dark and light modes, and border elevation tokens are added to the design system. Button, input, select, and version selector styles are updated to use the new tokens.
Core state management and settings persistence
shared/utils/constants.ts, app/composables/useSettings.ts, app/utils/prehydrate.ts
Foreground theme constants, settings fields, defaults, composable state, and prehydration logic are added for reading and applying the selected foreground theme.
UI components for theme selection
app/components/Settings/FgThemePicker.vue, app/pages/settings.vue
A new swatch-based foreground theme picker is added and placed in the Appearance section of settings.
Command palette integration for theme navigation
app/types/command-palette.ts, app/composables/useCommandPaletteGlobalCommands.ts, i18n/locales/en.json, i18n/schema.json
The command palette gains a foreground-themes view and commands, along with labels, announcement text, and schema entries for the new theme settings.
Test coverage for foreground theme feature
test/e2e/hydration.spec.ts, test/nuxt/a11y.spec.ts, test/nuxt/components/CommandPalette.spec.ts, test/nuxt/components/HeaderConnectorModal.spec.ts, test/nuxt/composables/use-command-palette-commands.spec.ts
Hydration, accessibility, command palette, and composable tests are extended for foreground theme selection and persistence.

Sequence Diagram(s)

sequenceDiagram
  participant SettingsPage
  participant useForegroundTheme
  participant document.documentElement
  participant localStorage
  SettingsPage->>useForegroundTheme: select foreground theme
  useForegroundTheme->>document.documentElement: set data-fg-theme
  useForegroundTheme->>localStorage: persist preferredForegroundTheme
  localStorage->>document.documentElement: prehydrate saved theme
Loading

Suggested reviewers: ghostdevv, gameroman

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed It clearly describes the main change: increasing contrast for text and interactive elements.
Description check ✅ Passed The description matches the implemented contrast and foreground-theme work.
Linked Issues check ✅ Passed The PR improves shared contrast tokens, borders and hover states, and keeps the dimmed theme available as a selectable foreground option.
Out of Scope Changes check ✅ Passed The changes stay focused on contrast/theme adjustments, settings UI, command palette support, and related tests.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Apr 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 61.90476% with 16 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
app/utils/prehydrate.ts 0.00% 4 Missing and 2 partials ⚠️
app/composables/useCommandPaletteGlobalCommands.ts 66.66% 3 Missing and 2 partials ⚠️
app/composables/useSettings.ts 63.63% 3 Missing and 1 partial ⚠️
app/components/Settings/FgThemePicker.vue 85.71% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@github-actions

github-actions Bot commented May 13, 2026

Copy link
Copy Markdown

Lunaria Status Overview

🌕 This pull request will trigger status changes.

Learn more

By default, every PR changing files present in the Lunaria configuration's files property will be considered and trigger status changes accordingly.

You can change this by adding one of the keywords present in the ignoreKeywords property in your Lunaria configuration file in the PR's title (ignoring all files) or by including a tracker directive in the merged commit's description.

Tracked Files

File Note
i18n/locales/en.json Source changed, localizations will be marked as outdated.
Warnings reference
Icon Description
🔄️ The source for this localization has been updated since the creation of this pull request, make sure all changes in the source have been applied.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/components/Settings/FgThemePicker.vue`:
- Around line 8-11: The selector construction using
settings.preferredForegroundTheme (variable id) can throw if id contains invalid
characters; update the prehydrate logic in FgThemePicker.vue to validate or
sanitize id before passing it to el.querySelector: either check that id exists
in the canonical list of theme ids used by this component (e.g., the array/prop
that holds available theme ids) and only build the selector when it matches, or
call CSS.escape(id) to safely escape the value before interpolation; ensure you
reference and use the same identifier names (settings.preferredForegroundTheme /
id and the el.querySelector(...) call) when applying the validation/sanitization
so querySelector cannot be given a malformed selector.

In `@app/utils/prehydrate.ts`:
- Around line 42-46: preferredForegroundTheme is read from settings and applied
directly to document.documentElement.dataset.fgTheme; validate it first against
the allowed set ["muted","standard","contrast"] before assigning. Update the
logic around settings.preferredForegroundTheme in prehydrate.ts to: check that
preferredForegroundTheme is a string and is one of the allowed ids (e.g., via a
small const ALLOWED_FG_THEMES = new Set([...]) or array.includes), and only then
set document.documentElement.dataset.fgTheme = preferredForegroundTheme;
otherwise skip the assignment (or fall back to a safe default).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f6954aee-32cc-45e6-ac0c-22c64796aaad

📥 Commits

Reviewing files that changed from the base of the PR and between c2c2754 and c7bab73.

📒 Files selected for processing (21)
  • app/assets/main.css
  • app/components/AppHeader.vue
  • app/components/Button/Base.vue
  • app/components/Input/Base.vue
  • app/components/Select/Base.vue
  • app/components/Settings/FgThemePicker.vue
  • app/composables/useCommandPaletteGlobalCommands.ts
  • app/composables/useSettings.ts
  • app/pages/settings.vue
  • app/types/command-palette.ts
  • app/utils/prehydrate.ts
  • i18n/locales/en.json
  • i18n/schema.json
  • lunaria/styles.ts
  • shared/utils/constants.ts
  • test/e2e/hydration.spec.ts
  • test/nuxt/a11y.spec.ts
  • test/nuxt/components/CommandPalette.spec.ts
  • test/nuxt/components/HeaderConnectorModal.spec.ts
  • test/nuxt/composables/use-command-palette-commands.spec.ts
  • uno.theme.ts

Comment thread app/components/Settings/FgThemePicker.vue
Comment thread app/utils/prehydrate.ts
@trueberryless

Copy link
Copy Markdown
Member

Looks very clean, amazing work 🥰

One nitpicky detail I noticed: The version seems a little bit more grey than all the other text around it. Not sure if this is a11y related, but I think we could change it to be white as well (currently it only gets white on hover).

Screenshot_20260603-151427.png

Wdyt?

@alexdln

alexdln commented Jun 3, 2026

Copy link
Copy Markdown
Member Author

@trueberryless Good point, we've heard many times that the version is too unnoticeable and needs to be more visible

@ghostdevv

Copy link
Copy Markdown
Member

@alexdln we still wanna merge this? If so I can rebase and review 😄

@gameroman gameroman added the front Frontend, Design label Jul 6, 2026
@WilcoSp

WilcoSp commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

at least in my opinion this should be merged eventually as it does improve accessibility.

the only reason why I hadn't reviewed this pr was because of the concerns that coderabbit had raised.

@alexdln

alexdln commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

@ghostdevv thank you for the bump, ready for review :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

front Frontend, Design

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Non-text contrast is not sufficient (almost everywhere)

5 participants