feat: glass ui pass
This commit is contained in:
@@ -58,16 +58,16 @@ export function AppearanceSettings() {
|
||||
|
||||
return (
|
||||
<SettingsContent>
|
||||
<div className="space-y-7">
|
||||
<div className="space-y-5">
|
||||
<div>
|
||||
<SectionHeading icon={Palette} title="Appearance" />
|
||||
<p className="max-w-2xl text-sm leading-6 text-muted-foreground">
|
||||
<p className="max-w-2xl text-[length:var(--conversation-caption-font-size)] leading-(--conversation-caption-line-height) text-(--ui-text-tertiary)">
|
||||
These are desktop-only display preferences. Mode controls brightness; theme controls the accent palette and
|
||||
chat surface styling.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<section className="rounded-2xl border border-border/50 bg-card/55 p-4 shadow-sm">
|
||||
<section className="rounded-xl border border-(--ui-stroke-tertiary) bg-(--glass-chat-bubble-background) p-3 shadow-sm">
|
||||
<div className="mb-3 flex items-center justify-between gap-3">
|
||||
<div>
|
||||
<div className="text-sm font-medium">Color Mode</div>
|
||||
@@ -84,8 +84,8 @@ export function AppearanceSettings() {
|
||||
return (
|
||||
<button
|
||||
className={cn(
|
||||
'group rounded-xl border border-border/45 bg-background/55 p-3 text-left transition hover:border-primary/35 hover:bg-accent/45',
|
||||
active && 'border-primary/65 bg-primary/8 ring-2 ring-primary/25'
|
||||
'group rounded-lg border border-(--ui-stroke-tertiary) bg-(--ui-bg-quinary) p-2.5 text-left transition hover:bg-(--chrome-action-hover)',
|
||||
active && 'border-(--ui-stroke-secondary) bg-(--ui-bg-tertiary)'
|
||||
)}
|
||||
key={id}
|
||||
onClick={() => {
|
||||
@@ -104,15 +104,15 @@ export function AppearanceSettings() {
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="mt-3 text-sm font-medium">{label}</div>
|
||||
<div className="mt-1 text-xs leading-5 text-muted-foreground">{description}</div>
|
||||
<div className="mt-2 text-[length:var(--conversation-text-font-size)] font-medium">{label}</div>
|
||||
<div className="mt-1 text-[length:var(--conversation-caption-font-size)] leading-(--conversation-caption-line-height) text-(--ui-text-tertiary)">{description}</div>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="rounded-2xl border border-border/50 bg-card/55 p-4 shadow-sm">
|
||||
<section className="rounded-xl border border-(--ui-stroke-tertiary) bg-(--glass-chat-bubble-background) p-3 shadow-sm">
|
||||
<div className="mb-3 flex items-center justify-between gap-3">
|
||||
<div>
|
||||
<div className="text-sm font-medium">Tool Call Display</div>
|
||||
@@ -142,8 +142,8 @@ export function AppearanceSettings() {
|
||||
return (
|
||||
<button
|
||||
className={cn(
|
||||
'group rounded-xl border border-border/45 bg-background/55 p-3 text-left transition hover:border-primary/35 hover:bg-accent/45',
|
||||
active && 'border-primary/65 bg-primary/8 ring-2 ring-primary/25'
|
||||
'group rounded-lg border border-(--ui-stroke-tertiary) bg-(--ui-bg-quinary) p-2.5 text-left transition hover:bg-(--chrome-action-hover)',
|
||||
active && 'border-(--ui-stroke-secondary) bg-(--ui-bg-tertiary)'
|
||||
)}
|
||||
key={option.id}
|
||||
onClick={() => {
|
||||
@@ -153,21 +153,21 @@ export function AppearanceSettings() {
|
||||
type="button"
|
||||
>
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div className="text-sm font-medium">{option.label}</div>
|
||||
<div className="text-[length:var(--conversation-text-font-size)] font-medium">{option.label}</div>
|
||||
{active && (
|
||||
<span className="grid size-5 place-items-center rounded-full bg-primary text-primary-foreground">
|
||||
<Check className="size-3.5" />
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="mt-1 text-xs leading-5 text-muted-foreground">{option.description}</div>
|
||||
<div className="mt-1 text-[length:var(--conversation-caption-font-size)] leading-(--conversation-caption-line-height) text-(--ui-text-tertiary)">{option.description}</div>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="rounded-2xl border border-border/50 bg-card/55 p-4 shadow-sm">
|
||||
<section className="rounded-xl border border-(--ui-stroke-tertiary) bg-(--glass-chat-bubble-background) p-3 shadow-sm">
|
||||
<div className="mb-3 flex items-center justify-between gap-3">
|
||||
<div>
|
||||
<div className="text-sm font-medium">Theme</div>
|
||||
@@ -184,8 +184,8 @@ export function AppearanceSettings() {
|
||||
return (
|
||||
<button
|
||||
className={cn(
|
||||
'rounded-2xl border border-border/45 bg-background/50 p-2.5 text-left transition hover:border-primary/35 hover:bg-accent/35',
|
||||
active && 'border-primary/65 bg-primary/8 ring-2 ring-primary/25'
|
||||
'rounded-lg border border-(--ui-stroke-tertiary) bg-(--ui-bg-quinary) p-2 text-left transition hover:bg-(--chrome-action-hover)',
|
||||
active && 'border-(--ui-stroke-secondary) bg-(--ui-bg-tertiary)'
|
||||
)}
|
||||
key={theme.name}
|
||||
onClick={() => {
|
||||
@@ -197,8 +197,8 @@ export function AppearanceSettings() {
|
||||
<ThemePreview name={theme.name} />
|
||||
<div className="mt-3 flex items-start justify-between gap-3 px-1">
|
||||
<div className="min-w-0">
|
||||
<div className="truncate text-sm font-medium">{theme.label}</div>
|
||||
<div className="mt-0.5 line-clamp-2 text-xs leading-5 text-muted-foreground">
|
||||
<div className="truncate text-[length:var(--conversation-text-font-size)] font-medium">{theme.label}</div>
|
||||
<div className="mt-0.5 line-clamp-2 text-[length:var(--conversation-caption-font-size)] leading-(--conversation-caption-line-height) text-(--ui-text-tertiary)">
|
||||
{theme.description}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
Brain,
|
||||
Lock,
|
||||
type LucideIcon,
|
||||
type IconComponent,
|
||||
MessageCircle,
|
||||
Mic,
|
||||
Monitor,
|
||||
@@ -302,7 +302,7 @@ export interface ModeOption {
|
||||
id: ThemeMode
|
||||
label: string
|
||||
description: string
|
||||
icon: LucideIcon
|
||||
icon: IconComponent
|
||||
}
|
||||
|
||||
export const MODE_OPTIONS: ModeOption[] = [
|
||||
|
||||
@@ -45,22 +45,22 @@ function ModeCard({
|
||||
return (
|
||||
<button
|
||||
className={cn(
|
||||
'rounded-2xl border p-4 text-left transition',
|
||||
'rounded-xl border p-3 text-left transition',
|
||||
active
|
||||
? 'border-primary bg-primary/10 ring-2 ring-primary/15'
|
||||
: 'border-border bg-background/60 hover:bg-muted/40',
|
||||
? 'border-(--ui-stroke-secondary) bg-(--ui-bg-tertiary)'
|
||||
: 'border-(--ui-stroke-tertiary) bg-(--ui-bg-quinary) hover:bg-(--chrome-action-hover)',
|
||||
disabled && 'cursor-not-allowed opacity-50'
|
||||
)}
|
||||
disabled={disabled}
|
||||
onClick={onSelect}
|
||||
type="button"
|
||||
>
|
||||
<div className="flex items-center gap-2 text-sm font-medium">
|
||||
<div className="flex items-center gap-2 text-[length:var(--conversation-text-font-size)] font-medium">
|
||||
<Icon className="size-4 text-muted-foreground" />
|
||||
<span>{title}</span>
|
||||
{active ? <Check className="ml-auto size-4 text-primary" /> : null}
|
||||
</div>
|
||||
<p className="mt-2 text-xs leading-5 text-muted-foreground">{description}</p>
|
||||
<p className="mt-1.5 text-[length:var(--conversation-caption-font-size)] leading-(--conversation-caption-line-height) text-(--ui-text-tertiary)">{description}</p>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
@@ -191,20 +191,20 @@ export function GatewaySettings() {
|
||||
|
||||
return (
|
||||
<SettingsContent>
|
||||
<div className="mb-6">
|
||||
<div className="flex items-center gap-2 text-sm font-medium">
|
||||
<div className="mb-5">
|
||||
<div className="flex items-center gap-2 text-[length:var(--conversation-text-font-size)] font-medium">
|
||||
<Globe className="size-4 text-muted-foreground" />
|
||||
Gateway Connection
|
||||
{state.envOverride ? <Pill tone="primary">env override</Pill> : null}
|
||||
</div>
|
||||
<p className="mt-2 max-w-2xl text-xs leading-5 text-muted-foreground">
|
||||
<p className="mt-2 max-w-2xl text-[length:var(--conversation-caption-font-size)] leading-(--conversation-caption-line-height) text-(--ui-text-tertiary)">
|
||||
Hermes Desktop starts its own local gateway by default. Use a remote gateway when you want this app to control
|
||||
an already-running Hermes backend on another machine or behind a trusted proxy.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{state.envOverride ? (
|
||||
<div className="mb-5 flex items-start gap-2 rounded-2xl border border-destructive/30 bg-destructive/10 px-4 py-3 text-xs text-destructive">
|
||||
<div className="mb-5 flex items-start gap-2 rounded-xl border border-destructive/30 bg-destructive/10 px-3 py-2.5 text-[length:var(--conversation-caption-font-size)] text-destructive">
|
||||
<AlertCircle className="mt-0.5 size-4 shrink-0" />
|
||||
<div>
|
||||
<div className="font-medium">Environment variables are controlling this desktop session.</div>
|
||||
|
||||
@@ -3,7 +3,8 @@ import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { deleteEnvVar, getEnvVars, revealEnvVar, setEnvVar } from '@/hermes'
|
||||
import { Check, Eye, EyeOff, Save, Settings2, Trash2, X, Zap } from '@/lib/icons'
|
||||
import { Codicon } from '@/components/ui/codicon'
|
||||
import { Check, Eye, EyeOff, Save, Settings2, Trash2, Zap } from '@/lib/icons'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { notify, notifyError } from '@/store/notifications'
|
||||
import type { EnvVarInfo } from '@/types/hermes'
|
||||
@@ -169,7 +170,7 @@ function EnvVarRow({
|
||||
{saving === varKey ? 'Saving' : 'Save'}
|
||||
</Button>
|
||||
<Button onClick={() => setEdits(c => withoutKey(c, varKey))} size="sm" variant="outline">
|
||||
<X />
|
||||
<Codicon name="close" />
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -2,14 +2,14 @@ import type { ReactNode } from 'react'
|
||||
|
||||
import { PageLoader } from '@/components/page-loader'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import type { LucideIcon } from '@/lib/icons'
|
||||
import type { IconComponent } from '@/lib/icons'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
export function SettingsContent({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<section className="min-h-0 overflow-hidden">
|
||||
<div className="h-full min-h-0 overflow-y-auto px-8 py-6 pb-24">
|
||||
<div className="mx-auto w-full max-w-5xl">{children}</div>
|
||||
<div className="h-full min-h-0 overflow-y-auto px-5 py-4 pb-20">
|
||||
<div className="mx-auto w-full max-w-4xl">{children}</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
@@ -19,7 +19,7 @@ export function Pill({ tone = 'muted', children }: { tone?: 'muted' | 'primary';
|
||||
return (
|
||||
<span
|
||||
className={cn(
|
||||
'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[0.66rem]',
|
||||
'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[0.6875rem]',
|
||||
tone === 'primary' ? 'bg-primary/10 text-primary' : 'bg-muted text-muted-foreground'
|
||||
)}
|
||||
>
|
||||
@@ -28,9 +28,9 @@ export function Pill({ tone = 'muted', children }: { tone?: 'muted' | 'primary';
|
||||
)
|
||||
}
|
||||
|
||||
export function SectionHeading({ icon: Icon, title, meta }: { icon: LucideIcon; title: string; meta?: string }) {
|
||||
export function SectionHeading({ icon: Icon, title, meta }: { icon: IconComponent; title: string; meta?: string }) {
|
||||
return (
|
||||
<div className="mb-3 flex items-center gap-2 pt-3.5 text-sm font-medium">
|
||||
<div className="mb-2.5 flex items-center gap-2 pt-2 text-[length:var(--conversation-text-font-size)] font-medium">
|
||||
<Icon className="size-4 text-muted-foreground" />
|
||||
<span>{title}</span>
|
||||
{meta && <Pill>{meta}</Pill>}
|
||||
@@ -44,7 +44,7 @@ export function NavLink({
|
||||
active,
|
||||
onClick
|
||||
}: {
|
||||
icon: LucideIcon
|
||||
icon: IconComponent
|
||||
label: string
|
||||
active: boolean
|
||||
onClick: () => void
|
||||
@@ -52,8 +52,8 @@ export function NavLink({
|
||||
return (
|
||||
<Button
|
||||
className={cn(
|
||||
'flex min-h-8 w-full justify-start gap-2 rounded-lg px-2.5 text-left text-sm transition',
|
||||
active ? 'bg-muted text-foreground' : 'text-foreground/80 hover:bg-muted/70'
|
||||
'flex min-h-7 w-full justify-start gap-2 rounded-md px-2 text-left text-[length:var(--conversation-text-font-size)] transition',
|
||||
active ? 'bg-(--ui-bg-tertiary) text-foreground' : 'text-(--ui-text-secondary) hover:bg-(--chrome-action-hover) hover:text-foreground'
|
||||
)}
|
||||
onClick={onClick}
|
||||
size="sm"
|
||||
@@ -84,13 +84,13 @@ export function ListRow({
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'grid gap-4 py-3.5 sm:grid-cols-[minmax(0,1fr)_minmax(15rem,22rem)] sm:items-center',
|
||||
'grid gap-3 py-3 sm:grid-cols-[minmax(0,1fr)_minmax(15rem,22rem)] sm:items-center',
|
||||
wide && 'sm:grid-cols-1 sm:items-start'
|
||||
)}
|
||||
>
|
||||
<div className="min-w-0">
|
||||
<div className="text-sm font-medium text-foreground">{title}</div>
|
||||
{description && <div className="mt-1 text-xs leading-5 text-muted-foreground">{description}</div>}
|
||||
<div className="text-[length:var(--conversation-text-font-size)] font-medium text-foreground">{title}</div>
|
||||
{description && <div className="mt-1 text-[length:var(--conversation-caption-font-size)] leading-(--conversation-caption-line-height) text-(--ui-text-tertiary)">{description}</div>}
|
||||
{hint && <div className="mt-1 block font-mono text-[0.68rem] text-muted-foreground/45">{hint}</div>}
|
||||
{below}
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Dispatch, SetStateAction } from 'react'
|
||||
|
||||
import type { HermesGateway } from '@/hermes'
|
||||
import type { LucideIcon } from '@/lib/icons'
|
||||
import type { IconComponent } from '@/lib/icons'
|
||||
import type { EnvVarInfo } from '@/types/hermes'
|
||||
|
||||
export type SettingsView = 'about' | 'gateway' | 'keys' | 'mcp' | 'tools' | `config:${string}`
|
||||
@@ -28,7 +28,7 @@ export interface ProviderGroup {
|
||||
export interface DesktopConfigSection {
|
||||
id: string
|
||||
label: string
|
||||
icon: LucideIcon
|
||||
icon: IconComponent
|
||||
keys: string[]
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user