refactor(web): dashboard typography & contrast pass - #28832
refactor(web): dashboard typography & contrast pass#28832austinpickett wants to merge 19 commits into
Conversation
Why - Whole dashboard was force-uppercased by a single \`uppercase\` on the App.tsx root, which inherited into every page and forced ~23 \`normal-case\` opt-outs across 7 files just to keep dynamic content (model names, theme names, etc.) readable. - Micro-typography (\`text-[0.55rem]\` / \`text-[0.6rem]\` / \`text-[9px]\` / \`text-[10px]\` / \`text-[11px]\`) combined with stacked alpha (\`text-muted-foreground/60\` over a 55%-alpha base, \`opacity-30\` on nav headers) produced text that fails WCAG AA at small sizes. - Per-theme \`--theme-font-sans\` was being clobbered by a hard-coded \`font-mondwest\` on the App.tsx root. Changes - Drop global \`uppercase\` + \`font-mondwest\` from the App.tsx root; default to \`text-text-primary\` so body content inherits the theme font. - Map \`--color-muted-foreground\` to \`--color-text-secondary\` so the long tail of \`text-muted-foreground\` call sites get a WCAG-AA-targeted color instead of 55%-alpha midground. - Apply the new DS \`text-display\` utility on intentional brand chrome (sidebar nav section labels, page titles, mobile header brand, segmented filters, badges, ChatSidebar headings). - Remove the 23 \`normal-case\` opt-outs that only existed to fight the global \`uppercase\`. Retain \`normal-case\` on the 4 DS \`Button\` instances that legitimately display dynamic content. - Bump every \`text-[0.55-0.7rem]\` / \`text-[9-11px]\` to \`text-xs\` (12px floor) across PluginsPage, ConfigPage, SkillsPage, ModelsPage, SessionsPage, AnalyticsPage, LogsPage, EnvPage, ChatPage, ChatSidebar, ToolCall, ModelInfoCard, ModelPickerDialog, SidebarStatusStrip, SidebarFooter, OAuthProvidersCard, SlashPopover, ThemeSwitcher, LanguageSwitcher, BottomPickSheet, AutoField. - Replace stacked-alpha refs (\`text-muted-foreground/60\`, \`text-midground/70\`, \`opacity-30/50/60\` on text) with semantic tokens (\`text-text-secondary\`, \`text-text-tertiary\`, \`text-text-disabled\`). - Bump \`@nous-research/ui\` to 0.16.0 (which adds the \`text-display\` utility and semantic text tokens this PR depends on). - Add a Typography & contrast rules section to \`web/README.md\` codifying the 12px text floor, 0.7 opacity floor on text, "uppercase via text-display only" rule, and "prefer semantic tokens" guideline so the dashboard doesn't drift back. This pairs with NousResearch/design-language#22 which provides the \`text-display\` utility and semantic text tokens. Co-authored-by: Cursor <cursoragent@cursor.com>
🔎 Lint report:
|
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Pull request overview
This PR refactors the web dashboard’s typography and contrast to make brand styling opt-in (via the new text-display utility) and to improve readability across themes by switching from stacked alpha colors to semantic text tokens. It updates the app shell, multiple pages/components, and codifies the new rules in web/README.md, alongside a design-system dependency bump.
Changes:
- Remove global
uppercase+font-mondwestinheritance from the App root and apply display styling only where intended. - Replace low-contrast alpha-stacked text colors and sub-12px micro-type with semantic
text-text-*tokens and atext-xsfloor across pages/components. - Update theming compatibility by remapping
--color-muted-foregroundand document the typography/contrast rules; bump@nous-research/uito0.16.0.
Reviewed changes
Copilot reviewed 28 out of 29 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/App.tsx | Drops global uppercase/display font, updates sidebar/header chrome to opt-in text-display + semantic text colors. |
| web/src/index.css | Remaps --color-muted-foreground to --color-text-secondary to improve contrast for legacy text-muted-foreground call sites. |
| web/src/plugins/PluginPage.tsx | Swaps alpha-stacked midground colors for semantic text tokens. |
| web/src/pages/SkillsPage.tsx | Replaces micro-type + stacked alpha with text-xs and semantic tokens; applies text-display to filter/category chrome. |
| web/src/pages/SessionsPage.tsx | Raises small text to text-xs and replaces muted alpha text with semantic token classes. |
| web/src/pages/ProfilesPage.tsx | Removes now-unneeded normal-case wrapper that previously opted out of global uppercase. |
| web/src/pages/PluginsPage.tsx | Applies text-display selectively and replaces arbitrary font sizes / alpha colors with semantic tokens. |
| web/src/pages/ModelsPage.tsx | Raises micro-type to text-xs, replaces muted alpha with semantic tokens, and applies text-display to intentional chrome labels. |
| web/src/pages/LogsPage.tsx | Uses semantic text token for debug lines and raises badge text size to text-xs. |
| web/src/pages/EnvPage.tsx | Refactors unset-row de-emphasis away from low opacity and raises text sizes to text-xs with semantic tokens. |
| web/src/pages/ConfigPage.tsx | Updates filter/section chrome to text-display and replaces micro-type + stacked alpha. |
| web/src/pages/ChatPage.tsx | Removes now-unneeded normal-case root opt-out and updates muted text styling to semantic tokens. |
| web/src/pages/AnalyticsPage.tsx | Raises micro-type to text-xs and swaps muted alpha icons/text for semantic tokens. |
| web/src/components/ToolCall.tsx | Updates tool-call meta styling to semantic tokens and text-display for section labels. |
| web/src/components/ThemeSwitcher.tsx | Switches headings/meta text to text-display + semantic tokens and raises micro-type to text-xs. |
| web/src/components/SlashPopover.tsx | Replaces muted alpha meta text with semantic token usage. |
| web/src/components/SidebarStatusStrip.tsx | Replaces opacity-based de-emphasis with semantic token coloring and raises text size floor. |
| web/src/components/SidebarFooter.tsx | Applies text-display/semantic token styling and removes low-contrast alpha usage. |
| web/src/components/OAuthProvidersCard.tsx | Raises badge micro-type and replaces opacity-based meta text with semantic tokens. |
| web/src/components/ModelPickerDialog.tsx | Applies semantic token styling to provider meta and text-display for the “current” tag. |
| web/src/components/ModelInfoCard.tsx | Raises micro-type and replaces muted alpha with semantic tokens. |
| web/src/components/LanguageSwitcher.tsx | Applies text-display for intended chrome and uses semantic token text colors. |
| web/src/components/ChatSidebar.tsx | Removes global casing opt-out and applies text-display + semantic tokens to sidebar labels. |
| web/src/components/BottomPickSheet.tsx | Switches heading styling to text-display and semantic token coloring. |
| web/src/components/AutoField.tsx | Replaces micro-type and muted alpha with text-xs and semantic tokens. |
| web/README.md | Adds typography/contrast rules for size floors, opacity guidance, text-display, fonts, and tokens. |
| web/package.json | Bumps @nous-research/ui to 0.16.0. |
| web/package-lock.json | Updates lockfile for the DS bump and new transitive dependencies. |
| nix/web.nix | Updates fetchNpmDeps hash to match the new npm dependency graph. |
Files not reviewed (1)
- web/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Clarify that raw uppercase is legacy-only (prefer text-display for new code) and broaden when normal-case is appropriate on DS buttons. Co-authored-by: Cursor <cursoragent@cursor.com>
Drop mondwest on version footer (mono-ui only) and opt the mobile model/tools sheet title into text-display after removing global uppercase. Co-authored-by: Cursor <cursoragent@cursor.com>
Register @font-face rules for Mondwest, Collapse, and Rules so DS components load brand fonts after the 0.14.x split from globals.css. Also merged main to sync the branch. Co-authored-by: Cursor <cursoragent@cursor.com>
Page title h1 and mobile/sidebar brand labels now opt into the DS text-display utility (with Mondwest on brand wordmarks) so chrome stays uppercase after removing the global App root transform. Co-authored-by: Cursor <cursoragent@cursor.com>
Drop the Typography mondwest prop on sidebar/mobile brand labels; it forced tracking-[0.1875rem] instead of the original tight brand tracking. Use font-mondwest via className like main did via shell inheritance. Co-authored-by: Cursor <cursoragent@cursor.com>
text-display alone is correct in source but stale web_dist or missing DS CSS leaves nav looking title-cased; explicit uppercase restores brand chrome. Document Vite vs dashboard URL in web README. Co-authored-by: Cursor <cursoragent@cursor.com>
Replace Typography on Hermes Agent labels with a plain span using font-mondwest + uppercase (matching main via shell inheritance). Typography was injecting font-sans and fighting font-mondwest; text-display was not the pre-refactor brand style. Co-authored-by: Cursor <cursoragent@cursor.com>
Restore main-style Typography on the brand title (Collapse via font-sans), without font-mondwest or forced uppercase on the logo. Co-authored-by: Cursor <cursoragent@cursor.com>
Restore pre-typography-refactor brand classes and explicitly opt out of uppercase so the logo stays "Hermes Agent", not HERMES. Co-authored-by: Cursor <cursoragent@cursor.com>
Follow-up to PR NousResearch#28832 — the dashboard plugin routes now accept slashed names like `observability/langfuse` and `image_gen/openai`, but `_sanitize_plugin_name` still rejected forward slash and so dashboard update + remove on those plugins fell through to '404 not found' even though they exist on disk. Adds an opt-in `allow_subdir=True` flag that: - Permits internal forward slashes (category-namespaced plugin keys emitted by `_discover_all_plugins`). - Strips leading and trailing slashes. - Still rejects `..` and backslash, and still asserts the resolved target lives inside `plugins_dir`. Opted in at the two read-paths that operate on installed plugins: `_require_installed_plugin` (CLI update/remove) and `_user_installed_plugin_dir` (dashboard update/remove). The install path keeps the default (`allow_subdir=False`) because freshly-cloned plugins always land top-level under `~/.hermes/plugins/<name>/`. Adds 6 targeted unit tests covering the new flag's allow/reject matrix. #AI commit#
Removes the global `uppercase` + `font-mondwest` from the App.tsx root
that forced every page to opt-out, replaces stacked-alpha text colors
with semantic tokens for WCAG-AA contrast across all 7 themes, and
applies the new `text-display` utility from @nous-research/ui@0.16.0
on intentional brand chrome (page titles, sidebar headings, segmented
filters) only. Bumps every sub-12px arbitrary text size to text-xs.
Also widens the dashboard plugin routes (/api/dashboard/agent-plugins/
{name:path}/...) so category-namespaced plugins like observability/
langfuse and image_gen/openai can be enable/disabled from the dashboard
— previously the FE encodeURIComponent-ed the slash and the backend
{name} route rejected it. _validate_plugin_name still blocks .. and
backslash, and strips leading/trailing slash.
Touches sessions/env/keys page chrome and adds two new i18n keys
(`overview`, `showMore`/`showLess`) across all 18 locales.
Squashes 19 commits from PR NousResearch#28832.
Co-authored-by: Hermes <noreply@nousresearch.com>
Follow-up to PR NousResearch#28832 — the dashboard plugin routes now accept slashed names like `observability/langfuse` and `image_gen/openai`, but `_sanitize_plugin_name` still rejected forward slash and so dashboard update + remove on those plugins fell through to '404 not found' even though they exist on disk. Adds an opt-in `allow_subdir=True` flag that: - Permits internal forward slashes (category-namespaced plugin keys emitted by `_discover_all_plugins`). - Strips leading and trailing slashes. - Still rejects `..` and backslash, and still asserts the resolved target lives inside `plugins_dir`. Opted in at the two read-paths that operate on installed plugins: `_require_installed_plugin` (CLI update/remove) and `_user_installed_plugin_dir` (dashboard update/remove). The install path keeps the default (`allow_subdir=False`) because freshly-cloned plugins always land top-level under `~/.hermes/plugins/<name>/`. Adds 6 targeted unit tests covering the new flag's allow/reject matrix.
Removes the global `uppercase` + `font-mondwest` from the App.tsx root
that forced every page to opt-out, replaces stacked-alpha text colors
with semantic tokens for WCAG-AA contrast across all 7 themes, and
applies the new `text-display` utility from @nous-research/ui@0.16.0
on intentional brand chrome (page titles, sidebar headings, segmented
filters) only. Bumps every sub-12px arbitrary text size to text-xs.
Also widens the dashboard plugin routes (/api/dashboard/agent-plugins/
{name:path}/...) so category-namespaced plugins like observability/
langfuse and image_gen/openai can be enable/disabled from the dashboard
— previously the FE encodeURIComponent-ed the slash and the backend
{name} route rejected it. _validate_plugin_name still blocks .. and
backslash, and strips leading/trailing slash.
Touches sessions/env/keys page chrome and adds two new i18n keys
(`overview`, `showMore`/`showLess`) across all 18 locales.
Squashes 19 commits from PR NousResearch#28832.
Co-authored-by: Hermes <noreply@nousresearch.com>
Follow-up to PR NousResearch#28832 — the dashboard plugin routes now accept slashed names like `observability/langfuse` and `image_gen/openai`, but `_sanitize_plugin_name` still rejected forward slash and so dashboard update + remove on those plugins fell through to '404 not found' even though they exist on disk. Adds an opt-in `allow_subdir=True` flag that: - Permits internal forward slashes (category-namespaced plugin keys emitted by `_discover_all_plugins`). - Strips leading and trailing slashes. - Still rejects `..` and backslash, and still asserts the resolved target lives inside `plugins_dir`. Opted in at the two read-paths that operate on installed plugins: `_require_installed_plugin` (CLI update/remove) and `_user_installed_plugin_dir` (dashboard update/remove). The install path keeps the default (`allow_subdir=False`) because freshly-cloned plugins always land top-level under `~/.hermes/plugins/<name>/`. Adds 6 targeted unit tests covering the new flag's allow/reject matrix.
Removes the global `uppercase` + `font-mondwest` from the App.tsx root
that forced every page to opt-out, replaces stacked-alpha text colors
with semantic tokens for WCAG-AA contrast across all 7 themes, and
applies the new `text-display` utility from @nous-research/ui@0.16.0
on intentional brand chrome (page titles, sidebar headings, segmented
filters) only. Bumps every sub-12px arbitrary text size to text-xs.
Also widens the dashboard plugin routes (/api/dashboard/agent-plugins/
{name:path}/...) so category-namespaced plugins like observability/
langfuse and image_gen/openai can be enable/disabled from the dashboard
— previously the FE encodeURIComponent-ed the slash and the backend
{name} route rejected it. _validate_plugin_name still blocks .. and
backslash, and strips leading/trailing slash.
Touches sessions/env/keys page chrome and adds two new i18n keys
(`overview`, `showMore`/`showLess`) across all 18 locales.
Squashes 19 commits from PR #28832.
Co-authored-by: Hermes <noreply@nousresearch.com>
Follow-up to PR #28832 — the dashboard plugin routes now accept slashed names like `observability/langfuse` and `image_gen/openai`, but `_sanitize_plugin_name` still rejected forward slash and so dashboard update + remove on those plugins fell through to '404 not found' even though they exist on disk. Adds an opt-in `allow_subdir=True` flag that: - Permits internal forward slashes (category-namespaced plugin keys emitted by `_discover_all_plugins`). - Strips leading and trailing slashes. - Still rejects `..` and backslash, and still asserts the resolved target lives inside `plugins_dir`. Opted in at the two read-paths that operate on installed plugins: `_require_installed_plugin` (CLI update/remove) and `_user_installed_plugin_dir` (dashboard update/remove). The install path keeps the default (`allow_subdir=False`) because freshly-cloned plugins always land top-level under `~/.hermes/plugins/<name>/`. Adds 6 targeted unit tests covering the new flag's allow/reject matrix.
Removes the global `uppercase` + `font-mondwest` from the App.tsx root
that forced every page to opt-out, replaces stacked-alpha text colors
with semantic tokens for WCAG-AA contrast across all 7 themes, and
applies the new `text-display` utility from @nous-research/ui@0.16.0
on intentional brand chrome (page titles, sidebar headings, segmented
filters) only. Bumps every sub-12px arbitrary text size to text-xs.
Also widens the dashboard plugin routes (/api/dashboard/agent-plugins/
{name:path}/...) so category-namespaced plugins like observability/
langfuse and image_gen/openai can be enable/disabled from the dashboard
— previously the FE encodeURIComponent-ed the slash and the backend
{name} route rejected it. _validate_plugin_name still blocks .. and
backslash, and strips leading/trailing slash.
Touches sessions/env/keys page chrome and adds two new i18n keys
(`overview`, `showMore`/`showLess`) across all 18 locales.
Squashes 19 commits from PR NousResearch#28832.
Co-authored-by: Hermes <noreply@nousresearch.com>
Follow-up to PR NousResearch#28832 — the dashboard plugin routes now accept slashed names like `observability/langfuse` and `image_gen/openai`, but `_sanitize_plugin_name` still rejected forward slash and so dashboard update + remove on those plugins fell through to '404 not found' even though they exist on disk. Adds an opt-in `allow_subdir=True` flag that: - Permits internal forward slashes (category-namespaced plugin keys emitted by `_discover_all_plugins`). - Strips leading and trailing slashes. - Still rejects `..` and backslash, and still asserts the resolved target lives inside `plugins_dir`. Opted in at the two read-paths that operate on installed plugins: `_require_installed_plugin` (CLI update/remove) and `_user_installed_plugin_dir` (dashboard update/remove). The install path keeps the default (`allow_subdir=False`) because freshly-cloned plugins always land top-level under `~/.hermes/plugins/<name>/`. Adds 6 targeted unit tests covering the new flag's allow/reject matrix.
Removes the global `uppercase` + `font-mondwest` from the App.tsx root
that forced every page to opt-out, replaces stacked-alpha text colors
with semantic tokens for WCAG-AA contrast across all 7 themes, and
applies the new `text-display` utility from @nous-research/ui@0.16.0
on intentional brand chrome (page titles, sidebar headings, segmented
filters) only. Bumps every sub-12px arbitrary text size to text-xs.
Also widens the dashboard plugin routes (/api/dashboard/agent-plugins/
{name:path}/...) so category-namespaced plugins like observability/
langfuse and image_gen/openai can be enable/disabled from the dashboard
— previously the FE encodeURIComponent-ed the slash and the backend
{name} route rejected it. _validate_plugin_name still blocks .. and
backslash, and strips leading/trailing slash.
Touches sessions/env/keys page chrome and adds two new i18n keys
(`overview`, `showMore`/`showLess`) across all 18 locales.
Squashes 19 commits from PR NousResearch#28832.
Co-authored-by: Hermes <noreply@nousresearch.com>
Follow-up to PR NousResearch#28832 — the dashboard plugin routes now accept slashed names like `observability/langfuse` and `image_gen/openai`, but `_sanitize_plugin_name` still rejected forward slash and so dashboard update + remove on those plugins fell through to '404 not found' even though they exist on disk. Adds an opt-in `allow_subdir=True` flag that: - Permits internal forward slashes (category-namespaced plugin keys emitted by `_discover_all_plugins`). - Strips leading and trailing slashes. - Still rejects `..` and backslash, and still asserts the resolved target lives inside `plugins_dir`. Opted in at the two read-paths that operate on installed plugins: `_require_installed_plugin` (CLI update/remove) and `_user_installed_plugin_dir` (dashboard update/remove). The install path keeps the default (`allow_subdir=False`) because freshly-cloned plugins always land top-level under `~/.hermes/plugins/<name>/`. Adds 6 targeted unit tests covering the new flag's allow/reject matrix.
Follow-up to PR NousResearch#28832 — the dashboard plugin routes now accept slashed names like `observability/langfuse` and `image_gen/openai`, but `_sanitize_plugin_name` still rejected forward slash and so dashboard update + remove on those plugins fell through to '404 not found' even though they exist on disk. Adds an opt-in `allow_subdir=True` flag that: - Permits internal forward slashes (category-namespaced plugin keys emitted by `_discover_all_plugins`). - Strips leading and trailing slashes. - Still rejects `..` and backslash, and still asserts the resolved target lives inside `plugins_dir`. Opted in at the two read-paths that operate on installed plugins: `_require_installed_plugin` (CLI update/remove) and `_user_installed_plugin_dir` (dashboard update/remove). The install path keeps the default (`allow_subdir=False`) because freshly-cloned plugins always land top-level under `~/.hermes/plugins/<name>/`. Adds 6 targeted unit tests covering the new flag's allow/reject matrix.
Removes the global `uppercase` + `font-mondwest` from the App.tsx root
that forced every page to opt-out, replaces stacked-alpha text colors
with semantic tokens for WCAG-AA contrast across all 7 themes, and
applies the new `text-display` utility from @nous-research/ui@0.16.0
on intentional brand chrome (page titles, sidebar headings, segmented
filters) only. Bumps every sub-12px arbitrary text size to text-xs.
Also widens the dashboard plugin routes (/api/dashboard/agent-plugins/
{name:path}/...) so category-namespaced plugins like observability/
langfuse and image_gen/openai can be enable/disabled from the dashboard
— previously the FE encodeURIComponent-ed the slash and the backend
{name} route rejected it. _validate_plugin_name still blocks .. and
backslash, and strips leading/trailing slash.
Touches sessions/env/keys page chrome and adds two new i18n keys
(`overview`, `showMore`/`showLess`) across all 18 locales.
Squashes 19 commits from PR NousResearch#28832.
Co-authored-by: Hermes <noreply@nousresearch.com>
Follow-up to PR NousResearch#28832 — the dashboard plugin routes now accept slashed names like `observability/langfuse` and `image_gen/openai`, but `_sanitize_plugin_name` still rejected forward slash and so dashboard update + remove on those plugins fell through to '404 not found' even though they exist on disk. Adds an opt-in `allow_subdir=True` flag that: - Permits internal forward slashes (category-namespaced plugin keys emitted by `_discover_all_plugins`). - Strips leading and trailing slashes. - Still rejects `..` and backslash, and still asserts the resolved target lives inside `plugins_dir`. Opted in at the two read-paths that operate on installed plugins: `_require_installed_plugin` (CLI update/remove) and `_user_installed_plugin_dir` (dashboard update/remove). The install path keeps the default (`allow_subdir=False`) because freshly-cloned plugins always land top-level under `~/.hermes/plugins/<name>/`. Adds 6 targeted unit tests covering the new flag's allow/reject matrix.
Removes the global `uppercase` + `font-mondwest` from the App.tsx root
that forced every page to opt-out, replaces stacked-alpha text colors
with semantic tokens for WCAG-AA contrast across all 7 themes, and
applies the new `text-display` utility from @nous-research/ui@0.16.0
on intentional brand chrome (page titles, sidebar headings, segmented
filters) only. Bumps every sub-12px arbitrary text size to text-xs.
Also widens the dashboard plugin routes (/api/dashboard/agent-plugins/
{name:path}/...) so category-namespaced plugins like observability/
langfuse and image_gen/openai can be enable/disabled from the dashboard
— previously the FE encodeURIComponent-ed the slash and the backend
{name} route rejected it. _validate_plugin_name still blocks .. and
backslash, and strips leading/trailing slash.
Touches sessions/env/keys page chrome and adds two new i18n keys
(`overview`, `showMore`/`showLess`) across all 18 locales.
Squashes 19 commits from PR NousResearch#28832.
Co-authored-by: Hermes <noreply@nousresearch.com>
Follow-up to PR NousResearch#28832 — the dashboard plugin routes now accept slashed names like `observability/langfuse` and `image_gen/openai`, but `_sanitize_plugin_name` still rejected forward slash and so dashboard update + remove on those plugins fell through to '404 not found' even though they exist on disk. Adds an opt-in `allow_subdir=True` flag that: - Permits internal forward slashes (category-namespaced plugin keys emitted by `_discover_all_plugins`). - Strips leading and trailing slashes. - Still rejects `..` and backslash, and still asserts the resolved target lives inside `plugins_dir`. Opted in at the two read-paths that operate on installed plugins: `_require_installed_plugin` (CLI update/remove) and `_user_installed_plugin_dir` (dashboard update/remove). The install path keeps the default (`allow_subdir=False`) because freshly-cloned plugins always land top-level under `~/.hermes/plugins/<name>/`. Adds 6 targeted unit tests covering the new flag's allow/reject matrix.
Removes the global `uppercase` + `font-mondwest` from the App.tsx root
that forced every page to opt-out, replaces stacked-alpha text colors
with semantic tokens for WCAG-AA contrast across all 7 themes, and
applies the new `text-display` utility from @nous-research/ui@0.16.0
on intentional brand chrome (page titles, sidebar headings, segmented
filters) only. Bumps every sub-12px arbitrary text size to text-xs.
Also widens the dashboard plugin routes (/api/dashboard/agent-plugins/
{name:path}/...) so category-namespaced plugins like observability/
langfuse and image_gen/openai can be enable/disabled from the dashboard
— previously the FE encodeURIComponent-ed the slash and the backend
{name} route rejected it. _validate_plugin_name still blocks .. and
backslash, and strips leading/trailing slash.
Touches sessions/env/keys page chrome and adds two new i18n keys
(`overview`, `showMore`/`showLess`) across all 18 locales.
Squashes 19 commits from PR NousResearch#28832.
Co-authored-by: Hermes <noreply@nousresearch.com>
Follow-up to PR NousResearch#28832 — the dashboard plugin routes now accept slashed names like `observability/langfuse` and `image_gen/openai`, but `_sanitize_plugin_name` still rejected forward slash and so dashboard update + remove on those plugins fell through to '404 not found' even though they exist on disk. Adds an opt-in `allow_subdir=True` flag that: - Permits internal forward slashes (category-namespaced plugin keys emitted by `_discover_all_plugins`). - Strips leading and trailing slashes. - Still rejects `..` and backslash, and still asserts the resolved target lives inside `plugins_dir`. Opted in at the two read-paths that operate on installed plugins: `_require_installed_plugin` (CLI update/remove) and `_user_installed_plugin_dir` (dashboard update/remove). The install path keeps the default (`allow_subdir=False`) because freshly-cloned plugins always land top-level under `~/.hermes/plugins/<name>/`. Adds 6 targeted unit tests covering the new flag's allow/reject matrix.
What does this PR do?
Pays down accumulated typography and contrast debt in the dashboard:
uppercase+font-mondweston the App.tsx root that was inheriting into every page and forcing ~23normal-caseopt-outs across 7 files.text-displayutility from@nous-research/ui@0.16.0on intentional brand chrome (page titles, sidebar section headings, segmented filters) so the brand uppercase look is opt-in per element instead of global.text-muted-foreground/60over a 55%-alpha base,opacity-30on nav headers, etc.) with the new semantic text tokens (text-text-primary/secondary/tertiary/disabled) so contrast stays WCAG-AA across all 7 built-in themes.text-[…rem|px]arbitrary value totext-xs(12px floor) where it was actually content rather than decoration.--color-muted-foregroundto--color-text-secondaryinindex.cssso existingtext-muted-foregroundcall sites land on the new contrast floor without per-file changes.web/README.mdso we don't drift back.Pairs with NousResearch/design-language#22 (the DS PR that ships
text-display+ semantic text tokens + sourcemaps).Related Issue
Fixes #
Type of Change
web/README.md)Changes Made
App / theming
web/src/App.tsx— drop globaluppercase+font-mondwest; default totext-text-primary. Applytext-display+ semantic text tokens on sidebar nav section labels, mobile header brand, sidebar brand, system actions.web/src/index.css— map--color-muted-foregroundto--color-text-secondary.Components
web/src/components/AutoField.tsx,BottomPickSheet.tsx,ChatSidebar.tsx,LanguageSwitcher.tsx,ModelInfoCard.tsx,ModelPickerDialog.tsx,OAuthProvidersCard.tsx,SidebarFooter.tsx,SidebarStatusStrip.tsx,SlashPopover.tsx,ThemeSwitcher.tsx,ToolCall.tsx— replace micro-type + stacked alpha withtext-xsand semantic tokens; applytext-displayon intentional brand chrome only.Pages
web/src/pages/AnalyticsPage.tsx,ChatPage.tsx,ConfigPage.tsx,EnvPage.tsx,LogsPage.tsx,ModelsPage.tsx,PluginsPage.tsx,ProfilesPage.tsx,SessionsPage.tsx,SkillsPage.tsx— same sweep across each page.web/src/plugins/PluginPage.tsx— swaptext-midground/70→text-text-secondary/text-text-tertiary.Dependency bump
web/package.json—@nous-research/ui0.14.0→0.16.0(DS PR providestext-display+ semantic text tokens).web/package-lock.json— regenerated for the DS bump.nix/web.nix—fetchNpmDepshash refreshed vianix run .#fix-lockfiles.Docs
web/README.md— new "Typography & contrast rules" section: 12px text floor, 0.7 opacity floor on text,text-display(prefer over rawuppercase), prefer semantic tokens.How to Test
cd web && npm install && npm run build && npm run dev— verify the dashboard builds and renders.default-large,midnight,ember,mono,cyberpunk,rose. Body content should pick up each theme'sfontSansinstead of Mondwest. Brand chrome should remain Mondwest + uppercase.text-xs). The only sub-12px content remaining should be decorative (chart stripe overlay on ModelsPage, empty-state icons).normal-caseon DS buttons still works where sentence-case UI is intended (model picker, theme/language switchers, EnvPage toggle, sidebar "New chat").pytest tests/ -q— no changes outsideweb/, but run it to confirm.Checklist
Code
refactor(web): …)pytest tests/ -qand all tests pass — N/A, frontend-only refactorDocumentation & Housekeeping
docs/, docstrings) —web/README.mdupdated with rules sectioncli-config.yaml.exampleif I added/changed config keys — N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — N/AScreenshots / Logs