Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions design-system/apps/design-lab/src/i18n/componentMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const descriptionKeys: Readonly<Record<string, MessageKey>> = {
GlobSearchToolCard: "component.GlobSearchToolCard.description",
GrepSearchToolCard: "component.GrepSearchToolCard.description",
Icon: "component.Icon.description",
ThinkingIndicator: "component.ThinkingIndicator.description",
IconButton: "component.IconButton.description",
Input: "component.Input.description",
KeyHint: "component.KeyHint.description",
Expand Down Expand Up @@ -92,6 +93,7 @@ const descriptionKeys: Readonly<Record<string, MessageKey>> = {
ReadFileToolCard: "component.ReadFileToolCard.description",
ReviewSummaryToolCard: "component.ReviewSummaryToolCard.description",
RollingText: "component.RollingText.description",
ShimmerText: "component.ShimmerText.description",
RunCodeToolCard: "component.RunCodeToolCard.description",
SearchField: "component.SearchField.description",
SegmentedControl: "component.SegmentedControl.description",
Expand Down
21 changes: 21 additions & 0 deletions design-system/apps/design-lab/src/i18n/flowChatMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ export const flowChatEn = {
"runtimeCards.controlTitle": "Inspect capabilities",
"runtimeCards.result": "Result",
"flowChat.contextLoadGroup.summary": "{count} context loads",
"flowChat.fileEditGroup.summary": "{count} edits",
"flowChat.fileEditGroup.label": "{count} edits:",
"flowChat.fileEditGroup.expanded": "File edits:",
"flowChat.fileEditGroup.changes": "{additions} lines added, {deletions} lines removed",
"flowChat.fileEditGroup.description": "{path}, {count} consecutive edits",
"flowChat.fileEditGroup.revision": "Edit {count}",
"flowChat.fileEditGroup.failed": "{count} failed",
"flowChat.contextLoadGroup.description": "{count} context-loading calls, including repeat loads",
"component.FlowGroup.description": "A reusable collection with shared disclosure, scrolling and arrival feedback.",
"component.ContextLoadGroup.description": "Context loads with controlled disclosure for skills, tool specifications and capability discovery.",
Expand Down Expand Up @@ -204,6 +211,13 @@ export const flowChatZhCN = {
"runtimeCards.controlTitle": "查询控制能力",
"runtimeCards.result": "执行结果",
"flowChat.contextLoadGroup.summary": "{count} 次上下文加载",
"flowChat.fileEditGroup.summary": "{count} 次编辑",
"flowChat.fileEditGroup.label": "{count} 次编辑:",
"flowChat.fileEditGroup.expanded": "文件编辑:",
"flowChat.fileEditGroup.changes": "新增 {additions} 行,删除 {deletions} 行",
"flowChat.fileEditGroup.description": "{path},连续编辑 {count} 次",
"flowChat.fileEditGroup.revision": "第 {count} 次编辑",
"flowChat.fileEditGroup.failed": "{count} 次失败",
"flowChat.contextLoadGroup.description": "{count} 次上下文加载,含重复加载",
"component.FlowGroup.description": "可复用的收纳组,统一展开收起、内容滚动和接收反馈。",
"component.ContextLoadGroup.description": "上下文加载组,收纳技能、工具说明与能力查询,统一展开收起。",
Expand Down Expand Up @@ -344,6 +358,13 @@ export const flowChatZhTW = {
"runtimeCards.controlTitle": "查詢控制能力",
"runtimeCards.result": "執行結果",
"flowChat.contextLoadGroup.summary": "{count} 次上下文載入",
"flowChat.fileEditGroup.summary": "{count} 次編輯",
"flowChat.fileEditGroup.label": "{count} 次編輯:",
"flowChat.fileEditGroup.expanded": "檔案編輯:",
"flowChat.fileEditGroup.changes": "新增 {additions} 行,刪除 {deletions} 行",
"flowChat.fileEditGroup.description": "{path},連續編輯 {count} 次",
"flowChat.fileEditGroup.revision": "第 {count} 次編輯",
"flowChat.fileEditGroup.failed": "{count} 次失敗",
"flowChat.contextLoadGroup.description": "{count} 次上下文載入,含重複載入",
"component.FlowGroup.description": "可重用的收納組,統一展開收合、內容捲動與接收回饋。",
"component.ContextLoadGroup.description": "上下文載入組,收納技能、工具說明與能力查詢,統一展開收合。",
Expand Down
16 changes: 16 additions & 0 deletions design-system/apps/design-lab/src/i18n/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { brandAssetsEn, brandAssetsZhCN, brandAssetsZhTW } from "./brandMessages
import { designEn, designZhCN, designZhTW } from "./designMessages";
import { flowChatEn, flowChatZhCN, flowChatZhTW } from "./flowChatMessages";
import { subagentMotionEn, subagentMotionZhCN, subagentMotionZhTW } from "./subagentMotionMessages";
import { thinkingIndicatorEn, thinkingIndicatorZhCN, thinkingIndicatorZhTW } from "./thinkingIndicatorMessages";
import type { DesignLabLocale } from "./core.mjs";

export const enUSMessages = {
Expand All @@ -12,6 +13,7 @@ export const enUSMessages = {
...designEn,
...brandAssetsEn,
...subagentMotionEn,
...thinkingIndicatorEn,
...flowChatEn,
"component.OpenBitFunSolidMark.description": "The original silver solid mark on a transparent canvas, preserving its material and shading.",
"component.OpenBitFunAppIcon.description": "The application icon used by the installed product: silver mark, black rounded-square tile, and assets for different display sizes.",
Expand Down Expand Up @@ -184,6 +186,7 @@ export const enUSMessages = {
"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.RollingText.description": "Vertical text replacement with coordinated width, interruption handling, and reduced-motion support. Try repeated clicks in the replacement specimen.",
"component.ShimmerText.description": "A soft fade moves slowly across activity text, keeping every glyph visible. Reduced motion, high contrast and print keep the text static and readable.",
"components.preview.replaceText": "Replace title",
"components.preview.rollingTextLong": "Review workspace navigation and session switching",
"detail.option.replacing": "Replacement",
Expand Down Expand Up @@ -596,6 +599,9 @@ export const enUSMessages = {
"detail.option.display": "Display",
"detail.option.completed": "Completed",
"detail.option.expanded": "Expanded",
"detail.option.file-collapsed": "File revisions, collapsed",
"detail.option.file-expanded": "File revisions, expanded",
"detail.option.file-error": "File revisions, failed edit",
"detail.option.loading": "Loading",
"detail.option.multiple": "Multiple selection",
"detail.option.custom": "Custom value",
Expand Down Expand Up @@ -811,6 +817,7 @@ export const zhCNMessages = {
...designZhCN,
...brandAssetsZhCN,
...subagentMotionZhCN,
...thinkingIndicatorZhCN,
...flowChatZhCN,
"component.OpenBitFunSolidMark.description": "透明底的银色实体标志,保留原稿的材质、光泽与立体明暗。",
"component.OpenBitFunAppIcon.description": "实际应用使用的图标:银色实体标志、黑色圆角底板,以及适配不同显示尺寸的资源。",
Expand Down Expand Up @@ -983,6 +990,7 @@ export const zhCNMessages = {
"component.Switch.description": "通过原生复选框语义在开启与关闭之间切换单项设置。",
"component.TabGroup.description": "紧凑的单选标签组,支持前置图标、尾部操作与方向键自动切换。",
"component.RollingText.description": "垂直滚动替换文本,宽度同步过渡,支持连续切换与减少动态效果。可在替换示例中连续点击体验。",
"component.ShimmerText.description": "柔和的渐隐在运行文字间缓慢流动,始终保留完整字形;减少动态效果、高对比度和打印时保持静态可读。",
"components.preview.replaceText": "替换标题",
"components.preview.rollingTextLong": "检查工作区导航与会话切换时的交互行为",
"detail.option.replacing": "替换",
Expand Down Expand Up @@ -1395,6 +1403,9 @@ export const zhCNMessages = {
"detail.option.display": "展示",
"detail.option.completed": "已完成",
"detail.option.expanded": "展开",
"detail.option.file-collapsed": "文件修订 · 折叠",
"detail.option.file-expanded": "文件修订 · 展开",
"detail.option.file-error": "文件修订 · 编辑失败",
"detail.option.loading": "加载中",
"detail.option.multiple": "多选",
"detail.option.custom": "自定义值",
Expand Down Expand Up @@ -1608,6 +1619,7 @@ export const zhTWMessages = {
...previewZhTW,
...brandAssetsZhTW,
...subagentMotionZhTW,
...thinkingIndicatorZhTW,
...flowChatZhTW,
"patterns.description": "查看元件在常見介面中的組合與互動。",
"patterns.title": "組合範例",
Expand Down Expand Up @@ -1822,6 +1834,7 @@ export const zhTWMessages = {
"component.Switch.description": "以原生核取方塊語意在開啟與關閉之間切換單一設定。",
"component.TabGroup.description": "緊湊的單選標籤群組,支援前置圖示、尾端操作與方向鍵自動切換。",
"component.RollingText.description": "垂直捲動替換文字,寬度同步過渡,支援連續切換與減少動態效果。可在替換範例中連續點擊體驗。",
"component.ShimmerText.description": "柔和的漸隱在執行文字間緩慢流動,始終保留完整字形;減少動態效果、高對比度和列印時保持靜態可讀。",
"components.preview.replaceText": "替換標題",
"components.preview.rollingTextLong": "檢查工作區導覽與工作階段切換時的互動行為",
"detail.option.replacing": "替換",
Expand Down Expand Up @@ -2136,6 +2149,9 @@ export const zhTWMessages = {
"detail.option.display": "展示",
"detail.option.completed": "已完成",
"detail.option.expanded": "展開",
"detail.option.file-collapsed": "檔案修訂 · 收合",
"detail.option.file-expanded": "檔案修訂 · 展開",
"detail.option.file-error": "檔案修訂 · 編輯失敗",
"detail.option.loading": "載入中",
"detail.option.multiple": "多選",
"detail.option.custom": "自訂值",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const subagentMotionEn = {
"subagentMotion.nod.description": "One small nod acknowledges taking the task. The body moves first; the joystick follows and settles.",
"subagentMotion.working.label": "Focused work",
"subagentMotion.working.hint": "A measured rhythm",
"subagentMotion.working.description": "The body stays grounded while the joystick moves gently, with pauses between movements. Loops while working.",
"subagentMotion.working.description": "The eyes lead each small lean, followed by the joystick. A grounded two-beat rhythm with brief pauses repeats while working.",
"subagentMotion.waiting.label": "Wait for you",
"subagentMotion.waiting.hint": "Look up, then hold",
"subagentMotion.waiting.description": "The character lifts its gaze once, then holds still while waiting for a response.",
Expand Down Expand Up @@ -122,7 +122,7 @@ export const subagentMotionZhCN = {
"subagentMotion.nod.description": "身体先轻轻点头,顶部摇杆延迟跟随,再回到原位。用于任务实际被接手之后。",
"subagentMotion.working.label": "专注工作",
"subagentMotion.working.hint": "有停顿的工作节奏",
"subagentMotion.working.description": "身体保持稳定,顶部摇杆小幅摆动,动作之间留出停顿。工作期间轻缓循环。",
"subagentMotion.working.description": "视线先偏移,身体轻轻侧倾,顶部摇杆随后跟上。底部保持稳定,以两拍动作和短暂停顿循环表达正在工作。",
"subagentMotion.waiting.label": "等待回应",
"subagentMotion.waiting.hint": "抬眼,安静等你",
"subagentMotion.waiting.description": "抬起视线看向你,只提示一次,然后保持注视,等待确认或补充信息。",
Expand Down Expand Up @@ -192,7 +192,7 @@ export const subagentMotionZhTW = {
"subagentMotion.nod.description": "身體先輕輕點頭,頂部搖桿延遲跟隨,再回到原位。用於任務實際被接手之後。",
"subagentMotion.working.label": "專注工作",
"subagentMotion.working.hint": "有停頓的工作節奏",
"subagentMotion.working.description": "身體保持穩定,頂部搖桿小幅擺動,動作之間留出停頓。工作期間輕緩循環。",
"subagentMotion.working.description": "視線先偏移,身體輕輕側傾,頂部搖桿隨後跟上。底部保持穩定,以兩拍動作和短暫停頓循環表達正在工作。",
"subagentMotion.waiting.label": "等待回應",
"subagentMotion.waiting.hint": "抬眼,安靜等你",
"subagentMotion.waiting.description": "抬起視線看向你,只提示一次,然後保持注視,等待確認或補充資訊。",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export const thinkingIndicatorEn = {
"component.ThinkingIndicator.description": "The original nodes and lines gradually form the mark, hold its complete shape, then dissolve before forming again.",
"thinkingIndicator.title": "Form, dissolve, form again",
"thinkingIndicator.route": "Nodes appear as lines unfold downwards. The complete mark holds, then retracts from bottom to top.",
"thinkingIndicator.detail": "Enlarged detail · 2.2-second loop",
"thinkingIndicator.sizes": "Actual icon sizes",
"thinkingIndicator.static": "Static",
"thinkingIndicator.stop": "Show static icon",
"thinkingIndicator.play": "Play loop",
"thinkingIndicator.label": "Thinking",
"thinkingIndicator.note": "Lines stop at node boundaries. Reduced motion keeps the complete static mark.",
} as const;

export const thinkingIndicatorZhCN = {
"component.ThinkingIndicator.description": "原有节点和连线逐步形成图标,完整停留后逐步消散,再重新形成。",
"thinkingIndicator.title": "形成、消散、再形成",
"thinkingIndicator.route": "节点依次出现,连线向下展开;完整停留后,从底部逐步收回。",
"thinkingIndicator.detail": "放大细节 · 2.2 秒循环",
"thinkingIndicator.sizes": "实际图标尺寸",
"thinkingIndicator.static": "静态",
"thinkingIndicator.stop": "切换为静态",
"thinkingIndicator.play": "播放循环",
"thinkingIndicator.label": "正在思考",
"thinkingIndicator.note": "连线止于节点边缘;开启减少动态效果后,保留完整的静态图标。",
} satisfies Record<keyof typeof thinkingIndicatorEn, string>;

export const thinkingIndicatorZhTW = {
"component.ThinkingIndicator.description": "原有節點和連線逐步形成圖示,完整停留後逐步消散,再重新形成。",
"thinkingIndicator.title": "形成、消散、再形成",
"thinkingIndicator.route": "節點依次出現,連線向下展開;完整停留後,從底部逐步收回。",
"thinkingIndicator.detail": "放大細節 · 2.2 秒循環",
"thinkingIndicator.sizes": "實際圖示尺寸",
"thinkingIndicator.static": "靜態",
"thinkingIndicator.stop": "切換為靜態",
"thinkingIndicator.play": "播放循環",
"thinkingIndicator.label": "正在思考",
"thinkingIndicator.note": "連線止於節點邊緣;開啟減少動態效果後,保留完整的靜態圖示。",
} satisfies Record<keyof typeof thinkingIndicatorEn, string>;
16 changes: 16 additions & 0 deletions design-system/apps/design-lab/src/pages/ComponentDetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ import {
Select,
Sheet,
StatusPill,
ShimmerText,
Spinner,
Switch,
TabGroup,
Expand Down Expand Up @@ -128,6 +129,7 @@ import type { ComponentMeta } from "@openbitfun/ui/registry";
import previewImage from "../assets/design-system-hero.webp";
import { IconCompositionPreview } from "../preview/IconCompositionPreview";
import { RollingTextPreview } from "../preview/RollingTextPreview";
import { ThinkingIndicatorPreview } from "../preview/ThinkingIndicatorPreview";
import { NestedMenuPattern } from "./ReferencePatterns";
import { useI18n, type MessageKey } from "../i18n";
import {
Expand Down Expand Up @@ -180,6 +182,7 @@ const optionLabelKeys: Readonly<Record<string, MessageKey>> = {
summary: "detail.option.summary",
visible: "detail.option.visible",
active: "detail.option.active",
static: "thinkingIndicator.static",
"active-option": "detail.option.active-option",
always: "detail.option.always",
asking: "detail.option.asking",
Expand Down Expand Up @@ -440,6 +443,12 @@ export function ComponentDetailPage({
const inspectorStates = states;

const codeSample = useMemo(() => {
if (component.name === "ThinkingIndicator") {
return `import { ThinkingIndicator } from "@openbitfun/ui";\n\n<ThinkingIndicator active={thinking} size="sm" label="${t("thinkingIndicator.label")}" />\n`;
}
if (component.name === "ShimmerText") {
return `import { ShimmerText } from "@openbitfun/ui";\n\n<ShimmerText active={running}>${t("components.preview.flowChat.running")}</ShimmerText>\n`;
}
if (component.name === "RollingText") {
return 'import { RollingText, TabGroup } from "@openbitfun/ui";\n\n// Keep the identity stable for title edits; change it when replacing the resource.\n<RollingText transitionKey={record.id}>{record.title}</RollingText>\n\n// TabGroup owns the text slot and composes RollingText without nested clipping.\n<TabGroup\n aria-label="Views"\n items={[{ value: slotId, label: record.title, labelTransitionKey: record.id }]}\n/>\n';
}
Expand Down Expand Up @@ -891,6 +900,9 @@ export function ComponentDetailPage({
if (component.name === "Icon") {
return <Icon name={iconName} size={iconSize} tone={iconTone} />;
}
if (component.name === "ThinkingIndicator") {
return <ThinkingIndicatorPreview key={state} state={state} />;
}

if (component.name === "MobileButton") {
return <MobileButton data-openbitfun-preview-state={state} disabled={state === "disabled"} loading={state === "loading"}>{t("components.preview.actionCardTitle")}</MobileButton>;
Expand Down Expand Up @@ -1873,6 +1885,10 @@ export function ComponentDetailPage({
return <RollingTextPreview interactive={state === "replacing"} />;
}

if (component.name === "ShimmerText") {
return <ShimmerText active={state !== "static"}>{t("components.preview.flowChat.running")}</ShimmerText>;
}

if (component.name === "TabGroup") {
return <NavigationExample name={component.name} key={state} state={state} size={tabGroupSize} />;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ function RelationPreview({ state, interactive }: PreviewProps) {
? t('toolCards.interaction.sendingMessage') : t('toolCards.interaction.messageSent');
return <ToolRelationRow status={resolveStatus(state)} result={result}
interaction={{ operation: 'send', source: { kind: 'session', label: t('toolCards.interaction.currentSession') },
target: { kind: 'agent', label: 'Maintainer', details: interactive ? result : undefined } }}
target: { kind: 'agent', label: 'Maintainer' } }}
details={interactive ? result : undefined} resultLabel={t('toolCards.interaction.inspectMessage')} />;
}

Expand Down Expand Up @@ -768,7 +768,8 @@ function ConcreteProminentPreview({
agentName="reviewer"
onOpenAgent={interactive ? () => undefined : undefined}
openAgentLabel="Open agent"
statusLabel={state === "error" ? t("components.preview.flowChat.failed") : undefined}
statusLabel={state === "error" ? t("components.preview.flowChat.failed")
: state === "loading" ? t("components.preview.flowChat.running") : undefined}
statusTone={state === "error" ? "danger" : "neutral"}
summary="Review the shared FlowChat card boundary"
/>
Expand Down
Loading
Loading