返回 CodeWhale
README.md
1 # Codewhale Ratatui
2
3 The terminal components behind [Codewhale](https://github.com/Hmbown/CodeWhale),
4 ready for your [Ratatui](https://ratatui.rs) app. Native layouts, ocean depth,
5 quiet motion, and a little life in the water.
6
7 ![Codewhale's native conversation, composer and Tasks workbar in Underwater](assets/readme/studio.dark-truecolor-1.svg)
8
9 <details>
10 <summary>See WhaleLight</summary>
11
12 ![The same native conversation, composer and workbar in WhaleLight](assets/readme/studio.light-truecolor-1.svg)
13
14 </details>
15
16 **One component or a whole workspace.** The original eight-panel workbar,
17 composer, sessions, settings, approvals and results share the same native
18 colors and backgrounds. All 16 TUI themes, fish, jellyfish, spinners and whale
19 actions are included. Your app owns the state and clock.
20
21 [Components](#explore-the-components) · [Terminal view guide](VIEWS.md) ·
22 [Design](DESIGN.md) · [Quality](QUALITY.md) · [Benchmarks](BENCHMARKS.md)
23
24 The [website explorer](WEBSITE.md) separates every catalogue entry into a
25 searchable component page, with terminal profiles, real width variants,
26 Rust rendering source and controlled animation playback.
27
28 ## Get started
29
30 ```toml
31 [dependencies]
32 codewhale-ratatui = { git = "https://github.com/Hmbown/codewhale-ratatui" }
33 ratatui = "0.30.2"
34 ```
35
36 ```rust
37 use codewhale_ratatui::{NativeComposer, Paint, Theme};
38
39 let theme = Theme::detect().tui();
40 let composer = NativeComposer::new("Review the changes")
41 .focused(true);
42 frame.render_widget(composer.themed(&theme), frame.area());
43 ```
44
45 Rust 1.89+. Your app chooses the terminal backend.
46 Try `cargo run --example starter` for a small editable app, or
47 `cargo run --example showcase` to explore the native layout.
48
49 ## Explore the components
50
51 Open a collection to see its full dark and light previews. Every one of the
52 199 gallery entries is here, rendered from actual Ratatui buffers. The
53 [component guide](COMPONENTS.md) maps them to Codewhale's terminal views.
54 Run `cargo run --example gallery` to try every variation yourself.
55
56 <!-- gallery:start -->
57
58 ### Native Codewhale
59
60 <a id="the-live-component-gallery"></a>
61 <details>
62 <summary>The live component gallery · 5 examples</summary>
63
64 The native conversation layout, composer and workbar, plus interactive component studies.
65
66 ![Showcase work — dark truecolor](<assets/readme/studio.dark-truecolor-1.svg>)
67
68 ![Showcase decision — dark truecolor](<assets/readme/studio.dark-truecolor-2.svg>)
69
70 ![Showcase color — dark truecolor](<assets/readme/studio.dark-truecolor-3.svg>)
71
72 ![Showcase life — dark truecolor](<assets/readme/studio.dark-truecolor-4.svg>)
73
74 ![Showcase narrow — dark truecolor](<assets/readme/studio.dark-truecolor-5.svg>)
75
76 <details>
77 <summary>Light appearance</summary>
78
79 ![Showcase work — light truecolor](<assets/readme/studio.light-truecolor-1.svg>)
80
81 ![Showcase decision — light truecolor](<assets/readme/studio.light-truecolor-2.svg>)
82
83 ![Showcase color — light truecolor](<assets/readme/studio.light-truecolor-3.svg>)
84
85 ![Showcase life — light truecolor](<assets/readme/studio.light-truecolor-4.svg>)
86
87 ![Showcase narrow — light truecolor](<assets/readme/studio.light-truecolor-5.svg>)
88
89 </details>
90
91 <details>
92 <summary>Watch the animation</summary>
93
94 ![Native work, approval and completion](<assets/readme/showcase.gif>)
95
96 ![The same native layout in WhaleLight](<assets/readme/showcase-light.gif>)
97
98 </details>
99
100 </details>
101
102 <a id="codewhale-terminal-views"></a>
103 <details>
104 <summary>Codewhale terminal views · 22 examples</summary>
105
106 Sessions, settings, pickers and work panels built from reusable native parts.
107
108 ![Instrument surface — dark truecolor](<assets/readme/native-views.dark-truecolor-1.svg>)
109
110 ![Session list — dark truecolor](<assets/readme/native-views.dark-truecolor-2.svg>)
111
112 ![View sessions — dark truecolor](<assets/readme/native-views.dark-truecolor-3.svg>)
113
114 ![View sessions narrow — dark truecolor](<assets/readme/native-views.dark-truecolor-4.svg>)
115
116 ![View sessions compact — dark truecolor](<assets/readme/native-views.dark-truecolor-5.svg>)
117
118 ![View sessions empty — dark truecolor](<assets/readme/native-views.dark-truecolor-6.svg>)
119
120 ![View settings — dark truecolor](<assets/readme/native-views.dark-truecolor-7.svg>)
121
122 ![View settings narrow — dark truecolor](<assets/readme/native-views.dark-truecolor-8.svg>)
123
124 ![View commands — dark truecolor](<assets/readme/native-views.dark-truecolor-9.svg>)
125
126 ![View models — dark truecolor](<assets/readme/native-views.dark-truecolor-10.svg>)
127
128 ![View models narrow — dark truecolor](<assets/readme/native-views.dark-truecolor-11.svg>)
129
130 ![View providers — dark truecolor](<assets/readme/native-views.dark-truecolor-12.svg>)
131
132 ![View theme — dark truecolor](<assets/readme/native-views.dark-truecolor-13.svg>)
133
134 ![View mode — dark truecolor](<assets/readme/native-views.dark-truecolor-14.svg>)
135
136 ![View status — dark truecolor](<assets/readme/native-views.dark-truecolor-15.svg>)
137
138 ![View file picker — dark truecolor](<assets/readme/native-views.dark-truecolor-16.svg>)
139
140 ![View fleet dock — dark truecolor](<assets/readme/native-views.dark-truecolor-17.svg>)
141
142 ![View jobs dock — dark truecolor](<assets/readme/native-views.dark-truecolor-18.svg>)
143
144 ![View files dock — dark truecolor](<assets/readme/native-views.dark-truecolor-19.svg>)
145
146 ![View context dock — dark truecolor](<assets/readme/native-views.dark-truecolor-20.svg>)
147
148 ![View git dock — dark truecolor](<assets/readme/native-views.dark-truecolor-21.svg>)
149
150 ![View cost dock — dark truecolor](<assets/readme/native-views.dark-truecolor-22.svg>)
151
152 <details>
153 <summary>Light appearance</summary>
154
155 ![Instrument surface — light truecolor](<assets/readme/native-views.light-truecolor-1.svg>)
156
157 ![Session list — light truecolor](<assets/readme/native-views.light-truecolor-2.svg>)
158
159 ![View sessions — light truecolor](<assets/readme/native-views.light-truecolor-3.svg>)
160
161 ![View sessions narrow — light truecolor](<assets/readme/native-views.light-truecolor-4.svg>)
162
163 ![View sessions compact — light truecolor](<assets/readme/native-views.light-truecolor-5.svg>)
164
165 ![View sessions empty — light truecolor](<assets/readme/native-views.light-truecolor-6.svg>)
166
167 ![View settings — light truecolor](<assets/readme/native-views.light-truecolor-7.svg>)
168
169 ![View settings narrow — light truecolor](<assets/readme/native-views.light-truecolor-8.svg>)
170
171 ![View commands — light truecolor](<assets/readme/native-views.light-truecolor-9.svg>)
172
173 ![View models — light truecolor](<assets/readme/native-views.light-truecolor-10.svg>)
174
175 ![View models narrow — light truecolor](<assets/readme/native-views.light-truecolor-11.svg>)
176
177 ![View providers — light truecolor](<assets/readme/native-views.light-truecolor-12.svg>)
178
179 ![View theme — light truecolor](<assets/readme/native-views.light-truecolor-13.svg>)
180
181 ![View mode — light truecolor](<assets/readme/native-views.light-truecolor-14.svg>)
182
183 ![View status — light truecolor](<assets/readme/native-views.light-truecolor-15.svg>)
184
185 ![View file picker — light truecolor](<assets/readme/native-views.light-truecolor-16.svg>)
186
187 ![View fleet dock — light truecolor](<assets/readme/native-views.light-truecolor-17.svg>)
188
189 ![View jobs dock — light truecolor](<assets/readme/native-views.light-truecolor-18.svg>)
190
191 ![View files dock — light truecolor](<assets/readme/native-views.light-truecolor-19.svg>)
192
193 ![View context dock — light truecolor](<assets/readme/native-views.light-truecolor-20.svg>)
194
195 ![View git dock — light truecolor](<assets/readme/native-views.light-truecolor-21.svg>)
196
197 ![View cost dock — light truecolor](<assets/readme/native-views.light-truecolor-22.svg>)
198
199 </details>
200
201 </details>
202
203 <a id="the-native-composer-and-footer"></a>
204 <details>
205 <summary>The native composer and footer · 22 examples</summary>
206
207 Composer geometry, permission and mode, workflow rows and model/context metrics.
208
209 ![Native composer rich selection, Native composer rich search, Native composer, Native composer narrow, Native composer quiet, Native composer target, Workflow progress live, Workflow progress settled, Workflow progress queued, Workflow progress narrow, Posture bar, Posture narrow, Posture context cap, Posture compact, Metrics line — dark truecolor](<assets/readme/native-chrome.dark-truecolor-1.svg>)
210
211 ![Metrics narrow, Metrics compact, Metrics startup, Workflow tree, Workflow tree selected, Workflow tree clipped, Workflow tree long — dark truecolor](<assets/readme/native-chrome.dark-truecolor-2.svg>)
212
213 <details>
214 <summary>Light appearance</summary>
215
216 ![Native composer rich selection, Native composer rich search, Native composer, Native composer narrow, Native composer quiet, Native composer target, Workflow progress live, Workflow progress settled, Workflow progress queued, Workflow progress narrow, Posture bar, Posture narrow, Posture context cap, Posture compact, Metrics line — light truecolor](<assets/readme/native-chrome.light-truecolor-1.svg>)
217
218 ![Metrics narrow, Metrics compact, Metrics startup, Workflow tree, Workflow tree selected, Workflow tree clipped, Workflow tree long — light truecolor](<assets/readme/native-chrome.light-truecolor-2.svg>)
219
220 </details>
221
222 </details>
223
224 <a id="the-native-workbar"></a>
225 <details>
226 <summary>The native workbar · 12 examples</summary>
227
228 Tasks, Fleet, Jobs, Files, Notes, Context, Git and Cost; bottom, top and side placement.
229
230 ![Workbar tasks, Workbar fleet, Workbar jobs, Workbar files, Workbar notes, Workbar context, Workbar git, Workbar cost, Workbar top — dark truecolor](<assets/readme/workbar.dark-truecolor-1.svg>)
231
232 ![Workbar narrow, Workbar left, Workbar right — dark truecolor](<assets/readme/workbar.dark-truecolor-2.svg>)
233
234 <details>
235 <summary>Light appearance</summary>
236
237 ![Workbar tasks, Workbar fleet, Workbar jobs, Workbar files, Workbar notes, Workbar context, Workbar git, Workbar cost, Workbar top — light truecolor](<assets/readme/workbar.light-truecolor-1.svg>)
238
239 ![Workbar narrow, Workbar left, Workbar right — light truecolor](<assets/readme/workbar.light-truecolor-2.svg>)
240
241 </details>
242
243 </details>
244
245 ### Color and atmosphere
246
247 <a id="every-codewhale-tui-theme"></a>
248 <details>
249 <summary>Every Codewhale TUI theme · 16 examples</summary>
250
251 Sixteen source presets with their actual backgrounds, status, permission and mode inks.
252
253 ![Tui theme underwater, Tui theme underwater retro, Tui theme shoreline — dark truecolor](<assets/readme/tui-palettes.dark-truecolor-1.svg>)
254
255 ![Tui theme shoreline light, Tui theme whale, Tui theme whale light — dark truecolor](<assets/readme/tui-palettes.dark-truecolor-2.svg>)
256
257 ![Tui theme terminal, Tui theme grayscale, Tui theme catppuccin mocha — dark truecolor](<assets/readme/tui-palettes.dark-truecolor-3.svg>)
258
259 ![Tui theme tokyo night, Tui theme dracula, Tui theme gruvbox dark — dark truecolor](<assets/readme/tui-palettes.dark-truecolor-4.svg>)
260
261 ![Tui theme claude, Tui theme matrix, Tui theme solarized light — dark truecolor](<assets/readme/tui-palettes.dark-truecolor-5.svg>)
262
263 ![Tui theme uwu — dark truecolor](<assets/readme/tui-palettes.dark-truecolor-6.svg>)
264
265 <details>
266 <summary>Light appearance</summary>
267
268 ![Tui theme underwater, Tui theme underwater retro, Tui theme shoreline — light truecolor](<assets/readme/tui-palettes.light-truecolor-1.svg>)
269
270 ![Tui theme shoreline light, Tui theme whale, Tui theme whale light — light truecolor](<assets/readme/tui-palettes.light-truecolor-2.svg>)
271
272 ![Tui theme terminal, Tui theme grayscale, Tui theme catppuccin mocha — light truecolor](<assets/readme/tui-palettes.light-truecolor-3.svg>)
273
274 ![Tui theme tokyo night, Tui theme dracula, Tui theme gruvbox dark — light truecolor](<assets/readme/tui-palettes.light-truecolor-4.svg>)
275
276 ![Tui theme claude, Tui theme matrix, Tui theme solarized light — light truecolor](<assets/readme/tui-palettes.light-truecolor-5.svg>)
277
278 ![Tui theme uwu — light truecolor](<assets/readme/tui-palettes.light-truecolor-6.svg>)
279
280 </details>
281
282 </details>
283
284 <a id="codewhale-water-and-ombres"></a>
285 <details>
286 <summary>Codewhale water and ombres · 10 examples</summary>
287
288 The current TUI ocean, plus optional Lagoon, Dusk, Coral and Graphite treatments.
289
290 ![Atmosphere ocean — dark truecolor](<assets/readme/water.dark-truecolor-1.svg>)
291
292 ![Atmosphere lagoon — dark truecolor](<assets/readme/water.dark-truecolor-2.svg>)
293
294 ![Atmosphere dusk — dark truecolor](<assets/readme/water.dark-truecolor-3.svg>)
295
296 ![Atmosphere coral — dark truecolor](<assets/readme/water.dark-truecolor-4.svg>)
297
298 ![Atmosphere graphite — dark truecolor](<assets/readme/water.dark-truecolor-5.svg>)
299
300 ![Ocean column — dark truecolor](<assets/readme/water.dark-truecolor-6.svg>)
301
302 ![Ocean phases — dark truecolor](<assets/readme/water.dark-truecolor-7.svg>)
303
304 ![Ocean context — dark truecolor](<assets/readme/water.dark-truecolor-8.svg>)
305
306 ![Ocean reduced — dark truecolor](<assets/readme/water.dark-truecolor-9.svg>)
307
308 ![Ocean native guarded — dark truecolor](<assets/readme/water.dark-truecolor-10.svg>)
309
310 <details>
311 <summary>Light appearance</summary>
312
313 ![Atmosphere ocean — light truecolor](<assets/readme/water.light-truecolor-1.svg>)
314
315 ![Atmosphere lagoon — light truecolor](<assets/readme/water.light-truecolor-2.svg>)
316
317 ![Atmosphere dusk — light truecolor](<assets/readme/water.light-truecolor-3.svg>)
318
319 ![Atmosphere coral — light truecolor](<assets/readme/water.light-truecolor-4.svg>)
320
321 ![Atmosphere graphite — light truecolor](<assets/readme/water.light-truecolor-5.svg>)
322
323 ![Ocean column — light truecolor](<assets/readme/water.light-truecolor-6.svg>)
324
325 ![Ocean phases — light truecolor](<assets/readme/water.light-truecolor-7.svg>)
326
327 ![Ocean context — light truecolor](<assets/readme/water.light-truecolor-8.svg>)
328
329 ![Ocean reduced — light truecolor](<assets/readme/water.light-truecolor-9.svg>)
330
331 ![Ocean native guarded — light truecolor](<assets/readme/water.light-truecolor-10.svg>)
332
333 </details>
334
335 </details>
336
337 ### Inputs and controls
338
339 <a id="the-codewhale-language"></a>
340 <details>
341 <summary>The Codewhale language · 7 examples</summary>
342
343 Depth, rules, marks, hints and terminal chrome.
344
345 ![Keys at the point of use, State, in a mark and a word, Dialog, Sheet, One space, several depths, A single horizon, Control vocabulary — dark truecolor](<assets/readme/foundation.dark-truecolor.svg>)
346
347 <details>
348 <summary>Light appearance</summary>
349
350 ![Keys at the point of use, State, in a mark and a word, Dialog, Sheet, One space, several depths, A single horizon, Control vocabulary — light truecolor](<assets/readme/foundation.light-truecolor.svg>)
351
352 </details>
353
354 </details>
355
356 <a id="input-and-selection"></a>
357 <details>
358 <summary>Input and selection · 21 examples</summary>
359
360 Editable fields, forms, lists and focused choices.
361
362 ![Mode picker, Status picker, Picker query, Picker tabs preview, Picker no match, Text input empty, Text input typed, Text input unfocused, Text input invalid, Text input disabled, Text input secret, Text input long, Text input wide text — dark truecolor](<assets/readme/input.dark-truecolor-1.svg>)
363
364 ![Form, List, List scrolling, List tall rows, List long, List empty, Empty state, Empty state small — dark truecolor](<assets/readme/input.dark-truecolor-2.svg>)
365
366 <details>
367 <summary>Light appearance</summary>
368
369 ![Mode picker, Status picker, Picker query, Picker tabs preview, Picker no match, Text input empty, Text input typed, Text input unfocused, Text input invalid, Text input disabled, Text input secret, Text input long, Text input wide text — light truecolor](<assets/readme/input.light-truecolor-1.svg>)
370
371 ![Form, List, List scrolling, List tall rows, List long, List empty, Empty state, Empty state small — light truecolor](<assets/readme/input.light-truecolor-2.svg>)
372
373 </details>
374
375 </details>
376
377 <a id="navigation-and-controls"></a>
378 <details>
379 <summary>Navigation and controls · 7 examples</summary>
380
381 Headings, tabs, toggles and keyboard maps.
382
383 ![Keymap hints, Heading, Tabs, Toggle, Segmented, Setting row, Setting detail — dark truecolor](<assets/readme/chrome.dark-truecolor.svg>)
384
385 <details>
386 <summary>Light appearance</summary>
387
388 ![Keymap hints, Heading, Tabs, Toggle, Segmented, Setting row, Setting detail — light truecolor](<assets/readme/chrome.light-truecolor.svg>)
389
390 </details>
391
392 </details>
393
394 ### Conversation and work
395
396 <a id="conversation-and-queued-input"></a>
397 <details>
398 <summary>Conversation and queued input · 12 examples</summary>
399
400 Rich prose, code, attached context and the next instruction.
401
402 ![Pending queued, Pending steering, Pending paused, Pending context, Pending native mixed, Pending native queued, Transcript mounted, Transcript mounted focus, Transcript prose, Transcript list table, Transcript code, Transcript links — dark truecolor](<assets/readme/transcript.dark-truecolor.svg>)
403
404 <details>
405 <summary>Light appearance</summary>
406
407 ![Pending queued, Pending steering, Pending paused, Pending context, Pending native mixed, Pending native queued, Transcript mounted, Transcript mounted focus, Transcript prose, Transcript list table, Transcript code, Transcript links — light truecolor](<assets/readme/transcript.light-truecolor.svg>)
408
409 </details>
410
411 </details>
412
413 <a id="conversation-and-agents"></a>
414 <details>
415 <summary>Conversation and agents · 13 examples</summary>
416
417 Inline messages and optional tool, agent and fleet cards.
418
419 ![Workbench frame, Pane header, Context ribbon, Context ribbon narrow, Attention queue, Attention focused, Attention narrow, Attention empty, Message — dark truecolor](<assets/readme/components.dark-truecolor-1.svg>)
420
421 ![Composer, Tool card, Agent card, Fleet — dark truecolor](<assets/readme/components.dark-truecolor-2.svg>)
422
423 <details>
424 <summary>Light appearance</summary>
425
426 ![Workbench frame, Pane header, Context ribbon, Context ribbon narrow, Attention queue, Attention focused, Attention narrow, Attention empty, Message — light truecolor](<assets/readme/components.light-truecolor-1.svg>)
427
428 ![Composer, Tool card, Agent card, Fleet — light truecolor](<assets/readme/components.light-truecolor-2.svg>)
429
430 </details>
431
432 </details>
433
434 <a id="work-and-results"></a>
435 <details>
436 <summary>Work and results · 25 examples</summary>
437
438 Diffs, trees, progress, approvals and run results.
439
440 ![Artifact, Artifact shelf, Artifact narrow, Artifact unknown, Artifact empty, Receipt row, Receipt table, Receipt table compact, Receipt table minimal, Receipt table clipped — dark truecolor](<assets/readme/display.dark-truecolor-1.svg>)
441
442 ![Diff, Diff wrapped, Diff no numbers, Diff highlighted, Count bars — dark truecolor](<assets/readme/display.dark-truecolor-2.svg>)
443
444 ![Approval native band, Approval native band collapsed, Approval command, Approval outside, Approval patch — dark truecolor](<assets/readme/display.dark-truecolor-3.svg>)
445
446 ![Approval elevation, Approval clipped, Approval spoofed, Review verdicts, Review aggregate — dark truecolor](<assets/readme/display.dark-truecolor-4.svg>)
447
448 <details>
449 <summary>Light appearance</summary>
450
451 ![Artifact, Artifact shelf, Artifact narrow, Artifact unknown, Artifact empty, Receipt row, Receipt table, Receipt table compact, Receipt table minimal, Receipt table clipped — light truecolor](<assets/readme/display.light-truecolor-1.svg>)
452
453 ![Diff, Diff wrapped, Diff no numbers, Diff highlighted, Count bars — light truecolor](<assets/readme/display.light-truecolor-2.svg>)
454
455 ![Approval native band, Approval native band collapsed, Approval command, Approval outside, Approval patch — light truecolor](<assets/readme/display.light-truecolor-3.svg>)
456
457 ![Approval elevation, Approval clipped, Approval spoofed, Review verdicts, Review aggregate — light truecolor](<assets/readme/display.light-truecolor-4.svg>)
458
459 </details>
460
461 </details>
462
463 <a id="optional-workspace-compositions"></a>
464 <details>
465 <summary>Optional workspace compositions · 5 examples</summary>
466
467 Desktop-inspired conversation, review and fleet layouts you can compose from the library.
468
469 ![The everyday workspace — dark truecolor](<assets/readme/scenes.dark-truecolor-1.svg>)
470
471 ![Review in context — dark truecolor](<assets/readme/scenes.dark-truecolor-2.svg>)
472
473 ![Parallel work in view — dark truecolor](<assets/readme/scenes.dark-truecolor-3.svg>)
474
475 ![The workspace in a narrow terminal — dark truecolor](<assets/readme/scenes.dark-truecolor-4.svg>)
476
477 ![A living marine workspace — dark truecolor](<assets/readme/scenes.dark-truecolor-5.svg>)
478
479 <details>
480 <summary>Light appearance</summary>
481
482 ![The everyday workspace — light truecolor](<assets/readme/scenes.light-truecolor-1.svg>)
483
484 ![Review in context — light truecolor](<assets/readme/scenes.light-truecolor-2.svg>)
485
486 ![Parallel work in view — light truecolor](<assets/readme/scenes.light-truecolor-3.svg>)
487
488 ![The workspace in a narrow terminal — light truecolor](<assets/readme/scenes.light-truecolor-4.svg>)
489
490 ![A living marine workspace — light truecolor](<assets/readme/scenes.light-truecolor-5.svg>)
491
492 </details>
493
494 </details>
495
496 ### Motion and marine life
497
498 <a id="motion-and-feedback"></a>
499 <details>
500 <summary>Motion and feedback · 13 examples</summary>
501
502 Spinners, notifications and calm transitions.
503
504 ![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 — dark truecolor](<assets/readme/motion.dark-truecolor.svg>)
505
506 <details>
507 <summary>Light appearance</summary>
508
509 ![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 — light truecolor](<assets/readme/motion.light-truecolor.svg>)
510
511 </details>
512
513 <details>
514 <summary>Watch the animation</summary>
515
516 ![Working and verification spinners — Ocean](<assets/readme/motion-demo.gif>)
517
518 ![Working and verification spinners — Paper](<assets/readme/motion-demo-light.gif>)
519
520 </details>
521
522 </details>
523
524 <a id="life-in-the-water"></a>
525 <details>
526 <summary>Life in the water · 5 examples</summary>
527
528 Fish, jellyfish and bubbles, drawn in terminal cells.
529
530 ![Fish school, Jellyfish, Bubble field, Habitat ASCII, Habitat reduced — dark truecolor](<assets/readme/habitat.dark-truecolor.svg>)
531
532 <details>
533 <summary>Light appearance</summary>
534
535 ![Fish school, Jellyfish, Bubble field, Habitat ASCII, Habitat reduced — light truecolor](<assets/readme/habitat.light-truecolor.svg>)
536
537 </details>
538
539 <details>
540 <summary>Watch the animation</summary>
541
542 ![Native fish, jellyfish and bubbles](<assets/readme/habitat-motion.gif>)
543
544 </details>
545
546 </details>
547
548 <a id="a-whale-with-a-job"></a>
549 <details>
550 <summary>A whale with a job · 8 examples</summary>
551
552 Session state, attention, completion and the pod.
553
554 ![Whale rest, Whale busy, Whale needs, Whale done, Whale pod 1, Whale pod 3, Whale compact, Whale words only — dark truecolor](<assets/readme/whales.dark-truecolor.svg>)
555
556 <details>
557 <summary>Light appearance</summary>
558
559 ![Whale rest, Whale busy, Whale needs, Whale done, Whale pod 1, Whale pod 3, Whale compact, Whale words only — light truecolor](<assets/readme/whales.light-truecolor.svg>)
560
561 </details>
562
563 </details>
564
565 <a id="every-whale-action"></a>
566 <details>
567 <summary>Every whale action · 1 example</summary>
568
569 The complete v2 state vocabulary, in terminal cells.
570
571 ![Whale actions — dark truecolor](<assets/readme/whale-actions.dark-truecolor.svg>)
572
573 <details>
574 <summary>Light appearance</summary>
575
576 ![Whale actions — light truecolor](<assets/readme/whale-actions.light-truecolor.svg>)
577
578 </details>
579
580 <details>
581 <summary>Watch the animation</summary>
582
583 ![All seventeen native whale actions](<assets/readme/whale-performance.gif>)
584
585 </details>
586
587 </details>
588
589 <a id="terminal-profiles"></a>
590 <details>
591 <summary>All nine terminal profiles</summary>
592
593 ![The same status marks in all nine terminal profiles](<assets/readme/profile-comparison.svg>)
594
595 </details>
596
597 <!-- gallery:end -->
598
599 ## Build with the kit
600
601 <details>
602 <summary>Composition, editing and stateful widgets</summary>
603
604 ```rust
605 use codewhale_ratatui::{
606 Depth, KeyHint, KeyHints, Paint, Panel, Picker, PickerItem, PickerState, Theme,
607 };
608
609 // Once, after enabling raw mode, if the host does not already detect it:
610 codewhale_ratatui::detect::probe_terminal_background();
611 let theme = Theme::detect().tui();
612
613 // In your draw callback, with a Ratatui area and buffer:
614 let hints = KeyHints::new(vec![
615 KeyHint::new("↑↓", "move"),
616 KeyHint::new("Enter", "select"),
617 KeyHint::new("Esc", "cancel"),
618 ]);
619 let inner = Panel::new(Depth::Overlay)
620 .title("Mode")
621 .hints(&hints)
622 .draw(area, buf, &theme);
623 let items = [PickerItem::new("Work").key('1'), PickerItem::new("Plan").key('2')];
624 Picker::new(&items, PickerState::new(0)).paint(inner, buf, &theme);
625 ```
626
627 Every `Paint` component also becomes a Ratatui widget with `.themed(&theme)`:
628
629 ```rust
630 use codewhale_ratatui::{NativeComposer, Paint, Theme};
631 let theme = Theme::detect().tui();
632 let composer = NativeComposer::new("Review the changes")
633 .target("my-project / main");
634 frame.render_widget(composer.themed(&theme), frame.area());
635 ```
636
637 Keep a widget and render it by reference across frames:
638
639 ```rust
640 let widget = composer.themed(&theme);
641 frame.render_widget(&widget, frame.area());
642 ```
643
644 For a collection of different components, use `Themed::new(&dyn Paint, &theme)`.
645 The library enables no Ratatui terminal backend; your application selects its
646 backend. The [standalone consumer](tests/consumer/src/main.rs) demonstrates
647 this with `TestBackend`. The [starter app](examples/starter.rs) shows native
648 composition, Unicode editing, bracketed paste and terminal cleanup.
649
650 Lists and pickers also support `frame.render_stateful_widget`: keep a
651 `ListState` or `PickerState` in your app and pass the themed widget with that
652 state. Rendering stores the scroll offset for the actual viewport, including
653 query rows, tabs and clipping.
654
655 ```rust
656 use codewhale_ratatui::{List, ListState, Paint};
657 // Keep `state` in your app between frames.
658 let rows = ["First session", "Second session"];
659 let list = List::new(&rows, ListState::default());
660 frame.render_stateful_widget(list.themed(&theme), frame.area(), &mut state);
661 ```
662
663 Input states return outcomes for your app to act on. Typing and navigation
664 can repeat while a key is held; submit, choose, toggle and cancel require an
665 initial press. Modified navigation and activation shortcuts stay with your app.
666
667 Compose the native conversation layout:
668
669 ```rust
670 use codewhale_ratatui::{
671 Message, NativeComposer, Paint, PostureBar, TerminalShell,
672 Workbar, WorkbarPanel, WorkbarRow,
673 };
674
675 let composer = NativeComposer::new("Review the changes").focused(true);
676 let workbar = Workbar::new(WorkbarPanel::Tasks, vec![
677 WorkbarRow::new("task:review", "Review the changes").mark("●"),
678 ]);
679 let shell = TerminalShell::new(composer.desired_height(area.width, area.height))
680 .workbar_rows(workbar.height(area.width, &theme));
681 shell.paint(area, buf, &theme);
682 let regions = shell.areas(area);
683 Message::native("The changes are ready for review.").paint(regions.conversation, buf, &theme);
684 composer.paint(regions.composer, buf, &theme);
685 PostureBar::new("ask").paint(regions.posture, buf, &theme);
686 workbar.paint(regions.workbar, buf, &theme);
687 ```
688
689 Choose a native background and keep the same components:
690
691 ```rust
692 use codewhale_ratatui::{Theme, TuiPalette};
693 let theme = Theme::detect().tui_palette(TuiPalette::TokyoNight);
694 ```
695
696 `Theme::tui()` chooses Underwater for a dark terminal and WhaleLight for a
697 light terminal. `Whale` and `WhaleLight` preserve the terminal-owned shell
698 backgrounds from the TUI. `Theme::new` also supports the existing desktop
699 role-token theme; `Ombre` offers additional spatial treatments. Native view
700 recipes are in [src/gallery/native_views.rs](src/gallery/native_views.rs).
701
702 For open water, paint foreground content first, then call `Habitat::paint`.
703 It protects occupied cells and their clearance; the entire jellyfish is
704 withheld when its silhouette cannot fit. Pass decision and overlay rectangles
705 to `Habitat::protected` so their blank space stays protected too. Keep a
706 dedicated habitat viewport separate from any decision overlay. The habitat
707 never requests a frame itself. Selection and pointer helpers use the same clipped
708 viewport passed to painting.
709
710 The whale's ordinary `Paint` implementation shows its current poster pose.
711 For animation, pass the packed `whale::Grid` evaluated by your existing
712 owner to `Whale::paint_frame(area, buf, &theme, &grid)`. The widget paints that
713 exact frame and its state words; it owns no Director or clock. The whole
714 frame must fit, with a row for the label. Invalid, narrow or ASCII frames
715 fall back to words. Repaint the underlying surface first because empty
716 cells in the frame are transparent. For the native animated performance, use `whale_motion::Stage` and
717 `colored_braille`; the [showcase host](examples/showcase.rs) demonstrates the
718 shared clock and motion policy.
719
720 The [gallery fixtures](src/gallery/) are runnable usage examples for every
721 family. [Component contribution instructions](CONTRIBUTING-COMPONENTS.md)
722 explain the rendering and ownership contracts.
723
724 ## Choose a terminal profile
725
726 - **Truecolor:** native TUI presets retain exact source inks and grounds.
727 `Theme::tui()` selects the native default; desktop role-token mode is also available.
728 - **256 colors:** native preset RGBs use the nearest fixed-cube index. Desktop
729 role-token mode uses its contrast-audited table.
730 - **16 colors or unknown ground:** named terminal colors and visible marks/edges;
731 the terminal owns the background.
732 - **`NO_COLOR`:** words, weight and marks carry every state.
733 - **`CODEWHALE_ASCII_SAFE=1`:** component chrome uses ASCII glyphs; user-authored
734 Unicode remains text supplied by the host.
735
736 Set `CODEWHALE_APPEARANCE=light` or `dark` if the ground cannot be measured.
737 A host with its own detection can pass `Theme::new(Caps { depth, ascii,
738 appearance })` and avoid a second probe. Changes to a theme reach components
739 on their next paint; components hold roles rather than cached colors.
740
741
742 </details>
743
744 <details>
745 <summary>Full component reference</summary>
746
747 ## Component catalogue
748
749 | Family | Components | What they do |
750 |---|---|---|
751 | Optional workspace composition | `WorkspaceFrame`, `WorkspaceAreas`, `PaneHeader`, `ContextRibbon`, `ContextItem` | Responsive conversation and dock regions, one quiet module header, composer-adjacent facts folded by priority with explicit counts |
752 | Native shell | `TerminalShell`, `ShellAreas` | Current conversation → pending input → composer → posture → workflows → metrics → workbar ordering |
753 | Native workbar | `Workbar`, `WorkbarPanel`, `WorkbarRow`, `WorkbarState`, `WorkbarLayout`, `WorkbarScrollbar`, `DockTabRow`, `DockTabPlan`, `DockTabStyles`, `DockTabTarget` | All eight panels, goals, row selection, keyboard outcomes, scrolling, hitboxes and bottom/top/side placement |
754 | Native composer and workflow rows | `NativeComposer`, `WorkflowProgress`, `WorkflowRun` | Rounded input enclosure, prompt, submit control, target chip and borderless workflow progress |
755 | Native footer | `PostureBar`, `MetricsLine`, `MetricSegment` | Permission and mode, clocks, live counts, context warnings and width-aware model/usage facts |
756 | Native views | `InstrumentSurface`, `SessionList`, `SessionRow` | TUI title/action rails, quiet gutters, session selection, ranges, search and rename presentation |
757 | TUI themes | `TuiPalette`, `TuiInk` | All 16 fixed source palettes, exact grounds and distinct native permission/mode/status inks |
758 | Attention and results | `AttentionQueue`, `AttentionItem`, `ArtifactShelf`, `Artifact` | Project-aware decisions, selected action hints, review/file/run/link results and reported receipts |
759 | Marine life | `Habitat`, `FishSchool`, `Jellyfish`, `BubbleField`, `HabitatDensity` | Native braille poses and ASCII silhouettes, caller-clock motion, bounded populations, complete visitors and text-safe open-water collision |
760 | Water and palette | `OceanColumn`, `OceanRamp`, `OceanPhase`, `OceanPaintFacts`, `OceanCausticFacts`, `OceanContrastInks`, `ocean_semantic_surfaces`, `Ombre`, `WaterPalette` | Native TUI depth column, context rise, steady attention tint, completion breath and five spatial materials; contrast and fallback guards |
761 | Living whale | `whale_motion::Stage`, `Director`, `ColoredGrid` | One session performance, authored clips and springs, native colored props, shared terminal cadence and hide/resume boundaries |
762 | Session surfaces | `Message`, `ToolCard`, `Composer`, `AgentCard`, `Fleet` | Speaker anchors, output rails, honest omission counts, caller-owned prompts and each agent's own state, route and task |
763 | Pending input | `PendingInputPreview`, `PendingInputItem`, `ContextPreviewItem`, `PendingCard` | Queued, steering, editing, paused and in-flight input; native composer preview over localized caller facts; context and host-dispatched actions |
764 | Rich transcript | `Transcript`, `TranscriptBlock`, `TranscriptSpan`, `CodeBlock` | Authored headings, prose, quotes, lists, tables and numbered code; exact copy source and out-of-band links |
765 | Identity and state | `BrailleFrame`, `Whale`, `WhaleState`, `Icon`, `StatusMark`, `StateWords` | The v2 whale's 17 actions and pods; marks always paired with words; localized state labels |
766 | Surfaces | `Panel`, `Depth`, `Dialog`, `Sheet`, `HorizonRule` | Deep, stage, raised and overlay grounds; centered decisions, edge-anchored sheets and the composer ledge |
767 | Navigation | `Heading`, `Tabs`, `KeyHints`, `Keymap`, `Picker`, `List` | Shared heading hierarchy, selection, scrolling, keyboard labels and caller-owned outcomes |
768 | Input and controls | `TextInput`, `Form`, `Toggle`, `Segmented` | Unicode-aware editing, masked fields, validation and controls that explain disabled state |
769 | Search and empty states | `PickerQuery`, `PickerTabs`, `PickerMatches`, fuzzy matching helpers, `EmptyState` | Ranked choices, search highlights, tabs, previews and a clear next action when there are no results |
770 | Work and results | `Receipt`, `ReceiptTable`, `Diff`, `WorkflowTree`, `CountBar` | Measured values, explicit unknowns, numbered additions/removals, workflow hierarchy and progress from known totals |
771 | Decisions | `ApprovalCard`, `DecisionBand`, `ReviewVerdict`, `ReviewAggregate` | What will happen, where, why, and the caller's available next actions |
772 | Settings | `SettingRow`, `SettingDetail` | Value, source, lock reason, changed state, apply timing and reset details |
773 | Feedback and motion | `Toasts`, `Spinner`, `VerificationSpinner`, `MotionStep`, `MotionSet`, `FrameBudget` | Working swell, verification tick, notices, measured elapsed time, bounded transitions and reduced/still motion |
774
775 Words and data arrive from the caller, with English defaults where useful.
776 The kit does not calculate a diff, parse Markdown, validate credentials,
777 authorize a command, estimate cost or run an agent.
778
779 `OceanColumn` is adapted from the current TUI's three native stops:
780 `#102A45` → `#0A1E33` → `#061320`. Apply it after painting a scene to share
781 one continuous column behind ordinary grounds. Give it the full shell with
782 `.viewport(area)`, then use `.apply_matching(composer_area, buffer, theme, composer_ground)`
783 for a composer with its own base fill. The native [starter example](examples/starter.rs)
784 shows this complete composition. Selections, elevated panels,
785 diffs and code retain their backgrounds. The host supplies phase, elapsed time
786 and measured context; quiet policies stop breathing. The dark field is
787 opt-in on measured truecolor Ocean; light and limited-color terminals retain
788 their selected grounds.
789
790 `Ombre` finishes a painted scene with a spatial palette wash. It preserves
791 state ink and readable contrast, and leaves unsupported profiles unchanged.
792 The native TUI column is the studio default; the logo Ocean wash is also
793 available alongside Lagoon, Dusk, Coral and Graphite.
794
795
796 </details>
797
798 <details>
799 <summary>Animation, reduced motion and the host clock</summary>
800
801 ## Spinners and animation
802
803 `Spinner` uses Codewhale's eight-frame swell; `VerificationSpinner` uses the
804 Engine's distinct round verification tick. Both wait 400 ms before moving,
805 advance at five steps per second, and keep the caller's work verb visible.
806 Reduced and still motion show a static mark plus words. ASCII terminals have
807 their own frames.
808
809 `MotionStep` and `MotionSet` handle token-timed state ink, selection movement
810 and detail reveal. The caller changes the state and supplies the instant;
811 the state words change immediately. `FrameBudget` combines redraw deadlines
812 and lets the host claim one primary spinner per frame. Once transitions
813 settle, the host can wait for input instead of painting identical frames.
814
815 The animated demonstrations are under [Motion and feedback](#motion-and-feedback).
816 The normal gallery samples fixed instants; `cargo run --example motion` is
817 the live example.
818
819 The native whale performance lives in `whale_motion`. A host keeps one `Stage`
820 per foreground session, reports explicit owner inputs, and advances it on its
821 own clock. `Tier::Terminal` caps active paints at six per second and rest at
822 two. Reduced motion uses authored posters; hiding and resuming discard missed
823 motion. `colored_braille` adds native body and prop inks to the exact packed
824 geometry. It uses majority visible ink per Braille cell because terminals
825 provide one foreground per cell. The [source and fixtures](assets/whale-motion/PROVENANCE.md)
826 pin the native implementation and its conformance oracle.
827
828
829 </details>
830
831 [Contribution guide](CONTRIBUTING-COMPONENTS.md) · [Changelog](CHANGELOG.md)
832
833 <details>
834 <summary>Maintainer notes: render previews, verify and update source assets</summary>
835
836 ## Browse and regenerate
837
838 ```sh
839 cargo run --example starter # small native application
840 cargo run --example gallery # interactive catalogue
841 cargo run --example showcase # the full terminal studio
842 cargo run --example habitat # live fish, jellyfish, bubbles
843 cargo run --example motion # working, verification and transitions
844 cargo run --example gallery -- --print dark-256 # ANSI preview to stdout
845 cargo run --example gallery -- --dump out/ # .ans and styled .txt, all profiles
846 cargo run --example gallery -- --svg target/readme-buffers
847 python3 tools/render-gallery.py target/readme-buffers assets/readme --readme README.md
848 python3 tools/render-gallery.py target/readme-buffers assets/readme --readme README.md --check
849 ```
850
851 The optional animation build needs Node, `sharp` and FFmpeg. Each animation
852 comes from deterministic actual-buffer frames, using one shared media builder:
853
854 ```sh
855 cargo run --locked --example habitat -- --frames target/habitat-frames
856 node tools/render-animation.cjs target/habitat-frames assets/readme/habitat-motion.gif
857 python3 tools/check-animation.py target/habitat-frames assets/readme/habitat-motion.gif
858 cargo run --locked --example motion -- --frames target/motion-frames
859 node tools/render-animation.cjs target/motion-frames assets/readme/motion-demo.gif
860 python3 tools/check-animation.py target/motion-frames assets/readme/motion-demo.gif
861 cargo run --locked --example motion -- --frames target/motion-light-frames --profile light-truecolor
862 node tools/render-animation.cjs target/motion-light-frames assets/readme/motion-demo-light.gif
863 python3 tools/check-animation.py target/motion-light-frames assets/readme/motion-demo-light.gif
864 cargo run --locked --example showcase -- --frames target/showcase-frames
865 node tools/render-animation.cjs target/showcase-frames assets/readme/showcase.gif
866 python3 tools/check-animation.py target/showcase-frames assets/readme/showcase.gif
867 cargo run --locked --example showcase -- --frames target/showcase-light-frames --profile light-truecolor
868 node tools/render-animation.cjs target/showcase-light-frames assets/readme/showcase-light.gif
869 python3 tools/check-animation.py target/showcase-light-frames assets/readme/showcase-light.gif
870 cargo run --locked --example showcase -- --frames target/whale-action-frames --section life
871 node tools/render-animation.cjs target/whale-action-frames assets/readme/whale-performance.gif
872 python3 tools/check-animation.py target/whale-action-frames assets/readme/whale-performance.gif
873 ```
874
875 CI verifies both the current frame hash and the GIF file hash; it needs no
876 raster tools. Static previews and the live terminal example use the normal
877 Rust/Python toolchain.
878
879 In the interactive gallery: `↑↓` or `j/k` selects a component, `p/P` switches
880 terminal profile, `w/W` switches width, `PgUp/PgDn` scrolls tall previews,
881 `Home/End` jumps through them, and `q` or `Esc` exits. This includes the full
882 17-action whale sheet on an ordinary-height terminal. `f` expands the canvas
883 for the composed workspace scenes. The habitat example uses `p` for profile,
884 `m` for motion and `q` to close.
885 In the motion example, `Space` finishes or restarts the demonstration, `v`
886 switches working/verification, `r` replays, `p` changes profile, and `m`
887 changes motion policy. `q` or `Esc` closes it.
888
889 In the studio, `F1`–`F6` choose the six sections. `F7` changes terminal profile,
890 `F8` motion policy, `F9` native TUI theme, and `F10` the example work phase.
891 The composer starts focused. `Enter` queues a follow-up while work is running;
892 `Esc` interrupts the illustrative turn and keeps the draft. `Shift+Tab` changes
893 permission. The decision accepts an explicit answer. Life uses `←→` to study
894 an action and `Space` to play all seventeen.
895 In Work, `Ctrl+X` opens Fleet, `Alt+W` focuses the workbar, and Left/Right
896 switches its panel while focused. `Esc` closes the dock. Color controls select
897 optional ombré washes separately from the native F9 theme.
898 Components supports search and tall-preview scrolling. `Ctrl+R` restarts the
899 demonstration; `q` or `Esc` closes outside editing.
900 `Ctrl+C` closes from any section or focus.
901
902 Profiles: `dark-truecolor`, `dark-graphite`, `light-truecolor`, `dark-256`,
903 `light-256`, `ansi-16`, `unknown-ground`, `no-color`, `ascii`.
904
905 ## Verify it
906
907 ```sh
908 cargo fmt --check
909 cargo clippy --all-targets --locked -- -D warnings
910 cargo test --locked
911 cargo test --example gallery --locked
912 cargo run --locked --manifest-path tests/consumer/Cargo.toml
913 RUSTDOCFLAGS=-Dwarnings cargo doc --locked --no-deps
914 python3 vendor/codewhale-design/generate.py --check
915 ```
916
917 Run `cargo bench --bench render` for the prepared-widget and native-view
918 measurements described in [BENCHMARKS.md](BENCHMARKS.md).
919
920 Snapshots record the role each run uses, alongside its glyphs. Tests exercise
921 profiles and widths, Unicode input, missing data, clipped output and disabled
922 controls. The generated README boards can be checked separately with the
923 command above. GitHub CI qualifies the branch; a local pass proves local
924 behavior only.
925
926 ## Update source palettes and design assets
927
928 The native TUI palette export retains the source's backgrounds, permission,
929 mode and status slots. With a current Codewhale checkout:
930
931 ```sh
932 python3 tools/export-tui-palettes.py ../codewhale
933 python3 tools/export-tui-palettes.py ../codewhale --check
934 ```
935
936 Tokens are vendored from the private `codewhale-design` source. Maintainers
937 with that checkout can sync and regenerate:
938
939 ```sh
940 ../codewhale-design/scripts/sync-to.sh .
941 CODEWHALE_BLESS=1 cargo test --test generated
942 ```
943
944 `src/roles.rs` is generated from the tokens, including terminal-derived hint,
945 dim and diff-tint roles. Contrast tests cover truecolor and quantized colors.
946
947 `assets/whale-v2.scenes` holds contours exported from the v2 whale kit. To
948 update or check them with that source available:
949
950 ```sh
951 node tools/export-whale.cjs <path-to-whale-character-v2>
952 node tools/export-whale.cjs <path-to-whale-character-v2> --check
953 ```
954
955 `tests/whale.rs` checks all 17 actions against the kit's 32×16 and 20×10 stills,
956 dot for dot. Artwork shows up to three calves; the state label gives the true
957 agent count, including larger fleets. Compact or ASCII terminals keep the
958 state in words when the art cannot fit.
959
960
961 </details>
962
963 MIT · [License](LICENSE). Use as a Git dependency during development;
964 the crate has not been published to a package registry.
965
966 ### Native decision band
967
968 `DecisionBand` extends the approval components with a bottom-anchored native
969 band over caller-projected body, option and validated rule-coverage facts.
970 `plan(area)` returns the same body/control/save region, stable option-order
971 rectangles and save visibility that `render(area, buffer)` paints. A host keeps
972 its own decision handler and enables persistent-save keys only while the last
973 paint reports `save_shown`; no `ApprovalState` or second decision loop is needed.
974 The gallery's `approval-native-band` and collapsed companion use this real API.
975 The existing bordered `ApprovalCard` keeps its verbatim-subject and caller-key
976 contract. The band accepts host-projected display lines; it does not reparse
977 commands, infer policy or construct permission rules.
978
979 ### Mounted composer row plan
980
981 `NativeComposerFrame` projects host-owned scalar cursor/selection, localized
982 styled copy, completion/history menu facts and live styles through one pure
983 layout/paint/caret/viewport/pointer plan. Raw source positions retain hidden
984 characters; display content is guarded before width measurement and paint.
985 `NativeComposer` uses the same plan and keeps its existing grapheme cursor
986 API. The actual `native-composer-rich-selection` and `native-composer-rich-search` gallery
987 entries show both presentations. Editing, bindings, IME, completion filtering
988 and submit dispatch stay with the host.
989
990
991 ### Mounted transcript viewport
992
993 `TranscriptViewport` projects host-parsed styled rows through one clipped
994 content/chrome plan, retaining pinned rows, offsets, semantic styles and exact
995 scrollbar/jump geometry. `TranscriptViewportPlan::link_rects` returns only
996 visible cells and excludes opaque jump chrome; targets never enter kit data.
997 The measured selection helper accepts a host's existing terminal column grammar
998 without owning its parser, clipboard, streaming cache or selection state.
999 Staged content/chrome paint lets a host retain semantic Ocean finishing between
1000 them. The actual `transcript-mounted` and `transcript-mounted-focus` gallery
1001 entries use this API. Existing authored `Transcript`/`TranscriptBlock` remain
1002 the structured content option; this viewport does not reparse native rows.
1003
1004
1005 `ocean::OceanPaintFacts` carries cached absolute-row colors and protected
1006 semantic rectangles into `OceanColumn::apply_native`; its ink callback returns
1007 the exact color the host backend would show over the proposed water without
1008 changing source cells. `OceanContrastInks` maps the same decorative/supporting
1009 contrast floors to actual live palette colors. `ocean_semantic_surfaces`
1010 projects display-safe prewrapped styled rows using the host's column grammar;
1011 `TranscriptViewportPlan::display_rows()` supplies its exact pinned/offset rows;
1012 explicit backgrounds remain semantic even if their RGB equals a pane base.
1013 `apply_caustics` finishes only already painted ordinary water, shares capability
1014 and reduced-motion gates, and spares visible symbols, reversed cells and
1015 semantic padding. Both methods retain the existing measured dark truecolor
1016 Ocean gate; facts and an explicit ramp do not grant terminal capability. The
1017 `ocean-native-guarded` gallery entry exercises cached water, caustics, selected
1018 source, blank semantic padding and reverse protection across all profiles.
1019
1020 ### Host-owned Dock tabs and character frames
1021
1022 `DockTabRow` is the tab row used by `Workbar` and the native Engine Dock
1023 adapter. Give it the caller's available `WorkbarTab` facts, active panel,
1024 pressed/hovered targets, five live `DockTabStyles` and the close text that matches
1025 your actual action. `row.plan(area).hitboxes()` and `(&row).render(area, buf)` use
1026 the same fitting rules. The host owns focus, Esc handling and action dispatch.
1027 The Engine's full Dock body remains separate from this tab presentation slice.
1028
1029 For a small companion or an externally simulated frame with a raw caption:
1030
1031 ```rust
1032 use codewhale_ratatui::BrailleFrame;
1033 use ratatui::{style::Style, widgets::Widget};
1034
1035 // Row-major packed cells from your existing simulation; zero is transparent.
1036 BrailleFrame { cells: &cells, caption: "resting", style: Style::default() }
1037 .render(area, buf);
1038 ```
1039
1040 The last viewport row holds the centered caption. Tiny viewports keep the
1041 complete wrapped text cue. Ink and modifiers are supplied by the caller; the
1042 component has no clock or activity model. The Engine cameo and live embedded
1043 world both use this path. `Whale::paint_frame` shares its cell painter and keeps
1044 its own semantic caption, admission rules and theme gradient. This API does not
1045 replace the Engine's character controller or accessibility policy.
1046
1047 The guarded Ocean gallery uses `OceanPaintFacts`, `OceanCausticFacts` and
1048 `ocean_semantic_surfaces`; `OceanContrastInks` supplies host role mapping for
1049 native finishing through the existing guarded
1050 `OceanColumn` methods. Their facts preserve host protection and ink roles;
1051 terminal capability, motion and semantic contrast guards still apply.
1052
1053 `WorkbarLayout::for_body` fits the already-admitted body viewport from current
1054 row counts and header facts. `WorkbarScrollbar` paints its rail using the same
1055 current offset/counts and caller-supplied symbols/styles. Both Workbar and the
1056 Engine body use these calculations. No remembered selection, focus or scrolling
1057 state lives in the kit; native row composition and action receipts stay with
1058 the host.
1059
1059 lines MARKDOWN