ui-bausteine
Gemeinsame UI-Bausteine in zid: Schaltflächen (components/button.zig), Icon-Schaltflächen mit Tooltip (tooltip.iconButton/attach, hover_delay), Scrollbalken (scrollbar.zig), Lucide-Icons als Kontur (s
SKILL.md.claude/skills/ui-bausteine/SKILL.md
GitHubUI-Bausteine
Scrollbalken, Tooltips, Kontextmenüs und Eingabezeilen gibt es je einmal (scrollbar.zig,
tooltip.zig, context_menu.zig, line_edit.zig). Vor einem neuen Bedienelement dort suchen
und das Modul verwenden oder erweitern, nie parallel nachbauen: eine Kopie bekommt Fixes nicht
mit (der I-Beam über dem waagrechten Balken kam so in der Markdown-Vorschau zurück, die einen
eigenen Balken hatte). Kontextmenü: Skill menues-kuerzel; Eingabezeilen: Skill editor.
Schaltflächen: components/button.zig
- Einheitliches Aussehen über
button(id, text, theme, mouse_x, mouse_y, mouse_pressed, opts)mit den Rollenprimary(Hauptaktion),secondary(Nebenaktion) undghost(unauffällig, Fläche erst beim Überfahren).disableddämpft und schluckt Klicks. - Der Treffer wird gegen die Box aus dem letzten Layout gerechnet, nicht über
clay.pointerOver: im Frame eines RPC-Klicks kennt Clay die neue Zeigerposition noch nicht, der Klick ginge verloren. - Wer eine Schaltfläche braucht, nimmt diese Komponente statt selbst zu zeichnen, sonst fehlen Hover und Rahmen.
- Eine Aktion ohne sichtbare Folge bestätigt sich per
UI.showToast.
Tooltips für Icon-Schaltflächen
src/ui/components/tooltip.zig:iconButton(arena, theme, id, icon_id, icon, label, opts)ist der gemeinsame Knopf (Hintergrund beim Überfahren,toggledin Primärfarbe),attach(theme, id, label)hängt einen Tooltip an ein selbst gezeichnetes Element. Tooltip erscheint nach 700 ms über demselben Element unter dem Element (hover_delay.Hover, Modulhover_delay, unit-getestet);beginFrame/endFramerahmenrenderExampleein. Zustand ist modulweit, der Text muss den Frame überleben (Literal oder Frame-Arena).- Neue Icon-Knöpfe immer über
tooltip.iconButtonanlegen. - Beschriftungen wie VS Code: Timeline (Pin the Current Timeline / Unpin …, Refresh), Graph (Refresh, Open Changes), Changes (Commit, Sync Changes / Publish Branch, Refresh, Open File, Stage/Unstage/Discard Changes, Stage/Unstage/Discard All Changes), Diff-Editor (Previous/Next Change, Toggle Collapse Unchanged Regions, Switch to Inline/Side by Side View), Multi-File-Diff (Collapse/Expand All Diffs), Ordner-Dialog (Parent Folder), Statusleiste (Current Git Branch, Toggle Autosave).
- Jedes Hover-Element, das nicht selbst klickbar ist, braucht
pointer_capture_mode = .passthrough(wietooltip.attach, Cursorstriche, Platzhalter), sonst fängt es den Klick auf das Element darunter ab (Explorer-Tooltipfx_tooltipüber der nächsten Zeile). - E2E:
ui_state.tooltip= Text des Tooltips im letzten Frame (null ohne), geprüft ine2e_scm_changes.pyunde2e_timeline.py(Maus 1 s über dem Knopf halten).
Scrollbalken: src/ui/scrollbar.zig
- Modul
scrollbar, eigenes Modul, weil code_editor.zig ein eigenes Test-Root ist. Clay hat keinen Balken, nur Clip-Container; die virtualisierten Ansichten scrollen über eigene Offsets. Model(Achse, Track, total, visible, offset, max_offset) →geometry,hitTest(Thumb greifen oder Seite blättern),dragOffset,render.- Editor senkrecht und waagrecht (
vscrollModel/hscrollModel,vscroll_drag/hscroll_drag). Die waagrechte Editor-Leiste misst die längste Zeile der ganzen Datei (maxLineWidth, gecacht, nach einem Edit nur der betroffene Bereich), damit sie beim senkrechten Scrollen stabil bleibt, und deckt auch den Gutter ab. E2E:step_hscrollbarinscripts/e2e_editor.py. - Explorer:
FileExplorerState.scrollModelin Pixeln, der Balken hängt an der Hüllefile_tree_areaund beginnt so unter der Filterzeile. E2Ee2e_explorer.step_scrollbar. - Terminal:
TerminalInstance.scrollModelin Zeilen, Track über die volle Höhe vonterminal_outer(Lage aus dem Vorframe). E2Escripts/e2e_terminal.py(RPCterminal_state:view_row,total_rows,visible_rows,pane_indexfürelement_bounds_i("terminal_scrollbar_track", pane_index)). - Markdown-Vorschau: Skill
markdown-preview. Bei jedem neuen Balken den Cursor-Test ergänzen (Pfeil über dem Balken,ui_state.cursor).
Lucide-Icons sind Strichpfade
svg.Svg füllt den Pfad (Explorer-Chevrons und Datei-Icons so gewollt); reine Linienpfade wie
plus, minus, check, Pfeile bleiben gefüllt aber unsichtbar, Bögen (undo_2,
refresh_cw) werden zu Klecksen. Dafür svg.SvgStroke (Strichbreite 2 auf viewbox 24,
SvgRenderInfo.stroke_width, Atlas-Key unterscheidet Füllung/Strich). tooltip.iconButton, die
SCM-Zeilenaktionen, der Commit-Knopf und die Graph-Kopfzeile zeichnen als Kontur. Der
Rasterizer schreibt im Strich-Modus den Alpha auch nach R, weil text_atlas.wgsl mit R maskiert.