Appearance
UI Components and Storybook
Chat + Reasoning
AiConversation+AiMessagerender chat roles (user/assistant/tool/source) with optional thinking blocks.AiThinkingrenders a collapsible “Thinking…” section; passstatus="thinking" | "complete",durationLabel, andcontent(markdown rendered viaAiMarkdown).- Keep chat wrappers thin:
AiChatprovides a scroll container; inputs are kept separate.
Grapheme-Aware Typing (Tapia)
useGraphemes(value: string)splits text into grapheme clusters usingIntl.Segmenter(fallback toArray.from).CharDisplayis a dumb renderer that expectsshouldGraphemesandisGraphemes. It aligns glyphs (including emojis) and shows mismatches with an elevated correct glyph.
Desktop Layout
DesktopShellis a full-screen wrapper with optional left/right sidebars, header/footer slots, and overlay layer.- Sidebars are resizable via
re-resizable; passinitialLeftWidth/initialRightWidthandonLeftResizeStop/onRightResizeStopto persist widths (seePersistentWidthsstory). - The main column enforces
overflow-autowithmax-h-full, so long content scrolls while sidebars stay fixed. - Header is a render-prop: receives
toggleLeft,toggleRight, and open state so apps can control toggles (e.g., menu/info buttons).
Window drag regions (Electron)
- Electron (
desktop/soma): usedata-drag-region+ CSS-webkit-app-region: drag(seedesktop/soma/src/renderer/src/styles/app.scss). Mark interactive elements withdata-no-drag.
Storybook
- Components live in the
@soma/uipackage (desktop/desktp-ui). Stories are undersrc/stories. - Build locally:
pnpm --filter @soma/ui run storybook(dev) orpnpm --filter @soma/ui run build:storybook. - Docs pipeline:
just build-docsnow also builds Storybook intosite/storybookafter MkDocs runs.