Skip to main content

Crate bezel_theme

Crate bezel_theme 

Source
Expand description

The app theme — two concrete appearances, one token set.

Colors are precomputed from an oklch-derived neutral scale (perceptually even lightness steps; the same scale the reference Tailwind theme used) into gpui Hsla. Numbers drive layout, colors are paint: layout constants live here as plain numbers and never depend on which color is painted.

§Light is designed, not inverted

Mirroring lightness produces the classic “washed-out inverted” look, for three reasons this module handles explicitly:

  1. Surface order flips meaning. In dark, the main content panel is the darkest plane and raised surfaces get lighter. In light, the content panel is white and the shell/sidebar goes grey — chrome recedes by getting darker, not lighter. Popovers stay white and earn separation from a border and shadow rather than from lightness.
  2. Elevation reverses. On dark, a faint white wash means “raised”. Its literal translation — a faint black wash on white — means “recessed”, so the composer read as a dent instead of a plate. Light lifts with white plus a border and shadow (Theme::input_bg, the elevation ladder). Fill alphas carry over unchanged (INK_FILL_SCALE); only hairlines scale, so a 1px edge survives a bright surround (INK_HAIRLINE_SCALE).
  3. Accents must move down the scale. The dark palette’s 400-level accents (indigo/red/amber) are chosen for contrast against near-black; on white they fall to 2–4:1 and fail WCAG AA. Light mode uses the 600-level siblings at the same hue, which restores the contrast ratio the dark token had.

Text tones are chosen so each light token lands within ~0.5 of its dark counterpart’s contrast ratio against its own background — the pairing is verified in [tests::text_contrast_is_paired_across_appearances], not eyeballed.

Installed as a gpui Global at boot; read with Theme::of.

Modules§

appearance
Light/dark switching: what the user asked for, what the OS reports, and the plumbing that turns a change in either into a repaint.

Structs§

SyntaxPalette
Paint-only syntax colors. The hues follow the Git history graph’s lane palette (indigo, pink, emerald, amber, red, neutral), while light-mode variants are darkened enough to remain readable as text on white.
Theme
The app theme. Two concrete instances — Theme::dark and Theme::light.

Enums§

Appearance
Which appearance the app is painting.

Constants§

INK_FILL_SCALE
Light-mode alpha multiplier for fills (hover/active washes, chip and pill backgrounds).
INK_HAIRLINE_SCALE
Light-mode alpha multiplier for hairlines (borders, dividers, rings). Opposite of fills: a 1px edge has to hold its own against a bright surround, and the dark palette’s white hairlines are deliberately faint. Scaling up keeps separators legible instead of dissolving into the panel.
SCRIM_ALPHA_DARK
Alpha of the standard modal backdrop in dark mode. Call sites that need a heavier or lighter scrim pass their own dark-mode alpha to scrim.

Functions§

band
Recessed band behind a palette/picker header or footer strip.
card_selected_bg
Selected/keyboard-active treatment for rows and chips INSIDE a floating card (menu rows, the picker rail, segmented chips). The card is already the bright plane in light mode, so a white lift can’t read there — selection is the tone-flipped grey wash, at 6% (dark’s 11% read too dark on the bright plane, user report).
card_selected_shadows
Selection outline for rows and chips INSIDE a floating card (menu rows, the picker rail, segmented chips): the inset ring alone, in both appearances. Card rows fill with a translucent wash (card_selected_bg), and a drop shadow — a filled rect painted BEHIND the element — shows straight through a translucent fill as a grey plate (the same lesson glass_selected_shadows records for dark glass). The card already carries the elevation shadow; selection inside it only needs the edge.
contrast_ratio
WCAG 2.1 contrast ratio between two opaque colors (1.0 … 21.0).
current_appearance
The appearance the context-free paint helpers are painting for.
flatten
Composite fg (which may be translucent) over an opaque bg, returning the opaque result — the color the eye actually receives.
glass_selected_bg
Selected-state glass treatment (tabs, session rows, space rows): a TRANSLUCENT wash the vibrancy reads through — heavier flat washes blocked the glass (user request). Dark: the 11% wash. Light: the tone-flipped wash at 6% — 11% black read too dark over the bright frost (user report; light also previously ran a near-opaque white chip, rejected the same way). Same fill as Theme::glass_hover — the ring in glass_selected_shadows is what distinguishes selection. Selection inside floating cards is different — see card_selected_bg.
glass_selected_shadows
The selected chip’s bright outline, as an INSET shadow: gpui paints inset shadows ON TOP of the background, edges only — a border with zero layout cost. Drop shadows are filled rects painted BEHIND the element, and behind a 5% fill they showed straight through as an opaque dark plate with a greyed ring (user report) — nothing may paint behind a glass chip.
grey
An exact achromatic tone from an 8-bit channel value (grey(13)#0d0d0d) — for surfaces matched against reference-screenshot samples.
hairline
Translucent hairline ink for borders, dividers and rings: white on dark, black on light at INK_HAIRLINE_SCALE of the alpha.
ink
Translucent fill ink for interactive states and chip plates: soft-white on dark, soft-black on light at INK_FILL_SCALE of the alpha.
mix
Linear per-component mix of two colors (paint helper for the gradient spinner).
neutral
A neutral (chroma 0) oklch tone as Hsla. Chroma 0 means r == g == b exactly, so this goes straight to an achromatic Hsla (skipping the hue math avoids float-noise saturation).
oklch
Convert an oklch color (CSS notation: L 0..1, C, H in degrees) to gpui Hsla.
relative_luminance
WCAG 2.1 relative luminance of an opaque color.
scrim
Modal backdrop at alpha_dark (quoted, as everywhere, in dark-mode terms).
set_current_appearance
Point the context-free paint helpers at an appearance. Called by Theme::install; exposed for tests that build a theme without an App.
theme_generation
Monotonic id of the current palette — see [THEME_GENERATION].
user_bubble_bg
The user message bubble’s plate: the same translucent wash family as glass_selected_bg, one step softer — at the selection weight the bubble read too strong for settled content (user report), and an opaque plate before that read as a solid slab over glass.
wash
Interactive-state wash: a softened ink that stops short of pure black or white so hover plates read as tinted glass rather than paint.