Improve styling.

This commit is contained in:
Greyson Parrelli
2026-08-12 21:15:07 -04:00
parent 4e0e400372
commit e16b147e16
13 changed files with 1104 additions and 119 deletions
+66 -5
View File
@@ -6,9 +6,9 @@ A proof-of-concept workspace built on
**saved layouts** that open a whole arrangement — directories, scripts and all —
in one go.
The sidebar holds the window controls, a new-tab button, and one row per tab
the layout Zen Browser uses for vertical tabs — with the content inset to its
right.
The sidebar holds the window controls, a new-tab button, one row per tab, and a
settings gear at its foot — the layout Zen Browser uses for vertical tabs —
with the content inset to its right.
## Quick start
@@ -107,7 +107,8 @@ just the VT core.
## Architecture
```
main.zig AdwApplication, CSS loading
main.zig AdwApplication startup
appearance.zig the colour scheme: preference -> libadwaita, CSS, palette
Window.zig sidebar + GtkStack of views, tab management, shortcuts
View.zig one tab's content: its panes, their layout, and drag handling
Layout.zig the split tree: nodes, rearranging, GtkPaned materialization
@@ -121,7 +122,9 @@ SaveLayoutDialog.zig turns the current tab into a saved layout
Session.zig libghostty-vt Terminal + parser, fed by the PTY
Pty.zig openpt/fork/exec, controlling terminal setup
key.zig GDK keyval -> libghostty-vt key mapping
theme.zig colors libghostty-vt has no opinion about
theme.zig colors libghostty-vt has no opinion about, per scheme
Settings.zig preferences: model, JSON on disk
SettingsDialog.zig the settings page
```
A tab is a **view**, and a view holds one or more **panes** arranged in a
@@ -286,6 +289,9 @@ in principle, but a terminal grid is small.
- **Zooming a pane** to fill its tab and back, from the header button or
`Ctrl+Shift+Z`. Nothing closes and nothing moves — hidden panes keep running
and the split comes back exactly as it was. See [Zoom](#zoom)
- **Light and dark schemes**, following the desktop by default and pinnable
from the settings page, applying to open tabs immediately — terminal palette
included. See [Theme](#theme)
### Shortcuts
@@ -299,6 +305,7 @@ in principle, but a terminal grid is small.
| `Ctrl+Shift+V` | paste into a terminal (bracketed-paste aware, refuses unsafe pastes) |
| `Ctrl+Shift+R` | rename the current tab (empty name = follow the terminal) |
| `Ctrl+Shift+Z` | zoom the focused pane to fill the tab, and back |
| `Ctrl+,` | settings |
| `Ctrl+PageUp/PageDown` | previous / next tab |
| `Alt+1`..`Alt+8` | jump to tab N, `Alt+9` jumps to the last |
@@ -468,6 +475,60 @@ smolvm machine exec --name NAME -- mkdir -p /root/.claude/hooks
image that has no `jq`; if the title can't be read the state still reports and
the tab simply keeps the name it had.
## Theme
Deep navy surfaces with Signal's ultramarine (`#3a76f0`) as the accent, in a
light and a dark scheme. `Ctrl+,` or the gear at the foot of the sidebar opens
**Settings**, which currently holds one choice: light, dark, or **system**,
which is the default and follows the desktop.
The preference lives in `~/.config/playpen/settings.json` (or
`$XDG_CONFIG_HOME`), beside `layouts.json`:
```json
{
"version": 1,
"theme": "system"
}
```
Switching applies immediately to every open tab — nothing needs restarting, and
a shell that has been running all day repaints along with everything else.
Three separate colour systems have to agree for that to be true, which is what
`appearance.zig` exists to arrange:
- **libadwaita's style manager** colours the stock widgets — popovers, entries,
dialog chrome. It is told to force a scheme, or left on `default` to follow
the desktop.
- **`style.css`** colours everything the app draws itself. It is written
entirely against named colours, with one palette file per scheme
(`palette-dark.css`, `palette-light.css`); the matching palette is prepended
and the pair loaded as a single `GtkCssProvider`. No rule in `style.css` may
hardcode a colour — a literal hex is a rule that looks right in whichever
scheme you happened to be testing in.
- **`theme.zig`** holds what Cairo draws the terminal grid from: the default
background, foreground and cursor, plus the 16 ANSI colours. The style tree
is never consulted there, so a CSS reload alone would leave every terminal
painted in the scheme it started in.
The ANSI palette is the part that is easy to skip and shouldn't be. The
standard xterm yellow is `#cdcd00`, which on a white background is close to
invisible — and prompts and build tools use it constantly, so a light scheme
without a light palette is a light scheme you can't read. The 240 colours above
index 16 are fixed by spec and left alone; only the 16 named ones change.
They are swapped through libghostty-vt's `DynamicPalette.changeDefault`, which
changes what the palette *defaults* to. Anything a program set for itself with
OSC 4 survives the switch, and a later OSC 104 reset returns to the current
scheme's palette rather than the one the app happened to start in.
Whether "system" currently means light or dark is libadwaita's answer, not
ours: it already watches the desktop for the setting. So the stylesheet follows
its `dark` property rather than the stored preference, and the preference only
decides what the style manager is told. A desktop that switches at sunset takes
this app with it, with no extra machinery and no second source of truth.
## Not implemented
This is a proof of concept, and the following are deliberately absent: