Skip to content

Add a CSS + @media demo over tty capability maps - #19

Open
natemoo-re wants to merge 2 commits into
experiments/cssfrom
nmoo/experiments/media
Open

natemoo-re wants to merge 2 commits into
experiments/cssfrom
nmoo/experiments/media

Conversation

@natemoo-re

Copy link
Copy Markdown
Member

What does this PR do?

Stacks on #17 (which stacks on #15): adds examples/css-tty, a demo that wires @bomb.sh/tty's capability maps into @bomb.sh/css's computeTree({ env }) and drives @media queries from terminal facts.

  • detectTerminal() + a bounded raw-mode probe round-trip fold capability responses (theme colors, color depth, kitty protocols) onto the static terminfo capabilities.
  • environmentFromCapabilities builds the CSS environment: terminal size becomes the viewport at 8×16px per cell (matching the engine's ch unit, so @media (min-width: 80ch) selects 80 columns), the probed background color becomes prefers-color-scheme via relative luminance, and the host wires its own reduced-motion switch.
  • capabilityVariables exposes facts without an environment slot as root custom properties through the root's inline style.
  • The demo prints the capability → env mapping plus per-node computed styles, and re-evaluates @media live on resize; the stylesheet compiles once and is reused per evaluation (the engine's per-frame story).
  • Colors go through light-dark() resolved against the probed scheme (using the support added in Add a CSS engine to experiments/css #17); layout flips through @media (min-width: 80ch) and (orientation: …).
  • Bumps the @bomb.sh/tty catalog to ^0.10.0 (terminfo capability maps).

Validation

  • pnpm --filter @examples/css-tty test: 12 tests, including the stylesheet's behavior through the real engine (80ch flip, orientation axis, motion switch, light-dark under both schemes, computed-value drop for malformed inline calls).
  • pnpm --filter @examples/css-tty typecheck passes; the css ABI is pinned with a local type stub.
  • pnpm test (root): 14 test files pass; framework example suites pass.
  • pnpm format:check and pnpm lint pass (93 pre-existing warnings).
  • pnpm demo verified in a non-TTY run (static capabilities + dark fallback).

Type of change

  • Feature
  • Bug fix
  • Refactor (no behavior change)
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Checklist

  • All tests pass (pnpm test)
  • Files are formatted (pnpm format)
  • I have added/updated tests for my changes (if applicable)
  • I have added a changeset

AI-generated code disclosure

  • This PR includes AI-generated code

@socket-security

socket-security Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​bomb.sh/​tty@​0.10.0841009993100

View full report

A `@bomb.sh/dom` document is snapshotted into `@bomb.sh/css` and styled
with an environment built from `@bomb.sh/tty`'s capability maps, so the
terminal's own facts drive the stylesheet:

- The capability map is `term.capabilities`: the demo holds a term
  created with `detectTerminal()`'s `TerminalInfo` and feeds `scan()`
  events straight through `term.update()`, which folds probe responses
  (theme colors, color depth, kitty protocols) into the merged view.
  Nothing is folded in the demo itself.
- `environmentFromCapabilities` builds the `env` record for
  `computeTree({ env })`: terminal size becomes the viewport at 8×16px
  per cell (matching the engine's `ch` unit, so `@media (min-width:
  80ch)` selects an 80-column terminal), the probed background color
  becomes `prefers-color-scheme` via relative luminance, the host wires
  its own reduced-motion switch, and resolution is 1.
- `capabilityVariables` renders facts without an environment slot
  (color depth, kitty graphics) as root custom properties through the
  root's inline style.

`@bomb.sh/dom` has no run loop by design (frame scheduling belongs to
consumers), so the demo owns a minimal one: a bounded raw-mode probe
window that always restores the terminal, repaint on resize, and a
kept-alive event loop (stdin stays referenced; Ctrl-C/Ctrl-D-style
signals release the sheet and exit). Real applications get the loop
from the platform (`@clack/ui`'s `createUI().main()`).

The demo prints the capability → env mapping plus per-node computed
styles and re-evaluates the `@media` queries live on resize; the
stylesheet is compiled once and reused per evaluation. Piped, it
performs one evaluation with a dark fallback scheme.

The stylesheet demonstrates both mechanisms: `@media` blocks flip the
board's column count and main axis on width/orientation and honor the
motion switch, while colors go through `light-dark()` resolved against
the probed scheme — on `color`/`*-color` properties only, so panels use
`background-color` and borders use `border-color`.

Bump the `@bomb.sh/tty` catalog to ^0.10.0 (terminfo capability maps,
`term.update()` folding). Tests cover the adapter in isolation and the
stylesheet's behavior through the real engine; typecheck pins the css
ABI with a local type stub.
@natemoo-re
natemoo-re force-pushed the nmoo/experiments/media branch from 73e56b1 to 6d3b5b9 Compare October 22, 2026 03:19
The demo now renders instead of printing declarations. A bridge maps
each node's computed declarations to `@bomb.sh/tty` render ops, so the
terminal draws what the CSS says:

- `width`/`height` percentages fill the terminal, `flex: 1` grows boxes
  to share space (the board absorbs the leftover so the status bar pins
  to the bottom), `flex-direction` picks the main axis, and `gap` /
  `padding` / `border` lengths map to cells.
- `color` paints text, `background-color` paints cells, and `border` +
  `border-color` draw borders; colors arrive canonicalized and parse
  back to packed rgba.

The stylesheet gains the visible flips: the accent hands from amber to
violet exactly at the 80ch breakpoint, so resizing across it changes
the colors as well as the layout, and a status bar prints the numbers —
cells → px, scheme, color count, the CSS-decided axis/gap/breakpoint,
and the motion switch — recomputed live.

The render loop follows the suggested integration: repaint-on-change
(diffing happens inside `Term.render`, so only changed cells hit the
wire), with resizes folded into the term via
`term.update([{ type: "resize", width, height }])` before the
stylesheet re-evaluates. Full-screen apps enter the alternate buffer
with a hidden cursor and revert on exit; the probe window restores raw
mode in a `finally`. Degenerate ptys reporting 0×0 fall back to 80×24
(zero-sized terms lay out nothing), and the event loop is anchored by
both stdin and a timer so the demo cannot drain while it waits for
resizes. Piped, it still performs one evaluation and prints the
numbers and computed declarations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant