Skip to content

Proof of concept: cell-relative borders for terminal UIs - #1947

Draft
joshka wants to merge 1 commit into
raphamorim:mainfrom
joshka:joshka/cell-border-proof-of-concept
Draft

joshka wants to merge 1 commit into
raphamorim:mainfrom
joshka:joshka/cell-border-proof-of-concept

Conversation

@joshka

@joshka joshka commented Sep 19, 2026 •

Copy link
Copy Markdown

I want boxes around things that sit at the edge of the terminal cell, rather than through its center, with configurable colors and widths. Borders should work whether a cell contains text or is empty. Centerlines and parts of those lines are useful too, particularly with quadrant and half-block characters.

The deeper rationale is that by stopping using characters to draw borders, you free up the UI to just be text. You can use proper underlines or custom parts of a border, colored as needed, without using character positions for the decoration. It also gives a cell another color independently of its foreground and background.

These borders are terminal-drawn and sized relative to the cell. They follow the cell geometry as the window and font scale, rather than requiring the application to draw borders into an image at a particular pixel size. Horizontal and vertical strokes should have the same physical thickness.

This is a vibeslopped proof of concept for discussing the idea, not a request to merge the code. It was one-shotted with Codex, then tweaked to add examples showing why this might be useful. The protocol and implementation are there to make it possible to try, rather than as a finished design.

What the later examples explore

  • Thin borders around a dialog, buttons, and active/inactive text fields; text fields with only an underline.
  • Proportion: generally one row of vertical space should balance two columns horizontally.
  • Inside versus centered strokes, different button sizes, and text immediately next to the borders.
  • Different RGB colors for dimmer/brighter borders and fills, including differently colored edges on the same button.
  • Borders directly around text, without added padding.
  • Quadrant and half-block characters forming smaller button backgrounds, with centerlines following their internal edges. Half-length centerlines make the corner turns without leaving a cross.
  • T-junctions where dividers above and below a shared line meet at different columns, as in a header or status bar.

The small protocol sketch uses an experimental APC namespace, similar to Rio's Glyph Protocol. It paints border attributes onto existing cells without changing their text or moving the cursor. Placement and text layering are included to experiment with strokes inside or overlapping the cell boundary.

Try it

cargo build -p rioterm
./target/debug/rio -e python3 misc/scripts/cell-borders.py

The demo needs at least 88 columns by 42 rows. b toggles borders; p shows placement; c shows colors; h shows half-block buttons; j shows T-junctions; w changes stroke width on the geometry views; q exits. You can start directly with --placement, --colors, --blocks, or --junctions after the script name.

The prototype builds, and 550 terminal-core tests and six border-renderer tests pass. The examples have been iterated on interactively; Codex could not inspect Rio's window through its computer-use tool. Cross-row overlap still follows the renderer's row order, and saved text/style snapshots omit borders. Those are prototype limits, not settled protocol decisions.

Original prompt

I'd love to be able to put a custom colored border at the top/left/bottom/right of any cell, regardless of whether it has content in it or not. The color and width should be configurable; this should be like an SGR-type extension (or similar escape code).

The idea is that border symbols don't quite fit well because they can only be a single foreground color, and they're rendered in the middle of the cell, not the edge. I think I'd likely still need a center cross option too, to handle putting borders around quadrants neatly. That would make thin borders a possible thing. It would also be useful for text fields, active and inactive. Mostly this is to add a third color to cells that need it. I'm unsure if each part of the border should be colored—probably, to make combinations easy to do.

Design this as an extended protocol similar to the recent font-changing ideas. Then build it as a prototype and give me testing code to show how it works. For instance, the attached screenshot could really do with some thin borders. I'm unsure if there's prior art on this, and it's something that definitely pushes the border of thinking outside the box (pun intended).

I just want something that looks good that can be a prototype for something that improves the general TUI border perspective. I suspect it may be worth considering border types that can be against the border, and some types that can overlap the border as well. Note also that the size of the horizontal and vertical should be similar. That's a problem with using Unicode eighth pieces: an eighth of the horizontal height is about double an eighth of the vertical width.

It's also possible that z-order matters for this in some cases, so perhaps make that part of the definition. Optimize for a quick protocol doc, then prototype. Omit huge amounts of detail and find it while prototyping as needed.

The prompt referred to a screenshot of a TUI confirmation dialog with filled panels and buttons.

CleanShot 2026-09-19 at 06 56 21

Paint independently colored cell edges and center lines without
consuming text positions. Use an experimental APC namespace and a
shared physical width scale so thin strokes match on both axes.

Support inside and centered placement and row-local text layers.
Include a compact protocol and interactive comparison demo.
@joshka

joshka commented Sep 23, 2026

Copy link
Copy Markdown
Author

See also on this discussion in ghostty ghostty-org/ghostty#14324

This branch has not been deployed

No deployments
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