Skip to content

fix: replace all buttons for design system buttons#17007

Merged
austinpickett merged 11 commits into
mainfrom
austin/fix/more-design-system
Apr 28, 2026
Merged

fix: replace all buttons for design system buttons#17007
austinpickett merged 11 commits into
mainfrom
austin/fix/more-design-system

Conversation

@austinpickett

@austinpickett austinpickett commented Apr 28, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

Migrates the Hermes Agent dashboard to the upgraded @nous-research/ui API and eliminates every native <button> element in hermes-agent/web/src/ (final count: 25 → 0). Every interactive control now flows through a DS component. Drops the local !p-2 aspect-square / !bg-destructive / text-destructive hover:!text-destructive workarounds along with three full local primitives that were duplicating DS work.

End state:

  • Icon-only / ghost / destructive buttons render through DS Button's proper size="icon" / size="xs" / ghost / destructive props
  • Full-width list rows (provider lists, theme lists, model pickers, slash command popovers, accordion headers, etc.) render through the new DS <ListItem> instead of 13 ad-hoc <button class="w-full flex…"> patterns
  • Toggle switches, tabs, and segmented filter controls are now DS primitives — three local files deleted
  • Stats summary tiles use DS <Stats>; copy-with-feedback affordances use DS <CopyButton>
  • The brand mondwest voice is preserved on popover triggers (Language / Theme switchers) by composing DS <Button ghost> with inner <Typography mondwest>

The companion DS work (design-language repo, ships as @nous-research/ui@0.9.0) extended the existing <Button> and added four new components:

  • <Button> extensions — added size: 'xs' for tight inline contexts (eg clear-search × inside an Input). Earlier in this PR series size: 'icon' | 'sm' | 'default' + ghost + destructive already landed.
  • <ListItem> (new) — full-width row primitive with active / disabled / prefix / suffix and pass-through ARIA. Used everywhere a list row needed click affordance.
  • <Switch> (new) — toggle switch primitive (replaces local components/ui/switch.tsx).
  • <Tabs> / <TabsList> / <TabsTrigger> (new) — tab primitive with the same render-prop API as the previous local component, so plugin-SDK callers don't need to change (replaces local components/ui/tabs.tsx).
  • <Segmented> / <FilterGroup> (new) — segmented filter chip group with optional label wrapper (replaces local components/ui/segmented.tsx).

Also picked up <Select> / <SelectOption> from a sibling DS port done in this same series.

All new DS APIs are additive — existing <Button invert outlined> and <Card> callers across all Nous products are 100% unchanged. Storybook coverage added for ListItem, Switch, Tabs, Segmented, and Select.

A resolve.dedupe block in vite.config.ts covers react, react-dom, three, gsap, leva, @react-three/fiber, @observablehq/plot. Defensive — it's a no-op under registry installs but lets future local DS iteration via a file: symlink to a sibling design-language checkout work without dual-React-instance hook crashes.

Related Issue

N/A (internal design-system consolidation; no tracking issue)

Type of Change

  • ♻️ Refactor (no behavior change)
  • ✨ New feature (consumes new DS primitives — additive, non-breaking)

Changes Made

DS Button consumption (icon / ghost / destructive / size variants)

  • src/pages/CronPage.tsx — Pause/Resume/Trigger row buttons → ghost size="icon"; Delete → ghost destructive size="icon"
  • src/pages/ConfigPage.tsx — Export/Import/Reset toolbar → ghost size="icon"; clear-search × → ghost size="xs"; YAML toggle / Save → size="sm" (header chrome should not be hero-CTA height)
  • src/pages/SessionsPage.tsx — Resume row → ghost size="icon"; Delete row → ghost destructive size="icon"; pagination chevrons → outlined size="icon"; clear-search × → ghost size="xs"; banner-dismiss → ghost size="icon"
  • src/pages/SkillsPage.tsx — clear-search × → ghost size="xs"
  • src/pages/EnvPage.tsx — Eye/EyeOff reveal → ghost size="icon"; Clear → outlined destructive size="sm"; all Set/Replace/Save/Cancel/Show-advanced row actions → size="sm"; "not configured" disclosure → ghost size="sm"
  • src/pages/AnalyticsPage.tsx — 7D/30D/90D filter chips + Refresh → size="sm"
  • src/pages/LogsPage.tsx — Refresh → size="sm"
  • src/components/OAuthProvidersCard.tsx — Docs link → ghost size="icon"; Refresh / Login / Disconnect → size="sm"
  • src/components/ChatSidebar.tsx — model-picker trigger → ghost size="sm" with link styling overrides; Reconnect → outlined size="sm"
  • src/components/ModelPickerDialog.tsx — close × → ghost size="icon"
  • src/components/OAuthLoginModal.tsx — close × → ghost size="icon"
  • src/components/ui/confirm-dialog.tsx — Confirm button → destructive prop (replaces className={destructive ? "!bg-destructive !text-destructive-foreground" : undefined})
  • src/App.tsx — mobile-nav hamburger / mobile-sidebar close → ghost size="icon"; full-screen backdrop scrim → childless <Button ghost> with block p-0 overrides
  • src/pages/ChatPage.tsx — mobile-panel close → ghost size="icon"; mobile model-tools header trigger → <Button ghost> with custom border chrome; copy-last-response → <Button ghost> pinned to xterm theme color; full-screen backdrop scrim → childless <Button ghost>

DS <ListItem> adoption (13 list-row buttons swept)

  • src/components/SlashPopover.tsx — slash-command popover row
  • src/components/ToolCall.tsx — tool-call disclosure header
  • src/components/ModelPickerDialog.tsx — provider list row + model list row
  • src/components/ThemeSwitcher.tsx — theme list row (the trigger itself uses <Button ghost> with <Typography mondwest> inside, see Bucket D below)
  • src/pages/ConfigPage.tsx — sidebar category nav row
  • src/pages/EnvPage.tsx — provider accordion header
  • src/pages/SessionsPage.tsx — tool-call action banner row (warning-tone variant via className)
  • src/pages/SkillsPage.tsx — skill key-picker chip + source-panel item (PanelItem)
  • src/App.tsx — system-action menu list items (busy / pending / disabled state)

New DS composite primitives (replaces local files)

  • src/components/ui/switch.tsxdeleted, all callers now import Switch from @nous-research/ui (SkillsPage, LogsPage, AutoField)
  • src/components/ui/tabs.tsxdeleted, plugin SDK in plugins/registry.ts now re-exports DS Tabs/TabsList/TabsTrigger
  • src/components/ui/segmented.tsxdeleted, all callers (LogsPage) now import Segmented/FilterGroup from @nous-research/ui

Brand-font popover triggers (preserves font-mondwest)

  • src/components/LanguageSwitcher.tsx — flag + lang code button rebuilt as <Button ghost> + inner <Typography mondwest>
  • src/components/ThemeSwitcher.tsx — palette-icon trigger rebuilt the same way

DS components for shared patterns

  • src/pages/AnalyticsPage.tsx — three-SummaryCard grid → single DS <Stats> (5 metrics: total tokens, input, output, sessions, API calls); two-column Stats + TokenBarChart layout on lg: viewports
  • src/components/OAuthProvidersCard.tsx — local copy-CLI Button + copiedId state + handleCopy → DS <CopyButton> (deletes the state and handler entirely)
  • src/components/OAuthLoginModal.tsx — local copy-user-code Button + codeCopied state + handleCopyUserCode → DS <CopyButton> (same simplification)

Local primitives removed

  • src/components/ui/button.tsxdeleted (everything imports from @nous-research/ui)
  • src/components/ui/switch.tsxdeleted
  • src/components/ui/tabs.tsxdeleted
  • src/components/ui/segmented.tsxdeleted
  • src/components/ui/select.tsxdeleted (sibling DS <Select> port)

Vite config

  • vite.config.ts — added resolve.dedupe for shared deps that exist in both hermes-agent/web/node_modules and design-language/node_modules. Inline comment explains why.

Verification

  • npx tsc -b --noEmit --force — clean
  • npm run build — clean
  • rg '<button[\s>]' over hermes-agent/web/src0 matches
  • ESLint — only pre-existing technical-debt warnings remain (setState-in-effect, react-hooks/exhaustive-deps for unrelated effects); no new warnings introduced

Known follow-up (out of scope)

  • src/pages/DocsPage.tsx — keeps a hand-rolled DS_BUTTON_OUTLINED_LINK_CN constant because the docs CTA renders as <a> and the DS Button is <button>-only. A future polymorphic as prop on DS Button would let us delete that.

How to Test

After npm install && npm run dev (the dashboard now pulls @nous-research/ui@^0.9.0 from the registry):

  1. Cron → trigger a job. Pause/Play/Trigger/Delete row buttons are compact icon squares; Pause is amber, Play is green, Delete is red ghost.
  2. Sessions → rows show ghost Resume + ghost-destructive Delete; pagination chevrons are outlined icon squares; clear-search × in the page header is a tiny xs button that fits inside the Input edge; tool-call action banner row is a <ListItem> with warning tone.
  3. Env → Eye/EyeOff reveal is a ghost icon square; Clear is outlined destructive size="sm"; all row Set/Replace/Save/Cancel buttons are size="sm" (header-row height, not hero-CTA height); Show-advanced and "not configured" disclosure also size="sm"; provider accordion headers click as <ListItem>.
  4. Config → Export/Import/Reset toolbar are ghost icon squares; YAML and Save are size="sm"; sidebar category nav uses <ListItem>; clear-search × in header uses size="xs".
  5. Skills → source-panel items (Markets/Editorial/etc.) are <ListItem>; key-picker chips are <ListItem>; toggles use DS <Switch>; clear-search × uses size="xs".
  6. Logs → severity / component / lines filter rows use DS <Segmented> + <FilterGroup>; auto-refresh toggle uses DS <Switch>; Refresh button is size="sm".
  7. Analytics → at lg+ width, Stats card sits beside <TokenBarChart> in a 2-col grid; 7D/30D/90D filter chips and Refresh are all size="sm".
  8. OAuth providers → Refresh / Login / Disconnect are size="sm"; copy-CLI uses DS <CopyButton>.
  9. Chat → model-picker dialog rows use <ListItem>; slash-command popover uses <ListItem>; tool-call disclosure headers use <ListItem>; sidebar model-picker trigger uses <Button ghost size="sm"> with link aesthetic; backdrop scrims (mobile nav, mobile model-tools panel) are childless <Button ghost> with full-screen overrides.
  10. Header → LanguageSwitcher and ThemeSwitcher render via <Button ghost> but keep their font-mondwest voice via inner <Typography mondwest>.
  11. Confirm-delete dialog → Confirm is solid red on destructive paths; non-destructive dialogs render the default solid CTA.

Visually verify nothing regresses (no useRef of null from React-instance dupes, no missing icons, no oversized header rows, no clipped Badge text).

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (feat(dashboard): / refactor(dashboard):)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this DS adoption
  • I've run pytest tests/ -q and all tests pass — N/A (frontend-only PR, no Python touched)
  • I've added tests for my changes — N/A (visual/structural refactor; existing pages exercise the new components; new DS primitives covered by storybook stories)
  • I've tested on my platform: Linux (WSL2) via Vite dev server + production build (npm run build)

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — N/A (CSS-only frontend change)
  • I've updated tool descriptions/schemas if I changed tool behavior — N/A

Screenshots / Logs

image image image image image image image

@alt-glitch alt-glitch added type/refactor Code restructuring, no behavior change P3 Low — cosmetic, nice to have labels Apr 28, 2026
@NousResearch NousResearch deleted a comment from github-actions Bot Apr 28, 2026
@austinpickett austinpickett merged commit 7d46484 into main Apr 28, 2026
7 of 10 checks passed
@austinpickett austinpickett deleted the austin/fix/more-design-system branch April 28, 2026 18:46
thesunofdog pushed a commit to thesunofdog/hermes-agent that referenced this pull request Apr 28, 2026
`web/package-lock.json` was updated by the design-system refactor
(merged via NousResearch#17007 + follow-ups: spinner / select / badges / buttons)
without bumping `nix/web.nix::npmDeps.hash`, breaking nix builds on
every PR + main since 2026-04-28T18:46.

Hash sourced from the actual `Check flake` failure output:
  specified: sha256-AahWmJ9gDQ9pMPa1FYwUjYdO2mOi6JM9Mst27E0vp68=
  got:       sha256-+B2+Fe4djPzHHcUXRx+m0cuyaopAhW0PcHsMgYfV5VE=

Standalone single-file fix so it can land fast and clear nix on
every other open PR.
ulasbilgen pushed a commit to ulasbilgen/hermes-adhd-agent that referenced this pull request May 1, 2026
…re-design-system

fix: replace all buttons for design system buttons
ulasbilgen pushed a commit to ulasbilgen/hermes-adhd-agent that referenced this pull request May 1, 2026
`web/package-lock.json` was updated by the design-system refactor
(merged via NousResearch#17007 + follow-ups: spinner / select / badges / buttons)
without bumping `nix/web.nix::npmDeps.hash`, breaking nix builds on
every PR + main since 2026-04-28T18:46.

Hash sourced from the actual `Check flake` failure output:
  specified: sha256-AahWmJ9gDQ9pMPa1FYwUjYdO2mOi6JM9Mst27E0vp68=
  got:       sha256-+B2+Fe4djPzHHcUXRx+m0cuyaopAhW0PcHsMgYfV5VE=

Standalone single-file fix so it can land fast and clear nix on
every other open PR.
donald131 pushed a commit to donald131/hermes-agent that referenced this pull request May 2, 2026
`web/package-lock.json` was updated by the design-system refactor
(merged via NousResearch#17007 + follow-ups: spinner / select / badges / buttons)
without bumping `nix/web.nix::npmDeps.hash`, breaking nix builds on
every PR + main since 2026-04-28T18:46.

Hash sourced from the actual `Check flake` failure output:
  specified: sha256-AahWmJ9gDQ9pMPa1FYwUjYdO2mOi6JM9Mst27E0vp68=
  got:       sha256-+B2+Fe4djPzHHcUXRx+m0cuyaopAhW0PcHsMgYfV5VE=

Standalone single-file fix so it can land fast and clear nix on
every other open PR.
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
…re-design-system

fix: replace all buttons for design system buttons
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
`web/package-lock.json` was updated by the design-system refactor
(merged via NousResearch#17007 + follow-ups: spinner / select / badges / buttons)
without bumping `nix/web.nix::npmDeps.hash`, breaking nix builds on
every PR + main since 2026-04-28T18:46.

Hash sourced from the actual `Check flake` failure output:
  specified: sha256-AahWmJ9gDQ9pMPa1FYwUjYdO2mOi6JM9Mst27E0vp68=
  got:       sha256-+B2+Fe4djPzHHcUXRx+m0cuyaopAhW0PcHsMgYfV5VE=

Standalone single-file fix so it can land fast and clear nix on
every other open PR.
dannyJ848 pushed a commit to dannyJ848/hermes-agent that referenced this pull request May 17, 2026
…re-design-system

fix: replace all buttons for design system buttons
dannyJ848 pushed a commit to dannyJ848/hermes-agent that referenced this pull request May 17, 2026
`web/package-lock.json` was updated by the design-system refactor
(merged via NousResearch#17007 + follow-ups: spinner / select / badges / buttons)
without bumping `nix/web.nix::npmDeps.hash`, breaking nix builds on
every PR + main since 2026-04-28T18:46.

Hash sourced from the actual `Check flake` failure output:
  specified: sha256-AahWmJ9gDQ9pMPa1FYwUjYdO2mOi6JM9Mst27E0vp68=
  got:       sha256-+B2+Fe4djPzHHcUXRx+m0cuyaopAhW0PcHsMgYfV5VE=

Standalone single-file fix so it can land fast and clear nix on
every other open PR.
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
…re-design-system

fix: replace all buttons for design system buttons
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
`web/package-lock.json` was updated by the design-system refactor
(merged via NousResearch#17007 + follow-ups: spinner / select / badges / buttons)
without bumping `nix/web.nix::npmDeps.hash`, breaking nix builds on
every PR + main since 2026-04-28T18:46.

Hash sourced from the actual `Check flake` failure output:
  specified: sha256-AahWmJ9gDQ9pMPa1FYwUjYdO2mOi6JM9Mst27E0vp68=
  got:       sha256-+B2+Fe4djPzHHcUXRx+m0cuyaopAhW0PcHsMgYfV5VE=

Standalone single-file fix so it can land fast and clear nix on
every other open PR.
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
…re-design-system

fix: replace all buttons for design system buttons
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
`web/package-lock.json` was updated by the design-system refactor
(merged via NousResearch#17007 + follow-ups: spinner / select / badges / buttons)
without bumping `nix/web.nix::npmDeps.hash`, breaking nix builds on
every PR + main since 2026-04-28T18:46.

Hash sourced from the actual `Check flake` failure output:
  specified: sha256-AahWmJ9gDQ9pMPa1FYwUjYdO2mOi6JM9Mst27E0vp68=
  got:       sha256-+B2+Fe4djPzHHcUXRx+m0cuyaopAhW0PcHsMgYfV5VE=

Standalone single-file fix so it can land fast and clear nix on
every other open PR.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P3 Low — cosmetic, nice to have type/refactor Code restructuring, no behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants