feat(desktop): theme polish, prose chat typography, composer chrome

- DS tokens/midground, Backdrop, scoped scrollbars, typography plugin + prose
- Composer liquid/radius utilities, thread font parity, tool/thinking cues
- File tree label scale, preview flex, thread retry loading + streaming tests
This commit is contained in:
Brooklyn Nicholson
2026-05-11 10:25:23 -04:00
parent 61fb5a48b7
commit bff052d61f
32 changed files with 1180 additions and 676 deletions
+12
View File
@@ -149,6 +149,11 @@ function lightColors(seed: DesktopTheme, skinName: string): DesktopThemeColors {
border,
input: mix('#e2e2e6', accent, 0.18),
ring: accent,
// Brand-accent stroke layer carries the seed's identity color into the
// light palette intact (no mix-with-white softening) so DS components
// and `bg-midground/N` surfaces still read as branded against white.
midground: seed.colors.midground ?? accent,
midgroundForeground: readableOn(seed.colors.midground ?? accent),
destructive: '#b94a3a',
destructiveForeground: '#ffffff',
sidebarBackground: mix('#fafafa', accent, 0.05),
@@ -220,6 +225,11 @@ function applyTheme(theme: DesktopTheme, mode: 'light' | 'dark') {
root.dataset.hermesTheme = skinNameFromTheme(theme, mode)
root.classList.toggle('dark', rendered === 'dark')
// Brand-accent stroke layer. Falls back to ring when the theme doesn't
// declare its own midground, so existing/custom themes keep working.
const midground = c.midground ?? c.ring
const midgroundForeground = c.midgroundForeground ?? readableOn(midground)
const vars: Record<string, string> = {
'--dt-background': c.background,
'--dt-foreground': c.foreground,
@@ -238,6 +248,8 @@ function applyTheme(theme: DesktopTheme, mode: 'light' | 'dark') {
'--dt-border': c.border,
'--dt-input': c.input,
'--dt-ring': c.ring,
'--dt-midground': midground,
'--dt-midground-foreground': midgroundForeground,
'--dt-destructive': c.destructive,
'--dt-destructive-foreground': c.destructiveForeground,
'--dt-sidebar-bg': c.sidebarBackground ?? c.background,
+9
View File
@@ -51,6 +51,7 @@ export const nousLightTheme: DesktopTheme = {
border: '#E3DDCF',
input: '#D8D1C3',
ring: '#A0782A',
midground: '#A0782A',
destructive: '#b94a3a',
destructiveForeground: '#ffffff',
sidebarBackground: '#F5F2EC',
@@ -74,6 +75,7 @@ export const hermesGoldTheme: DesktopTheme = {
accent: '#fbf3d4',
accentForeground: '#5a4310',
ring: '#d4af37',
midground: '#d4af37',
userBubble: '#f6efd5'
}
}
@@ -103,6 +105,7 @@ export const nousTheme: DesktopTheme = {
border: `color-mix(in srgb, ${NOUS_LENS_BLUE} 22%, transparent)`,
input: `color-mix(in srgb, ${NOUS_LENS_BLUE} 30%, transparent)`,
ring: NOUS_LENS_BLUE,
midground: NOUS_LENS_BLUE,
destructive: '#C72E4D',
destructiveForeground: '#FFFFFF',
sidebarBackground: `color-mix(in srgb, ${NOUS_LENS_BLUE} 2.5%, #FFFFFF)`,
@@ -140,6 +143,7 @@ export const defaultTheme: DesktopTheme = {
border: '#1e3232',
input: '#1e3232',
ring: '#6bbfb5',
midground: '#6bbfb5',
destructive: '#c0473a',
destructiveForeground: '#fef2f2',
sidebarBackground: '#0a1616',
@@ -172,6 +176,7 @@ export const midnightTheme: DesktopTheme = {
border: '#1e1e52',
input: '#1e1e52',
ring: '#8b80e8',
midground: '#8b80e8',
destructive: '#b03060',
destructiveForeground: '#fef2f2',
sidebarBackground: '#06061a',
@@ -208,6 +213,7 @@ export const emberTheme: DesktopTheme = {
border: '#3a1c08',
input: '#3a1c08',
ring: '#d97316',
midground: '#d97316',
destructive: '#c43010',
destructiveForeground: '#fef2f2',
sidebarBackground: '#100600',
@@ -244,6 +250,7 @@ export const monoTheme: DesktopTheme = {
border: '#2a2a2a',
input: '#2a2a2a',
ring: '#9a9a9a',
midground: '#9a9a9a',
destructive: '#a84040',
destructiveForeground: '#fef2f2',
sidebarBackground: '#0a0a0a',
@@ -276,6 +283,7 @@ export const cyberpunkTheme: DesktopTheme = {
border: '#003000',
input: '#003000',
ring: '#00ff41',
midground: '#00ff41',
destructive: '#ff003c',
destructiveForeground: '#000a00',
sidebarBackground: '#000600',
@@ -312,6 +320,7 @@ export const slateTheme: DesktopTheme = {
border: '#30363d',
input: '#30363d',
ring: '#58a6ff',
midground: '#58a6ff',
destructive: '#cf4848',
destructiveForeground: '#fef2f2',
sidebarBackground: '#090d13',
+11
View File
@@ -49,6 +49,17 @@ export interface DesktopThemeColors {
input: string
/** Focus ring / primary accent tint. Also `text-ring` in action bars etc. */
ring: string
/**
* Brand-accent stroke layer. Distinct from `primary` (CTA fill) — this is
* the "this thing is alive / live / signal" color used on focus rings,
* streaming cursors, the active session pill, branded scrollbars, and text
* selection. Falls back to `ring` when omitted. Aliased to the DS
* `--midground` token so `@nous-research/ui` components inherit the
* desktop's active theme without further wiring.
*/
midground?: string
/** Text on `midground` fills (badges etc). Auto-derived from luminance when omitted. */
midgroundForeground?: string
/** Destructive action (delete, error). */
destructive: string
/** Text on destructive. */