From 75e29f97ee3919e6269542a5b6d0b3306816b10e Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Wed, 3 Jun 2026 22:17:26 -0500 Subject: [PATCH] style(desktop): add Switch xs size; move appearance controls inline-right Add an xs size variant to the Switch primitive and use it for the provider edit submenu toggles. In appearance settings, drop the redundant selection Pills (the UI already shows the active choice), move the Color Mode and Tool Call Display segmented controls into the section header's right side (responsive: stacks under the heading on narrow widths), and shrink the segmented control. --- .../src/app/settings/appearance-settings.tsx | 76 +++++++++---------- .../src/app/shell/model-edit-submenu.tsx | 3 +- apps/desktop/src/components/ui/switch.tsx | 53 +++++++++---- 3 files changed, 76 insertions(+), 56 deletions(-) diff --git a/apps/desktop/src/app/settings/appearance-settings.tsx b/apps/desktop/src/app/settings/appearance-settings.tsx index d60b119457..b249f0dff7 100644 --- a/apps/desktop/src/app/settings/appearance-settings.tsx +++ b/apps/desktop/src/app/settings/appearance-settings.tsx @@ -9,8 +9,7 @@ import { useTheme } from '@/themes/context' import { BUILTIN_THEMES } from '@/themes/presets' import { MODE_OPTIONS } from './constants' -import { prettyName } from './helpers' -import { Pill, SettingsContent } from './primitives' +import { SettingsContent } from './primitives' function ThemePreview({ name }: { name: string }) { const t = BUILTIN_THEMES[name] @@ -52,16 +51,16 @@ function ThemePreview({ name }: { name: string }) { ) } -function SectionHead({ title, description, pill }: { title: string; description: string; pill?: ReactNode }) { +function SectionHead({ title, description, control }: { title: string; description: string; control?: ReactNode }) { return ( -
-
+
+
{title}
{description}
- {pill} + {control &&
{control}
}
) } @@ -76,7 +75,7 @@ function SegmentedControl({ onChange: (id: T) => void }) { return ( -
+
{options.map(({ id, label, icon: Icon }) => { const active = value === id @@ -84,7 +83,7 @@ function SegmentedControl({ ) @@ -105,7 +104,6 @@ function SegmentedControl({ export function AppearanceSettings() { const { themeName, mode, availableThemes, setTheme, setMode } = useTheme() const toolViewMode = useStore($toolViewMode) - const activeTheme = availableThemes.find(t => t.name === themeName) return ( @@ -115,49 +113,47 @@ export function AppearanceSettings() { chat surface styling.

-
+
{ + triggerHaptic('crisp') + setMode(id) + }} + options={MODE_OPTIONS} + value={mode} + /> + } description="Pick a fixed mode or let Hermes follow your system setting." - pill={{prettyName(mode)}} title="Color Mode" /> - { - triggerHaptic('crisp') - setMode(id) - }} - options={MODE_OPTIONS} - value={mode} - />
-
+
{ + triggerHaptic('selection') + setToolViewMode(id) + }} + options={ + [ + { id: 'product', label: 'Product' }, + { id: 'technical', label: 'Technical' } + ] as const + } + value={toolViewMode} + /> + } description="Product hides raw tool payloads; Technical shows full input/output." - pill={{toolViewMode === 'technical' ? 'Technical' : 'Product'}} title="Tool Call Display" /> - { - triggerHaptic('selection') - setToolViewMode(id) - }} - options={ - [ - { id: 'product', label: 'Product' }, - { id: 'technical', label: 'Technical' } - ] as const - } - value={toolViewMode} - />
- {activeTheme.label} : undefined} - title="Theme" - /> +
{availableThemes.map(theme => { const active = themeName === theme.name diff --git a/apps/desktop/src/app/shell/model-edit-submenu.tsx b/apps/desktop/src/app/shell/model-edit-submenu.tsx index d2fb9279fe..1ccaa20396 100644 --- a/apps/desktop/src/app/shell/model-edit-submenu.tsx +++ b/apps/desktop/src/app/shell/model-edit-submenu.tsx @@ -191,6 +191,7 @@ export function ModelEditSubmenu({ checked={thinkingOn} className="ml-auto" onCheckedChange={checked => void patchReasoning(checked ? effort || 'medium' : 'none', currentReasoningEffort)} + size="xs" /> ) : null} @@ -200,7 +201,7 @@ export function ModelEditSubmenu({ onSelect={event => event.preventDefault()} > Fast - + ) : null} {reasoning ? ( diff --git a/apps/desktop/src/components/ui/switch.tsx b/apps/desktop/src/components/ui/switch.tsx index 237f696b9a..96bbe345d8 100644 --- a/apps/desktop/src/components/ui/switch.tsx +++ b/apps/desktop/src/components/ui/switch.tsx @@ -1,24 +1,47 @@ +import { cva, type VariantProps } from 'class-variance-authority' import { Switch as SwitchPrimitive } from 'radix-ui' import * as React from 'react' import { cn } from '@/lib/utils' -function Switch({ className, ...props }: React.ComponentProps) { +const switchVariants = cva( + 'peer inline-flex shrink-0 items-center rounded-full border border-[color-mix(in_srgb,var(--dt-foreground)_18%,transparent)] bg-[color-mix(in_srgb,var(--dt-background)_58%,var(--dt-input))] shadow-[inset_0_0_0_0.0625rem_color-mix(in_srgb,var(--dt-foreground)_8%,transparent)] transition-colors outline-none focus-visible:border-ring focus-visible:ring-[0.1875rem] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:border-transparent data-[state=checked]:bg-primary', + { + variants: { + size: { + default: 'h-5 w-9', + xs: 'h-4 w-7' + } + }, + defaultVariants: { + size: 'default' + } + } +) + +const switchThumbVariants = cva( + 'pointer-events-none block rounded-full bg-foreground shadow-[0_0.0625rem_0.1875rem_color-mix(in_srgb,var(--dt-background)_50%,transparent)] ring-0 transition-transform data-[state=unchecked]:translate-x-0 data-[state=checked]:bg-background', + { + variants: { + size: { + default: 'size-4 data-[state=checked]:translate-x-4', + xs: 'size-3 data-[state=checked]:translate-x-3.5' + } + }, + defaultVariants: { + size: 'default' + } + } +) + +function Switch({ + className, + size, + ...props +}: React.ComponentProps & VariantProps) { return ( - - + + ) }