返回 CodeWhale
COMPONENTS.md
根目录 / vendor / codewhale-ratatui / COMPONENTS.md
1 # Component source crosswalk
2
3 This library extracts the current Codewhale TUI into reusable Ratatui parts.
4 The native components preserve its layout and palettes. Optional compositions
5 retain useful desktop-inspired alternatives. See [VIEWS.md](VIEWS.md) for the
6 terminal view inventory and runnable recipes.
7
8 Source snapshots inspected for this crosswalk:
9
10 - **Engine:** `Hmbown/CodeWhale` at
11 [`a79ce5c4d5ed1a5f7032185710c27343a900351c`](https://github.com/Hmbown/CodeWhale/tree/a79ce5c4d5ed1a5f7032185710c27343a900351c).
12 Engine paths below start at `crates/tui/src/tui/`.
13 - **Native GPUI:** `Hmbown/codewhale-app` at
14 [`ed626e636904ab5b5ae6df6306006d90497f10c6`](https://github.com/Hmbown/codewhale-app/tree/ed626e636904ab5b5ae6df6306006d90497f10c6).
15 Native paths below start at `src/`. The shared character export separately
16 pins `bc1044887b4ef973e444b6f8f83f9389daffee2a`; see
17 [its provenance](assets/whale-motion/PROVENANCE.md).
18 - **Design authority:** `codewhale-design` at
19 `642795c1f9ef465b8d4f4df8584d23be28af6e9f`, `DIRECTION.md` and
20 `tokens.json` version **1.1.2**. This kit vendors its token release in
21 [vendor/codewhale-design](vendor/codewhale-design).
22 - **Kit baseline:** `d02d14799b046fb6c9fdd3969c36ec9202251f34`, with the
23 native component extraction represented below.
24
25 The current terminal source is the native baseline. Desktop references inform
26 optional cards and workspace compositions; the shared whale performance core
27 retains the native character. The library supplies reusable presentation and
28 input helpers, while each consuming app supplies its own data and actions.
29 The inspected terminal files are recorded in [assets/tui-source.json](assets/tui-source.json).
30
31 ## From product source to kit parts
32
33 “Primitive” means a small visual or input building block. “Composite” means
34 a reusable arrangement of those parts over facts supplied by the host.
35 Gallery names are the exact names accepted by the gallery example; the
36 [gallery sources](src/gallery) contain the fixture calls and all variants.
37
38 | Native reference | Public kit family | Kind | Gallery entries |
39 |---|---|---|---|
40 | Engine `menu_style.rs::StatusMark`, `StatusKind`; GPUI `workspace/mod.rs::set_theme` and `workspace/render/conversation.rs` state readouts | `StatusMark`, `State`, `StateWords`, `Icon` | Primitive | `status-marks`, `icons` |
41 | Engine `views/mod.rs::ActionHint`, `widgets/key_hint.rs`; GPUI `chrome.rs::MenuRow`, `MenuSpec` | `KeyHint`, `KeyHints`, `Keymap`, `Binding`, `KeyChord` | Primitive | `key-hints`, `keymap-hints` |
42 | Engine `views/mod.rs::render_modal_surface`, `render_underwater_surface`; GPUI `workspace/dock/skin.rs::QuietDockSkin`, `TabStrip` | `Panel`, `Depth`, `Dialog`, `Sheet`, `HorizonRule`, `Heading`, `Tabs` | Primitive | `depth`, `dialog`, `sheet`, `horizon`, `heading`, `tabs` |
43 | Engine `views/mode_picker.rs::ModePickerView`, `views/status_picker.rs::StatusPickerView`, `views/mod.rs::EmptyState`; GPUI `workspace/palette.rs`, `modules/function_line.rs::FunctionLine` | `Picker`, `PickerQuery`, `PickerTabs`, `PickerMatches`, `List`, fuzzy matching helpers, `EmptyState` | Primitive/composite | `mode-picker`, `status-picker`, `picker-query`, `picker-tabs-preview`, `picker-no-match`, `list`, `list-scrolling`, `list-tall-rows`, `list-empty`, `empty-state` |
44 | Engine `app/composer.rs`, `views/automations/editor.rs`; GPUI `workspace/render/composer.rs`, `workspace/settings/mod.rs::Field`, `Control` | `LineBuffer`, `TextInputState`, `TextInput`, `Form`, `Toggle`, `Segmented` | Primitive/composite | `text-input-empty`, `text-input-typed`, `text-input-secret`, `text-input-invalid`, `text-input-disabled`, `text-input-wide-text`, `form`, `toggle`, `segmented` |
45 | Engine `history/message.rs::render_message`, `composer_chrome.rs::ComposerChrome`, `widgets/tool_card.rs::ToolFamily`, `CardRail`; GPUI `workspace/render/conversation.rs::render_prepared_row`, `workspace/render/composer.rs` | `Message::native`, optional `Composer`, `ToolCard` | Native inline message / optional composites | `message`, `composer`, `tool-card` |
46 | Engine `widgets/agent_card.rs::DelegateCard`, `FanoutCard`, `AgentLifecycle`, `views/fleet_roster.rs::FleetRosterView`; GPUI `workspace/dock/agents.rs::AgentsModule` | `AgentCard`, `Fleet` | Composite | `agent-card`, `fleet`, `fleet-scene` |
47 | Engine `phase_strip.rs::TidelineFooter`, `workspace_context.rs`; GPUI `workspace/dock/skin.rs::QuietDockSkin`, `workspace/render/composer.rs` context controls | `WorkspaceFrame`, `WorkspaceAreas`, `PaneHeader`, `ContextRibbon`, `ContextItem` | Composite | `workbench-frame`, `pane-header`, `context-ribbon`, `context-ribbon-narrow`, `workspace-scene`, `workspace-scene-narrow` |
48 | Engine `work_surface/{model,input,views}.rs`, `work_surface/render/{mod,layout,rows}.rs` | `Workbar`, `WorkbarRow`, `WorkbarPanel`, `WorkbarState`, `WorkbarLayout`, `WorkbarScrollbar`, `DockTabRow`, `DockTabPlan`, `DockTabEntry`, `DockTabStyles`, `DockTabTarget` | Native extraction | `workbar-tasks`, `workbar-fleet`, `workbar-jobs`, `workbar-files`, `workbar-notes`, `workbar-context`, `workbar-git`, `workbar-cost`, placement and narrow variants |
49 | Engine `widgets/workbar.rs` | `WorkflowProgress`, `WorkflowRun` | Native extraction | `workflow-*` |
50 | Engine `widgets/mod.rs`, `composer_chrome.rs`, `composer_ui.rs`, `mouse_ui.rs` | `NativeComposer`, `NativeComposerFrame`, `NativeComposerPlan`, `NativeComposerSourcePlan` | Native extraction | `native-composer-*` |
51 | Engine `phase_strip.rs`, `infoline.rs`, `ui/frame.rs` | `PostureBar`, `MetricsLine`, `TerminalShell` | Native extraction | `posture-*`, `metrics-*`, `showcase-work`, `showcase-narrow` |
52 | Engine `views/mod.rs::render_underwater_surface`, `session_picker.rs::SessionPickerView` | `InstrumentSurface`, `SessionList`, `SessionRow` | Native extraction and view recipes | `native-*` |
53 | Engine `crates/palette/src/{rgb,tokens,themes}.rs` | `TuiPalette`, `TuiInk` | Generated source palette | all 16 `tui-theme-*` previews |
54 | Engine `widgets/pending_input_preview.rs::PendingInputPreview`, `ContextPreviewItem`; GPUI `workspace/queue.rs::QueuedMessage`, `RowAction`, `Workspace::render_queue`, `workspace/render/composer.rs` attachments | `PendingInputPreview`, `PendingInputItem`, `PendingInputStatus`, `PendingInputAction`, `ContextPreviewItem`, `ContextPreviewState`, `PendingCard`, `PendingCardWords`, `PendingCardContext`, `PendingCardStyles` | Composite | `pending-queued`, `pending-steering`, `pending-paused`, `pending-context`, `pending-native-mixed`, `pending-native-queued` |
55 | Engine `markdown_render.rs::Block`, `RenderedMarkdownLine`, `history/message.rs::render_message_with_copy_metadata`; GPUI `workspace/markdown.rs::MessageText`, `text`, `sanitize` | `Transcript`, `TranscriptBlock`, `TranscriptSpan`, `TranscriptSpanRole`, `CodeBlock`, `TranscriptLink`, `TranscriptAction` | Primitive/composite | `transcript-prose`, `transcript-list-table`, `transcript-code`, `transcript-links` |
56 | Engine `widgets/mod.rs::ChatWidget`, `agent_focus.rs::render_focus`, `live_transcript.rs::LiveTranscriptOverlay` | `TranscriptViewport`, `TranscriptViewportPlan`, `TranscriptViewportStyles`, `TranscriptScrollFacts` | Native extraction | `transcript-mounted`, `transcript-mounted-focus` |
57 | Engine `agent_roster.rs::render_agent_roster`, `widgets/workflow_panel.rs::row_receipt_text`, `gate_receipts.rs`; GPUI `usage.rs::TurnRow`, `workbar.rs::Readout`, `working_context.rs::ExecutionReceipt` | `Receipt`, `ReceiptTable`, `ReceiptValue`, `Cost`, formatting helpers | Primitive/composite | `receipt-row`, `receipt-table`, `receipt-table-compact`, `receipt-table-minimal`, `receipt-table-clipped` |
58 | Engine `diff_render.rs::BoundedDiffRender`, `render_diff_bounded`, `history/file_mutation.rs`; GPUI `review.rs::DiffRowKind`, `workspace/render/review.rs::ReviewRows` | `Diff`, `DiffLine`, `DiffKind`, `DiffGutter`, `DiffHighlight`, `parse_unified` | Primitive | `diff`, `diff-wrapped`, `diff-no-numbers`, `diff-highlighted`, `review-scene` |
59 | Engine `widgets/workflow_panel.rs::WorkflowPanel`, `WorkflowPanelRow`, `history/checklist.rs`; GPUI `plans.rs`, `workspace/render/workers.rs` | `WorkflowTree`, `TreeNode`, `TreeState`, `CountBar` | Primitive/composite | `workflow-tree`, `workflow-tree-selected`, `workflow-tree-clipped`, `workflow-tree-long`, `count-bars` |
60 | Engine `approval/view.rs::ApprovalView`, `approval/elevation.rs::ElevationView`, `auto_review.rs`; GPUI `workspace/render/conversation.rs::Workspace::render_attention`, `workspace/render/review.rs::Workspace::render_restore_confirmation` | `ApprovalCard`, `ApprovalSubject`, `ApprovalState`, `ApprovalChoice`, `ApprovalPaint`, `DecisionBand`, `DecisionBandPlan`, `DecisionBandAction`, `DecisionBandSave`, `ReviewVerdict`, `ReviewAggregate` | Composite | `approval-command`, `approval-outside`, `approval-patch`, `approval-elevation`, `approval-clipped`, `approval-spoofed`, `approval-native-band`, `approval-native-band-collapsed`, `review-verdicts`, `review-aggregate` |
61 | GPUI `workspace/render/conversation.rs::Workspace::render_attention`, `workspace/render/files.rs::Workspace::render_artifact_column` | `AttentionQueue`, `AttentionItem`, `ArtifactShelf`, `Artifact` | Composite | `attention-queue`, `attention-focused`, `attention-narrow`, `attention-empty`, `artifact`, `artifact-shelf`, `artifact-narrow`, `artifact-unknown`, `artifact-empty` |
62 | Engine `views/mod.rs::ConfigView`, `ConfigRow`, `ConfigView::render_setting_detail`; GPUI `settings.rs::Spec`, `Applies`, `workspace/settings/mod.rs::Settings` | `SettingRow`, `SettingDetail`, `SettingWords` | Composite | `setting-row`, `setting-detail` |
63 | Engine `app/status.rs::StatusToast`, `StatusToastLevel`, `spinner.rs`, `spinner.rs::verification_tick_frame`; GPUI `workspace/notify.rs::ThreadNotice`, `workspace/motion.rs` | `Toast`, `Toasts`, `Ttl`, `Spinner`, `VerificationSpinner`, `MotionMode`, `MotionStep`, `MotionSet`, `FrameBudget` | Primitive/composite | `toasts`, `toasts-stacked`, `toasts-fading`, `spinner`, `verification-pending`, `verification-earned`, `verification-modes`, `motion-modes`, `motion-working`, `motion-started`, `motion-mid-flight`, `motion-settled`, `motion-reduced` |
64 | Engine `ambient_life.rs`; GPUI `whale/habitat.rs`, `whale/stage.rs::CoveScene` | `Habitat`, `FishSchool`, `Jellyfish`, `BubbleField`, `HabitatDensity` | Primitive/composite | `fish-school`, `jellyfish`, `bubble-field`, `habitat-scene`, `habitat-ascii`, `habitat-reduced` |
65 | GPUI `whale/acting.rs::Director`, `whale/rig.rs`, `whale/scene.rs`, `whale/stage.rs::Stage`, canonical `vendor/whale-character-v2` authoring data; Engine `ambient_life/pet_widget.rs::render_grid`, `pet_watch/mod.rs` | `BrailleFrame`, `Whale`, `WhaleState`, `Whale::paint_frame`, `whale_motion::{Director, Stage, Inputs}`, colored Braille frame helpers | Character renderer/shared performance core | `whale-rest`, `whale-busy`, `whale-needs`, `whale-done`, `whale-pod-1`, `whale-pod-3`, `whale-actions`, `whale-compact`, `whale-words-only`, `showcase-life` |
66 | Engine `ocean.rs::OceanRamp`, `OceanColumn`, `underwater.rs::ShellPhase`; canonical logo and semantic tokens | `OceanRamp`, `OceanColumn`, `OceanPhase`, `OceanPaintFacts`, `OceanCausticFacts`, `OceanContrastInks`, `ocean_semantic_surfaces`; optional `Ombre`, `OmbreDirection`, `WaterPalette` | Background finishing passes | `ocean-column`, `ocean-phases`, `ocean-context`, `ocean-reduced`, `ocean-native-guarded`; `atmosphere-ocean`, `atmosphere-lagoon`, `atmosphere-dusk`, `atmosphere-coral`, `atmosphere-graphite`, `showcase-color` |
67
68 The integrated `showcase-work`, `showcase-decision`, `showcase-color`,
69 `showcase-life` and `showcase-narrow` scenes arrange existing components with
70 illustrative facts. They are examples of composition, not additional
71 production session models.
72
73 ## Pending input and authored transcript
74
75 These additive APIs close two concrete visual gaps found in the source
76 comparison. They represent the implementation slice's public contracts;
77 they do not claim the Engine or GPUI queue/parser has been migrated.
78
79 `PendingInputPreview::new(items, context)` accepts stable caller IDs,
80 reported pending states, attached context and optional selected ID. Its
81 `actions()`/`actions_for()` are metadata: the host sends, edits or drops an
82 item and reports the resulting state. An empty preview takes zero rows.
83 `Unconfirmed` context must not become an assertion that a file was included
84 or sent. Approval policy and attention prioritization remain with the host;
85 compose this preview beside `AttentionQueue` and `Composer` as appropriate.
86
87 `PendingCard` accepts the native composer's sending, editing and queued input,
88 independent context inclusion/removability/selection facts, priority notices,
89 localized `PendingCardWords` and optional five-slot `PendingCardStyles`. It
90 shares one measured row plan with `PendingInputPreview`, including clipping
91 and the one-row controls fallback. The host still owns every queue mutation,
92 child request and keyboard action.
93
94 `Transcript::new(blocks)` accepts already-authored blocks and semantic
95 spans. Headings, prose, quotes, lists, tables and `CodeBlock` do not require
96 another Markdown parser. `CodeBlock::copy_text()` supplies the original
97 source; the host decides whether to put it on the clipboard. `links()`
98 returns targets out of band; the host validates and dispatches them.
99 The text displayed on the terminal is sanitized independently of the source
100 bytes used for copy or link actions.
101
102 ## Host responsibilities
103
104 - **Engine and store:** the host owns sessions, turns, provider routing,
105 tools, permissions, queue mutation, persistence and event ordering. A
106 painted state or receipt is exactly what the caller supplied.
107 - **Input and actions:** kit state helpers report outcomes. They never
108 launch tools, submit prompts, allow commands or discard files. Approval
109 hosts retain the arm-after-paint guard and handle incomplete subjects.
110 - **Parser and highlighter:** the host owns Markdown parsing and syntax
111 highlighting. The kit paints structured transcript blocks and supplied
112 diff lines. `parse_unified` is a display convenience, not a diff engine.
113 - **Clipboard and links:** copy text and link targets are metadata. The host
114 owns clipboard access, URL validation and opening the destination; no
115 terminal escape sequence or inline media loader is introduced.
116 - **Clock and redraws:** elapsed `Duration` and sampled `Instant` come from
117 the host. The host owns one event loop and redraw schedule. Spinners,
118 transitions, habitat and Ocean do not acquire their own clocks.
119 - **Character performance:** keep one host-owned `whale_motion::Stage` or
120 `Director` per identity. Feed authoritative observed inputs into that core,
121 then paint its frame; widgets do not infer agent activity or instantiate
122 independent Directors.
123 - **Colors:** `Theme` and the vendored roles remain the authority for state
124 ink, actions and semantic surfaces. Native Ocean's exact dark stops apply
125 to ordinary grounds under known dark truecolor Underwater; other native
126 presets, lower depths and terminal-owned shells retain their own grounds. `Ombre` offers opt-in spatial washes, not new state
127 hues. Character and syntax colors are content.
128
129 ## Shared native Dock tabs and packed character raster
130
131 `Workbar` uses `DockTabRow` for its fitted tab paint and hitboxes. The Engine
132 adapter supplies available panels, counts, active/pressed/hovered targets, live
133 styles and the actual close label. `DockTabPlan` sheds counts before inactive
134 right-hand tabs and exposes only painted action boxes. Engine continues to own
135 keyboard focus, detail precedence, Esc meaning and every action. This shares the
136 tab row; it does not claim that Engine's full Dock body uses `Workbar`.
137
138 `BrailleFrame` paints the existing host's row-major packed cells and raw caption
139 with the supplied ink and modifiers, including the Engine's 18×5 cameo raster
140 and embedded world's current raster through their shared `render_grid` facade.
141 Zero cells remain transparent; a tiny viewport retains the wrapped caption.
142 `Whale::paint_frame` uses the same packed-cell painter while retaining its
143 semantic state words, whole-frame admission and theme gradient. Neither path
144 adds a clock, simulation, color classification or a new character authority.
145
146 The existing `ocean-native-guarded` gallery directly uses `OceanPaintFacts`,
147 `OceanCausticFacts` and `ocean_semantic_surfaces`. `OceanContrastInks` supplies
148 the host role mapping for guarded native finishing. These are
149 presentation facts and protection helpers; they do not grant terminal capability
150 or weaken motion, selection, REVERSED or contrast guards.
151
152 `WorkbarLayout::for_body` shares header folding, overflow reservation, content
153 geometry and offset fitting with Engine's body viewport. `WorkbarScrollbar`
154 shares its rail math and paint. Native row composition, detail/focus gutters
155 and caller action/tooltip projection remain Engine-owned; this does not yet
156 claim full row-composer replacement by `Workbar`.
157
157 lines MARKDOWN