Menu da documentação

Documentação

Design system

The component vocabulary TDE apps are built from.

Nesta página

TDE-CN

TDE UI is the design system every TDE-owned app and every tde-app-sdk app is built from. It takes the composition discipline of Ratatui and the coherent component vocabulary of shadcn/ui, and adapts both to a terminal — without turning the terminal into a bitmap surface.

It is shared vocabulary, not a web port. A Dialog here is a cell-based, rect-bound, immediate-mode surface that happens to answer to the same name.

The executable source of truth is the TDE UI Demo:

bash
tde ui-demo

The Demo is not a marketing gallery. It is the canonical inventory: every component appears exactly once, each page is smoke-rendered in every built-in theme at both a desktop 120 × 40 and a Web Share phone 30 × 24, and both sizes have readable textual goldens.

The six pillars

1. Semantic, theme-native styling

Components consume Theme, Tokens, TextRole, StatusKind and named icons. Apps never invent RGB values, spacing scales or private border conventions. Default always follows the active system theme, and all sixteen built-in palettes — from the default Tonal Slate through Editorial Paper, platform-inspired palettes and familiar editor themes — satisfy one semantic contract. See Themes.

2. Constraint-based composition

Geometry is computed before painting. Layout, LayoutConstraint, Flex, RectExt, PageContainer and the typed scaffolds return rectangles, and the same rectangles are shared by rendering and hit-testing. Components clip to the Rect they receive, including tiny and degenerate Web Share viewports.

3. A uniform widget contract

Reusable controls implement Widget or StatefulWidget. Configuration belongs to the widget; mutable selection and editing state belongs to the caller. In practice, every component:

  • renders into an explicit Rect;
  • exposes typed mouse and key outcomes, not app-specific side effects;
  • takes time and data by injection, and reads no global I/O during render;
  • measures what it paints and paints what it measured;
  • keeps rendering and hit-testing on one layout calculation.

4. Mouse-first, keyboard-complete

Every visible action has a mouse target first, and the same action must be reachable without a memorized shortcut: arrows move focus or selection, Enter / Space activate, Esc closes or returns, Tab may assist form traversal. Single-letter shortcuts are accelerators, never the only route.

Hidden in-place value cyclers are prohibited — use Select, SelectField, Toggle, Checkbox or SegmentedControl so the choice is visible.

5. One adaptive component model

The desktop and Web Share use the same components and the same state. At compact width the layout becomes Android-like: AppBar, NavDrawer, stacked content and touch-sized targets replace a permanently visible rail. The supported minimum catalog viewport is 30 × 24 cells, with no fake overflow. There is no second mobile component set.

6. Hybrid cells plus pixel-tier decoration

Cells stay canonical — for text, focus, input, SSH and fallback terminals. Components may additionally emit resolution-independent Decor intents for rounded corners, inset chips, hairlines and shadows. Kitty, Ghostty and Web Share render those intents at device resolution; every other host keeps the complete cell rendering. See Terminal graphics.

Text is never rasterized into decoration, apps never branch on the host, and no app draws private pixel chrome.

The catalog

Eight groups. Each component has exactly one canonical page in the Demo.

GroupComponents
FoundationsTheme, Tokens, Breakpoint, TextRole, Icon, Kbd, PaintCtx, Widget/StatefulWidget, Chrome, FocusScope, Elevation/Decor
InputsButton, Toggle, CheckboxGroup, RadioGroup, SegmentedControl, TextInput, TextArea, Field, Form, Select, SelectField, ColorPicker
NavigationAppBar, Breadcrumb, TabBar, SubTabs, Toolbar, Menu, NavDrawer, Scrollbar
Data DisplayList, Tree, DataTable, KeyValueTable, FileTree, FilePicker, FileBrowser, MarkdownBlock, QrCodePanel
Data VizGauge, Sparkline, BarChart, LineChart, AreaChart, Timeline, MetricCard
FeedbackBanner, StatusPill, Badge, Spinner, Skeleton, EmptyState, Toast, ToastStack
OverlaysDialog, Popover, Popup, SelectModal, ShortcutCaptureModal
LayoutsLayout/Constraints/Flex, Card, Divider, PageContainer, AppShell, FormPage, MasterDetail, SidebarShell, SplitPane, StatusBar

DataTable is canonical over Table: its named column ids and typed activation and sort outcomes are the stable app-author contract. Floating surfaces share one elevation contract — their cell fallback is opaque and legible, and their pixel tier adds the matching corners, hairline and shadow.

Compatibility aliases

These names still work so existing apps keep compiling, but they do not get their own catalog page:

Old nameCanonical
PanelCard
TextBoxTextInput
ProgressGauge
TableDataTable
SharedChromeChrome

Specialized renderers

Some content is deliberately not a generic widget: the terminal emulator, the code editor and its syntax and diff views, the spreadsheet grid, the browser and media surface, image and ANSI-art previews, and domain visualizers. They still obey the theme, the clipping, the chrome, the overlays and the keyboard rules — only their core pixels are custom.

The PaintCtx rule

Paint only through a component, or through a bounded PaintCtx. Never straight to the Canvas.

A raw Canvas knows one thing: the physical screen edge. It does not know about your window, a nested pane, a modal, or a 30-column Web Share viewport. A direct write is therefore a write that can escape any of them.

When no component models the surface you need — a per-character-styled diff row, a syntax-highlighted buffer, procedural art — the answer is a widget that takes PaintCtx, never a raw Canvas. That keeps the surface bounded by its own rect and inside the pixel-tier and Web Share paths.

Exemptions exist, but each one must be written down. A raw write survives only where the cell is a protocol payload rather than ink — the kitty placeholder cell encodes a 24-bit image id in its foreground and the raster row and column in its background, and the compositor inverts or blits already-composed cells, which no painting helper can express. Every such site carries a comment explaining the constraint; the gate rejects any that does not.

Interaction rules

  1. Compute layout once and share its rectangles with paint and hit-test paths.
  2. Paint only through a component or a bounded PaintCtx.
  3. Use PageContainer for standard page gutters and typed scaffolds for common screen shapes.
  4. Reserve DataTable for app-facing tabular data; use KeyValueTable for editable key/value records.
  5. Keep actions visible and consistently ordered. Destructive actions use the semantic danger role.
  6. Preserve the same task on desktop and compact layouts — change presentation, not capability.
  7. Emit Decor only as progressive enhancement over a complete cell rendering.
  8. Every mouse handler needs a visible keyboard path through focus plus Enter / Space.
  • Your first app — the SDK, the manifest and the harness.
  • Themes — the semantic palette these components consume.
  • Terminal graphics — which hosts render the pixel tier.
  • Web Share — the compact presentation the same components produce.