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 in
theme/layout.rs 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:
- 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.
- 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). - Accents must move down the scale. The dark palette’s 400-level accents
(red/amber, and whatever hue an app sets
Theme::accentto) 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/theme.rs, not eyeballed.
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§
- Brand
- What an app changes about the shipped palette without redesigning it.
- Syntax
Palette - 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::darkandTheme::light. - Tint
- A hue and how much of it, in oklch terms.
chroma: 0.0is the shipped neutral, soBrand::defaultreproduces the built-in palette exactly.
Enums§
- Appearance
- Which appearance the app is painting.
- Highlight
Kind - The token category a highlighter paints with, mirroring
SyntaxPalettefield-for-field so classification can name a kind without knowing its color.
Constants§
- BASE_
COLORS - The greys a UI is built on, as oklch hue and chroma.
- 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.
Traits§
- Theme
Ext - The carrier seam for catalog traits: any type holding a
Themeexposes it through this one method, and every component group (ui::widgets::Scaffolding, …) extends it, so group methods read the environment throughself.theme().
Functions§
- band
- Recessed band behind a palette/picker header or footer strip.
- brand
- Read the installed brand (the default before one is set).
- 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 lessonglass_selected_shadowsrecords 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 opaquebg, 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 asTheme::glass_hover— the ring inglass_selected_shadowsis what distinguishes selection. Selection inside floating cards is different — seecard_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_SCALEof the alpha. - hsl_
to_ rgb - HSL (gpui convention, all 0..1) → sRGB components 0..1.
- ink
- Translucent fill ink for interactive states and chip plates: soft-white on
dark, soft-black on light at
INK_FILL_SCALEof the alpha. - lightness
- The oklch lightness of an achromatic tone:
neutralinverted. - 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.
- oklch_
to_ srgb - oklch → sRGB (each 0..1, clamped/gamut-clipped per channel). Reference: Björn Ottosson’s OKLab definition (the same matrices CSS Color 4 uses).
- relative_
luminance - WCAG 2.1 relative luminance of an opaque color.
- rgb_
to_ hsl - sRGB (0..1 components) → HSL, all components 0..1 (gpui’s Hsla convention).
- scrim
- Modal backdrop at
alpha_dark(quoted, as everywhere, in dark-mode terms). - set_
brand - Install a brand and repaint every window with it.
- set_
current_ appearance - Point the context-free paint helpers at an appearance. Called by
Theme::install; exposed for tests that build a theme without anApp. - set_
glass_ bevel - Point
Theme::glass_bevelat a share of the inradius. - set_
glass_ magnify - Point
Theme::glass_magnifyat an amplitude. Signed. - set_
palette - Teach bezel how this app builds its palette, so light/dark switching rebuilds your colours instead of replacing them with the built-in ones.
- theme_
generation - Monotonic id of the current palette.
- tint
- Re-emit an achromatic tone at
hue, carrying as muchchromaas its lightness can hold. Alpha rides through untouched. - 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
inkthat stops short of pure black or white so hover plates read as tinted glass rather than paint.