mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-17 22:05:50 +00:00
* feat: 第一版大重构 * fix: 修复类型问题 * chore: 更新版本到 1.3.2 * Add brave as alternative WebSearchTool * fix: 修正顺序 * fix: 修复对穷鬼模式的 auto dream 和 session memory 越过 * feat: 穷鬼模式去除 session-summary * feat: 创建 builtin-tools 包,搬运所有工具实现 将 src/tools/ 下的全部 60 个工具目录迁移至 packages/builtin-tools/src/tools/, 内部导入路径已更新为 src/ alias 模式。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: 更新 src/ 中所有工具引用至 builtin-tools 包,删除 src/tools/ - src/tools.ts 及 178 个 src/ 文件的 import 路径从 ./tools/ 改为 builtin-tools/tools/ - 删除 src/tools/ 整个目录(已迁移至 packages/builtin-tools/) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: 添加 builtin-tools 路径别名至 tsconfig,更新 bun.lock - tsconfig.json 新增 builtin-tools/* 和 builtin-tools 路径映射 - 新增 packages/builtin-tools/src 至 include Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: 为 builtin-tools、mcp-client、agent-tools 添加 @claude-code-best 作用域前缀 所有包名及 import 路径统一添加 @claude-code-best/ 前缀: - builtin-tools → @claude-code-best/builtin-tools - mcp-client → @claude-code-best/mcp-client - agent-tools → @claude-code-best/agent-tools Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: 修复 node 环境没有 bun 的问题 --------- Co-authored-by: Eric-Guo <eric.guocz@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
391 lines
11 KiB
Markdown
391 lines
11 KiB
Markdown
# Chapter 5: Design System Components
|
|
|
|
Pre-built theme-aware UI components for common terminal interface patterns.
|
|
|
|
## Dialog
|
|
|
|
Modal dialog with border, title, and keyboard navigation.
|
|
|
|
```tsx
|
|
import { Dialog } from '@anthropic/ink'
|
|
|
|
<Dialog
|
|
title="Confirm Action"
|
|
subtitle="This cannot be undone"
|
|
onCancel={() => setShowDialog(false)}
|
|
color="warning"
|
|
>
|
|
<Text>Are you sure you want to proceed?</Text>
|
|
</Dialog>
|
|
```
|
|
|
|
### Props
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `title` | `ReactNode` | - | Dialog title (required) |
|
|
| `subtitle` | `ReactNode` | - | Optional subtitle |
|
|
| `children` | `ReactNode` | - | Dialog body content |
|
|
| `onCancel` | `() => void` | - | Called on Esc/n (required) |
|
|
| `color` | `keyof Theme` | `'permission'` | Title and border color |
|
|
| `hideInputGuide` | `boolean` | `false` | Hide the keyboard hint footer |
|
|
| `hideBorder` | `boolean` | `false` | Render without Pane border |
|
|
| `inputGuide` | `(exitState) => ReactNode` | - | Custom input guide footer |
|
|
| `isCancelActive` | `boolean` | `true` | Enable/disable cancel keybindings |
|
|
|
|
### Keyboard Shortcuts
|
|
|
|
- **Enter** -- Confirm (consumer handles this)
|
|
- **Esc / n** -- Cancel (calls `onCancel`)
|
|
- **Ctrl+C / Ctrl+D** -- Double-press to exit
|
|
|
|
### Custom Input Guide
|
|
|
|
```tsx
|
|
<Dialog
|
|
title="Save file?"
|
|
onCancel={handleCancel}
|
|
inputGuide={(exitState) => (
|
|
exitState.pending
|
|
? <Text>Press {exitState.keyName} again to exit</Text>
|
|
: <Text>Press Enter to save, Esc to cancel</Text>
|
|
)}
|
|
>
|
|
...
|
|
</Dialog>
|
|
```
|
|
|
|
## Pane
|
|
|
|
Bordered container with themed top border.
|
|
|
|
```tsx
|
|
import { Pane } from '@anthropic/ink'
|
|
|
|
<Pane color="permission">
|
|
<Text>Content inside a bordered pane</Text>
|
|
</Pane>
|
|
```
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `children` | `ReactNode` | - | Content |
|
|
| `color` | `keyof Theme` | `'permission'` | Top border color |
|
|
|
|
## ProgressBar
|
|
|
|
Visual progress indicator.
|
|
|
|
```tsx
|
|
import { ProgressBar } from '@anthropic/ink'
|
|
|
|
<ProgressBar
|
|
ratio={0.65}
|
|
width={40}
|
|
fillColor="rate_limit_fill"
|
|
emptyColor="rate_limit_empty"
|
|
/>
|
|
```
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `ratio` | `number` | - | Progress 0..1 (required) |
|
|
| `width` | `number` | - | Character width (required) |
|
|
| `fillColor` | `keyof Theme` | - | Filled portion color |
|
|
| `emptyColor` | `keyof Theme` | - | Empty portion color |
|
|
|
|
## Spinner
|
|
|
|
Animated loading spinner. No props.
|
|
|
|
```tsx
|
|
import { Spinner } from '@anthropic/ink'
|
|
|
|
<Box gap={1}>
|
|
<Spinner />
|
|
<Text>Loading...</Text>
|
|
</Box>
|
|
```
|
|
|
|
## LoadingState
|
|
|
|
Loading message with spinner and optional subtitle.
|
|
|
|
```tsx
|
|
import { LoadingState } from '@anthropic/ink'
|
|
|
|
<LoadingState
|
|
message="Installing dependencies"
|
|
subtitle="This may take a moment"
|
|
bold={true}
|
|
/>
|
|
```
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `message` | `string` | - | Loading message (required) |
|
|
| `bold` | `boolean` | `false` | Bold message |
|
|
| `dimColor` | `boolean` | `false` | Dimmed message |
|
|
| `subtitle` | `string` | - | Secondary text below |
|
|
|
|
## StatusIcon
|
|
|
|
Semantic status indicator with icon and color.
|
|
|
|
```tsx
|
|
import { StatusIcon } from '@anthropic/ink'
|
|
|
|
<StatusIcon status="success" withSpace />
|
|
<Text>Build complete</Text>
|
|
```
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `status` | `'success' \| 'error' \| 'warning' \| 'info' \| 'pending' \| 'loading'` | - | Status type (required) |
|
|
| `withSpace` | `boolean` | `false` | Add trailing space |
|
|
|
|
Status icons:
|
|
- `success` -- Green checkmark
|
|
- `error` -- Red cross
|
|
- `warning` -- Yellow warning
|
|
- `info` -- Blue info
|
|
- `pending` -- Dimmed circle
|
|
- `loading` -- Dimmed ellipsis
|
|
|
|
## FuzzyPicker
|
|
|
|
Full-featured fuzzy search selector with preview support.
|
|
|
|
```tsx
|
|
import { FuzzyPicker } from '@anthropic/ink'
|
|
|
|
<FuzzyPicker
|
|
title="Select a file"
|
|
items={files}
|
|
getKey={(f) => f.path}
|
|
renderItem={(f, focused) => <Text>{f.name}</Text>}
|
|
onQueryChange={(q) => setFilteredFiles(filterFiles(q))}
|
|
onSelect={(f) => openFile(f)}
|
|
onCancel={() => setShowPicker(false)}
|
|
/>
|
|
```
|
|
|
|
### Props
|
|
|
|
| Prop | Type | Description |
|
|
|------|------|-------------|
|
|
| `title` | `string` | Picker title (required) |
|
|
| `items` | `readonly T[]` | Items to display (required) |
|
|
| `getKey` | `(item: T) => string` | Unique key extractor (required) |
|
|
| `renderItem` | `(item: T, isFocused: boolean) => ReactNode` | Item renderer (required) |
|
|
| `onQueryChange` | `(query: string) => void` | Filter callback (required) |
|
|
| `onSelect` | `(item: T) => void` | Enter key handler (required) |
|
|
| `onCancel` | `() => void` | Esc handler (required) |
|
|
| `renderPreview` | `(item: T) => ReactNode` | Preview panel renderer |
|
|
| `previewPosition` | `'bottom' \| 'right'` | Preview placement |
|
|
| `visibleCount` | `number` | Max visible items |
|
|
| `direction` | `'down' \| 'up'` | Item ordering |
|
|
| `onTab` | `PickerAction<T>` | Tab key handler |
|
|
| `onShiftTab` | `PickerAction<T>` | Shift+Tab handler |
|
|
| `onFocus` | `(item: T \| undefined) => void` | Focus change callback |
|
|
| `emptyMessage` | `string \| ((query: string) => string)` | Empty state message |
|
|
| `matchLabel` | `string` | Status line below list |
|
|
| `placeholder` | `string` | Input placeholder |
|
|
| `initialQuery` | `string` | Initial search query |
|
|
| `selectAction` | `string` | Action label for byline |
|
|
| `extraHints` | `ReactNode` | Additional keyboard hints |
|
|
|
|
## Tabs / Tab
|
|
|
|
Tabbed interface with keyboard navigation.
|
|
|
|
```tsx
|
|
import { Tabs, Tab } from '@anthropic/ink'
|
|
|
|
<Tabs title="Settings" color="claude">
|
|
<Tab title="General" id="general">
|
|
<GeneralSettings />
|
|
</Tab>
|
|
<Tab title="Advanced" id="advanced">
|
|
<AdvancedSettings />
|
|
</Tab>
|
|
</Tabs>
|
|
```
|
|
|
|
### Tabs Props
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `children` | `ReactElement<TabProps>[]` | - | Tab elements |
|
|
| `title` | `string` | - | Header title |
|
|
| `color` | `keyof Theme` | - | Active tab indicator color |
|
|
| `defaultTab` | `string` | - | Initial tab id |
|
|
| `selectedTab` | `string` | - | Controlled selected tab |
|
|
| `onTabChange` | `(tabId: string) => void` | - | Tab change callback |
|
|
| `hidden` | `boolean` | `false` | Hide tab headers |
|
|
| `useFullWidth` | `boolean` | `false` | Use full terminal width |
|
|
| `banner` | `ReactNode` | - | Banner below tab headers |
|
|
| `disableNavigation` | `boolean` | `false` | Disable keyboard nav |
|
|
| `initialHeaderFocused` | `boolean` | `true` | Start with header focused |
|
|
| `contentHeight` | `number` | - | Fixed content height |
|
|
| `navFromContent` | `boolean` | `false` | Allow Tab/Arrow from content |
|
|
|
|
### Tab Props
|
|
|
|
| Prop | Type | Description |
|
|
|------|------|-------------|
|
|
| `title` | `string` | Tab label (required) |
|
|
| `id` | `string` | Tab identifier |
|
|
| `children` | `ReactNode` | Tab content |
|
|
|
|
### Tab Hooks
|
|
|
|
```tsx
|
|
import { useTabsWidth, useTabHeaderFocus } from '@anthropic/ink'
|
|
|
|
const width = useTabsWidth() // Available content width
|
|
const focused = useTabHeaderFocus() // Whether tab header is focused
|
|
```
|
|
|
|
## ListItem
|
|
|
|
Selectable list item with focus/selection indicators.
|
|
|
|
```tsx
|
|
import { ListItem } from '@anthropic/ink'
|
|
|
|
<ListItem isFocused={index === focusedIndex} isSelected={item.checked}>
|
|
<Text>{item.label}</Text>
|
|
</ListItem>
|
|
```
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `isFocused` | `boolean` | - | Keyboard focus (required) |
|
|
| `isSelected` | `boolean` | `false` | Checked/active state |
|
|
| `children` | `ReactNode` | - | Content |
|
|
| `description` | `string` | - | Secondary text below |
|
|
| `styled` | `boolean` | `true` | Auto-style based on state |
|
|
| `disabled` | `boolean` | `false` | Dimmed, non-interactive |
|
|
| `showScrollDown` | `boolean` | `false` | Scroll-down hint arrow |
|
|
| `showScrollUp` | `boolean` | `false` | Scroll-up hint arrow |
|
|
| `declareCursor` | `boolean` | `true` | Declare terminal cursor |
|
|
|
|
## SearchBox
|
|
|
|
Search input with theme-aware styling.
|
|
|
|
```tsx
|
|
import { SearchBox } from '@anthropic/ink'
|
|
|
|
<SearchBox
|
|
query={searchQuery}
|
|
placeholder="Search..."
|
|
isFocused={true}
|
|
isTerminalFocused={true}
|
|
width="100%"
|
|
/>
|
|
```
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `query` | `string` | - | Current search text |
|
|
| `placeholder` | `string` | - | Placeholder text |
|
|
| `isFocused` | `boolean` | - | Focus state |
|
|
| `isTerminalFocused` | `boolean` | - | Terminal focus state |
|
|
| `prefix` | `string` | - | Input prefix label |
|
|
| `width` | `number \| string` | - | Input width |
|
|
| `cursorOffset` | `number` | - | Cursor position offset |
|
|
| `borderless` | `boolean` | `false` | Remove border |
|
|
|
|
## Divider
|
|
|
|
Horizontal/vertical divider line.
|
|
|
|
```tsx
|
|
import { Divider } from '@anthropic/ink'
|
|
|
|
<Divider width={60} color="subtle" />
|
|
<Divider title="Section Title" />
|
|
```
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `width` | `number` | Terminal width | Divider width |
|
|
| `color` | `keyof Theme` | Dimmed | Line color |
|
|
| `char` | `string` | `'─'` | Line character |
|
|
| `padding` | `number` | `0` | Width reduction |
|
|
| `title` | `string` | - | Centered title text |
|
|
|
|
## Byline
|
|
|
|
Footer with middot-separated items.
|
|
|
|
```tsx
|
|
import { Byline } from '@anthropic/ink'
|
|
|
|
<Byline>
|
|
<KeyboardShortcutHint shortcut="Enter" action="confirm" />
|
|
<KeyboardShortcutHint shortcut="Esc" action="cancel" />
|
|
</Byline>
|
|
```
|
|
|
|
## KeyboardShortcutHint
|
|
|
|
Display a keyboard shortcut with its action.
|
|
|
|
```tsx
|
|
import { KeyboardShortcutHint } from '@anthropic/ink'
|
|
|
|
<KeyboardShortcutHint shortcut="Enter" action="confirm" />
|
|
<KeyboardShortcutHint shortcut="↑/↓" action="navigate" parens />
|
|
```
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `shortcut` | `string` | - | Key or chord to display |
|
|
| `action` | `string` | - | Action description |
|
|
| `parens` | `boolean` | `false` | Wrap in parentheses |
|
|
| `bold` | `boolean` | `false` | Bold shortcut text |
|
|
|
|
## ConfigurableShortcutHint
|
|
|
|
Displays a shortcut hint that reads the actual keybinding from config.
|
|
|
|
```tsx
|
|
import { ConfigurableShortcutHint } from '@anthropic/ink'
|
|
|
|
<ConfigurableShortcutHint
|
|
action="confirm:no"
|
|
context="Confirmation"
|
|
fallback="Esc"
|
|
description="cancel"
|
|
/>
|
|
```
|
|
|
|
| Prop | Type | Description |
|
|
|------|------|-------------|
|
|
| `action` | `string` | Keybinding action name |
|
|
| `context` | `string` | Keybinding context |
|
|
| `fallback` | `string` | Default shortcut if unbound |
|
|
| `description` | `string` | Action description |
|
|
| `parens` | `boolean` | Wrap in parentheses |
|
|
| `bold` | `boolean` | Bold shortcut text |
|
|
|
|
## Ratchet
|
|
|
|
Animated counter component that prevents layout jumps.
|
|
|
|
```tsx
|
|
import { Ratchet } from '@anthropic/ink'
|
|
|
|
<Ratchet lock="always">
|
|
<Text>{count}</Text>
|
|
</Ratchet>
|
|
```
|
|
|
|
| Prop | Type | Default | Description |
|
|
|------|------|---------|-------------|
|
|
| `children` | `ReactNode` | - | Content |
|
|
| `lock` | `'always' \| 'offscreen'` | `'always'` | Width locking strategy. `'always'` locks always; `'offscreen'` only locks when the element is scrolled off-screen |
|