▄▄ ▄▄ ▄▄
▀██ ▀██ ▀██
▄█▀▀█▄ ██▀▀█▄ ▄▀▀▀█▄ ▀█▄▀▀█▄ ▄█▀▀█▄ ▄█▀▀█▄ ██ ██
██ ██ ██ ▄█▀▀██ ██ ▀ ██ ██▄▄█▀ ██ ██
▀█▄▄▄▀ ██ ██▀▀█▄▄▀█▄▄██▄ ▀█▄▄▄▀ ▀█▄▄▄▀ ██▀ ██▀ ▄▄
▀██
▄█▀▀█▄ ██▀▀█▄ ▄▀▀▀█▄ ▀█▄▀▀█▄
██ ██ ██ ▄█▀▀██ ██ ▀
▀█▄▄▄▀ ██ ██▀▀█▄▄▀█▄▄██▄ ▄██ ▄██
▄▄▄▄ ▄▄▄▄ ██ ██
██ ▀▀ ██ ██ ██ ██
██ ▄ ██▀▀▀▄ ██▄ ██▄
▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀introduction
premise
charcell is a ui kit for react, vue and svelte that looks like a terminal. it draws only what a character-cell screen could: every component sits on a grid of cells, and each cell holds one character, its font color and background color. it relies on box drawing characters for framing and segmentation. the palette is black, white and three shades of gray. those constraints are the design.
quickstart
pnpm add charcell @zag-js/react # or @zag-js/vue, @zag-js/svelteimport 'charcell/css/base';
import 'charcell/css/preflight';
import { Button } from 'charcell/react';
<Button label="kick" />constraints
a cell is 8 x 16 pixels at the default size of 14px. widths count in cells and heights in rows, and nothing sits between two cells.
a cell holds a character or a line, never both. its background color is free. lines are box drawing, so they run through the middle of their cells. a frame keeps a ring of cells for its line and sets its title on the top one. each side's line is single, rounded, heavy or double, as box drawing draws them; a double right and bottom raise a window.
the three grays are faint, mid and strong, counted from the background. each has a job:
- faint: separators and the hover background, never text
- mid: boxes at rest and secondary text
- strong: hovered lines
- white: text as well as focused, active or selected lines
light mode swaps black and white, and the grays flip accordingly.
within these constraints, every component can be represented as text: the characters a terminal would print, with their colors. each component's page has an "as text" example demonstrating this.
states
a state changes colors and characters, never geometry. nothing moves, resizes or fades: each state is on or off.
- hover: a faint background
- active: inverted, the font and background colors swapped, for as long as it is held
- selected, checked, current or open: persistently inverted, dimmed when hovered
- focus: ❯ in the cell before the text, a cell that is always there and stays empty until focus fills it
- disabled: mid text
a checkbox, a radio button or a boxed tab shows its value with its mark or its shape instead of inverting. a boxed control also brightens its line: strong on hover, white on focus and while pressed.
fonts
charcell bundles two fonts: overpass mono for upright text and lilex italic for italics. both are modified to fit the cell exactly, 8 x 16 pixels at 14px, and renamed charcell overpass mono and charcell lilex. both are under the sil open font license 1.1.
in both, the box drawing, block, shade and braille characters are redrawn as whole-pixel shapes, the way a terminal draws them itself, so lines meet without gaps or blur. ❯ and ❮ are added, since neither font had them, and the triangles and bullets are redrawn to fill the cell. the pipe is redrawn to stay inside its line. ligatures are off, so every character keeps its own cell.
┌─┬─┐╔═╦═╗┏━┳━┓╭─╮╒═╕╓─╖ │ │ │║ ║ ║┃ ┃ ┃│ │╞═╡╟─╢ ├─┼─┤╠═╬═╣┣━╋━┫╰─╯╘═╛╙─╜ └─┴─┘╚═╩═╝┗━┻━┛┄┈╌┅┉╍╤╥ ┍┎┑┒┕┖┙┚┝┞┟┠┡┢┥┦┧┨╼╽╾╿╪╫ ╴╵╶╷╸╹╺╻ ┆┊╎┇┋╏ ╧╨ ▀▄█▌▐░▒▓▖▗▘▝▙▚▛▜▞▟▔▕ ▁▂▃▅▆▇▉▊▋▍▎▏ ⠿⣿⠁⠂⠄⡀⠈⠐⠠⢀⣀⠛⠶⣤⡇⢸⠉ ❯ ❮ ▶ ◀ ▲ ▼ ▸ ◂ ▴ ▾ ● •