Chat primitives
Inline event notice with information, success or warning tone and an optional action slot.
Requires React 19, ReactDOM 19, TypeScript and lucide-react 1.14.0. Import frame.css once and use a frame-root wrapper; set its background to var(--color-bg-page) and color to var(--color-text-primary), or supply a matching host surface; add dark to an ancestor for dark mode.
Tested with shadcn 4.21.0, React 19.2.5, Vite 8.0.10 and Tailwind 3.4.19 / 4.3.3. Start with a configured React/Vite shadcn app. Files install into src/components/frame; import its frame.css. For manual copy, save the complete component and stylesheet below. Examples leave optional voice features off; retain the MIT license and third-party notices.
Required stylesheet: frame.cssnpx shadcn@4.21.0 add https://raw.githubusercontent.com/BeibeiZhang/frame-design-system/main/registry/message-card.json
Inline card-style message for meta-events in a chat stream — distinct from a regular ChatMessage bubble. Three tones: info / success / warning.
Heads up
Branch merged
Conflict detected
Extension details (1 fork)
- WorkPal fork:
apps/workpal/src/components/MessageCard.tsx
User and assistant message presentation with a visual streaming state.
Requires React 19, ReactDOM 19, TypeScript and lucide-react 1.14.0. Import frame.css once and use a frame-root wrapper; set its background to var(--color-bg-page) and color to var(--color-text-primary), or supply a matching host surface; add dark to an ancestor for dark mode.
Tested with shadcn 4.21.0, React 19.2.5, Vite 8.0.10 and Tailwind 3.4.19 / 4.3.3. Start with a configured React/Vite shadcn app. Files install into src/components/frame; import its frame.css. For manual copy, save the complete component and stylesheet below. Examples leave optional voice features off; retain the MIT license and third-party notices.
Required stylesheet: frame.cssnpx shadcn@4.21.0 add https://raw.githubusercontent.com/BeibeiZhang/frame-design-system/main/registry/chat-message.json
Single chat bubble. role='user' (right, no avatar) or role='assistant' (left, default Sparkles avatar; showAvatar={false} renders none — WorkPal's configuration). Optional streaming dots.
Product extensions
Extension details (2 forks)
- Wingman fork:
apps/wingman/src/components/ChatMessage.tsx - WorkPal fork:
apps/workpal/src/components/ChatMessage.tsx
THE shared answer toolbar under an AI reply. Two abilities are built in — read-aloud (plays the whole answer, click again to stop) and copy (glyph flips to a check on success). Everything else — thumbs-up/down, retry, share — is optional and injected by the host through `actions`, laid out in the locked order: read-aloud · copy · injected. Used by the viewer's Ask-AI panel and WorkPal's chat. Read-aloud runs on the browser Web-Speech engine by default; a host can pass a `readAloud` transport (the viewer routes it to a server-side `/api/tts` so no key reaches the frontend).
Read-aloud + copy are built in; share / thumbs-up / thumbs-down / retry are optional actions the host wires up — shown here as no-op placeholders. Read-aloud uses the browser Web-Speech engine, so the demo makes no server call.
With a timestamp
Pass `timestamp` and the row shows when the message was sent — a relative time refreshed once a minute, full local time on hover. An AI answer puts it after the buttons; a user message puts it first (`timestampPosition="start"`) in a right-aligned row with Copy. Omit it and the row is unchanged.
Shared agent carousel, greeting, commit/cancel behavior, and collapsed return state. Products configure identity copy and optional capabilities; they do not fork the carousel.
The product-owned production strings “What should we work on?” and “Customize” stay in English. Viewer annotations and explicitly localized demo labels follow the selected language.
Prompt composer with callback-based sending, optional attachments and mentions. No model provider is included.
Requires React 19, ReactDOM 19, TypeScript and lucide-react 1.14.0. Import frame.css once and use a frame-root wrapper; set its background to var(--color-bg-page) and color to var(--color-text-primary), or supply a matching host surface; add dark to an ancestor for dark mode.
Tested with shadcn 4.21.0, React 19.2.5, Vite 8.0.10 and Tailwind 3.4.19 / 4.3.3. Start with a configured React/Vite shadcn app. Files install into src/components/frame; import its frame.css. For manual copy, save the complete component and stylesheet below. Examples leave optional voice features off; retain the MIT license and third-party notices.
Required stylesheet: frame.cssnpx shadcn@4.21.0 add https://raw.githubusercontent.com/BeibeiZhang/frame-design-system/main/registry/chat-input.json
Bottom composer — the brand-gradient pill **both Wingman and WorkPal render**, via a thin wrapper (`apps/{wingman,workpal}/src/components/ChatInput.tsx`) that opts into the features each call site needs through `features={{…}}`: attach, voice mode, voice input, action chips, @mentions, send overrides, and draft per-key. (A `features`-less baseline mode — controlled `value`/`onChange`, plain textarea — also exists for callers that just need a bare composer; no product uses it in V0.1.)
@ references and / commands
Default off. Pass an async mentions.source for @ (e.g. files) and features.commands for / at the start of the input. The master debounces, aborts stale requests and shows loading / empty states; the product owns the data and what a command does. Sample data below is a viewer demo, not a real product source. Use the sun/moon toggle to check dark mode.
Suggested reply
Optional suggestion prop. While the input is empty the predicted reply shows in grey as the placeholder; Tab (or → in the empty input) fills it, and a touch device gets a Use chip instead of the Tab hint. Tab keeps its normal focus behaviour with no suggestion or with text in the box. Wingman does not pass it.
useSuggestedReply
useSuggestedReply (@beibei/design-system/suggest) produces it: one request per finished turn you watched; the host supplies its messages and the request. Demo: a static suggestion.
Actual product configurations
Same master primitive, visibly different product choices. The profiles below are imported by the real wrappers and welcome call sites, so this comparison changes with the products instead of duplicating a Wingman or WorkPal specification in the viewer.
Both still share attachments (10 files, up to 2 MB each), voice transcription, per-chat drafts, AI-response gating, and the same responsive shell. Try @ in Wingman to open its product-only mention picker; WorkPal intentionally has no mention configuration.
Extension details (2 forks, 9 flag uses)
- Wingman fork:
apps/wingman/src/components/ChatInput.tsx - WorkPal fork:
apps/workpal/src/components/ChatInput.tsx - Wingman feature flag:
apps/wingman/src/components/ChatInput.tsx(actionChips + attach + draft + forceSendActive + isAiResponding + mentions + voice + voiceInput) - Wingman feature flag:
apps/wingman/src/components/chatInputMentionsCommands.test.tsx(commands + mentions) - Wingman feature flag:
apps/wingman/src/components/chatInputTooltipAria.test.tsx(attach + voice + voiceInput) - Wingman feature flag:
apps/wingman/src/pages/QuizChatPage.tsx(actionChips + draft) - Wingman feature flag:
apps/wingman/src/pages/SelfTestChatPage.tsx(actionChips + draft) - WorkPal feature flag:
apps/workpal/src/components/liveDictation.test.tsx(attach + voiceInput) - WorkPal feature flag:
apps/workpal/src/components/nestedOverlayPopovers.test.tsx(attach) - WorkPal feature flag:
apps/workpal/src/components/voiceComposerFuse.test.tsx(attach + voice + voiceInput) - WorkPal feature flag:
apps/workpal/src/components/voiceErrorFused.test.tsx(attach + voice + voiceInput)
One attached-file pill — 48×48 thumbnail or icon area + filename (truncates at `maxNameWidth`, default 160px) + size, on a `bg-bg-message` surface. Two optional affordances: `onRemove` (hover-revealed ×, used in the input pending strip) or `showDownload` (Download icon at the right edge, used in sent message bubbles paired with an `<a download>` wrapper). PR #54 unified the visual chrome — same chip across input + bubble.
Input strip — narrow, × on hover:
Sent in bubble — wider, Download icon:
Conversation layout with message and composer slots and near-bottom scrolling.
Requires React 19, ReactDOM 19, TypeScript and lucide-react 1.14.0. Import frame.css once and use a frame-root wrapper; set its background to var(--color-bg-page) and color to var(--color-text-primary), or supply a matching host surface; add dark to an ancestor for dark mode.
Tested with shadcn 4.21.0, React 19.2.5, Vite 8.0.10 and Tailwind 3.4.19 / 4.3.3. Start with a configured React/Vite shadcn app. Files install into src/components/frame; import its frame.css. For manual copy, save the complete component and stylesheet below. Examples leave optional voice features off; retain the MIT license and third-party notices.
Required stylesheet: frame.cssnpx shadcn@4.21.0 add https://raw.githubusercontent.com/BeibeiZhang/frame-design-system/main/registry/chat-panel.json
Container for a chat surface — optional toolbar + header (one frosted sticky layer the messages scroll beneath) + scrollable message list + pinned input. Auto-scrolls to bottom when content grows (unless user scrolled up).
Extension details (1 fork)
- WorkPal fork:
apps/workpal/src/components/ChatPanel.tsx