diff --git a/design-system/README.md b/design-system/README.md index 28c5c651d0..884f5f503f 100644 --- a/design-system/README.md +++ b/design-system/README.md @@ -18,6 +18,27 @@ Design Lab exposes an Overview, a searchable component catalog with interactive `@bitfun/ui/registry` is the component source of truth. Design Lab derives its component navigation, counts, token scopes, and detail routes from that package export; adding Lab copy or a preview cannot publish a component or keep a removed component alive. +The same entry publishes `ChatComposer`, the shared context-band and +compact/expanded input anatomy used by product composers without importing +their stores, localized menus, editor, model, voice, or host actions. + +FlowChat tool-card frameworks are published from `@bitfun/ui/flow-chat` as +`AmbientToolCard` and `ProminentToolCard`. The names describe whether a tool +result should stay in the conversational background or receive deliberate user +attention. Concrete package views cover the reusable FlowChat families for file +and command execution, search and web results, agent and session activity, Git +and review summaries, page lifecycle, code execution, todos, images, and other +routine tool traces. Product adapters continue to own parsing, stores, +localization, host capabilities, and heavy renderers passed through semantic +slots; the package owns each migrated card's anatomy, state presentation, and +interaction structure. + +Design Lab exposes FlowChat as its own library category. Both framework and +tool-view entries come from `@bitfun/ui/registry`; its typed preview registry is +exhaustive over those package entries. The tool gallery renders only real +public views used by migrated adapters and lists bespoke product cards +separately instead of substituting generic previews for them. + ## Commands ```bash diff --git a/design-system/apps/design-lab/src/App.tsx b/design-system/apps/design-lab/src/App.tsx index 1ec3aa9d3c..f662ab53be 100644 --- a/design-system/apps/design-lab/src/App.tsx +++ b/design-system/apps/design-lab/src/App.tsx @@ -22,6 +22,7 @@ import { PanelTop, Search, Settings2, + SquareTerminal, Sun, ToggleLeft, X, @@ -71,6 +72,7 @@ type LabRoute = | { page: "overview" } | { page: "getting-started" } | { page: "components" } + | { page: "flow-chat" } | { page: "colors" } | { page: "resources" } | { page: "tokens" } @@ -85,12 +87,21 @@ interface SearchDestination { } const componentIcons: Record = { + AmbientToolCard: SquareTerminal, Button: MousePointerClick, Modal: AppWindow, + ProminentToolCard: SquareTerminal, Switch: ToggleLeft, TabGroup: PanelTop, }; +const flowChatComponents = componentRegistry.filter( + (component) => component.category === "flow-chat", +); +const standardComponents = componentRegistry.filter( + (component) => component.category !== "flow-chat", +); + function getThemeDataName( colorScheme: ColorScheme, contrast: ContrastMode, @@ -118,6 +129,9 @@ function parseRoute(hash: string): LabRoute { if (route === "components") { return { page: "components" }; } + if (route === "flow-chat") { + return { page: "flow-chat" }; + } if (route === "resources") { return { page: "resources" }; } @@ -201,6 +215,13 @@ export function App() { label: t("nav.components"), route: { page: "components" }, }, + { + detail: t("search.flowChatDetail", { count: flowChatComponents.length }), + icon: SquareTerminal, + keywords: `FlowChat tool cards ambient prominent ${t("nav.flowChat")}`, + label: t("nav.flowChat"), + route: { page: "flow-chat" }, + }, { detail: t("search.resourcesDetail"), icon: FileText, @@ -343,6 +364,10 @@ export function App() { const activeComponent = route.page === "component" ? componentRegistry.find((component) => component.name === route.componentName) : undefined; + const isFlowChatRoute = route.page === "flow-chat" + || activeComponent?.category === "flow-chat"; + const isStandardComponentRoute = route.page === "components" + || Boolean(activeComponent && activeComponent.category !== "flow-chat"); return (
{t("nav.library")} { event.preventDefault(); @@ -432,7 +457,7 @@ export function App() { {t("nav.components")}
- {componentRegistry.map((component) => { + {standardComponents.map((component) => { const Icon = componentIcons[component.name] ?? Blocks; const active = route.page === "component" && route.componentName === component.name; return ( @@ -451,6 +476,39 @@ export function App() { ); })}
+ { + event.preventDefault(); + navigate({ page: "flow-chat" }); + }} + > + +
+ {flowChatComponents.map((component) => { + const Icon = componentIcons[component.name] ?? SquareTerminal; + const active = route.page === "component" && route.componentName === component.name; + return ( + { + event.preventDefault(); + navigate({ componentName: component.name, page: "component" }); + }} + > + + ); + })} +
@@ -643,6 +701,18 @@ export function App() { /> )} + {route.page === "flow-chat" && ( + openTokenPage()} + onOpenComponent={(name) => navigate({ componentName: name, page: "component" })} + tokenOverrides={tokenOverrides} + /> + )} + {route.page === "component" && activeComponent && ( navigate({ page: "components" })} + onBack={() => navigate({ + page: activeComponent.category === "flow-chat" + ? "flow-chat" + : "components", + })} onInspectTokens={openTokenPage} tokenOverrides={tokenOverrides} /> diff --git a/design-system/apps/design-lab/src/i18n/componentMetadata.ts b/design-system/apps/design-lab/src/i18n/componentMetadata.ts index 9d0aac1a60..834840cb1a 100644 --- a/design-system/apps/design-lab/src/i18n/componentMetadata.ts +++ b/design-system/apps/design-lab/src/i18n/componentMetadata.ts @@ -6,6 +6,7 @@ type Translate = (key: MessageKey, params?: TranslateParams) => string; const categoryKeys: Readonly> = { action: "meta.category.action", feedback: "meta.category.feedback", + "flow-chat": "meta.category.flowChat", form: "meta.category.form", navigation: "meta.category.navigation", primitive: "meta.category.primitive", @@ -15,24 +16,51 @@ const descriptionKeys: Readonly> = { ActionCard: "component.ActionCard.description", ActionItem: "component.ActionItem.description", ActivityItem: "component.ActivityItem.description", + AgentControlToolCard: "component.AgentControlToolCard.description", + AgentWaitToolCard: "component.AgentWaitToolCard.description", + AmbientToolCard: "component.AmbientToolCard.description", Button: "component.Button.description", Card: "component.Card.description", + CommandToolCard: "component.CommandToolCard.description", Composer: "component.Composer.description", ConfirmDialog: "component.ConfirmDialog.description", + ContextCompressionToolCard: "component.ContextCompressionToolCard.description", + DefaultToolCard: "component.DefaultToolCard.description", + DirectoryListToolCard: "component.DirectoryListToolCard.description", Field: "component.Field.description", FieldGroup: "component.FieldGroup.description", + FileDiffToolCard: "component.FileDiffToolCard.description", + FileOperationToolCard: "component.FileOperationToolCard.description", + GetToolSpecToolCard: "component.GetToolSpecToolCard.description", + GitToolCard: "component.GitToolCard.description", + GlobSearchToolCard: "component.GlobSearchToolCard.description", + GrepSearchToolCard: "component.GrepSearchToolCard.description", IconButton: "component.IconButton.description", Input: "component.Input.description", KeyHint: "component.KeyHint.description", Menu: "component.Menu.description", Modal: "component.Modal.description", NavigationPanel: "component.NavigationPanel.description", + PageDeployToolCard: "component.PageDeployToolCard.description", PageHeader: "component.PageHeader.description", + PagePublishToolCard: "component.PagePublishToolCard.description", + ProminentToolCard: "component.ProminentToolCard.description", + ReadFileToolCard: "component.ReadFileToolCard.description", + ReviewSummaryToolCard: "component.ReviewSummaryToolCard.description", + RunCodeToolCard: "component.RunCodeToolCard.description", SearchField: "component.SearchField.description", SegmentedControl: "component.SegmentedControl.description", + SessionControlToolCard: "component.SessionControlToolCard.description", + SessionMessageToolCard: "component.SessionMessageToolCard.description", + SkillToolCard: "component.SkillToolCard.description", Switch: "component.Switch.description", TabGroup: "component.TabGroup.description", + TerminalControlToolCard: "component.TerminalControlToolCard.description", + TodoToolCard: "component.TodoToolCard.description", Toolbar: "component.Toolbar.description", + ViewImageToolCard: "component.ViewImageToolCard.description", + WebFetchToolCard: "component.WebFetchToolCard.description", + WebSearchToolCard: "component.WebSearchToolCard.description", }; export function getComponentCategoryLabel(category: string, t: Translate): string { diff --git a/design-system/apps/design-lab/src/i18n/messages.ts b/design-system/apps/design-lab/src/i18n/messages.ts index eb0fc9a8ac..ec18d6eda6 100644 --- a/design-system/apps/design-lab/src/i18n/messages.ts +++ b/design-system/apps/design-lab/src/i18n/messages.ts @@ -13,6 +13,7 @@ export const enUSMessages = { "nav.colors": "Colors", "nav.library": "Library", "nav.components": "Components", + "nav.flowChat": "FlowChat", "nav.docs": "Docs", "nav.resources": "Resources", "search.label": "Search Design Lab", @@ -23,6 +24,7 @@ export const enUSMessages = { "search.tokensDetail": "{count} editable contracts", "search.colorsDetail": "{count} semantic color tokens and real reference scales", "search.componentsDetail": "{count} registered components", + "search.flowChatDetail": "{count} shared templates and standard tool-card specimens", "search.resourcesDetail": "Package documentation and release policy", "search.componentDetail": "{category}", "theme.switchToDark": "Switch to dark scheme", @@ -46,31 +48,60 @@ export const enUSMessages = { "meta.category.action": "Action", "meta.category.form": "Form", "meta.category.feedback": "Feedback", + "meta.category.flowChat": "Flow Chat", "meta.category.navigation": "Navigation", "meta.category.primitive": "Primitive", "meta.category.other": "Component", "component.ActionCard.description": "An actionable card with independent leading, title, description, selection, and sibling action areas.", "component.ActionItem.description": "A native button row with independent leading, shortcut, and sibling action areas.", "component.ActivityItem.description": "A compact activity row with independent identity, description, metadata, and sibling action areas.", + "component.AgentControlToolCard.description": "A prominent subagent card with an openable identity, lifecycle state, and expandable prompt.", + "component.AgentWaitToolCard.description": "An ambient trace for background-agent wait progress and completion summaries.", + "component.AmbientToolCard.description": "A low-attention tool trace that stays glanceable in the conversation and can reveal supporting detail.", + "component.AskUser.description": "A controlled question card with responsive choices, custom answers, submission feedback, and an answered disclosure summary.", "component.Button.description": "A compact action with outline, filled, primary, and text presentation variants.", "component.Card.description": "A composable content surface with independent media, header, body, footer, spacing, clipping, and elevation contracts.", + "component.CommandToolCard.description": "A prominent command view with controlled output disclosure, process metadata, and capability-driven actions.", "component.Composer.description": "A composable message editor shell with independent context, editor, and action regions.", "component.ConfirmDialog.description": "A semantic confirmation dialog with optional preview content, destructive emphasis, and async actions.", + "component.ContextCompressionToolCard.description": "A prominent context-compression result with one compact length-and-ratio summary, plus progress and failure states.", + "component.DefaultToolCard.description": "The ambient fallback for an unregistered tool summary, sanitized input, result, and confirmation state.", + "component.DirectoryListToolCard.description": "An ambient directory-list card with structured metadata and file results.", "component.Field.description": "Associates label content, optional actions, description, and adjacent controls with one primary form control.", "component.FieldGroup.description": "Composes titled form sections, grouped field surfaces, and independently padded rows.", + "component.FileDiffToolCard.description": "A prominent file-diff card with a compact file path, change summary, message, and renderer slot.", + "component.FileOperationToolCard.description": "An adaptive file-operation view: ambient for deletion, prominent and expandable for writes and edits.", + "component.GetToolSpecToolCard.description": "An ambient trace for loading a deferred tool specification into runtime context.", + "component.GitToolCard.description": "A prominent Git command card with output, warning, failure, and execution metadata.", + "component.GlobSearchToolCard.description": "An ambient file-pattern search card with reusable result-list anatomy.", + "component.GrepSearchToolCard.description": "An ambient text-search card with query metadata and a scrollable result preview.", "component.IconButton.description": "A labeled icon-only action with quiet, filled, and primary presentation variants.", "component.Input.description": "A native text field with independent leading and trailing content slots.", "component.KeyHint.description": "A semantic keyboard hint with optional decorative icon content.", "component.Menu.description": "A grouped, scrollable menu surface with heading actions, native item roles, and keyboard navigation.", "component.Modal.description": "A portaled dialog with focus management, configurable geometry, semantic header content, and a floating action footer.", "component.NavigationPanel.description": "A scrollable application navigation panel with independent header, grouped content, selected items, and footer slots.", + "component.PageDeployToolCard.description": "A prominent page-deploy card with version metadata and host-provided actions.", "component.PageHeader.description": "A title composition with independent leading content, semantic level, visual size, description, action, and alignment.", + "component.PagePublishToolCard.description": "A prominent page-publish card with production and preview metadata and actions.", + "component.ProminentToolCard.description": "An attention-worthy tool result with a stable summary region, hover-revealed actions, and controlled detail disclosure.", + "component.ReadFileToolCard.description": "An ambient read-file trace with progress, permission-aware interaction, completion, and failure summaries.", + "component.ReviewSummaryToolCard.description": "A prominent review summary with changed files, status, and a host navigation action.", + "component.RunCodeToolCard.description": "An ambient code-execution card with host-rendered program and output slots.", "component.ScrollArea.description": "A native scroll viewport with configurable direction and scrollbar visibility.", "component.SearchField.description": "A search input with optional leading icon, shortcut hint, and Enter submission.", "component.SegmentedControl.description": "A compact pill-shaped single-choice control that switches between a small set of exclusive modes.", + "component.SessionControlToolCard.description": "An ambient session-lifecycle card with semantic detail fields and session rows.", + "component.SessionMessageToolCard.description": "An ambient cross-session message card with target details and message content.", + "component.SkillToolCard.description": "An ambient trace for skill loading progress and outcomes.", "component.Switch.description": "Toggles a single setting between on and off with native checkbox semantics.", "component.TabGroup.description": "A compact single-selection tab list with optional leading icons, end actions, and automatic keyboard activation.", + "component.TerminalControlToolCard.description": "An ambient trace for interrupting or terminating a terminal session.", + "component.TodoToolCard.description": "An ambient task-progress card with compact and expandable list presentations.", "component.Toolbar.description": "A responsive bar with independent leading, centered, trailing, and horizontally scrollable composition regions.", + "component.ViewImageToolCard.description": "An ambient image-result card with an expandable preview and accessible lightbox.", + "component.WebFetchToolCard.description": "An ambient web-fetch card with source metadata, result actions, and content preview.", + "component.WebSearchToolCard.description": "An ambient web-search card with link, snippet, URL, and summary result presentations.", "overview.intro": "A modern design system for building consistent, accessible, and delightful BitFun products.", "overview.getStarted": "Get started", "overview.viewTokens": "View design tokens", @@ -132,6 +163,54 @@ export const enUSMessages = { "components.preview.activityCopy": "Copy command", "components.preview.activityDownload": "Download output", "components.preview.activityOpen": "Open details", + "components.preview.flowChat.askUserAnswered": "1 question answered", + "components.preview.flowChat.askUserBetaDescription": "Latest Beta pre-release — newer and has passed basic testing", + "components.preview.flowChat.askUserError": "Questions could not be loaded", + "components.preview.flowChat.askUserHeader": "1 question", + "components.preview.flowChat.askUserLoading": "Loading questions…", + "components.preview.flowChat.askUserNightly": "Nightly build", + "components.preview.flowChat.askUserNightlyDescription": "Daily automatic builds — contain the latest code but are untested", + "components.preview.flowChat.askUserOther": "Other", + "components.preview.flowChat.askUserOtherDescription": "Provide custom text input", + "components.preview.flowChat.askUserOtherInputLabel": "Custom version", + "components.preview.flowChat.askUserOtherPlaceholder": "Enter a version", + "components.preview.flowChat.askUserQuestion": "BitFun has three versions — which would you like me to pull?", + "components.preview.flowChat.askUserStableDescription": "The stable release marked as Latest on GitHub — the most stable one", + "components.preview.flowChat.askUserSubmit": "Submit", + "components.preview.flowChat.askUserSubmitting": "Submitting…", + "components.preview.flowChat.askUserSummaryPrefix": "Choose version", + "components.preview.flowChat.askUserWaiting": "Waiting for your answer", + "components.preview.flowChat.changeSummary": "6 additions and 0 deletions", + "components.preview.flowChat.commandFailed": "Command exited with code 1.", + "components.preview.flowChat.commandWaiting": "Waiting for process output…", + "components.preview.flowChat.completed": "Completed", + "components.preview.flowChat.contextCompression": "Compress context", + "components.preview.flowChat.contextDetail": "Older conversation segments were summarized while recent tool context was retained.", + "components.preview.flowChat.contextError": "Context compression could not be completed.", + "components.preview.flowChat.contextMeta": "93k tokens removed", + "components.preview.flowChat.contextProcessing": "Analyzing conversation context…", + "components.preview.flowChat.contextSummary": "Compressed context length 31k (compression ratio 75%)", + "components.preview.flowChat.copy": "Copy command", + "components.preview.flowChat.deleteFile": "Delete file", + "components.preview.flowChat.download": "Download output", + "components.preview.flowChat.duration": "Duration", + "components.preview.flowChat.editFile": "Edit file", + "components.preview.flowChat.emptyCommand": "No command available", + "components.preview.flowChat.exitCode": "Exit code", + "components.preview.flowChat.failed": "Failed", + "components.preview.flowChat.fileChangeSummary": "12 additions and 4 deletions", + "components.preview.flowChat.fileErrorMessage": "The target changed before the operation could be applied.", + "components.preview.flowChat.fileErrorTitle": "File operation failed", + "components.preview.flowChat.fileLoading": "Applying changes…", + "components.preview.flowChat.openFile": "Open file", + "components.preview.flowChat.interruptProcess": "Interrupt process", + "components.preview.flowChat.pollProcess": "Poll process", + "components.preview.flowChat.readFile": "Read file", + "components.preview.flowChat.readFailed": "Could not read src/flow_chat/tool-cards/index.ts", + "components.preview.flowChat.readingFile": "Reading src/flow_chat/tool-cards/index.ts…", + "components.preview.flowChat.runCommand": "Run command", + "components.preview.flowChat.running": "Running", + "components.preview.flowChat.writeFile": "Write file", "components.preview.add": "Add", "components.preview.more": "More actions", "components.preview.appearance": "Appearance", @@ -206,6 +285,26 @@ export const enUSMessages = { "components.kicker": "Library", "components.title": "Components", "components.description": "Production package exports, rendered against the active theme and density contract.", + "components.flowChat.kicker": "FlowChat library", + "components.flowChat.title": "FlowChat", + "components.flowChat.description": "Shared attention-based card frameworks and standard tool-card specimens built from those public contracts.", + "components.flowChat.templatesKicker": "Shared frameworks", + "components.flowChat.templatesTitle": "General card templates", + "components.flowChat.templatesDescription": "Ambient and Prominent define the stable anatomy, behavior, accessibility, and disclosure rules used by standard FlowChat tools.", + "components.flowChat.toolsKicker": "Tool cards", + "components.flowChat.toolsTitle": "Migrated tool cards", + "components.flowChat.toolsDescription": "Every specimen below renders the actual public component used by its Web UI adapter. Product-owned cards are listed separately and are not represented by substitute previews.", + "components.flowChat.ambientTitle": "Ambient tools", + "components.flowChat.ambientDescription": "Routine execution traces that remain lightweight and easy to scan.", + "components.flowChat.prominentTitle": "Prominent tools", + "components.flowChat.prominentDescription": "Results and operations that warrant deliberate user attention.", + "components.flowChat.toolCount": "{count} cards", + "components.flowChat.attention.adaptive": "Adaptive", + "components.flowChat.attention.ambient": "Ambient", + "components.flowChat.attention.prominent": "Prominent", + "components.flowChat.openComponent": "Open {name} component details", + "components.flowChat.dedicatedTitle": "Dedicated cards remain product-owned", + "components.flowChat.dedicatedDescription": "Distinct product workflows keep their own presentation and are intentionally excluded from the shared templates.", "components.inspectAllTokens": "Inspect all tokens", "components.summaryLabel": "Component library summary", "components.registeredCount": "registered components", @@ -216,6 +315,7 @@ export const enUSMessages = { "components.primitivesTitle": "ThemeRoot and Stack hold the canvas together.", "components.primitivesDescription": "These primitives remain intentionally small: ThemeRoot establishes scheme, contrast, density, and token overrides; Stack owns only layout direction, alignment, wrapping, and system spacing.", "detail.back": "Components", + "detail.backFlowChat": "FlowChat", "detail.breadcrumbLabel": "Component breadcrumb", "detail.livePlayground": "Live playground", "detail.allStates": "Preview states", @@ -263,6 +363,7 @@ export const enUSMessages = { "detail.option.md": "Medium", "detail.option.lg": "Large", "detail.option.default": "Default", + "detail.option.asking": "Asking", "detail.option.hover": "Hover", "detail.option.info": "Information", "detail.option.warning": "Warning", @@ -291,12 +392,16 @@ export const enUSMessages = { "detail.option.focus-visible": "Focus visible", "detail.option.disabled": "Disabled", "detail.option.display": "Display", + "detail.option.completed": "Completed", + "detail.option.expanded": "Expanded", "detail.option.loading": "Loading", + "detail.option.submitting": "Submitting", "detail.option.none": "None", "detail.option.chevron": "Chevron", "detail.option.center": "Center", "detail.option.left": "Left", "detail.option.right": "Right", + "detail.option.confirmation": "Confirmation", "detail.option.off": "Off", "detail.option.on": "On", "detail.option.selected": "Selected", @@ -503,6 +608,7 @@ export const zhCNMessages = { "nav.colors": "Colors", "nav.library": "组件库", "nav.components": "组件", + "nav.flowChat": "FlowChat", "nav.docs": "文档", "nav.resources": "资源", "search.label": "搜索 Design Lab", @@ -513,6 +619,7 @@ export const zhCNMessages = { "search.tokensDetail": "{count} 个可编辑契约", "search.colorsDetail": "{count} 个语义颜色 Token 与真实基础色阶", "search.componentsDetail": "{count} 个已注册组件", + "search.flowChatDetail": "{count} 个通用模板及标准工具卡片样例", "search.resourcesDetail": "包文档与发布策略", "search.componentDetail": "{category}", "theme.switchToDark": "切换到深色模式", @@ -536,31 +643,60 @@ export const zhCNMessages = { "meta.category.action": "操作", "meta.category.form": "表单", "meta.category.feedback": "反馈", + "meta.category.flowChat": "FlowChat", "meta.category.navigation": "导航", "meta.category.primitive": "基础组件", "meta.category.other": "组件", "component.ActionCard.description": "可独立配置前置内容、标题、说明、选中状态和同级尾部操作的可交互卡片。", "component.ActionItem.description": "使用原生按钮语义,并拆分前置、快捷键与同级尾部操作区域的行项目。", "component.ActivityItem.description": "紧凑的活动行,可独立配置标识、描述、统计信息和同级尾部操作。", + "component.AgentControlToolCard.description": "关注型子 Agent 卡片,统一呈现可打开的身份、生命周期状态和可展开提示词。", + "component.AgentWaitToolCard.description": "低关注等待轨迹,用于呈现后台 Agent 的等待进度与完成摘要。", + "component.AmbientToolCard.description": "用于低关注工具轨迹,在对话中保持轻量易扫读,并可按需展开辅助详情。", + "component.AskUser.description": "受控的提问卡片,包含响应式选项、自定义答案、提交反馈与已回答展开摘要。", "component.Button.description": "紧凑的操作组件,支持描边、填充、主要和文字呈现方式。", "component.Card.description": "媒体、头部、主体、底部、间距、裁切与层级彼此独立的可组合内容表面。", + "component.CommandToolCard.description": "关注型命令视图,统一承载受控输出展开、进程元数据与能力驱动的操作。", "component.Composer.description": "可组合的消息编辑外壳,提供彼此独立的上下文、编辑和操作区域。", "component.ConfirmDialog.description": "支持可选预览、危险操作强调和异步操作的语义化确认对话框。", + "component.ContextCompressionToolCard.description": "关注型上下文压缩结果,以一条紧凑信息呈现压缩后长度与压缩比例,并保留处理和失败状态。", + "component.DefaultToolCard.description": "未注册工具的低关注兜底卡片,统一承载摘要、净化后的输入、结果与确认状态。", + "component.DirectoryListToolCard.description": "带结构化元数据和文件结果的低关注目录列表卡片。", "component.Field.description": "将标签内容、可选操作、说明和相邻控件与一个主要表单控件关联。", "component.FieldGroup.description": "组合带标题的表单区段、分组字段表面和可独立调整内边距的字段行。", + "component.FileDiffToolCard.description": "关注型文件差异卡片,以紧凑文件路径和变更统计承载说明与渲染插槽。", + "component.FileOperationToolCard.description": "自适应文件操作视图:删除采用低关注呈现,写入与编辑采用可展开的关注型呈现。", + "component.GetToolSpecToolCard.description": "低关注工具规范轨迹,用于将延迟加载的工具说明载入运行时上下文。", + "component.GitToolCard.description": "关注型 Git 命令卡片,统一呈现输出、警告、失败与执行元数据。", + "component.GlobSearchToolCard.description": "复用结果列表结构的低关注文件模式搜索卡片。", + "component.GrepSearchToolCard.description": "带查询元数据和可滚动结果预览的低关注文本搜索卡片。", "component.IconButton.description": "带无障碍标签的纯图标操作组件,支持安静、填充和主要呈现方式。", "component.Input.description": "使用原生输入语义,并提供独立前置与后置内容槽的文本字段。", "component.KeyHint.description": "使用键盘提示语义,并支持可选装饰图标的基础组件。", "component.Menu.description": "支持分组标题、标题操作、原生项目语义、键盘导航与滚动的菜单表面。", "component.Modal.description": "具备 Portal、焦点管理、可配置表面几何、语义标题内容和浮动操作栏的对话框。", "component.NavigationPanel.description": "具备独立头部、分组内容、选中项、滚动主体与底栏槽位的应用导航面板。", + "component.PageDeployToolCard.description": "关注型页面部署卡片,统一呈现版本元数据与宿主操作。", "component.PageHeader.description": "前置内容、标题语义层级、视觉大小、说明、操作区与对齐方式彼此独立的标题组合。", + "component.PagePublishToolCard.description": "关注型页面发布卡片,统一呈现生产与预览元数据和操作。", + "component.ProminentToolCard.description": "用于需要用户关注的工具结果,左侧摘要始终稳定,右侧操作悬停出现,并支持受控展开。", + "component.ReadFileToolCard.description": "低关注读取文件轨迹,统一呈现进度、权限相关交互、完成与失败摘要。", + "component.ReviewSummaryToolCard.description": "关注型审查摘要,统一呈现变更文件、状态和宿主导航操作。", + "component.RunCodeToolCard.description": "低关注代码执行卡片,通过插槽承载宿主渲染的程序与输出。", "component.ScrollArea.description": "支持配置滚动方向与滚动条可见性的原生滚动视口。", "component.SearchField.description": "支持可选前置图标、快捷键提示和回车提交的搜索输入。", "component.SegmentedControl.description": "紧凑的胶囊式单选控件,用于在少量互斥模式之间切换。", + "component.SessionControlToolCard.description": "低关注会话生命周期卡片,包含语义详情字段与会话行。", + "component.SessionMessageToolCard.description": "低关注跨会话消息卡片,包含目标详情与消息内容。", + "component.SkillToolCard.description": "低关注 Skill 轨迹,用于呈现加载进度和执行结果。", "component.Switch.description": "通过原生复选框语义在开启与关闭之间切换单项设置。", "component.TabGroup.description": "紧凑的单选标签组,支持前置图标、尾部操作与方向键自动切换。", + "component.TerminalControlToolCard.description": "低关注终端控制轨迹,用于呈现中断或终止终端会话的结果。", + "component.TodoToolCard.description": "低关注任务进度卡片,支持紧凑摘要与可展开列表两种呈现。", "component.Toolbar.description": "具备独立前置、居中、尾部与横向滚动区域的响应式工具栏。", + "component.ViewImageToolCard.description": "低关注图片结果卡片,包含可展开预览和无障碍灯箱。", + "component.WebFetchToolCard.description": "低关注网页读取卡片,包含来源元数据、结果操作与内容预览。", + "component.WebSearchToolCard.description": "低关注网页搜索卡片,统一呈现链接、摘要、网址与结果列表。", "overview.intro": "用于构建一致、易用且令人愉悦的 BitFun 产品的现代设计系统。", "overview.getStarted": "开始使用", "overview.viewTokens": "查看 Design Token", @@ -622,6 +758,54 @@ export const zhCNMessages = { "components.preview.activityCopy": "复制命令", "components.preview.activityDownload": "下载输出", "components.preview.activityOpen": "打开详情", + "components.preview.flowChat.askUserAnswered": "1 个问题已回答", + "components.preview.flowChat.askUserBetaDescription": "最新 Beta 预发布版——版本更新,且已通过基础测试", + "components.preview.flowChat.askUserError": "无法加载问题", + "components.preview.flowChat.askUserHeader": "1 个问题", + "components.preview.flowChat.askUserLoading": "正在加载问题…", + "components.preview.flowChat.askUserNightly": "Nightly 构建", + "components.preview.flowChat.askUserNightlyDescription": "每日自动构建——包含最新代码,但尚未测试", + "components.preview.flowChat.askUserOther": "其他", + "components.preview.flowChat.askUserOtherDescription": "提供自定义文本输入", + "components.preview.flowChat.askUserOtherInputLabel": "自定义版本", + "components.preview.flowChat.askUserOtherPlaceholder": "输入版本", + "components.preview.flowChat.askUserQuestion": "BitFun 有三个版本——你希望我拉取哪一个?", + "components.preview.flowChat.askUserStableDescription": "GitHub 标记为 Latest 的稳定版本——稳定性最佳", + "components.preview.flowChat.askUserSubmit": "提交", + "components.preview.flowChat.askUserSubmitting": "正在提交…", + "components.preview.flowChat.askUserSummaryPrefix": "选择版本", + "components.preview.flowChat.askUserWaiting": "等待你的回答", + "components.preview.flowChat.changeSummary": "新增 6 行,删除 0 行", + "components.preview.flowChat.commandFailed": "命令退出,状态码为 1。", + "components.preview.flowChat.commandWaiting": "正在等待进程输出…", + "components.preview.flowChat.completed": "已完成", + "components.preview.flowChat.contextCompression": "压缩上下文", + "components.preview.flowChat.contextDetail": "较早的对话片段已被摘要,并保留近期工具上下文。", + "components.preview.flowChat.contextError": "无法完成上下文压缩。", + "components.preview.flowChat.contextMeta": "已减少 93k Token", + "components.preview.flowChat.contextProcessing": "正在分析对话上下文…", + "components.preview.flowChat.contextSummary": "压缩后上下文长度 31k(压缩比例 75%)", + "components.preview.flowChat.copy": "复制命令", + "components.preview.flowChat.deleteFile": "删除文件", + "components.preview.flowChat.download": "下载输出", + "components.preview.flowChat.duration": "耗时", + "components.preview.flowChat.editFile": "编辑文件", + "components.preview.flowChat.emptyCommand": "没有可用命令", + "components.preview.flowChat.exitCode": "退出码", + "components.preview.flowChat.failed": "失败", + "components.preview.flowChat.fileChangeSummary": "新增 12 行,删除 4 行", + "components.preview.flowChat.fileErrorMessage": "应用操作前目标文件已发生变化。", + "components.preview.flowChat.fileErrorTitle": "文件操作失败", + "components.preview.flowChat.fileLoading": "正在应用变更…", + "components.preview.flowChat.openFile": "打开文件", + "components.preview.flowChat.interruptProcess": "中断进程", + "components.preview.flowChat.pollProcess": "轮询进程", + "components.preview.flowChat.readFile": "读取文件", + "components.preview.flowChat.readFailed": "无法读取 src/flow_chat/tool-cards/index.ts", + "components.preview.flowChat.readingFile": "正在读取 src/flow_chat/tool-cards/index.ts…", + "components.preview.flowChat.runCommand": "运行命令", + "components.preview.flowChat.running": "运行中", + "components.preview.flowChat.writeFile": "写入文件", "components.preview.add": "添加", "components.preview.more": "更多操作", "components.preview.appearance": "外观", @@ -696,6 +880,26 @@ export const zhCNMessages = { "components.kicker": "组件库", "components.title": "组件", "components.description": "真实的生产包导出,并使用当前主题与密度契约渲染。", + "components.flowChat.kicker": "FlowChat 组件库", + "components.flowChat.title": "FlowChat", + "components.flowChat.description": "以用户关注程度组织的通用卡片框架,以及基于这些公共契约构建的标准工具卡片样例。", + "components.flowChat.templatesKicker": "通用框架", + "components.flowChat.templatesTitle": "通用卡片模板", + "components.flowChat.templatesDescription": "Ambient 与 Prominent 定义标准 FlowChat 工具共享的稳定结构、交互、无障碍与详情展开规则。", + "components.flowChat.toolsKicker": "工具卡片", + "components.flowChat.toolsTitle": "已迁移工具卡片", + "components.flowChat.toolsDescription": "下方每个样例均渲染 Web UI 适配器实际使用的公共组件。产品层卡片单独列出,不再使用替代预览伪装为已组件化。", + "components.flowChat.ambientTitle": "低关注工具", + "components.flowChat.ambientDescription": "保持轻量、易扫读的常规执行轨迹。", + "components.flowChat.prominentTitle": "关注型工具", + "components.flowChat.prominentDescription": "需要用户明确关注其结果或操作过程的工具。", + "components.flowChat.toolCount": "{count} 张卡片", + "components.flowChat.attention.adaptive": "自适应关注型", + "components.flowChat.attention.ambient": "低关注型", + "components.flowChat.attention.prominent": "关注型", + "components.flowChat.openComponent": "打开 {name} 组件详情", + "components.flowChat.dedicatedTitle": "定制卡片继续由产品层维护", + "components.flowChat.dedicatedDescription": "具有独特产品流程的卡片保留自己的呈现方式,不纳入通用模板。", "components.inspectAllTokens": "检查全部 Token", "components.summaryLabel": "组件库摘要", "components.registeredCount": "个已注册组件", @@ -706,6 +910,7 @@ export const zhCNMessages = { "components.primitivesTitle": "ThemeRoot 与 Stack 共同支撑整个画布。", "components.primitivesDescription": "这些原语刻意保持精简:ThemeRoot 建立模式、对比度、密度和 Token 覆盖;Stack 只负责布局方向、对齐、换行与系统间距。", "detail.back": "组件", + "detail.backFlowChat": "FlowChat", "detail.breadcrumbLabel": "组件面包屑", "detail.livePlayground": "实时工作台", "detail.allStates": "状态预览", @@ -753,6 +958,7 @@ export const zhCNMessages = { "detail.option.md": "中", "detail.option.lg": "大", "detail.option.default": "默认", + "detail.option.asking": "提问中", "detail.option.hover": "悬停", "detail.option.info": "信息", "detail.option.warning": "警告", @@ -781,12 +987,16 @@ export const zhCNMessages = { "detail.option.focus-visible": "焦点可见", "detail.option.disabled": "禁用", "detail.option.display": "展示", + "detail.option.completed": "已完成", + "detail.option.expanded": "展开", "detail.option.loading": "加载中", + "detail.option.submitting": "提交中", "detail.option.none": "无", "detail.option.chevron": "箭头", "detail.option.center": "居中", "detail.option.left": "左侧", "detail.option.right": "右侧", + "detail.option.confirmation": "待确认", "detail.option.off": "关闭", "detail.option.on": "开启", "detail.option.selected": "选中", @@ -991,6 +1201,7 @@ export const zhTWMessages = { "nav.colors": "Colors", "nav.library": "元件庫", "nav.components": "元件", + "nav.flowChat": "FlowChat", "nav.docs": "文件", "nav.resources": "資源", "search.label": "搜尋 Design Lab", @@ -1001,6 +1212,7 @@ export const zhTWMessages = { "search.tokensDetail": "{count} 個可編輯契約", "search.colorsDetail": "{count} 個語意顏色 Token 與真實基礎色階", "search.componentsDetail": "{count} 個已註冊元件", + "search.flowChatDetail": "{count} 個通用模板及標準工具卡片範例", "search.resourcesDetail": "套件文件與發佈策略", "theme.switchToDark": "切換至深色模式", "theme.switchToLight": "切換至淺色模式", @@ -1023,28 +1235,57 @@ export const zhTWMessages = { "meta.category.action": "操作", "meta.category.form": "表單", "meta.category.feedback": "回饋", + "meta.category.flowChat": "FlowChat", "meta.category.navigation": "導覽", "meta.category.primitive": "基礎元件", "meta.category.other": "元件", "component.ActionCard.description": "可獨立設定前置內容、標題、說明、選取狀態和同級尾端操作的可互動卡片。", "component.ActionItem.description": "使用原生按鈕語意,並拆分前置、快捷鍵與同級尾端操作區域的列項目。", "component.ActivityItem.description": "緊湊的活動列,可獨立設定標識、描述、統計資訊和同級尾端操作。", + "component.AgentControlToolCard.description": "關注型子 Agent 卡片,統一呈現可開啟的身分、生命週期狀態和可展開提示詞。", + "component.AgentWaitToolCard.description": "低關注等待軌跡,用於呈現背景 Agent 的等待進度與完成摘要。", + "component.AmbientToolCard.description": "用於低關注工具軌跡,在對話中保持輕量易掃讀,並可按需展開輔助詳情。", + "component.AskUser.description": "受控的提問卡片,包含響應式選項、自訂答案、提交回饋與已回答展開摘要。", "component.Button.description": "緊湊的中性操作元件,支援描邊和填滿兩種呈現方式。", "component.Card.description": "媒體、頂部、主體、底部、間距、裁切與層級彼此獨立的可組合內容表面。", + "component.CommandToolCard.description": "關注型命令檢視,統一承載受控輸出展開、程序中繼資料與能力驅動操作。", "component.Composer.description": "可組合的訊息編輯外殼,提供彼此獨立的上下文、編輯和操作區域。", "component.ConfirmDialog.description": "支援可選預覽、危險操作強調和非同步操作的語意化確認對話框。", + "component.ContextCompressionToolCard.description": "關注型上下文壓縮結果,以一條緊湊資訊呈現壓縮後長度與壓縮比例,並保留處理和失敗狀態。", + "component.DefaultToolCard.description": "未註冊工具的低關注預設卡片,統一承載摘要、淨化後的輸入、結果與確認狀態。", + "component.DirectoryListToolCard.description": "帶結構化中繼資料和檔案結果的低關注目錄列表卡片。", "component.Field.description": "將標籤內容、可選操作、說明和相鄰控制項與一個主要表單控制項關聯。", "component.FieldGroup.description": "組合帶標題的表單區段、分組欄位表面和可獨立調整內距的欄位列。", + "component.FileDiffToolCard.description": "關注型檔案差異卡片,以緊湊檔案路徑和變更統計承載說明與呈現插槽。", + "component.FileOperationToolCard.description": "自適應檔案操作檢視:刪除採低關注呈現,寫入與編輯採可展開的關注型呈現。", + "component.GetToolSpecToolCard.description": "低關注工具規範軌跡,用於將延遲載入的工具說明載入執行階段上下文。", + "component.GitToolCard.description": "關注型 Git 命令卡片,統一呈現輸出、警告、失敗與執行中繼資料。", + "component.GlobSearchToolCard.description": "重用結果列表結構的低關注檔案模式搜尋卡片。", + "component.GrepSearchToolCard.description": "帶查詢中繼資料和可捲動結果預覽的低關注文字搜尋卡片。", "component.KeyHint.description": "使用鍵盤提示語意,並支援可選裝飾圖示的基礎元件。", "component.Menu.description": "支援分組標題、標題操作、原生項目語意、鍵盤導覽與捲動的選單表面。", "component.Modal.description": "具備 Portal、焦點管理、可設定表面幾何、語意標題內容和浮動操作列的對話框。", "component.NavigationPanel.description": "具備獨立頂部、分組內容、選取項目、捲動主體與底欄插槽的應用導覽面板。", + "component.PageDeployToolCard.description": "關注型頁面部署卡片,統一呈現版本中繼資料與宿主操作。", "component.PageHeader.description": "前置內容、標題語意層級、視覺大小、說明、操作區與對齊方式彼此獨立的標題組合。", + "component.PagePublishToolCard.description": "關注型頁面發佈卡片,統一呈現正式環境與預覽中繼資料和操作。", + "component.ProminentToolCard.description": "用於需要使用者關注的工具結果,左側摘要始終穩定,右側操作懸停出現,並支援受控展開。", + "component.ReadFileToolCard.description": "低關注讀取檔案軌跡,統一呈現進度、權限相關互動、完成與失敗摘要。", + "component.ReviewSummaryToolCard.description": "關注型審查摘要,統一呈現變更檔案、狀態和宿主導覽操作。", + "component.RunCodeToolCard.description": "低關注程式碼執行卡片,透過插槽承載宿主呈現的程式與輸出。", "component.ScrollArea.description": "支援設定捲動方向與捲動條可見性的原生捲動視口。", "component.SegmentedControl.description": "緊湊的膠囊式單選控制項,用於在少量互斥模式之間切換。", + "component.SessionControlToolCard.description": "低關注工作階段生命週期卡片,包含語意詳情欄位與工作階段列。", + "component.SessionMessageToolCard.description": "低關注跨工作階段訊息卡片,包含目標詳情與訊息內容。", + "component.SkillToolCard.description": "低關注 Skill 軌跡,用於呈現載入進度和執行結果。", "component.Switch.description": "以原生核取方塊語意在開啟與關閉之間切換單一設定。", "component.TabGroup.description": "緊湊的單選標籤群組,支援前置圖示、尾端操作與方向鍵自動切換。", + "component.TerminalControlToolCard.description": "低關注終端控制軌跡,用於呈現中斷或終止終端工作階段的結果。", + "component.TodoToolCard.description": "低關注任務進度卡片,支援緊湊摘要與可展開列表兩種呈現。", "component.Toolbar.description": "具備獨立前置、置中、尾端與橫向捲動區域的響應式工具列。", + "component.ViewImageToolCard.description": "低關注圖片結果卡片,包含可展開預覽和無障礙燈箱。", + "component.WebFetchToolCard.description": "低關注網頁讀取卡片,包含來源中繼資料、結果操作與內容預覽。", + "component.WebSearchToolCard.description": "低關注網頁搜尋卡片,統一呈現連結、摘要、網址與結果列表。", "overview.intro": "用於建構一致、易用且令人愉悅的 BitFun 產品的現代設計系統。", "overview.getStarted": "開始使用", "overview.viewTokens": "檢視 Design Token", @@ -1106,6 +1347,54 @@ export const zhTWMessages = { "components.preview.activityCopy": "複製命令", "components.preview.activityDownload": "下載輸出", "components.preview.activityOpen": "開啟詳情", + "components.preview.flowChat.askUserAnswered": "1 個問題已回答", + "components.preview.flowChat.askUserBetaDescription": "最新 Beta 預發佈版——版本更新,且已通過基礎測試", + "components.preview.flowChat.askUserError": "無法載入問題", + "components.preview.flowChat.askUserHeader": "1 個問題", + "components.preview.flowChat.askUserLoading": "正在載入問題…", + "components.preview.flowChat.askUserNightly": "Nightly 建置", + "components.preview.flowChat.askUserNightlyDescription": "每日自動建置——包含最新程式碼,但尚未測試", + "components.preview.flowChat.askUserOther": "其他", + "components.preview.flowChat.askUserOtherDescription": "提供自訂文字輸入", + "components.preview.flowChat.askUserOtherInputLabel": "自訂版本", + "components.preview.flowChat.askUserOtherPlaceholder": "輸入版本", + "components.preview.flowChat.askUserQuestion": "BitFun 有三個版本——你希望我拉取哪一個?", + "components.preview.flowChat.askUserStableDescription": "GitHub 標記為 Latest 的穩定版本——穩定性最佳", + "components.preview.flowChat.askUserSubmit": "提交", + "components.preview.flowChat.askUserSubmitting": "正在提交…", + "components.preview.flowChat.askUserSummaryPrefix": "選擇版本", + "components.preview.flowChat.askUserWaiting": "等待你的回答", + "components.preview.flowChat.changeSummary": "新增 6 行,刪除 0 行", + "components.preview.flowChat.commandFailed": "命令結束,狀態碼為 1。", + "components.preview.flowChat.commandWaiting": "正在等待程序輸出…", + "components.preview.flowChat.completed": "已完成", + "components.preview.flowChat.contextCompression": "壓縮上下文", + "components.preview.flowChat.contextDetail": "較早的對話片段已被摘要,並保留近期工具上下文。", + "components.preview.flowChat.contextError": "無法完成上下文壓縮。", + "components.preview.flowChat.contextMeta": "已減少 93k Token", + "components.preview.flowChat.contextProcessing": "正在分析對話上下文…", + "components.preview.flowChat.contextSummary": "壓縮後上下文長度 31k(壓縮比例 75%)", + "components.preview.flowChat.copy": "複製命令", + "components.preview.flowChat.deleteFile": "刪除檔案", + "components.preview.flowChat.download": "下載輸出", + "components.preview.flowChat.duration": "耗時", + "components.preview.flowChat.editFile": "編輯檔案", + "components.preview.flowChat.emptyCommand": "沒有可用命令", + "components.preview.flowChat.exitCode": "結束碼", + "components.preview.flowChat.failed": "失敗", + "components.preview.flowChat.fileChangeSummary": "新增 12 行,刪除 4 行", + "components.preview.flowChat.fileErrorMessage": "套用操作前目標檔案已發生變化。", + "components.preview.flowChat.fileErrorTitle": "檔案操作失敗", + "components.preview.flowChat.fileLoading": "正在套用變更…", + "components.preview.flowChat.openFile": "開啟檔案", + "components.preview.flowChat.interruptProcess": "中斷進程", + "components.preview.flowChat.pollProcess": "輪詢進程", + "components.preview.flowChat.readFile": "讀取檔案", + "components.preview.flowChat.readFailed": "無法讀取 src/flow_chat/tool-cards/index.ts", + "components.preview.flowChat.readingFile": "正在讀取 src/flow_chat/tool-cards/index.ts…", + "components.preview.flowChat.runCommand": "執行命令", + "components.preview.flowChat.running": "執行中", + "components.preview.flowChat.writeFile": "寫入檔案", "components.preview.add": "新增", "components.preview.more": "更多操作", "components.preview.appearance": "外觀", @@ -1175,6 +1464,26 @@ export const zhTWMessages = { "components.kicker": "元件庫", "components.title": "元件", "components.description": "真實的正式套件匯出,並使用目前主題與密度契約呈現。", + "components.flowChat.kicker": "FlowChat 元件庫", + "components.flowChat.title": "FlowChat", + "components.flowChat.description": "依使用者關注程度組織的通用卡片框架,以及基於這些公開契約建構的標準工具卡片範例。", + "components.flowChat.templatesKicker": "通用框架", + "components.flowChat.templatesTitle": "通用卡片模板", + "components.flowChat.templatesDescription": "Ambient 與 Prominent 定義標準 FlowChat 工具共用的穩定結構、互動、無障礙與詳情展開規則。", + "components.flowChat.toolsKicker": "工具卡片", + "components.flowChat.toolsTitle": "已遷移工具卡片", + "components.flowChat.toolsDescription": "下方每個範例均呈現 Web UI 介接層實際使用的公開元件。產品層卡片單獨列出,不再使用替代預覽偽裝為已元件化。", + "components.flowChat.ambientTitle": "低關注工具", + "components.flowChat.ambientDescription": "保持輕量、易掃讀的日常執行軌跡。", + "components.flowChat.prominentTitle": "關注型工具", + "components.flowChat.prominentDescription": "需要使用者明確關注其結果或操作過程的工具。", + "components.flowChat.toolCount": "{count} 張卡片", + "components.flowChat.attention.adaptive": "自適應關注型", + "components.flowChat.attention.ambient": "低關注型", + "components.flowChat.attention.prominent": "關注型", + "components.flowChat.openComponent": "開啟 {name} 元件詳情", + "components.flowChat.dedicatedTitle": "定製卡片繼續由產品層維護", + "components.flowChat.dedicatedDescription": "具有獨特產品流程的卡片保留自己的呈現方式,不納入通用模板。", "components.inspectAllTokens": "檢查全部 Token", "components.summaryLabel": "元件庫摘要", "components.registeredCount": "個已註冊元件", @@ -1185,6 +1494,7 @@ export const zhTWMessages = { "components.primitivesTitle": "ThemeRoot 與 Stack 共同支撐整個畫布。", "components.primitivesDescription": "這些原語刻意保持精簡:ThemeRoot 建立模式、對比度、密度和 Token 覆寫;Stack 只負責版面方向、對齊、換行與系統間距。", "detail.back": "元件", + "detail.backFlowChat": "FlowChat", "detail.breadcrumbLabel": "元件麵包屑", "detail.livePlayground": "即時工作台", "detail.allStates": "狀態預覽", @@ -1227,6 +1537,7 @@ export const zhTWMessages = { "detail.option.md": "中", "detail.option.lg": "大", "detail.option.default": "預設", + "detail.option.asking": "提問中", "detail.option.hover": "懸停", "detail.option.info": "資訊", "detail.option.warning": "警告", @@ -1254,12 +1565,16 @@ export const zhTWMessages = { "detail.option.focus-visible": "焦點可見", "detail.option.disabled": "停用", "detail.option.display": "展示", + "detail.option.completed": "已完成", + "detail.option.expanded": "展開", "detail.option.loading": "載入中", + "detail.option.submitting": "提交中", "detail.option.none": "無", "detail.option.chevron": "箭頭", "detail.option.center": "置中", "detail.option.left": "左側", "detail.option.right": "右側", + "detail.option.confirmation": "待確認", "detail.option.off": "關閉", "detail.option.on": "開啟", "detail.option.selected": "已選取", diff --git a/design-system/apps/design-lab/src/pages/ComponentDetailPage.tsx b/design-system/apps/design-lab/src/pages/ComponentDetailPage.tsx index 64c51603a9..1c9c88d3e6 100644 --- a/design-system/apps/design-lab/src/pages/ComponentDetailPage.tsx +++ b/design-system/apps/design-lab/src/pages/ComponentDetailPage.tsx @@ -91,6 +91,10 @@ import { getComponentCategoryLabel, getComponentDescription, } from "../i18n/componentMetadata"; +import { + FlowChatComponentPreview, + getFlowChatPreviewDefinition, +} from "../preview/FlowChatPreviewRegistry"; interface ComponentDetailPageProps { colorScheme: ColorScheme; @@ -127,6 +131,7 @@ const iconTones = ["inherit", "primary", "secondary", "muted", "disabled", "info const optionLabelKeys: Readonly> = { active: "detail.option.active", always: "detail.option.always", + asking: "detail.option.asking", auto: "detail.option.auto", both: "detail.option.both", chevron: "detail.option.chevron", @@ -134,6 +139,8 @@ const optionLabelKeys: Readonly> = { default: "detail.option.default", disabled: "detail.option.disabled", display: "detail.option.display", + error: "detail.option.error", + expanded: "detail.option.expanded", fill: "detail.option.fill", "focus-visible": "detail.option.focus-visible", hover: "detail.option.hover", @@ -163,18 +170,20 @@ const optionLabelKeys: Readonly> = { quiet: "detail.option.quiet", raised: "detail.option.raised", right: "detail.option.right", + confirmation: "detail.option.confirmation", + completed: "detail.option.completed", selected: "detail.option.selected", sm: "detail.option.sm", start: "detail.option.start", surface: "detail.option.surface", subtle: "detail.option.subtle", + submitting: "detail.option.submitting", success: "detail.option.success", text: "detail.option.text", media: "detail.option.media", unselected: "detail.option.unselected", vertical: "detail.option.vertical", warning: "detail.option.warning", - error: "detail.option.error", }; function InspectorSelect({ @@ -287,8 +296,14 @@ export function ComponentDetailPage({ const [navigationPanelShowScrollbar, setNavigationPanelShowScrollbar] = useState(true); const [composerShowContext, setComposerShowContext] = useState(false); const [composerShowToolbar, setComposerShowToolbar] = useState(true); + const flowChatPreview = getFlowChatPreviewDefinition(component.name); + const isFlowChatComponent = Boolean(flowChatPreview); const states = useMemo(() => { + if (flowChatPreview) { + return component.states; + } + switch (component.name) { case "ActionCard": return ["default", "hover", "active", "focus-visible", "selected", "disabled"] as const; @@ -333,12 +348,16 @@ export function ComponentDetailPage({ default: return ["off", "on", "focus-visible", "disabled"] as const; } - }, [component.name]); + }, [component.name, component.states, flowChatPreview]); const inspectorStates = component.name === "Button" || component.name === "IconButton" ? buttonInspectorStates : states; const codeSample = useMemo(() => { + if (flowChatPreview) { + return flowChatPreview.codeSample(t); + } + if (component.name === "ActionCard") { return `import { ActionCard } from "@bitfun/ui";\nimport { MessageCircle, MoreHorizontal } from "lucide-react";\n\n, label: "${t("components.preview.more")}" },\n ]}\n description="${t("components.preview.actionCardDescription")}"\n leading={}\n size="${actionCardSize}"\n>\n ${t("components.preview.actionCardTitle")}\n`; } @@ -475,6 +494,7 @@ export function ComponentDetailPage({ fieldShowControlLeading, fieldShowControlTrailing, fieldShowLabelAction, + flowChatPreview, iconButtonVariant, iconName, iconSize, @@ -676,6 +696,16 @@ export function ComponentDetailPage({ previewVariant = variant, applyInspectorControls = false, ) { + if (isFlowChatComponent) { + return ( + + ); + } + if (component.name === "Icon") { return ; } @@ -1417,7 +1447,9 @@ export function ComponentDetailPage({ return (
@@ -1488,6 +1520,30 @@ export function ComponentDetailPage({ {renderPreview(previewState)}
+ ) : isFlowChatComponent ? ( +
+ {states.map((state) => ( +
+
+ {t(optionLabelKeys[state] ?? "detail.option.default")} + {state} +
+
+ {renderPreview(state)} +
+
+ ))} +
) : component.name === "Button" ? (
+ ); + } switch (component.name) { case "ActionCard": @@ -441,6 +458,7 @@ function ComponentCardPreview({ component }: { component: ComponentMeta }) { } export function ComponentsPage({ + category, colorScheme, contrast, density, @@ -449,14 +467,31 @@ export function ComponentsPage({ tokenOverrides, }: ComponentsPageProps) { const { t } = useI18n(); + const isFlowChatCategory = category === "flow-chat"; + const visibleComponents = componentRegistry.filter((component) => + isFlowChatCategory + ? component.category === "flow-chat" + : component.category !== "flow-chat", + ); + const catalogComponents = isFlowChatCategory + ? flowChatPreviewRegistry + .filter(({ definition }) => definition.section === "framework") + .map(({ component }) => component) + : visibleComponents; return ( -
+
- {t("components.kicker")} -

{t("components.title")}

-

{t("components.description")}

+ {t(isFlowChatCategory + ? "components.flowChat.kicker" + : "components.kicker")} +

{t(isFlowChatCategory + ? "components.flowChat.title" + : "components.title")}

+

{t(isFlowChatCategory + ? "components.flowChat.description" + : "components.description")}

- {componentRegistry.length} {t("components.registeredCount")} - {componentRegistry.reduce((total, item) => total + item.states.length, 0)} {t("components.statesCount")} + {visibleComponents.length} {t("components.registeredCount")} + {visibleComponents.reduce((total, item) => total + item.states.length, 0)} {t("components.statesCount")}
+ {isFlowChatCategory && ( +
+
+ {t("components.flowChat.templatesKicker")} +

{t("components.flowChat.templatesTitle")}

+
+

{t("components.flowChat.templatesDescription")}

+
+ )} + - {componentRegistry.map((component) => { - const Icon = componentIcons[component.name as keyof typeof componentIcons]; + {catalogComponents.map((component) => { + const Icon = getFlowChatPreviewDefinition(component.name)?.icon + ?? componentIcons[component.name as keyof typeof componentIcons]; return (
); } diff --git a/design-system/apps/design-lab/src/preview/FlowChatPreviewRegistry.css b/design-system/apps/design-lab/src/preview/FlowChatPreviewRegistry.css new file mode 100644 index 0000000000..6ad4b12e9b --- /dev/null +++ b/design-system/apps/design-lab/src/preview/FlowChatPreviewRegistry.css @@ -0,0 +1,248 @@ +.flow-chat-tool-card-preview { + inline-size: 100%; + min-inline-size: 0; + text-align: start; +} + +.flow-chat-composer-preview { + inline-size: 100%; + min-inline-size: 0; + text-align: start; +} + +.flow-chat-composer-preview__context { + display: flex; + min-inline-size: 0; + inline-size: 100%; + align-items: center; + gap: var(--bf-space-3); + overflow: hidden; + color: var(--bf-color-content-secondary); + font-family: var(--bf-font-family-control); + font-size: var(--bf-font-size-meta); + white-space: nowrap; +} + +.flow-chat-composer-preview__context > span { + display: inline-flex; + min-inline-size: 0; + align-items: center; + gap: var(--bf-space-1); + overflow: hidden; + text-overflow: ellipsis; +} + +.flow-chat-composer-preview__context svg { + inline-size: var(--bf-font-size-body); + block-size: var(--bf-font-size-body); + flex: 0 0 auto; +} + +.flow-chat-composer-preview__permission { + margin-inline-start: auto; + padding: var(--bf-space-1) var(--bf-space-2); + border-radius: var(--bf-radius-pill); + color: var(--bf-color-status-success-content); + background: var(--bf-color-status-success-surface); +} + +.flow-chat-composer-preview textarea { + min-inline-size: 0; + inline-size: 100%; + block-size: 100%; + resize: none; + margin: 0; + padding: 0; + border: 0; + outline: 0; + color: var(--bf-color-content-primary); + background: transparent; + font: inherit; + line-height: var(--bf-line-height-base); +} + +.flow-chat-composer-preview textarea::placeholder { + color: var(--bf-color-content-muted); + opacity: 1; +} + +.flow-chat-composer-preview [data-bf-layout="compact"] textarea { + line-height: var(--bf-control-chat-composer-compact-track-height); +} + +.flow-chat-composer-preview__action, +.flow-chat-composer-preview__model { + display: inline-flex; + min-inline-size: 0; + block-size: var(--bf-control-chat-composer-control-height); + align-items: center; + justify-content: center; + margin: 0; + padding: 0; + border: 0; + color: var(--bf-color-action-neutral-content); + background: transparent; + cursor: pointer; +} + +.flow-chat-composer-preview__action { + inline-size: var(--bf-control-chat-composer-control-height); + aspect-ratio: 1; + border-radius: var(--bf-radius-pill); +} + +.flow-chat-composer-preview [data-bf-layout="compact"] + :is(.flow-chat-composer-preview__action, .flow-chat-composer-preview__model) { + block-size: 100%; +} + +.flow-chat-composer-preview [data-bf-layout="compact"] + .flow-chat-composer-preview__action { + inline-size: auto; +} + +.flow-chat-composer-preview__action--fill { + background: var(--bf-color-action-neutral-surface); +} + +.flow-chat-composer-preview__action--primary { + color: var(--bf-color-action-primary-content); + background: var(--bf-color-action-primary-background); +} + +.flow-chat-composer-preview__action > svg { + inline-size: var(--bf-font-size-body); + block-size: var(--bf-font-size-body); +} + +.flow-chat-composer-preview__model { + max-inline-size: 180px; + gap: var(--bf-space-1); + padding-inline: var(--bf-space-2); + border-radius: var(--bf-radius-pill); + font-family: var(--bf-font-family-control); + font-size: var(--bf-font-size-small); +} + +.flow-chat-composer-preview__model > span { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.flow-chat-composer-preview__model > small { + color: var(--bf-color-content-muted); + font: inherit; +} + +.flow-chat-composer-preview__action:hover:not(:disabled), +.flow-chat-composer-preview__model:hover:not(:disabled) { + background: var(--bf-color-action-neutral-surface-hover); +} + +.flow-chat-composer-preview__action:focus-visible, +.flow-chat-composer-preview__model:focus-visible { + outline: var(--bf-focus-width) solid var(--bf-color-focus-ring); + outline-offset: var(--bf-focus-offset); +} + +.flow-chat-tool-card-preview__command { + display: block; + overflow: hidden; + min-inline-size: 0; + color: inherit; + font-family: var(--bf-font-family-mono); + text-overflow: ellipsis; + white-space: nowrap; +} + +.flow-chat-tool-card-preview__action { + display: inline-grid; + inline-size: var(--bf-space-6); + block-size: var(--bf-space-6); + place-items: center; + margin: 0; + padding: 0; + border: 0; + border-radius: var(--bf-radius-sm); + color: var(--bf-color-content-muted); + background: transparent; + cursor: pointer; +} + +.flow-chat-tool-card-preview__action:hover { + color: var(--bf-color-content-primary); + background: var(--bf-color-action-neutral-surface); +} + +.flow-chat-tool-card-preview__action:focus-visible { + outline: var(--bf-focus-width) solid var(--bf-color-focus-ring); + outline-offset: var(--bf-focus-offset); +} + +.flow-chat-tool-card-preview__action > svg { + inline-size: var(--bf-font-size-base); + block-size: var(--bf-font-size-base); +} + +.flow-chat-tool-card-preview__details { + display: grid; + gap: var(--bf-space-2); + min-inline-size: 0; +} + +.flow-chat-tool-card-preview__details code { + overflow: hidden; + color: var(--bf-color-content-primary); + font-family: var(--bf-font-family-mono); + text-overflow: ellipsis; + white-space: nowrap; +} + +.flow-chat-tool-card-preview__details span { + color: var(--bf-color-content-muted); +} + +.flow-chat-tool-card-preview__duration { + display: inline-flex; + align-items: center; + gap: var(--bf-space-1); + color: var(--bf-color-content-muted); + font-family: var(--bf-font-family-mono); + font-variant-numeric: tabular-nums; +} + +.flow-chat-tool-card-preview__duration[data-status="completed"] { + color: var(--bf-color-status-success-content); +} + +.flow-chat-tool-card-preview__duration > svg { + inline-size: var(--bf-font-size-small); + block-size: var(--bf-font-size-small); +} + +.flow-chat-tool-card-preview__output, +.flow-chat-tool-card-preview__diff { + display: grid; + gap: var(--bf-space-1); + margin: 0; + color: var(--bf-color-content-secondary); + font-family: var(--bf-font-family-mono); + font-size: var(--bf-font-size-small); + line-height: var(--bf-line-height-body); + white-space: pre-wrap; +} + +.flow-chat-tool-card-preview__diff [data-change="added"] { + color: var(--bf-color-status-success-content); +} + +.flow-chat-tool-card-preview__diff [data-change="removed"] { + color: var(--bf-color-status-danger-content); +} + +@media (prefers-reduced-motion: reduce) { + .flow-chat-tool-card-preview__action { + transition: none; + } +} diff --git a/design-system/apps/design-lab/src/preview/FlowChatPreviewRegistry.tsx b/design-system/apps/design-lab/src/preview/FlowChatPreviewRegistry.tsx new file mode 100644 index 0000000000..fefa250fed --- /dev/null +++ b/design-system/apps/design-lab/src/preview/FlowChatPreviewRegistry.tsx @@ -0,0 +1,1242 @@ +import { + Fragment, + useState, + type ReactNode, +} from "react"; +import { + Archive, + ArrowDownToLine, + ArrowUp, + Bot, + CheckCircle2, + Circle, + Code2, + Copy, + FileEdit, + FileText, + FolderOpen, + FolderSearch, + GitBranch, + GitCompare, + Globe, + Hourglass, + Image as ImageIcon, + Info, + Layers, + ListTodo, + MessageSquare, + Mic, + Monitor, + Plus, + Rocket, + Search, + SearchCheck, + Shield, + SquareTerminal, + Terminal, + Timer, + Zap, + type LucideIcon, +} from "lucide-react"; +import { + AgentControlToolCard, + AgentWaitToolCard, + AmbientToolCard, + AmbientToolCardHeader, + AskUser, + ChatComposer, + CommandToolCard, + ContextCompressionToolCard, + DefaultToolCard, + DirectoryListToolCard, + FileDiffToolCard, + FileOperationToolCard, + GetToolSpecToolCard, + GitToolCard, + GlobSearchToolCard, + GrepSearchToolCard, + PageDeployToolCard, + PagePublishToolCard, + ProminentToolCard, + ProminentToolCardHeader, + ReadFileToolCard, + ReviewSummaryToolCard, + RunCodeToolCard, + SessionControlToolCard, + SessionMessageToolCard, + SkillToolCard, + TerminalControlToolCard, + TodoToolCard, + ToolCardChangeSummary, + ToolCardHeaderActions, + ViewImageToolCard, + WebFetchToolCard, + WebSearchToolCard, + type FileOperationKind, + type FlowChatToolStatus, + type AskUserAnswers, + type AskUserState, +} from "@bitfun/ui/flow-chat"; +import { componentRegistry } from "@bitfun/ui/registry"; +import { useI18n } from "../i18n"; +import "./FlowChatPreviewRegistry.css"; + +type RegisteredComponent = (typeof componentRegistry)[number]; + +export type FlowChatComponentMeta = Extract< + RegisteredComponent, + { readonly category: "flow-chat" } +>; +export type FlowChatComponentName = FlowChatComponentMeta["name"]; +export type FlowChatPreviewAttention = "adaptive" | "ambient" | "prominent"; +export type FlowChatPreviewSection = "framework" | "tool-card"; +export type FlowChatPreviewState = FlowChatComponentMeta["states"][number]; + +export interface FlowChatToolSpecimen { + tool: string; +} + +interface FlowChatPreviewRenderOptions { + interactive: boolean; + specimen?: FlowChatToolSpecimen; + state: FlowChatPreviewState; +} + +type Translate = ReturnType["t"]; + +export interface FlowChatPreviewDefinition { + attention: FlowChatPreviewAttention; + codeSample: (t: Translate) => string; + icon: LucideIcon; + render: (options: FlowChatPreviewRenderOptions) => ReactNode; + section: FlowChatPreviewSection; + specimens: readonly FlowChatToolSpecimen[]; +} + +type FlowChatPreviewDefinitionMap = { + readonly [Name in FlowChatComponentName]: FlowChatPreviewDefinition; +}; + +type PreviewProps = FlowChatPreviewRenderOptions; + +function ChatComposerPreview({ interactive, state }: PreviewProps) { + const [value, setValue] = useState(""); + const expanded = state === "expanded"; + + return ( +
+ + + BitFun + + + + +
+ )} + disabled={state === "disabled"} + endActions={( + <> + + + + + )} + layout={expanded ? "expanded" : "compact"} + startActions={( + + )} + > +