Skip to main content

max / alloy_tui

8.4 KB · 81 lines History Blame Raw
1 # Alloy Design Language
2
3 The visual rules Alloy's authored TUIs follow, and that adopted apps are themed toward where possible. Since the 2026-07-17 pivot, "authored" means ratatui terminal surfaces; the principles below are toolkit-agnostic, and the mechanics are stated for a terminal cell grid (with notes for any adopted GUI surface where they differ).
4
5 Reference imagery: [inspo/]inspo/: terminal rices that demonstrate most of these principles.
6
7 ## Core principle: tinted greyscale chrome, color as information
8
9 The UI is monochrome in a single tinted greyscale ramp. "Tinted" is the load-bearing word: the ramp is biased toward a hue (warm beige in light mode, warm charcoal in dark), never neutral grey, never pure white or black at the extremes. Surfaces, text, borders, box-drawing, scrollbars, focus borders, all live on this ramp.
10
11 Color is reserved for information. A red value means something is wrong. A green bar means utilization. A syntax-highlighted token carries semantic weight worth the eye's attention. If a color does not encode information, it does not appear.
12
13 This is the rule that organizes everything else, and it is a natural fit for a terminal, where color is scarce and legible precisely because it is rare.
14
15 ## Light and dark are polarity flips of the same tint
16
17 Dark mode is not a different palette. It is the light-mode ramp with its lightness inverted along the same hue axis. A warm-beige light mode flips to a warm-charcoal dark mode; the tint hue is preserved. Components reference ramp positions (`surface`, `surface-raised`, `text-primary`, `text-muted`, `border`) and never raw values. The mode toggle inverts lightness only.
18
19 ## The information palette
20
21 A small, fixed set of accent hues, used only when their meaning is the point:
22
23 - **Red**: error, over-threshold, destructive action confirmed
24 - **Yellow / amber**: warning, near-threshold, attention without alarm
25 - **Green**: healthy, success, in-bounds utilization
26 - **Blue**: informational, link, in-progress
27 - **Magenta / violet**: categorical accent for syntax or data series where the other four are taken
28
29 Saturation stays moderate. Accents sit as foreground on the tinted-greyscale surface; they do not become the surface. A dense data readout is fully colored where it encodes severity or series identity, with every cell of chrome remaining tinted grey.
30
31 ## What this rules out
32
33 - Branded accent colors on non-data chrome (no "Alloy" accent on pane borders, headers, or focus).
34 - Ambient color washes, gratuitous reverse-video blocks, rainbow chrome.
35 - Per-app theming that introduces a new hue. An app picks a position on the existing ramp; it does not extend the palette.
36 - Status communicated by color alone. Color-as-information is paired with a label or glyph, never color alone (accessibility floor, and doubly important in a terminal where a user may have remapped the 16-color base).
37
38 ## Typography
39
40 Mono, by nature: a terminal renders one fixed-width font (IosevkaTerm Nerd Font). The former two-font working/display split does not apply; hierarchy comes from the levers a terminal has: **weight** (`Modifier::BOLD` for emphasis and section headers), **case** (`UPPERCASE` letter-labels above readouts, in the mil-spec placard tradition), and **Nerd Font glyphs**. Column alignment is free: the terminal font is already tabular, so numeric columns align without a special display font. The exact tokens live in [TOKENS.md]TOKENS.md#typography.
41
42 ## Geometry
43
44 Rectilinear, and a terminal is rectilinear by construction. Box-drawing borders (`BorderType::Plain`) in a low-contrast ramp position. No shadows (a terminal has none to give, which suits the no-decorative-shadows rule). No corner radius (cells cannot round). Generous blank-cell padding around tabular regions so the data, which carries the color, has room to breathe against the grey chrome.
45
46 ## Affordance: depth via ramp, not via color
47
48 Monochrome chrome, no shadows, and color-reserved-for-information remove the usual vocabularies for signaling interactivity. In the Apple HIG tradition of *discoverable depth*, the replacement vocabulary:
49
50 **Surface elevation is the depth language.** Use at least three ramp positions that read as elevation: `surface` (base, the terminal background), `surface-raised` (bordered controls), `surface-overlay` (popovers, menus, dialogs). The step between levels is tonal. A control announces itself by sitting on a raised, bordered surface; a data panel sits flush and borderless on `surface`. Elevation is a static affordance for control chrome, not a focus cue: the focused pane does *not* swap its surface.
51
52 **State variants are mandatory, not optional.** A terminal has no pointer, so the states reduce to what keyboard focus expresses: `default`, `focused`, `selected`, `disabled`. Focused switches the pane's border to `border-strong`, and nothing else changes: no surface swap, no title reweighting, no glyph. Selected does the same at row scope: a `border-strong` leading-edge stripe (a border-like cue) and no surface change. Disabled drops text to `text-muted`. No Alloy widget ships with only a default state. (Hover/pressed remain documented for any adopted GUI surface but do not apply to authored TUIs.)
53
54 **Borders are the boundary cue.** A single box-drawing border at `border` announces a control's edge; switching that border to `border-strong` announces focus. This is functional chrome, not decoration.
55
56 **Focus is obligatory, unambiguous, and border-only.** Keyboard focus is shown by the focused pane's border going to `border-strong`, with enough contrast to be unmistakable at arm's length, and that is the *entire* cue. No surface swap, no accent, no glyph, no title styling change. Focus uses the ramp, not the information palette; it is chrome, not data. Making focus subtle as a "clean" choice is a regression; stacking extra signals on top of the border is also a regression, in the other direction.
57
58 **Square-and-flush is for data; bordered is for controls.** Data panels and tabular regions are borderless and flush on `surface`. Interactive controls (fields, list rows that respond to Enter, buttons) carry a box border. The presence or absence of a border is itself the affordance cue.
59
60 ## Composition patterns
61
62 Binding wherever the layout applies.
63
64 **Action hierarchy: polarity-driven.** A primary action inverts polarity (its cell run is `text-primary` background with `surface-raised` text), visually heavy without recruiting an accent. Secondary actions sit on `surface` with normal text. Disabled actions hold `text-muted`. A pane never shows more than one primary action.
65
66 **List and pane selection: leading-edge stripe.** The current selection in a list is marked with a `border-strong` stripe (a single reverse or block cell) along the leading edge of the row. The row's surface does not change, and no glyph or reweighting is added; the stripe is the only cue, matching the pane-border rule at row scope. It rhymes with the focus border (also `border-strong`) but reads as an edge, so selection and focus stay distinguishable when they coincide. Selection is chrome; never an accent.
67
68 **Inline messages: accent only at the edge and glyph.** A color-as-information message (error, warn, healthy, info) carries a single-cell accent bar at the leading edge and an accent glyph; the message body stays `text-primary`. The accent never fills the message's surface (that would turn chrome into data).
69
70 **Titlebars / header rows: one step above raised.** A window or pane header sits on `surface-overlay` to mark its perimeter as distinct from content on `surface-raised`.
71
72 **Tabular numerics: the terminal font, right-aligned.** Numeric columns align for free in a fixed-width terminal font; right-align them and pad with blank cells. No special display font is needed or available.
73
74 ## Iconography
75
76 Two tiers with non-overlapping roles. Functional icons are Nerd Font glyphs from the terminal font, used inline at cell size, and are the primary tier for TUIs. Hero illustrations survive only on the few graphical surfaces that remain (splash, swaylock background). Full rules in [ICONOGRAPHY.md]ICONOGRAPHY.md.
77
78 ## Scope
79
80 Binding for the ratatui surfaces Alloy authors (`alloy_tui`, the console). Adopted apps (sway chrome, swaylock, mako, helix, yazi, bottom) are themed toward the ramp where their theming permits, and accepted as-is where it does not. Heterogeneity at the seam between authored and adopted is a known trade, called out in [MANIFESTO.md]MANIFESTO.md#what-we-author-vs-what-we-adopt.
81