@q1travel/design-system 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/.agents/skills/product-design/AGENTS.md +9 -0
  2. package/.agents/skills/product-design/SKILL.md +63 -0
  3. package/.agents/skills/product-design/exemplars/README.md +12 -0
  4. package/.agents/skills/product-design/references/copy.md +7 -0
  5. package/.agents/skills/product-design/references/coverage-gaps.md +9 -0
  6. package/.agents/skills/product-design/references/glossary.md +5 -0
  7. package/.agents/skills/product-design/references/interface-quality.md +7 -0
  8. package/.agents/skills/product-design/references/patterns.md +13 -0
  9. package/.agents/skills/product-design/references/product-judgment.md +7 -0
  10. package/.agents/skills/product-design/references/resilience.md +13 -0
  11. package/.agents/skills/product-design/references/review-geist.md +94 -0
  12. package/.agents/skills/product-design/references/rules.md +17 -0
  13. package/.agents/skills/product-design/references/surfaces-forms.md +14 -0
  14. package/.agents/skills/product-design/references/surfaces-overlays.md +12 -0
  15. package/.agents/skills/product-design/references/surfaces.md +14 -0
  16. package/bin/q1-design.mjs +464 -0
  17. package/contracts/design-engineering-principles.md +39 -0
  18. package/contracts/design.dark.md +333 -0
  19. package/contracts/design.md +333 -0
  20. package/contracts/icon-system.md +77 -0
  21. package/contracts/implementation-map.md +29 -0
  22. package/contracts/interface-guidelines.md +122 -0
  23. package/contracts/token-naming.md +82 -0
  24. package/{dist → dist-pkg}/design-system.d.ts +36 -26
  25. package/{dist → dist-pkg}/design-system.js +222 -216
  26. package/{dist → dist-pkg}/style.css +2 -2
  27. package/package.json +19 -9
  28. package/tooling/README.md +9 -0
  29. package/tooling/scripts/evals/fixtures.json +7 -0
  30. package/tooling/scripts/evals/rules-checklist.json +23 -0
  31. package/tooling/scripts/evals/transition-all/after/example.css +4 -0
  32. package/tooling/scripts/evals/transition-all/before/example.css +4 -0
@@ -0,0 +1,77 @@
1
+ # 图标系统 · Icons
2
+
3
+ > **状态**:本规范定义图标系统的**目标态**。当前文档站的界面图标仍由 `lucide-react` 渲染(其几何与下方规范一致),并存在若干 `18px` 等迁移前尺寸;迁移到自建工厂 + 注册表是独立排期任务,尚未完成。品牌符号已是自有原生 SVG。
4
+
5
+ q1travel 的界面图标**目标是**一套自建的线性图标系统:几何参照 Lucide,实现为受控的原生 SVG,不依赖第三方图标库。品牌符号(q1travel 标识)不属于此系统,作为品牌资产单独维护。
6
+
7
+ 本规范是图标系统的**单一真相源**;自建工厂落地时,其代码注释应指回本规范,而非另立编号体系。
8
+
9
+ ---
10
+
11
+ ## 设计规范
12
+
13
+ 所有界面图标共享同一组参数,由图标工厂统一强制,不依赖单个图标自觉遵守。
14
+
15
+ | 属性 | 值 |
16
+ | --- | --- |
17
+ | 画布 `viewBox` | `0 0 24 24` |
18
+ | 描边宽度 `stroke-width` | `1.8` |
19
+ | 填充 `fill` | `none` |
20
+ | 描边颜色 `stroke` | `currentColor` |
21
+ | 线帽 `stroke-linecap` | `round` |
22
+ | 连接 `stroke-linejoin` | `round` |
23
+ | `aria-hidden` | `true`(装饰默认)|
24
+ | `focusable` | `false` |
25
+
26
+ - **线性风格**:统一描边、无填充,与 Lucide 图标库一致的线性视觉语言。
27
+ - **`currentColor`**:图标颜色继承当前文本颜色,随主题与组件状态自动适配;**不在图标内写死颜色**。
28
+
29
+ ---
30
+
31
+ ## 尺寸
32
+
33
+ 按所在场景的密度选择,不在区间内随意取值。**默认 16px**(不传 size 时)。现有 `18px` 等实例为迁移前遗留,随自建迁移一并收敛(见顶部状态)。
34
+
35
+ | 尺寸 | 值 | 场景 |
36
+ | --- | --- | --- |
37
+ | 小 | `16px`(默认)| 按钮内、紧凑控件、导航 |
38
+ | 中 | `20px` | 独立图标、列表项 |
39
+ | 大 | `24px` | 强调、空状态 |
40
+
41
+ ---
42
+
43
+ ## 来源
44
+
45
+ | 类别 | 方案 |
46
+ | --- | --- |
47
+ | 界面图标 | 几何参照 Lucide,自建原生 SVG;**不引入** `lucide-react` 或任何第三方图标库(目标态,迁移中)|
48
+ | 品牌符号 | q1travel 标识,自有原生 SVG,作为品牌资产单独维护 |
49
+
50
+ 参照 Lucide 几何,是为沿用其成熟、克制的线性视觉;自建实现,是为完全可控、无第三方依赖、可统一治理。
51
+
52
+ ---
53
+
54
+ ## 治理
55
+
56
+ 图标是受控资源,统一遵循以下约束:
57
+
58
+ - **工厂**:所有图标经统一工厂创建,几何参数、颜色、尺寸与可访问性默认值由工厂强制,而非逐个图标维护。
59
+ - **注册表**:所有图标登记在唯一清单中,记录名称、用途与同义词;语义重复的图标只保留一个(例如「编辑」不并存 edit / pencil / modify)。
60
+ - **单一入口**:界面一律使用图标组件,不在业务代码中内联 `<svg>`。
61
+ - **受控例外(special)**:带额外状态或逻辑、确实无法走工厂的历史图标,登记在注册表的 `special` 字段、单独维护,不作为新增图标的范例。
62
+ - **新增流程**:先登记注册表、补入图标库展示,再投入使用。
63
+
64
+ ---
65
+
66
+ ## 可访问性
67
+
68
+ - 图标默认 `aria-hidden="true"` 且 `focusable="false"`,视为装饰;语义由相邻文本或调用方的 `aria-label` 承担。
69
+ - 纯图标控件(如图标按钮)必须由调用方提供可访问名称。
70
+
71
+ ---
72
+
73
+ ## 使用
74
+
75
+ - **颜色**:不为图标单独设色,依赖 `currentColor` 跟随文本。
76
+ - **间距**:图标与文本之间保留一致间距,并与文本基线对齐。
77
+ - **一致性**:同一控件组内不混用不同描边或尺寸。
@@ -0,0 +1,29 @@
1
+ # q1travel Design System Implementation Map
2
+
3
+ This map records how external reference intent is translated into q1travel production code. It is not a screenshot checklist and it is not a source for copied markup or copied styles.
4
+
5
+ ## Directory Shape
6
+
7
+ README owns the repository inventory and generated-file boundary. This file owns the reference-to-implementation mapping.
8
+
9
+ | Reference intent | q1travel semantic | Canonical surface | Token source | State | Responsive | Accessibility |
10
+ | --- | --- | --- | --- | --- | --- | --- |
11
+ | Bounded documentation frame | Public design-system shell | `AppShell`, `Sidebar`, `Topbar` | `--q1-color-bg-canvas`, `--q1-color-border`, spacing tokens | Route changes reset document scroll | Frame width and sidebar collapse through layout CSS | Landmarks, keyboard search, focus-visible ring |
12
+ | Compact search and command menu | Fast documentation navigation | `CommandMenu`, `Topbar` search trigger | Surface, border, text, focus tokens | Open, active option, escape close | Dialog width clamps on small screens | `role="dialog"`, `aria-modal`, keyboard navigation |
13
+ | Foundation page rhythm | Scannable reference pages | `PageHeader`, `SpecSection`, `SpecTable` | Heading, copy, border, spacing tokens | None beyond links and focus | Tables scroll horizontally when needed | Semantic headings and tables |
14
+ | Introduction tile grid | Entry points into public groups | `IntroTileGrid`, `IntroTile` | Surface, border, text, spacing tokens | Hover, focus | Two columns on desktop, one column on small screens | Tile is a single link with hidden decorative visual |
15
+ | Brand lockup preview | q1travel identity specimen | `Q1travelSymbol` with custom lockup composition | Text, border, spacing tokens plus documented lockup variables | None | Asset stage clamps to tile width | Decorative visual is hidden from assistive tech |
16
+ | Icon matrix preview | Icon component density sample | `showcaseIconEntries` rendered with Lucide icons | `currentColor`, text-secondary token | None | Grid clamps inside tile | Icons are decorative in the tile, named on the Icon component page |
17
+ | Component preview tile | Control density sample | Custom preview composition using component token mappings | Surface, border, action, focus, radius tokens | Button and segment visual states | Flex wrap preserves compact layout | Decorative in intro, real controls documented on component pages |
18
+ | Color rods preview | Color scale summary | Custom preview composition using color scale aliases | `--q1-color-scale-*` aliases | None | Rods distribute across available width | Semantic labels identify the represented scale |
19
+ | Color page reference and semantic tokens | Token reference and theme value copy | `ColorSwatch`, `SemanticColorListItem`, and `SemanticColorDemo` inside `ColorsPage` | `--q1-color-*`, semantic color tokens, and semantic action tokens | Left click copies token, context menu copies resolved value. The focus shadow token shows as an applied focus ring, not a flat color swatch | Ten-step grid and semantic rows adapt to available width | Button labels, semantic rows, live copy feedback |
20
+ | Page footer navigation | Sequential documentation reading | `PageNavigation` | Surface, border, text, spacing tokens | Hover, focus, feedback buttons | Three-column footer collapses with content | Links are named and feedback controls are buttons |
21
+
22
+ ## Implementation Rules
23
+
24
+ - Reference behavior must map to a q1travel semantic before it reaches `src`.
25
+ - New public tokens use `--q1-*`; existing product `--ds-*` names are legacy migration inputs, not new contract names.
26
+ - Canonical components own repeated structure. Page-local custom structures are allowed only for visual specimens with a narrow purpose.
27
+ - Token references are the design source for production code. Current theme resolved values are clipboard output only.
28
+ - The same public navigation groups remain in the product surface: `基础`, `品牌`, and `组件`.
29
+ - If a capability is missing from a shared component, add the capability to that component before adding another page-local pattern.
@@ -0,0 +1,122 @@
1
+ # q1travel Interface Guidelines
2
+
3
+ These guidelines adapt mature web interface rules into q1travel contracts. They apply to documentation pages, component samples, and future product surfaces that consume this design system. The public localized version is the `/guidelines` page (`src/pages/GuidelinesPage.tsx`); keep both in sync.
4
+
5
+ ## Interactions
6
+
7
+ - MUST support keyboard operation for every interactive path.
8
+ - MUST show a visible `:focus-visible` state for every focusable element.
9
+ - MUST manage focus for overlays: move focus on open, return it on close, and trap it where the APG pattern requires.
10
+ - MUST use native links for navigation and native buttons for actions.
11
+ - MUST keep visual and hit targets aligned; controls smaller than 24px need a larger interactive area.
12
+ - MUST keep mobile control targets at least 44px where touch is expected.
13
+ - NEVER disable browser zoom.
14
+ - MUST avoid dead zones: if a region looks clickable, the clickable element must cover it.
15
+ - MUST show a loading indicator on in-flight buttons while keeping the original label.
16
+ - SHOULD delay spinners and skeletons by ~150–300ms and keep them visible for ~300–500ms so fast responses do not flicker.
17
+ - SHOULD update the UI optimistically when success is likely, and roll back with an error (or offer Undo) on failure.
18
+ - MUST require confirmation or offer a safe-window Undo for destructive actions.
19
+ - MUST announce async updates (toasts, inline validation) via polite `aria-live`.
20
+ - SHOULD set `overscroll-behavior: contain` inside modals and drawers to prevent scroll chaining.
21
+ - SHOULD delay only the first tooltip in a group; subsequent peers open without delay.
22
+ - SHOULD persist meaningful UI state in the URL when state must survive refresh, sharing, or Back/Forward navigation.
23
+
24
+ ## Forms
25
+
26
+ - MUST associate every input, textarea, select, checkbox, radio, and switch with a label or accessible name.
27
+ - MUST focus the associated control when its label is clicked; label and control share one generous hit target.
28
+ - MUST allow paste and password-manager behavior unless the field has a documented security reason.
29
+ - MUST validate after input instead of blocking normal typing.
30
+ - MUST show validation near the field and move focus to the first blocking error on submit.
31
+ - MUST keep submit enabled until the request starts; disable and show loading only while the request is in flight.
32
+ - SHOULD submit on Enter when a single text input is focused; in a textarea, ⌘/⌃+Enter submits and Enter inserts a newline.
33
+ - MUST keep mobile input text at 16px or larger.
34
+ - SHOULD use correct `type` and `inputmode` values for better keyboards and validation.
35
+ - SHOULD set `autocomplete` and meaningful `name` values so browser autofill works.
36
+ - MUST trim trailing whitespace introduced by IME or text replacement before validating.
37
+ - SHOULD use placeholders only as examples or patterns, and end placeholder copy with `…`.
38
+
39
+ ## Layout
40
+
41
+ - MUST align every element intentionally to a grid, edge, baseline, or optical center.
42
+ - MUST prefer CSS grid, flex, and intrinsic sizing over JavaScript measurement.
43
+ - SHOULD balance contrast in icon-and-text lockups by adjusting weight, size, spacing, or color.
44
+ - MUST avoid unwanted internal scrollbars.
45
+ - MUST verify small, laptop, desktop, and wide layouts.
46
+ - SHOULD respect device safe areas (notches, gesture zones) with safe-area variables.
47
+ - SHOULD use semantic layout tokens for repeated frame, rail, topbar, page-header, and specimen proportions.
48
+ - SHOULD allow small optical adjustments when they are named and localized.
49
+
50
+ ## Content And Accessibility
51
+
52
+ - MUST keep headings hierarchical and provide stable section anchors where deep links exist.
53
+ - MUST keep `<title>` reflecting the current context.
54
+ - MUST provide accessible names for icon-only controls.
55
+ - MUST hide decorative visuals from assistive technology.
56
+ - MUST use redundant status cues; color alone is not enough.
57
+ - MUST mirror final content geometry in skeletons to avoid layout shift when loading completes.
58
+ - MUST design empty, sparse, dense, and error states.
59
+ - MUST offer a next step or recovery path on every screen; no dead ends.
60
+ - MUST keep layouts resilient to short, average, and very long content, especially user-generated content.
61
+ - SHOULD format dates, times, numbers, and currencies for the user's locale.
62
+ - MUST keep technical identifiers, token names, and brand names protected from browser translation with `translate="no"` where appropriate.
63
+ - SHOULD prefer inline help over tooltips.
64
+ - SHOULD use tabular numbers for comparison rows and token tables.
65
+
66
+ ## Accessibility Tiers
67
+
68
+ Every component is classified into one accessibility tier; the tier sets its bar. The tier is decided by how much keyboard and focus behavior the component must own beyond native semantics. The keyboard model source is always the matching WAI-ARIA APG pattern, not invention — established design systems follow APG too, so "matching a reference" and "following APG" do not conflict.
69
+
70
+ - **Tier A — composite widgets** (calendar, combobox, menu, modal, drawer, tabs, slider, listbox, tree, …): MUST implement the full keyboard model of the matching APG pattern (roving tabindex; arrow / `Home` / `End` / `PageUp` / `PageDown` as the pattern defines; `Enter` / `Space` activation; `Esc` dismissal that returns focus to the trigger), MUST manage focus on open and close, MUST expose the required ARIA (`role`, `aria-selected` / `aria-expanded` / `aria-controls`, `aria-live` where state changes), MUST document the key map as a「按键 | 行为」keyboard table (`.a11y-keys`) in the page's 可访问性 section, and MUST be locked by a runtime keyboard assertion in `scripts/check-browser.mjs`.
71
+ - **Tier B — native-semantic controls** (button, input, textarea, checkbox, radio, switch, select, links): MUST rely on native elements for keyboard and role, MUST carry an associated label or accessible name, and MUST show a visible `:focus-visible` state through the shared focus token. No custom key handling is expected.
72
+ - **Tier C — display / decorative** (avatar, badge, banner, book, browser, icon, card, skeleton, …): MUST hide purely decorative visuals from assistive technology (`aria-hidden`, non-focusable) and MUST give every icon-only control an accessible name. No keyboard model is required.
73
+
74
+ Calendar (`src/pages/CalendarPage.tsx`) and Tabs (`src/pages/TabsPage.tsx`) are the Tier A reference implementations to copy.
75
+
76
+ ## Animation
77
+
78
+ - MUST honor `prefers-reduced-motion`.
79
+ - MUST animate only `opacity` and `transform` unless a documented reason requires otherwise.
80
+ - SHOULD prefer CSS, then the Web Animations API, then JavaScript libraries; avoid main-thread-driven animation.
81
+ - SHOULD choose easing based on what changes (size, distance, trigger).
82
+ - SHOULD keep animations interruptible by user input.
83
+ - SHOULD animate in response to input instead of autoplaying.
84
+ - SHOULD anchor `transform-origin` where the motion physically starts.
85
+ - NEVER use `transition: all`.
86
+ - SHOULD animate only to clarify cause and effect or to reinforce a deliberate state change.
87
+
88
+ ## Theming
89
+
90
+ - MUST support light and dark themes through tokens, not page-local color constants.
91
+ - MUST set the appropriate `color-scheme` so native controls and scrollbars match the current theme.
92
+ - MUST keep browser theme color aligned with the first paint background.
93
+ - SHOULD give `:hover` / `:active` / `:focus` states more contrast than the rest state.
94
+ - MUST explicitly set native select foreground and background when styling select controls.
95
+
96
+ ## Performance
97
+
98
+ - MUST prevent layout shift by reserving space for media, fonts, and stable specimens.
99
+ - MUST avoid repeated layout reads and writes during interaction.
100
+ - SHOULD complete POST/PATCH/DELETE requests within 500ms.
101
+ - SHOULD keep controlled input updates cheap and use uncontrolled inputs where appropriate.
102
+ - SHOULD subset CJK fonts and preload critical above-the-fold fonts to avoid flashes and layout shift.
103
+ - SHOULD move long tasks to Web Workers instead of blocking the main thread.
104
+ - SHOULD virtualize long lists before they become a documentation or product performance problem.
105
+
106
+ ## Copy
107
+
108
+ - MUST be public, neutral, and specific.
109
+ - MUST use consistent nouns across pages, navigation, tables, and examples.
110
+ - SHOULD prefer short action-oriented labels.
111
+ - MUST use active voice.
112
+ - MUST use unambiguous action labels (「保存 API Key」, not 「继续」).
113
+ - MUST make error messages guide the exit: say how to fix it, not only what failed.
114
+ - SHOULD default to positive, problem-solving language, including errors.
115
+ - SHOULD use numerals for counts and keep number/unit formatting consistent.
116
+ - MUST keep currency decimal places consistent within a context (0 or 2, never mixed).
117
+
118
+ ## Agent Integration
119
+
120
+ - This file is the machine-readable mirror of the public 界面准则 page (`/guidelines`); keep them in sync.
121
+ - `AGENTS.md` at the repository root constrains agent generation and modification behavior.
122
+ - `npm run check` (build + shell contract + browser contract) is the merge gate for any interface change.
@@ -0,0 +1,82 @@
1
+ # q1travel Token Naming Contract
2
+
3
+ Status: accepted
4
+
5
+ This contract defines the token naming standard for q1travel Design System v1. It records the naming decision only; it does not migrate existing `q1travel-web` runtime tokens.
6
+
7
+ ## Decision
8
+
9
+ New public design-system tokens use the `--q1-*` prefix.
10
+
11
+ Existing `--ds-*` tokens in product repositories are legacy implementation tokens. They may remain during migration, but they are not the source name for new q1travel Design System contracts, documentation, or component examples.
12
+
13
+ External reference systems can guide the token layer model and page behavior. Their exact token names, class names, and computed styles are not implementation source.
14
+
15
+ ## Layers
16
+
17
+ ### Reference Tokens
18
+
19
+ Reference tokens hold source values and scale steps. They are useful for color ramps, spacing scales, radius scales, and typography primitives.
20
+
21
+ Examples:
22
+
23
+ - `--q1-color-gray-100`
24
+ - `--q1-color-primary-700`
25
+ - `--q1-color-background-100`
26
+ - `--q1-space-4`
27
+ - `--q1-radius-2`
28
+ - `--q1-font-size-copy-14`
29
+
30
+ Reference color scales use numeric steps from `100` to `1000`.
31
+
32
+ ### Semantic Tokens
33
+
34
+ Semantic tokens describe product meaning. Product surfaces should consume these before reaching for reference tokens.
35
+
36
+ Examples:
37
+
38
+ - `--q1-color-bg-canvas`
39
+ - `--q1-color-bg-panel`
40
+ - `--q1-color-text-primary`
41
+ - `--q1-color-border`
42
+ - `--q1-color-action-primary`
43
+ - `--q1-color-status-danger`
44
+ - `--q1-shadow-focus`
45
+
46
+ ### Component Tokens
47
+
48
+ Component tokens are allowed only when a shared component needs a stable public customization surface. Do not create component tokens for one page or one specimen.
49
+
50
+ Pattern:
51
+
52
+ - `--q1-<component>-<slot>`
53
+ - `--q1-<component>-<slot>-<state>`
54
+
55
+ Examples:
56
+
57
+ - `--q1-button-bg`
58
+ - `--q1-button-bg-hover`
59
+ - `--q1-input-border-focus`
60
+
61
+ ## Usage Rules
62
+
63
+ - Product code should use semantic tokens first.
64
+ - Documentation color ramps may show and copy reference tokens.
65
+ - Documentation semantic color rows may show and copy semantic tokens.
66
+ - Left-clicking a color token swatch copies the token reference; context menu copies the current theme resolved value for inspection.
67
+ - Raw hex values are contract source values and inspection output, not the preferred product-consumption API.
68
+ - Shadow tokens should be displayed as token references, not as color swatches.
69
+ - Theme-specific values may differ, but token names must stay stable across light and dark themes.
70
+
71
+ ## Migration Rules
72
+
73
+ - Do not create new public `--ds-*` tokens.
74
+ - Do not rename all product `--ds-*` tokens in a broad sweep.
75
+ - During migration, add explicit aliases only when they reduce risk and point toward the accepted `--q1-*` naming.
76
+ - Treat `--ds-*` tokens in `q1travel-web` as legacy product implementation until a dedicated migration plan lands.
77
+
78
+ ## Non-Goals
79
+
80
+ - This contract does not publish an npm token package.
81
+ - This contract does not migrate `q1travel-web`.
82
+ - This contract does not require deleting every local or private product CSS variable.
@@ -7,6 +7,7 @@ import { KeyboardEventHandler } from 'react';
7
7
  import { MouseEventHandler } from 'react';
8
8
  import { ReactElement } from 'react';
9
9
  import { ReactNode } from 'react';
10
+ import { Ref } from 'react';
10
11
  import { RefObject } from 'react';
11
12
  import { SelectHTMLAttributes } from 'react';
12
13
  import { TextareaHTMLAttributes } from 'react';
@@ -17,13 +18,13 @@ export declare function Avatar({ title, src, letter, glyph, placeholder, icon, i
17
18
 
18
19
  export declare function AvatarGroup({ members, label, size, limit, overlap, reverse, className, }: {
19
20
  members: AvatarMember[];
20
- /** 可选整组名;传入则套 role=group 作整组增强,不传则跟 Geist 默认逐个头像标注(读屏念每个成员名)。 */
21
+ /** 可选整组名;传入则套 role=group 作整组增强,不传则默认逐个头像标注(读屏念每个成员名)。 */
21
22
  label?: string;
22
23
  /** 成员统一直径;缺省 32。 */
23
24
  size?: number;
24
25
  /** 显示上限,超出收纳为 +N;非法值(负数/NaN)忽略。 */
25
26
  limit?: number;
26
- /** 重叠像素;'auto' = 尺寸的 30% 取整(Geist 实测 16→5 / 24→7 / 32→10 / 48→14);负数按 0 处理。 */
27
+ /** 重叠像素;'auto' = 尺寸的 30% 取整(例:16→5 / 24→7 / 32→10 / 48→14);负数按 0 处理。 */
27
28
  overlap?: number | 'auto';
28
29
  /** 翻转堆叠顺序。 */
29
30
  reverse?: boolean;
@@ -43,7 +44,7 @@ export declare type AvatarProps = {
43
44
  glyph?: ReactNode;
44
45
  /** 加载占位骨架;只用于加载态,不作长期缺省。 */
45
46
  placeholder?: boolean;
46
- /** 右下角标图标(对标 Geist With custom icon);纯装饰,语义信息由调用方文字承载。 */
47
+ /** 右下角标图标;纯装饰,语义信息由调用方文字承载。 */
47
48
  icon?: ReactNode;
48
49
  /** 角标底色(任意 CSS color,建议用语义 token);缺省中性灰盘。 */
49
50
  iconColor?: string;
@@ -63,7 +64,7 @@ export declare type BadgeProps = {
63
64
  subtle?: boolean;
64
65
  /** 反转高对比形态;设置后忽略 tone/subtle。 */
65
66
  inverted?: boolean;
66
- /** 尺寸档 20/24/32(Geist 实测阶梯)。 */
67
+ /** 尺寸档 20/24/32。 */
67
68
  size?: BadgeSize;
68
69
  /** 前置图标;纯装饰(组件自动 aria-hidden),宽高随档位 12/14/16 由样式钉死。 */
69
70
  icon?: ReactNode;
@@ -88,12 +89,12 @@ export declare type BannerProps = {
88
89
  tone?: BannerTone;
89
90
  /** 卡条形态的前缀图标;纯装饰(组件自动 aria-hidden)。公告形态与进度形态不渲染图标。 */
90
91
  icon?: ReactNode;
91
- /** 主操作:公告形态渲染恒深药丸(无 chevron,Geist 同款);卡条形态渲染描边药丸 + chevron。进度形态忽略 action——任务进行中不挂主跳转,完成后换普通卡条。 */
92
+ /** 主操作:公告形态渲染恒深药丸(无 chevron);卡条形态渲染描边药丸 + chevron。进度形态忽略 action——任务进行中不挂主跳转,完成后换普通卡条。 */
92
93
  action?: {
93
94
  label: string;
94
95
  href: string;
95
96
  };
96
- /** 关闭回调;设置后渲染关闭按钮。公告形态无关闭(跟 Geist);进度形态渲染在进度头右侧。 */
97
+ /** 关闭回调;设置后渲染关闭按钮。公告形态无关闭;进度形态渲染在进度头右侧。 */
97
98
  onDismiss?: () => void;
98
99
  /** 进度形态(自有扩展):value 为 0–100 的百分比(非法值归 0),label 供读屏。进度恒为卡条形态。 */
99
100
  progress?: {
@@ -111,11 +112,11 @@ export declare function Book({ title, variant, color, bandColor, textColor, icon
111
112
  export declare type BookProps = {
112
113
  /** 封面标题;语义由标题承载,封面其余元素均为装饰。 */
113
114
  title: string;
114
- /** stripe=顶部色带+下方标签区(Geist 默认);simple=纯封面、标题置顶。 */
115
+ /** stripe=顶部色带+下方标签区(默认);simple=纯封面、标题置顶。 */
115
116
  variant?: 'stripe' | 'simple';
116
- /** 封面底色;建议传设计 token(var(--q1-color-…)),勿用裸 hex(Geist Best Practices 同款要求)。 */
117
+ /** 封面底色;建议传设计 token(var(--q1-color-…)),勿用裸 hex。 */
117
118
  color?: string;
118
- /** stripe 色带颜色;缺省琥珀(Geist 实测默认带色)。 */
119
+ /** stripe 色带颜色;缺省琥珀。 */
119
120
  bandColor?: string;
120
121
  /** 标题颜色;自定义封面色时务必保证对比可读。 */
121
122
  textColor?: string;
@@ -123,7 +124,7 @@ export declare type BookProps = {
123
124
  icon?: ReactNode;
124
125
  /** 整幅插画:铺满封面、裁切;标题浮于其上;aria-hidden。 */
125
126
  illustration?: ReactNode;
126
- /** 细密交叉纹理(自有配方;Geist 的多款纹理样式记 non-goal)。仅用于主视觉,成排书架勿用。 */
127
+ /** 细密交叉纹理(自有配方);只提供单一纹理样式,未做多纹理体系(记 non-goal)。仅用于主视觉,成排书架勿用。 */
127
128
  textured?: boolean;
128
129
  /** 数字按 px;字符串原样透传(如 clamp(...) 做响应式宽度)。内部排版随宽度等比缩放。
129
130
  * width 是唯一尺寸入口:用 style.width 改宽会与内部缩放脱节。 */
@@ -188,7 +189,7 @@ declare type ButtonProps = {
188
189
  iconOnly?: boolean;
189
190
  /** 圆形——仅用于 icon-only 按钮。与 rounded 互斥(同传时 circle 优先)。 */
190
191
  circle?: boolean;
191
- /** 药丸形(full radius)+ 柔和抬起阴影(对标 Geist Rounded,营销页/落地页文字 CTA 用)。与 circle 互斥。 */
192
+ /** 药丸形(full radius)+ 柔和抬起阴影,营销页/落地页文字 CTA 用。与 circle 互斥。 */
192
193
  rounded?: boolean;
193
194
  loading?: boolean;
194
195
  disabled?: boolean;
@@ -205,6 +206,8 @@ declare type ButtonProps = {
205
206
  onFocus?: FocusEventHandler<HTMLButtonElement | HTMLAnchorElement>;
206
207
  onBlur?: FocusEventHandler<HTMLButtonElement | HTMLAnchorElement>;
207
208
  onKeyDown?: KeyboardEventHandler<HTMLButtonElement | HTMLAnchorElement>;
209
+ /** 渲染为 <button> 或 <a>(取决于是否传 href),供 focus 管理、测量、浮层定位等场景使用。 */
210
+ ref?: Ref<HTMLButtonElement | HTMLAnchorElement>;
208
211
  };
209
212
 
210
213
  export declare type ButtonSize = 'sm' | 'md' | 'lg';
@@ -245,13 +248,13 @@ declare type CardOwnProps = {
245
248
  hover?: boolean;
246
249
  /** 次要表面:更弱的底色,与主卡片区分层级。 */
247
250
  secondary?: boolean;
248
- /** 分段:用分隔线把卡片切成几段(对齐 Geist borderBetween)。 */
251
+ /** 分段:用分隔线把卡片切成几段。 */
249
252
  divided?: boolean;
250
253
  /** 分段方向:column 竖排(默认)/ row 横排。与 divided 正交——单传 row 只横向铺开,配 divided 才加分隔线。 */
251
254
  direction?: CardDirection;
252
- /** 常驻柔和投影(对齐 Geist shadow):让卡片浮于背景,用于落地/营销卡片。 */
255
+ /** 常驻柔和投影:让卡片浮于背景,用于落地/营销卡片。 */
253
256
  shadow?: boolean;
254
- /** 是否带边框,默认 true。传 false 得无框卡片(靠底色/投影表达边界,对齐 Geist border 可选)。 */
257
+ /** 是否带边框,默认 true。传 false 得无框卡片(靠底色/投影表达边界)。 */
255
258
  bordered?: boolean;
256
259
  className?: string;
257
260
  children: ReactNode;
@@ -345,7 +348,8 @@ export declare function CodeTokens({ tokens }: {
345
348
  }): JSX.Element;
346
349
 
347
350
  export declare function Collapse({ title, defaultOpen, small, children, }: {
348
- title: string;
351
+ /** 固定文案传字符串;随展开/收起切换文案(如"显示代码"/"收起代码")传函数,入参为当前 open 状态。 */
352
+ title: string | ((open: boolean) => string);
349
353
  defaultOpen?: boolean;
350
354
  small?: boolean;
351
355
  children: ReactNode;
@@ -404,7 +408,7 @@ declare type CommandMenuProps = {
404
408
  };
405
409
 
406
410
  export declare type CommandMenuSection = {
407
- /** 段标题;缺省时该段以无标题分隔线与上文分隔(对标 Geist CommandMenuDivider)。 */
411
+ /** 段标题;缺省时该段以无标题分隔线与上文分隔。 */
408
412
  heading?: string;
409
413
  items: CommandMenuItem[];
410
414
  };
@@ -548,7 +552,7 @@ export declare type ErrorMessageSize = 'sm' | 'md' | 'lg';
548
552
  export declare function Feedback({ label, prompt, placeholder, inline, topics, }: {
549
553
  label?: string;
550
554
  prompt?: string;
551
- /** textarea 占位(对标 Geist Custom Placeholder):换成更具体的引导,帮助用户知道从哪里说起。 */
555
+ /** textarea 占位:换成更具体的引导,帮助用户知道从哪里说起。 */
552
556
  placeholder?: string;
553
557
  inline?: boolean;
554
558
  topics?: string[];
@@ -610,11 +614,11 @@ export declare function Input({ id, label, description, error, prefix, suffix, p
610
614
  error?: string;
611
615
  prefix?: ReactNode;
612
616
  suffix?: ReactNode;
613
- /** 置 false 去掉前缀的灰块底色与分隔线,变成纯文本/裸图标(对标 Geist prefixStyling)。 */
617
+ /** 置 false 去掉前缀的灰块底色与分隔线,变成纯文本/裸图标。 */
614
618
  prefixStyling?: boolean;
615
- /** 置 false 去掉后缀的灰块底色与分隔线(对标 Geist suffixStyling)。 */
619
+ /** 置 false 去掉后缀的灰块底色与分隔线。 */
616
620
  suffixStyling?: boolean;
617
- /** 药丸形全圆角外框(对标 Geist rounded,实测 9999px 级 pill 半径)。 */
621
+ /** 药丸形全圆角外框(9999px 级 pill 半径)。 */
618
622
  rounded?: boolean;
619
623
  wide?: boolean;
620
624
  size?: FieldSize;
@@ -714,8 +718,8 @@ declare type NativeInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'id'
714
718
 
715
719
  declare type NativeInputProps_2 = Omit<InputHTMLAttributes<HTMLInputElement>, 'type'>;
716
720
 
717
- export declare function Note({ type, size, filled, disabled, label, action, children, }: {
718
- type?: NoteType;
721
+ export declare function Note({ tone, size, filled, disabled, label, action, children, }: {
722
+ tone?: NoteTone;
719
723
  size?: NoteSize;
720
724
  filled?: boolean;
721
725
  disabled?: boolean;
@@ -726,7 +730,7 @@ export declare function Note({ type, size, filled, disabled, label, action, chil
726
730
 
727
731
  declare type NoteSize = 'small' | 'default' | 'large';
728
732
 
729
- declare type NoteType = 'info' | 'success' | 'warning' | 'error' | 'secondary';
733
+ export declare type NoteTone = 'info' | 'success' | 'warning' | 'error' | 'secondary';
730
734
 
731
735
  declare type PageLink = {
732
736
  title: string;
@@ -749,7 +753,7 @@ export declare function Phone({ screenLabel }: {
749
753
 
750
754
  export declare function Pill({ href, size, icon, title, className, children, ...rest }: PillProps): JSX.Element;
751
755
 
752
- declare type PillProps = {
756
+ export declare type PillProps = {
753
757
  href: string;
754
758
  size?: BadgeSize;
755
759
  /** 前置图标;纯装饰(组件自动 aria-hidden)。 */
@@ -799,7 +803,7 @@ export declare function RangeInputs({ value, withTime, onApply, pinnedTimezone,
799
803
  value: RangeValue;
800
804
  withTime: boolean;
801
805
  onApply: () => void;
802
- /** 固定时区(对标 Geist pinnedTimezone):传入时时区从可选 select 变只读文本、不可切换。 */
806
+ /** 固定时区:传入时时区从可选 select 变只读文本、不可切换。 */
803
807
  pinnedTimezone?: string;
804
808
  }): JSX.Element;
805
809
 
@@ -914,7 +918,7 @@ export declare function Snippet({ text, prompt, inverted, tone, copyText, onCopy
914
918
  prompt?: boolean;
915
919
  inverted?: boolean;
916
920
  tone?: SnippetTone;
917
- /** 显示与复制内容分离(对标 Geist):传了就复制它,不传复制显示内容。 */
921
+ /** 显示与复制内容分离:传了就复制它,不传复制显示内容。 */
918
922
  copyText?: string;
919
923
  /** 复制触发后调用,供外部消费复制事件(如埋点);不代表剪贴板写入一定成功。 */
920
924
  onCopy?: () => void;
@@ -1089,6 +1093,12 @@ export declare function useCopy(): {
1089
1093
  reset: () => void;
1090
1094
  };
1091
1095
 
1096
+ export declare function useRadio({ id, ...rest }: {
1097
+ id: string;
1098
+ } & NativeInputProps): {
1099
+ component: JSX.Element;
1100
+ };
1101
+
1092
1102
  export declare function useToast(): ToastContextValue;
1093
1103
 
1094
1104
  export declare function Video({ controls, loop }: {