Skip to content

zidane-ui/appearance/headless

import { … } from 'zidane-ui/appearance/headless'ui/src/appearance/headless/index.ts

Functions#

activeThemeIdFunction#

The theme id to show: the dark slot when the mode (or the OS, under system) asks for dark, else the light slot.

TypeScript
function activeThemeId(state: AppearanceState, prefersDark: boolean): string
Parameters
NameTypeDescription
stateAppearanceState

The preferences.

prefersDarkboolean

Whether the OS prefers dark.

string

ui/src/appearance/headless/prefs.ts:236

availableCuratedFontsFunction#

The curated fonts installed on this computer.

TypeScript
function availableCuratedFonts(): FontOption[]

ui/src/appearance/headless/fonts.ts:171

createStorageAppearancePrefsFunction#

Appearance preferences kept in a Storage under one key, read on first use and validated with parseAppearance. Another window's change (the storage event) is adopted and announced.

TypeScript
function createStorageAppearancePrefs(
  options: StorageAppearancePrefsOptions,
): AppearancePrefs
Parameters
NameTypeDescription
optionsStorageAppearancePrefsOptions

The storage, the key and how to check code theme ids.

ui/src/appearance/headless/storage.ts:47

createStorageBootFunction#

The pre-paint snapshot kept in a Storage as a flat JSON blob ({ appearance, vars }), so the page's inline script needs no logic beyond setProperty.

TypeScript
function createStorageBoot(storage: AppearanceStorage, key?: string): AppearanceBoot
Parameters
NameTypeDefaultDescription
storageAppearanceStorage

Where to keep it, such as localStorage.

key?stringBOOT_SNAPSHOT_KEY

The key. Default: BOOT_SNAPSHOT_KEY.

ui/src/appearance/headless/storage.ts:117

cssFamilyFunction#

Quotes a family name for CSS when it contains spaces or punctuation.

TypeScript
function cssFamily(family: string): string
Parameters
NameTypeDescription
familystring

The family name.

string

ui/src/appearance/headless/fonts.ts:72

fontStackFunction#

A font stack with the chosen family first, so a font that disappears degrades to the default stack.

TypeScript
function fontStack(choice: string | null, kind: 'ui' | 'mono'): string
Parameters
NameTypeDescription
choicestring | null

The chosen family, or null for the default stack.

kind'ui' | 'mono'

Which default stack follows it.

string

ui/src/appearance/headless/fonts.ts:82

fontsToCssVarsFunction#

The font CSS variables for the picked families and sizes.

TypeScript
function fontsToCssVars(fonts: FontChoices, sizes: FontSizes): FontCssVars
Parameters
NameTypeDescription
fontsFontChoices

The families per role.

sizesFontSizes

The sizes per role.

ui/src/appearance/headless/fonts.ts:105

guessKindFunction#

Guesses a family's kind from its name (the Local Font Access API doesn't classify).

TypeScript
function guessKind(family: string): 'mono' | 'sans' | 'serif'
Parameters
NameTypeDescription
familystring

The family name.

'mono' | 'sans' | 'serif'

ui/src/appearance/headless/fonts.ts:216

isFontAvailableFunction#

True when family renders differently from both generic fallbacks, i.e. the OS resolved it to an actual installed face. Cheap (three measureText calls), synchronous, no permission needed.

TypeScript
function isFontAvailable(family: string): boolean
Parameters
NameTypeDescription
familystring

The family name.

boolean

ui/src/appearance/headless/fonts.ts:146

parseAppearanceFunction#

Validates a stored blob field by field; anything unrecognised falls back to its default.

TypeScript
function parseAppearance(
  raw: string,
  options?: ParseAppearanceOptions,
): AppearanceState | undefined
Parameters
NameTypeDefaultDescription
rawstring

The stored JSON.

options?ParseAppearanceOptions{}

How to check code theme ids.

AppearanceState | undefined

The preferences, or undefined when raw is not a known blob.

ui/src/appearance/headless/prefs.ts:158

queryInstalledFontsFunction#

Installed families via the Local Font Access API. Resolves to [] when unsupported or denied. Families are de-duplicated and sorted; kind is guessed from the name because the API doesn't classify.

TypeScript
function queryInstalledFonts(): Promise<FontOption[]>
Promise<FontOption[]>

ui/src/appearance/headless/fonts.ts:185

resolveMotionFunction#

The motion level a preference resolves to: system follows the OS, an explicit choice wins.

TypeScript
function resolveMotion(
  pref: MotionPreference,
  osReducedMotion: boolean,
): 'off' | 'reduced' | 'full'
Parameters
NameTypeDescription
prefMotionPreference

The stored preference.

osReducedMotionboolean

Whether the OS asks for reduced motion.

'off' | 'reduced' | 'full'

ui/src/appearance/headless/prefs.ts:247

stepInterfaceScaleFunction#

The preferences with the interface scale one step up or down, or back to 1, clamped to LIMITS.

TypeScript
function stepInterfaceScale(
  prev: AppearanceState,
  direction: -1 | 0 | 1,
): AppearanceState
Parameters
NameTypeDescription
prevAppearanceState

The current preferences.

direction-1 | 0 | 1

1 one step up, -1 one step down, 0 back to 100%.

ui/src/appearance/headless/prefs.ts:222

zoomKeyCommandsFunction#

The zoom key commands over a host's preferences.

TypeScript
function zoomKeyCommands(prefs: Pick<AppearancePrefs, 'set'>): KeyCommands
Parameters
NameTypeDescription
prefsPick<AppearancePrefs, 'set'>

The appearance host's preferences.

ui/src/appearance/headless/zoom-commands.ts:15

Constants#

APPEARANCE_STORAGE_KEYConstant#

The key the preferences live under.

TypeScript
const APPEARANCE_STORAGE_KEY = 'zg:appearance:v1'

ui/src/appearance/headless/storage.ts:11

BOOT_SNAPSHOT_KEYConstant#

The key the pre-paint snapshot lives under. A page's inline script replays it before any bundle loads.

TypeScript
const BOOT_SNAPSHOT_KEY = 'zg:appearance:boot:v1'

ui/src/appearance/headless/storage.ts:14

CURATED_FONTSConstant#

Curated candidates. Order = display order within each kind. Availability is checked at runtime; missing ones are hidden from the picker.

TypeScript
const CURATED_FONTS: readonly FontOption[]

ui/src/appearance/headless/fonts.ts:35

DEFAULT_APPEARANCEConstant#

The preferences before the user changes anything.

TypeScript
const DEFAULT_APPEARANCE: AppearanceState

ui/src/appearance/headless/prefs.ts:99

FONT_STACKSConstant#

The default font stacks: the platform UI stack and ui-monospace.

TypeScript
const FONT_STACKS: { readonly mono: 'ui-monospace, \'SF Mono\', SFMono-Regular, Menlo, Monaco, Consolas, \'Liberation Mono\', monospace'; readonly ui: '-apple-system, BlinkMacSystemFont, \'Segoe UI\', system-ui, Roboto, sans-serif' }

ui/src/appearance/headless/fonts.ts:16

LIMITSConstant#

The bounds (and slider steps) of the numeric preferences.

TypeScript
const LIMITS: { readonly contrast: { readonly max: 200; readonly min: 50; readonly step: 5 }; readonly fontSize: { readonly max: 22; readonly min: 10; readonly step: 1 }; readonly interfaceScale: { readonly max: 1.5; readonly min: 0.8; readonly step: 0.05 }; readonly panelMs: { readonly max: 400; readonly min: 0; readonly step: 20 }; readonly panelWidth: { readonly max: 900; readonly min: 300 }; readonly sidebarWidth: { readonly max: 480; readonly min: 220 } }

ui/src/appearance/headless/prefs.ts:119

Interfaces#

AppearanceBootInterface#

Where the pre-paint snapshot goes.

TypeScript
interface AppearanceBoot
AppearanceBoot properties
NameTypeDescription
write(snapshot: BootSnapshot) => void

Stores the snapshot (after every apply that changed something).

ui/src/appearance/headless/host.ts:40

AppearanceHostInterface#

The appearance host. Only prefs is required.

TypeScript
interface AppearanceHost
AppearanceHost properties
NameTypeDescription
boot?AppearanceBoot

Where the pre-paint snapshot goes. Absent: none is written.

prefsAppearancePrefs

The stored preferences.

window?AppearanceWindow

Native window effects. Absent: the window is left alone.

themes?(folder: string) => Promise<readonly Theme[]>

Themes beyond the built-in ones for a folder (its extensions'). Absent: built-in themes only.

ui/src/appearance/headless/host.ts:56

AppearancePrefsInterface#

The stored preferences: read with get, follow with subscribe, change with set.

TypeScript
interface AppearancePrefs extends Readable<AppearanceState>
AppearancePrefs properties
NameTypeDescription
getfrom Readable() => AppearanceState

Returns the current value.

isFirstRun() => boolean

True until preferences were stored: the app's first run on this computer.

reset() => void

Back to DEFAULT_APPEARANCE.

set(update: Partial<AppearanceState> | ((prev: AppearanceState) => AppearanceState)) => void

Merges update into the preferences (or replaces them with what the function returns), stores them and tells subscribers. Equal preferences change nothing.

subscribefrom Readable(onChange: () => void) => () => void

Registers a listener called after the value changes. Returns a function that removes the listener.

ui/src/appearance/headless/host.ts:19

AppearanceStateInterface#

Every appearance preference, as stored.

TypeScript
interface AppearanceState
AppearanceState properties
NameTypeDescription
accentOverridestring | null

#rrggbb replacing the theme's accent, or null to use the theme's own.

codeThemeCodeThemeChoice

The code theme per appearance.

contrastnumber

50..200, 100 = as designed.

darkThemestring

The theme id shown while dark (registry or extension).

filesTreeSideFilesTreeSide

Which side of the Files tab the tree column sits on.

fontsFontChoices

Font families per role.

fontSizesFontSizes

Font sizes per role.

interfaceScalenumber

The interface zoom factor, 0.8..1.5.

lightThemestring

The theme id shown while light (registry or extension).

modeAppearanceMode

System, light or dark.

motionMotionPreference

The motion preference.

panelMsnumber

Panel open/close duration in ms (sidebar, side panels), 0..400.

panelWidthnumber

The side panel's drag-resized width in CSS px; persisted on drag end only.

sidebarWidthnumber

The sidebar's drag-resized width in CSS px; persisted on drag end only.

springsboolean

Spring animations: motion settles with physics (a hint of overshoot) instead of fixed ease-out curves. Only meaningful at the Full level.

version2

The blob's version.

ui/src/appearance/headless/prefs.ts:60

AppearanceWindowInterface#

What the window does natively when the appearance changes. Each member is optional.

TypeScript
interface AppearanceWindow
AppearanceWindow properties
NameTypeDescription
setBackground?(color: string) => Promise<void>

Paints the window background shown during resize, before the page does. #rrggbb.

setNativeTheme?(mode: AppearanceMode) => Promise<void>

Mirrors the mode into the native chrome (title bar, menus).

setZoom?(factor: number) => Promise<void>

Applies the interface scale (a zoom factor, 0.8..1.5).

ui/src/appearance/headless/host.ts:46

BootSnapshotInterface#

The pre-paint snapshot: the last applied CSS variables, replayed before any script loads.

TypeScript
interface BootSnapshot
BootSnapshot properties
NameTypeDescription
appearance'dark' | 'light'

The appearance class (.light / .dark).

varsRecord<string, string>

--zg-* name → value.

ui/src/appearance/headless/host.ts:32

CodeThemeChoiceInterface#

Syntax colours per appearance. Only the tokens come from the code theme; the code background is always the app's, so each slot holds a theme of its type.

TypeScript
interface CodeThemeChoice
CodeThemeChoice properties
NameTypeDescription
darkCodeThemePick

The pick while the app is dark.

lightCodeThemePick

The pick while the app is light.

ui/src/appearance/headless/prefs.ts:49

FontChoicesInterface#

The font families picked per role, as the OS names them. null: the stylesheet default.

TypeScript
interface FontChoices
FontChoices properties
NameTypeDescription
chatstring | null

The transcript font (default: the interface font).

monostring | null

The code font.

promptstring | null

The prompt font (default: the transcript font).

uistring | null

The interface font.

ui/src/appearance/headless/prefs.ts:18

FontOptionInterface#

A font the picker offers.

TypeScript
interface FontOption
FontOption properties
NameTypeDescription
familystring

Family name as passed to CSS.

kind'mono' | 'sans' | 'serif'

Its kind, for grouping.

labelstring

Name shown in the picker.

ui/src/appearance/headless/fonts.ts:22

FontSizesInterface#

Font sizes in CSS px.

TypeScript
interface FontSizes
FontSizes properties
NameTypeDescription
chatnumber

The transcript.

codenumber

Code blocks and the editor.

promptnumber

The prompt.

ui/src/appearance/headless/prefs.ts:30

ParseAppearanceOptionsInterface#

Options of parseAppearance.

TypeScript
interface ParseAppearanceOptions
ParseAppearanceOptions properties
NameTypeDescription
codeThemeType?(id: string) => 'dark' | 'light' | undefined

The appearance a code theme id is made for, undefined when unknown (codeThemeTypeOf from zidane-ui/appearance). A stored pick of the wrong type, or unknown, reads as 'auto'. Absent: any non-empty id is kept.

ui/src/appearance/headless/prefs.ts:129

StorageAppearancePrefsOptionsInterface#

Options of createStorageAppearancePrefs.

TypeScript
interface StorageAppearancePrefsOptions extends ParseAppearanceOptions
StorageAppearancePrefsOptions properties
NameTypeDescription
codeThemeType?from ParseAppearanceOptions(id: string) => 'dark' | 'light' | undefined

The appearance a code theme id is made for, undefined when unknown (codeThemeTypeOf from zidane-ui/appearance). A stored pick of the wrong type, or unknown, reads as 'auto'. Absent: any non-empty id is kept.

key?string

The key. Default: APPEARANCE_STORAGE_KEY.

storageAppearanceStorage

Where the preferences live.

watch?(key: string, onChange: () => void) => () => void

Calls onChange when another window changed the stored preferences; returns the unsubscribe. Default: the storage event of window, when there is one.

ui/src/appearance/headless/storage.ts:20

Types#

AppearanceModeType#

Which appearance the app shows: the OS's, or always light or dark.

TypeScript
type AppearanceMode = 'system' | 'light' | 'dark'

ui/src/appearance/headless/prefs.ts:12

AppearanceStorageType#

The Storage calls the appearance stores make (localStorage or a double).

TypeScript
type AppearanceStorage = Pick<Storage, 'getItem' | 'setItem'>

ui/src/appearance/headless/storage.ts:17

CodeThemePickType#

A bundled code theme id, or 'auto': the app theme's own mapping.

TypeScript
type CodeThemePick = 'auto' | (string & {})

ui/src/appearance/headless/prefs.ts:43

FilesTreeSideType#

Which side of the Files tab the tree column sits on.

TypeScript
type FilesTreeSide = 'left' | 'right'

ui/src/appearance/headless/prefs.ts:40

FontCssVarsType#

The font CSS variables fontsToCssVars writes.

TypeScript
type FontCssVars = Record<'--zg-font-ui' | '--zg-font-chat' | '--zg-font-prompt' | '--zg-font-mono' | '--zg-font-size-chat' | '--zg-font-size-prompt' | '--zg-font-size-code', string>

ui/src/appearance/headless/fonts.ts:88

MotionPreferenceType#

How much the UI animates. system follows the OS reduced-motion preference.

TypeScript
type MotionPreference = 'system' | 'off' | 'reduced' | 'full'

ui/src/appearance/headless/prefs.ts:15

Re-exports#

These names are documented on the entry point that owns them.