@q1travel/design-system 0.26.1 → 0.27.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.
- package/.agents/skills/product-design/exemplars/README.md +1 -1
- package/.agents/skills/product-design/references/glossary.md +1 -1
- package/contracts/button-api-compatibility.md +11 -11
- package/contracts/context-contrast-migration.md +3 -6
- package/contracts/design.dark.md +21 -2
- package/contracts/design.md +21 -2
- package/contracts/implementation-map.md +2 -2
- package/contracts/overlay-foundation.md +4 -4
- package/contracts/overlay-shadow-migration.md +5 -19
- package/contracts/pagination-migration.md +3 -3
- package/contracts/status-chip-badge-migration.md +3 -3
- package/contracts/table-migration.md +4 -4
- package/contracts/token-naming.md +40 -3
- package/dist-pkg/design-system.d.ts +89 -13
- package/dist-pkg/design-system.js +6718 -6285
- package/dist-pkg/style.css +717 -81
- package/dist-pkg/tokens.css +38 -0
- package/package.json +3 -3
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
用户可见文字与契约里的名词以此为准,跨页 / 表格 / 示例保持一致(`contracts/interface-guidelines.md` §Copy 要求 "consistent nouns")。
|
|
4
4
|
|
|
5
|
-
**Coverage gap
|
|
5
|
+
**Coverage gap**:统一术语表尚未成形。消费方整理出的中性术语应回流到这里,成为 canonical 词表。在此之前,遇到术语一致性问题记入 `references/coverage-gaps.md`。
|
|
6
6
|
|
|
7
7
|
## 组件文档页
|
|
8
8
|
|
|
@@ -40,18 +40,18 @@ Package-owned semantics are applied after native props. `type`, `className`, `di
|
|
|
40
40
|
|
|
41
41
|
`busyLabel` is an optional string. An empty string behaves as absent and never disables repeat-submission prevention. The original children remain the accessible-name source (and an explicit `aria-label` remains unchanged); the visible busy label is a separate decorative overlay, while the live status node is outside the button/anchor name calculation. The label slot reserves geometry for both values. Under `prefers-reduced-motion: reduce`, the spinner remains present but static; no rotation, pulse, scale, or spring animation is required to understand the state.
|
|
42
42
|
|
|
43
|
-
##
|
|
43
|
+
## Downstream Adapter Seam
|
|
44
44
|
|
|
45
|
-
The package deliberately does not add
|
|
45
|
+
The package deliberately does not add consumer-specific variant, size, or router props. A downstream adapter layer that maps its own button API onto the package owns these measurable rules:
|
|
46
46
|
|
|
47
|
-
|
|
|
47
|
+
| Downstream adapter input | Package base | Adapter acceptance rule |
|
|
48
48
|
| --- | --- | --- |
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
49
|
+
| Consumer-specific subtle variant | `variant="ghost"` for structure and behavior only | Preserve the consumer's existing fill, border, hover/focus, disabled states, and dark-theme tokens; do not present transparent package ghost as an equivalent visual migration. |
|
|
50
|
+
| Consumer-specific page-level size | `size="md"` for structure and behavior only | Preserve the consumer's existing min-height, padding, font size, and minimum width; never map it to package `lg` (`48px`). |
|
|
51
|
+
| Router-aware link button | `ButtonLink href={...}` | Generate `href` with the router's href resolver, keep router navigation handlers for SPA, modified-click, keyboard, and disabled behavior, and forward the ref to the real anchor. |
|
|
52
52
|
| `leadingIcon` / `trailingIcon` | `prefix` / `suffix` | Mechanical prop rename only; preserve the decorative slot boundary. |
|
|
53
53
|
|
|
54
|
-
The adapter must keep the package's real native `<a>` as the interactive owner; it must not move navigation roles, focus, keyboard handling, disabled semantics, or the ref onto a wrapper. Adapter implementation, SPA behavior tests, and
|
|
54
|
+
The adapter must keep the package's real native `<a>` as the interactive owner; it must not move navigation roles, focus, keyboard handling, disabled semantics, or the ref onto a wrapper. Adapter implementation, SPA behavior tests, and consumer evidence remain downstream adapter work and are not proven by this package gate.
|
|
55
55
|
|
|
56
56
|
## Component-Owned Semantics
|
|
57
57
|
|
|
@@ -66,8 +66,8 @@ Scan date: 2026-07-20
|
|
|
66
66
|
The scan covers the current local checkouts named below; it is not evidence about un-fetched branches or third-party packages.
|
|
67
67
|
|
|
68
68
|
- `q1travel-design-system`: recommended code examples in this source revision use `svgOnly` and `aria-label`. Deprecated names remain only where compatibility behavior is exercised or declared.
|
|
69
|
-
-
|
|
70
|
-
-
|
|
69
|
+
- Primary downstream web application: the package is used for its stylesheet and Badge export. Button and IconButton remain local components, so this change does not migrate them.
|
|
70
|
+
- Another downstream consumer: package Button consumers use text-button props and do not use `iconOnly`, `ariaLabel`, or `svgOnly`.
|
|
71
71
|
- Unknown third-party npm consumers cannot be enumerated from q1travel repositories, so a repository-local zero-result scan is not sufficient evidence for alias removal.
|
|
72
72
|
|
|
73
73
|
## Verification Boundary
|
|
@@ -92,8 +92,8 @@ Until then, the aliases remain tested public compatibility contracts.
|
|
|
92
92
|
|
|
93
93
|
## Non-Goals
|
|
94
94
|
|
|
95
|
-
- This contract does not migrate
|
|
95
|
+
- This contract does not migrate downstream consumers.
|
|
96
96
|
- This contract does not choose a package version, publish a package, or remove an alias.
|
|
97
|
-
- This contract does not migrate
|
|
97
|
+
- This contract does not migrate consumer-specific variant, size, or router adapter behavior into the package; those remain downstream adapter seams with the measurable rules above.
|
|
98
98
|
- This contract does not change Button size, variant, route, or existing loading compatibility beyond the state contract described above.
|
|
99
99
|
- This contract does not move button semantics or event handlers to a wrapper.
|
|
@@ -34,12 +34,9 @@ The regression gate checks named text/surface pairs and button-label/solid
|
|
|
34
34
|
pairs. It must not treat every color as text or accept unsupported color syntax
|
|
35
35
|
silently. Existing browser checks cover composed component colors.
|
|
36
36
|
|
|
37
|
-
Consumer follow-up after upgrading:
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
Recheck the related appearance labels, docs supporting text, raw-color ratchet,
|
|
41
|
-
`check-contrast-contract`, and full Web gates. Other #998 text-secondary
|
|
42
|
-
substitutions should be reviewed individually, not mechanically reverted.
|
|
37
|
+
Consumer follow-up after upgrading: remove any local text-muted workaround
|
|
38
|
+
and resume the normal `--q1-color-text-muted` mapping; review other local
|
|
39
|
+
text-secondary substitutions individually rather than reverting them mechanically.
|
|
43
40
|
|
|
44
41
|
## #245: Navigation active text
|
|
45
42
|
|
package/contracts/design.dark.md
CHANGED
|
@@ -170,6 +170,25 @@ semantic-colors:
|
|
|
170
170
|
status-info-text: "{colors.blue-900}"
|
|
171
171
|
status-info-surface: "{colors.blue-100}"
|
|
172
172
|
status-info-border: "#194f81"
|
|
173
|
+
auth-text-primary: "#f3f4f6"
|
|
174
|
+
auth-text-secondary: "#d1d5db"
|
|
175
|
+
auth-text-muted: "#9ca3af"
|
|
176
|
+
auth-border-strong: "#343943"
|
|
177
|
+
auth-surface-card: "#17191d"
|
|
178
|
+
auth-surface-subtle: "#101216"
|
|
179
|
+
auth-surface-disabled: "#202329"
|
|
180
|
+
auth-surface-media: "#04050a"
|
|
181
|
+
auth-action-disabled-bg: "#3b404a"
|
|
182
|
+
auth-action-disabled-border: "#3b404a"
|
|
183
|
+
auth-action-disabled-text: "#a6acb8"
|
|
184
|
+
auth-focus-ring: "rgba(126, 108, 255, 0.52)"
|
|
185
|
+
auth-danger-border: "#d92d20"
|
|
186
|
+
auth-danger-surface: "#241719"
|
|
187
|
+
auth-field-error-text: "#d32f2f"
|
|
188
|
+
auth-media-overlay: "rgba(4, 5, 10, 0.46)"
|
|
189
|
+
auth-media-overlay-hover: "rgba(4, 5, 10, 0.66)"
|
|
190
|
+
auth-on-media-border: "rgba(255, 255, 255, 0.22)"
|
|
191
|
+
auth-on-media-border-hover: "rgba(255, 255, 255, 0.34)"
|
|
173
192
|
typography:
|
|
174
193
|
heading-72:
|
|
175
194
|
fontFamily: Noto Sans SC
|
|
@@ -452,7 +471,7 @@ These components ship in the package. Compose from this list before writing new
|
|
|
452
471
|
- FilterOptionPanel is searchable single-select content inside Popover, usually anchored by FilterChip. It owns initial search focus, named combobox/listbox, active-descendant arrow navigation with disabled skipping, loading/error/retry/empty/no-match states, and label/keywords includes filtering. Callers own selection, closing, business ranking and async queries through controlled query/onQueryChange and an injected filter; Escape dismissal and trigger focus return stay with Popover. It does not provide multiselect or an application footer.
|
|
453
472
|
- IconButton requires an accessible name. An icon-only control without one is not deliverable.
|
|
454
473
|
|
|
455
|
-
**Text fields.** FormField, Label, Input, ClearableInput, SearchInput, InputOTP, Textarea, Select, Fieldset, ErrorMessage.
|
|
474
|
+
**Text fields.** FormField, Label, InfoTip, Input, ClearableInput, SearchInput, InputOTP, Textarea, Select, Fieldset, ErrorMessage.
|
|
456
475
|
|
|
457
476
|
- InputOTP collects a fixed six-digit code in one joined group by default; `separator` explicitly enables 3+3 groups. VerificationCodeInput and VerificationCodeInputProps remain deprecated aliases for one minor version; migrate to InputOTP and InputOTPProps before their removal in the next minor version. The old `/components/verification-code-input` route redirects to `/components/input-otp`.
|
|
458
477
|
- FormField owns the label, help text, and error slot. Do not assemble those three around a bare Input.
|
|
@@ -507,7 +526,7 @@ Static WCAG stroke contrast against canvas/panel (2026-10-07): light neutral 5.3
|
|
|
507
526
|
- Tabs switch between peer views of the same subject. They are not a way to shorten a page.
|
|
508
527
|
- ContextSwitcher is the two-level selection model; the consumer owns the state behind it.
|
|
509
528
|
|
|
510
|
-
**Identity and media.** Avatar, AvatarGroup, Book, Browser, BrowserDots, BrowserControls, BrowserAddress, BrowserTabs, BrowserPlaceholder, Phone, Video, ThemeSwitcher, ProductLockup, Q1travelSymbol.
|
|
529
|
+
**Identity and media.** Avatar, AvatarGroup, AvatarButton, Book, Browser, BrowserDots, BrowserControls, BrowserAddress, BrowserTabs, BrowserPlaceholder, Phone, Video, ThemeSwitcher, ProductLockup, Q1travelSymbol.
|
|
511
530
|
|
|
512
531
|
- ProductLockup combines a product icon, product name, and brand endorsement into one identity mark. The endorsement is smaller and uses secondary text color. Pass only the brand name through `brand`; the component renders "by" itself.
|
|
513
532
|
|
package/contracts/design.md
CHANGED
|
@@ -170,6 +170,25 @@ semantic-colors:
|
|
|
170
170
|
status-info-text: "#0064b8"
|
|
171
171
|
status-info-surface: "{colors.blue-100}"
|
|
172
172
|
status-info-border: "#abcff0"
|
|
173
|
+
auth-text-primary: "#061b31"
|
|
174
|
+
auth-text-secondary: "#273951"
|
|
175
|
+
auth-text-muted: "#64748d"
|
|
176
|
+
auth-border-strong: "#d6dde6"
|
|
177
|
+
auth-surface-card: "#ffffff"
|
|
178
|
+
auth-surface-subtle: "#f8fafc"
|
|
179
|
+
auth-surface-disabled: "#f6f9fc"
|
|
180
|
+
auth-surface-media: "#04050a"
|
|
181
|
+
auth-action-disabled-bg: "#c7c9cc"
|
|
182
|
+
auth-action-disabled-border: "#c7c9cc"
|
|
183
|
+
auth-action-disabled-text: "#ffffff"
|
|
184
|
+
auth-focus-ring: "rgba(83, 58, 253, 0.42)"
|
|
185
|
+
auth-danger-border: "#d92d20"
|
|
186
|
+
auth-danger-surface: "#fff8f7"
|
|
187
|
+
auth-field-error-text: "#d32f2f"
|
|
188
|
+
auth-media-overlay: "rgba(4, 5, 10, 0.46)"
|
|
189
|
+
auth-media-overlay-hover: "rgba(4, 5, 10, 0.66)"
|
|
190
|
+
auth-on-media-border: "rgba(255, 255, 255, 0.22)"
|
|
191
|
+
auth-on-media-border-hover: "rgba(255, 255, 255, 0.34)"
|
|
173
192
|
typography:
|
|
174
193
|
heading-72:
|
|
175
194
|
fontFamily: Noto Sans SC
|
|
@@ -452,7 +471,7 @@ These components ship in the package. Compose from this list before writing new
|
|
|
452
471
|
- FilterOptionPanel is searchable single-select content inside Popover, usually anchored by FilterChip. It owns initial search focus, named combobox/listbox, active-descendant arrow navigation with disabled skipping, loading/error/retry/empty/no-match states, and label/keywords includes filtering. Callers own selection, closing, business ranking and async queries through controlled query/onQueryChange and an injected filter; Escape dismissal and trigger focus return stay with Popover. It does not provide multiselect or an application footer.
|
|
453
472
|
- IconButton requires an accessible name. An icon-only control without one is not deliverable.
|
|
454
473
|
|
|
455
|
-
**Text fields.** FormField, Label, Input, ClearableInput, SearchInput, InputOTP, Textarea, Select, Fieldset, ErrorMessage.
|
|
474
|
+
**Text fields.** FormField, Label, InfoTip, Input, ClearableInput, SearchInput, InputOTP, Textarea, Select, Fieldset, ErrorMessage.
|
|
456
475
|
|
|
457
476
|
- InputOTP collects a fixed six-digit code in one joined group by default; `separator` explicitly enables 3+3 groups. VerificationCodeInput and VerificationCodeInputProps remain deprecated aliases for one minor version; migrate to InputOTP and InputOTPProps before their removal in the next minor version. The old `/components/verification-code-input` route redirects to `/components/input-otp`.
|
|
458
477
|
- FormField owns the label, help text, and error slot. Do not assemble those three around a bare Input.
|
|
@@ -507,7 +526,7 @@ Static WCAG stroke contrast against canvas/panel (2026-10-07): light neutral 5.3
|
|
|
507
526
|
- Tabs switch between peer views of the same subject. They are not a way to shorten a page. Optional `value` / `onValueChange` let the consumer own selection and URL synchronization; `defaultValue` seeds uncontrolled selection. Invalid or disabled values render the first enabled item without notifying. See `implementation-map.md` for selection ownership.
|
|
508
527
|
- ContextSwitcher is the two-level selection model; the consumer owns the state behind it.
|
|
509
528
|
|
|
510
|
-
**Identity and media.** Avatar, AvatarGroup, Book, Browser, BrowserDots, BrowserControls, BrowserAddress, BrowserTabs, BrowserPlaceholder, Phone, Video, ThemeSwitcher, ProductLockup, Q1travelSymbol.
|
|
529
|
+
**Identity and media.** Avatar, AvatarGroup, AvatarButton, Book, Browser, BrowserDots, BrowserControls, BrowserAddress, BrowserTabs, BrowserPlaceholder, Phone, Video, ThemeSwitcher, ProductLockup, Q1travelSymbol.
|
|
511
530
|
|
|
512
531
|
- ProductLockup combines a product icon, product name, and brand endorsement into one identity mark. The endorsement is smaller and uses secondary text color. Pass only the brand name through `brand`; the component renders "by" itself.
|
|
513
532
|
|
|
@@ -34,7 +34,7 @@ README owns the repository inventory and generated-file boundary. This file owns
|
|
|
34
34
|
- New public tokens use `--q1-*`; existing product `--ds-*` names are legacy migration inputs, not new contract names.
|
|
35
35
|
- Canonical components own repeated structure. Page-local custom structures are allowed only for visual specimens with a narrow purpose.
|
|
36
36
|
- Token references are the design source for production code. Current theme resolved values are clipboard output only.
|
|
37
|
-
- The public documentation navigation groups are `基础`, `品牌`, and `组件`. Product compositions are owned by
|
|
37
|
+
- The public documentation navigation groups are `基础`, `品牌`, and `组件`. Product compositions are owned by downstream consumers.
|
|
38
38
|
- If a capability is missing from a shared component, add the capability to that component before adding another page-local pattern.
|
|
39
39
|
|
|
40
40
|
## Documentation Section Ownership
|
|
@@ -114,7 +114,7 @@ Native buttons expose `aria-pressed` within `role="group"`. Roving tabindex and
|
|
|
114
114
|
- Verification: `scripts/check-checkbox-circle-contract.test.mjs`, `scripts/fixtures/checkbox-circle-api-consumer.tsx`, `scripts/lib/checkbox-circle-contrast.mjs`, `scripts/lib/check-checkbox-circle-browser.mjs`. Package gate covers API/default/native markup/readonly semantics/token existence and both-theme contrast; browser gate covers native toggles, focus without preview, readonly, tone fill, reduced motion and coarse hit targets.
|
|
115
115
|
## Chat messages
|
|
116
116
|
Bubble is separate from Message: chat has optional identity and direction, while Message retains its required author, comment attachments and receipt API unchanged. MessageScroller is separate from Scroller: keyed prepend anchors and message following need ownership of the viewport; the general Scroller API remains unchanged. The shadcn chat reference supplies conversation intent only; quiet Geist surfaces map to existing q1travel panel/selected backgrounds, borders, spacing, radii and Button. No reference CSS, motion background or private tokens are shipped.
|
|
117
|
-
The consumer mapping was checked against
|
|
117
|
+
The consumer mapping was checked against downstream chat-style implementations (read-only, no downstream edits).
|
|
118
118
|
| Web capability | Package support / caller boundary |
|
|
119
119
|
| --- | --- |
|
|
120
120
|
| message role user / assistant | Bubble direction outgoing / incoming |
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
- 不修改现有 overlay 组件实现;
|
|
27
27
|
- 不新增公开 `OverlayHost`、stack 或 hook API;
|
|
28
28
|
- 不修改 `public/design.md`、`public/design.dark.md` 等生成镜像;
|
|
29
|
-
-
|
|
29
|
+
- 不修改下游消费方,也不把下游的类名、DOM 结构或实现复制到本包;
|
|
30
30
|
- 不把 foundation、四个组件接入和 Web migration 合并为一个 PR。
|
|
31
31
|
|
|
32
32
|
### 2.2 第一批纳入 foundation 的 surface
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
|
|
46
46
|
### 2.3 行为证据的使用方式
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
下游消费方已有的浮层宿主与玻璃表面行为、测试和文档只能作为行为证据。它们不改变本包的设计权威,也不授权 Web migration。package contract、component API 和本仓库的 token 规则优先。
|
|
49
49
|
|
|
50
50
|
## 3. 术语与记录
|
|
51
51
|
|
|
@@ -194,7 +194,7 @@ D2 Overlay Foundation GREEN runtime
|
|
|
194
194
|
↓ all relevant checks green
|
|
195
195
|
D6 docs/browser contract completion and package PR
|
|
196
196
|
↓ separate release/consumer gate
|
|
197
|
-
D7
|
|
197
|
+
D7 downstream adoption/migration
|
|
198
198
|
```
|
|
199
199
|
|
|
200
200
|
- D1 不得修改四个生产组件;D2 不得在 RED review 前开始;D3–D5 分开审查和验证。
|
|
@@ -209,7 +209,7 @@ D7 q1travel-web adoption/migration
|
|
|
209
209
|
- **D1/D2 — Foundation RED/GREEN:已完成。** `9d0d56da527e66f3d2e793364bf0b2c9e2ebd828` 引入 shared `overlayCore`、`useOverlay` 与 Foundation runtime;当前 targeted runtime/browser contract `node --test scripts/check-overlay-foundation-red.test.mjs` 通过(2/2)。
|
|
210
210
|
- **D3–D5 — 首批组件接入:实现已进入 main。** `Modal`、`DestructiveActionModal`、`Sheet`、`Drawer` 均通过 `useOverlay` 接入;Sheet 保持 `blocking=true/outsidePointer=false`,DestructiveActionModal 的 loading policy 保留。实现证据不等于已建立对应的独立 GitHub blocking tickets。
|
|
211
211
|
- **D6 — package/release provenance:已完成。** 0.7.3 exact package source 为 `224f723f3a4e7bb3d5256ae2364783362b2f8eaf`,`v0.7.3` 已解析到该 source,registry provenance 已由 `b40a3b5ad49156c3d8b0409b226c15b37468f8c7` 写入 remote `main`。
|
|
212
|
-
- **D7 —
|
|
212
|
+
- **D7 — downstream adoption/migration:pending。** 本次没有修改 Web,也没有把 Web migration 伪装成 package acceptance;Web 仍需独立 ticket、consumer evidence 与单独授权。
|
|
213
213
|
- **Ticket graph:pending。** 当前 GitHub 中没有 Foundation、Modal、Sheet、Drawer、Web migration 的独立 blocking ticket 记录;本 contract 的 D3–D7 图是交付边界,不是 GitHub tracker 已建立的 blocking edges。
|
|
214
214
|
|
|
215
215
|
因此,#27 的 package-side implementation/provenance evidence 已具备;issue acceptance 仍不能在缺少独立 ticket graph、contract 状态同步与 D7 Web gate 的情况下被解释为全链路完成。
|
|
@@ -18,7 +18,7 @@ Decision date: 2026-08-26
|
|
|
18
18
|
|
|
19
19
|
关联:q1travel-design-system#140(B2-1)、q1travel-design-system#138(界面准则 · 设计章节)
|
|
20
20
|
|
|
21
|
-
这份合同冻结 `--q1-shadow-popover` 与 `--q1-shadow-modal`
|
|
21
|
+
这份合同冻结 `--q1-shadow-popover` 与 `--q1-shadow-modal` 由单层改为分层的取值、下游影响面与回滚单位。它**不修改下游仓库**,不创建下游迁移票,也不声称消费方已完成接入。
|
|
22
22
|
|
|
23
23
|
## 依据
|
|
24
24
|
|
|
@@ -45,21 +45,7 @@ Decision date: 2026-08-26
|
|
|
45
45
|
|
|
46
46
|
## 下游影响面
|
|
47
47
|
|
|
48
|
-
2026-08-26
|
|
49
|
-
|
|
50
|
-
| 仓库 | 依赖版本 | `--q1-shadow-popover` | `--q1-shadow-modal` |
|
|
51
|
-
| --- | --- | --- | --- |
|
|
52
|
-
| q1travel-web | `@q1travel/design-system` 0.7.3 | **2 处** | 0 处 |
|
|
53
|
-
| q1travel-api | 未依赖 | 0 处 | 0 处 |
|
|
54
|
-
| q1travel-chrome-extension | 未依赖 | 0 处 | 0 处 |
|
|
55
|
-
| q1travel-ai-search-worker | 未依赖 | 0 处 | 0 处 |
|
|
56
|
-
|
|
57
|
-
q1travel-web 的两个消费点:
|
|
58
|
-
|
|
59
|
-
- `src/components/CommandPalette.css:7`
|
|
60
|
-
- `src/pages/DocsPages.css:488`
|
|
61
|
-
|
|
62
|
-
(另有 `plans/001-design-system-menu-spatial-transition.md:45` 出现该 token,属计划文档,非运行代码。)
|
|
48
|
+
2026-08-26 对下游消费方的只读检索结果:`--q1-shadow-popover` 下游消费点 2 处,`--q1-shadow-modal` 下游消费点 0 处。
|
|
63
49
|
|
|
64
50
|
`--q1-shadow-modal` 下游零消费,已于第一步单独发布,无需下游动作。
|
|
65
51
|
|
|
@@ -67,9 +53,9 @@ q1travel-web 的两个消费点:
|
|
|
67
53
|
|
|
68
54
|
**消费方无需修改任何代码。** 两个 token 名称、消费方式与作用位置均未变,升级包版本后阴影自动变为分层。
|
|
69
55
|
|
|
70
|
-
需要做的只有视觉复核:升级后确认
|
|
56
|
+
需要做的只有视觉复核:升级后确认 2 处下游消费点的浮层在明暗双主题下的观感——预期是边缘更清晰、根部更实,而不是更重或更糊。
|
|
71
57
|
|
|
72
|
-
|
|
58
|
+
下游消费方升级时可能跨越多个版本;本合同只对阴影这一项负责,不代表其他差异已评估。
|
|
73
59
|
|
|
74
60
|
## 可接受变化
|
|
75
61
|
|
|
@@ -88,7 +74,7 @@ q1travel-web 当前停留在 0.7.3,与本仓 0.9.0 之间还隔着其他变更
|
|
|
88
74
|
|
|
89
75
|
## 非目标
|
|
90
76
|
|
|
91
|
-
-
|
|
77
|
+
- 不修改下游仓库,不代下游提交。
|
|
92
78
|
- 不新增第三档阴影,不为 Drawer / Sheet 引入共享阴影 token。
|
|
93
79
|
- 本次浮层阴影迁移不改动 `--q1-shadow-focus`;后续焦点环调整独立进行。
|
|
94
80
|
- 不在本合同内处理 `contracts/interface-guidelines.md` Design 章节的其余条款(嵌套圆角见 #141,色相一致见 #142)。
|
|
@@ -31,7 +31,7 @@ The `0.8.0` candidate freezes two independent product models:
|
|
|
31
31
|
- Unknown-tail: controlled `page` and `onChange`, with `hasNextPage`; it does not fabricate `total`, a last page, or numeric page-window controls.
|
|
32
32
|
- `true-cursor` remains deferred until a real consumer supplies the cursor ownership, request boundary, and acceptance evidence. It is not inferred from `total`, `page`, or `hasNextPage`.
|
|
33
33
|
|
|
34
|
-
TypeScript is the public input boundary for the mutually exclusive models. The package does not own
|
|
34
|
+
TypeScript is the public input boundary for the mutually exclusive models. The package does not own consumer data fetching, query-string state, router navigation, or cursor token parsing.
|
|
35
35
|
|
|
36
36
|
## #111 Shared slots and loading accessibility
|
|
37
37
|
|
|
@@ -81,7 +81,7 @@ The package contract must be backed by generated public declarations, a TypeScri
|
|
|
81
81
|
|
|
82
82
|
The documentation route `/components/pagination` is retained. It documents both the product `Pagination` boundary and the separate `DocsPagination` sequence-navigation boundary.
|
|
83
83
|
|
|
84
|
-
`DocsPagination` accepts consumer-owned real `href` values and renders native links. It does not import a
|
|
84
|
+
`DocsPagination` accepts consumer-owned real `href` values and renders native links. It does not import a consumer router or decide URL construction.
|
|
85
85
|
|
|
86
86
|
## Compatibility, removal, and rollback
|
|
87
87
|
|
|
@@ -92,6 +92,6 @@ The documentation route `/components/pagination` is retained. It documents both
|
|
|
92
92
|
|
|
93
93
|
## Web migration gate
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
Downstream migration remains a separate gate. This package candidate does not modify downstream consumers, does not claim consumer adoption, and does not publish or deploy. Web migration may start only after a verified published package release and a separately authorized consumer change.
|
|
96
96
|
|
|
97
97
|
This contract records the public boundary; it does not perform the `0.8.0` version bump, npm publish, Web migration, issue closure, or production validation.
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Status: accepted
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
关联:下游 StatusChip 消费方迁移
|
|
6
6
|
|
|
7
7
|
## 目标与边界
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
这份合同把下游消费方的展示型 `StatusChip` 映射到已发布的 `@q1travel/design-system` `Badge`。它只冻结 package props、语义映射、视觉取舍和回滚单位;不修改下游消费方,不把 `StatusChip` 兼容 alias 加入 package,也不批量迁移消费者。
|
|
10
10
|
|
|
11
11
|
`Badge` 已经是胶囊形(`border-radius: 999px`),因此迁移不需要新增 pill API。#24/#58 已裁定:状态 tone 使用现有 `subtle`,`quiet` 保留为低强调元数据档,StatusChip 原有 1px 描边并入 subtle,不新增 `outline`。
|
|
12
12
|
|
|
@@ -63,7 +63,7 @@ package `Badge` 的 subtle 派生色已在 #24 的双主题实测中验证:suc
|
|
|
63
63
|
|
|
64
64
|
## 非目标
|
|
65
65
|
|
|
66
|
-
-
|
|
66
|
+
- 不修改下游消费方。
|
|
67
67
|
- 不把 StatusChip 导出到 `@q1travel/design-system`。
|
|
68
68
|
- 不在本票新增 `outline`、`is-*`、page-local color token 或第三方路由依赖。
|
|
69
69
|
- 不因 package specimen 通过就宣称 61 个 Web 消费文件已迁移。
|
|
@@ -8,7 +8,7 @@ Related: q1travel-design-system#25
|
|
|
8
8
|
|
|
9
9
|
This contract freezes the first public boundary for a shared `Table`. It records
|
|
10
10
|
the behavior and ownership decisions needed before implementation; it does not
|
|
11
|
-
implement the component, change
|
|
11
|
+
implement the component, change downstream consumers, create migration tickets, or
|
|
12
12
|
claim consumer adoption.
|
|
13
13
|
|
|
14
14
|
## Public boundary
|
|
@@ -157,16 +157,16 @@ contract.
|
|
|
157
157
|
- The current-page select-all rule remains valid when the consumer changes
|
|
158
158
|
pages: off-page selected keys stay in the consumer's controlled collection,
|
|
159
159
|
while the header state is recalculated from the newly visible page.
|
|
160
|
-
-
|
|
160
|
+
- Downstream migration is a separate gate. It may begin only after the
|
|
161
161
|
package export, generated types, focused tests, published package identity,
|
|
162
162
|
and consumer adoption have each been independently verified.
|
|
163
|
-
- This contract does not modify
|
|
163
|
+
- This contract does not modify downstream consumers, publish the package, migrate a
|
|
164
164
|
consumer, close #25, or create implementation issues.
|
|
165
165
|
|
|
166
166
|
## Implementation sequence
|
|
167
167
|
|
|
168
168
|
`Table core` → `Interaction` → `Layout` → `export/types/tests` → `published
|
|
169
|
-
package verification` → `
|
|
169
|
+
package verification` → `downstream migration`
|
|
170
170
|
|
|
171
171
|
Each arrow is a separate acceptance gate. A passing documentation specimen,
|
|
172
172
|
local package build, or source-level assertion does not establish the next gate.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Status: accepted
|
|
4
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
|
|
5
|
+
This contract defines the token naming standard for q1travel Design System v1. It records the naming decision only; it does not migrate existing downstream runtime tokens.
|
|
6
6
|
|
|
7
7
|
## Decision
|
|
8
8
|
|
|
@@ -114,6 +114,43 @@ Owner-approved contrast roles (2026-10-07): `--q1-color-border-control` is the r
|
|
|
114
114
|
|
|
115
115
|
`--q1-touch-target-min` (`44px`) is the theme-independent semantic minimum for coarse-pointer hit regions, stored as `sizing.touch-target-min` in both theme contracts. It changes the invisible target, not the visual size.
|
|
116
116
|
|
|
117
|
+
### Domain Palettes
|
|
118
|
+
|
|
119
|
+
A domain palette is a set of semantic color tokens owned by one product domain whose visual identity intentionally differs from the shared neutral chain. It exists so that domain can consume tokens without a lossy substitution onto neutral roles.
|
|
120
|
+
|
|
121
|
+
Admission rules:
|
|
122
|
+
|
|
123
|
+
- A domain palette requires explicit owner approval. Product teams do not create one locally.
|
|
124
|
+
- It uses an independent prefix, `--q1-color-<domain>-<role>[-<state>]`, and declares every token in both light and dark themes.
|
|
125
|
+
- Its tokens are consumed only inside that domain and as a set. They are not mixed with the neutral chain (`text-*`, `bg-*`, `border-*`) on the same surface, and other surfaces do not borrow them.
|
|
126
|
+
- Values stay independent of the neutral chain unless an existing token is exactly equal; reusing a value never changes how either side renders.
|
|
127
|
+
|
|
128
|
+
Shipped domain palette (owner-approved 2026-10-13): `auth`, the cool blue-gray palette for account entry surfaces.
|
|
129
|
+
|
|
130
|
+
| Token | Light | Dark | Use |
|
|
131
|
+
| --- | --- | --- | --- |
|
|
132
|
+
| `--q1-color-auth-text-primary` | `#061b31` | `#f3f4f6` | Headings |
|
|
133
|
+
| `--q1-color-auth-text-secondary` | `#273951` | `#d1d5db` | Body copy |
|
|
134
|
+
| `--q1-color-auth-text-muted` | `#64748d` | `#9ca3af` | Supporting notes |
|
|
135
|
+
| `--q1-color-auth-border-strong` | `#d6dde6` | `#343943` | Card and input borders |
|
|
136
|
+
| `--q1-color-auth-surface-card` | `#ffffff` | `#17191d` | Card |
|
|
137
|
+
| `--q1-color-auth-surface-subtle` | `#f8fafc` | `#101216` | Preview area and input background |
|
|
138
|
+
| `--q1-color-auth-surface-disabled` | `#f6f9fc` | `#202329` | Disabled input |
|
|
139
|
+
| `--q1-color-auth-surface-media` | `#04050a` | `#04050a` | Page fallback before the media backdrop loads |
|
|
140
|
+
| `--q1-color-auth-action-disabled-bg` | `#c7c9cc` | `#3b404a` | Disabled submit button background |
|
|
141
|
+
| `--q1-color-auth-action-disabled-border` | `#c7c9cc` | `#3b404a` | Disabled submit button border |
|
|
142
|
+
| `--q1-color-auth-action-disabled-text` | `#ffffff` | `#a6acb8` | Disabled submit button label |
|
|
143
|
+
| `--q1-color-auth-focus-ring` | `rgba(83, 58, 253, 0.42)` | `rgba(126, 108, 255, 0.52)` | Single 3px focus ring |
|
|
144
|
+
| `--q1-color-auth-danger-border` | `#d92d20` | `#d92d20` | Failed validation border |
|
|
145
|
+
| `--q1-color-auth-danger-surface` | `#fff8f7` | `#241719` | Failed validation background |
|
|
146
|
+
| `--q1-color-auth-field-error-text` | `#d32f2f` | `#d32f2f` | Field error message |
|
|
147
|
+
| `--q1-color-auth-media-overlay` | `rgba(4, 5, 10, 0.46)` | `rgba(4, 5, 10, 0.46)` | Trigger background over a media backdrop |
|
|
148
|
+
| `--q1-color-auth-media-overlay-hover` | `rgba(4, 5, 10, 0.66)` | `rgba(4, 5, 10, 0.66)` | Same trigger, hover |
|
|
149
|
+
| `--q1-color-auth-on-media-border` | `rgba(255, 255, 255, 0.22)` | `rgba(255, 255, 255, 0.22)` | Trigger border over a media backdrop |
|
|
150
|
+
| `--q1-color-auth-on-media-border-hover` | `rgba(255, 255, 255, 0.34)` | `rgba(255, 255, 255, 0.34)` | Same trigger, hover |
|
|
151
|
+
|
|
152
|
+
The theme contracts register these as `semantic-colors.auth-*`, and `check:token-package` asserts that each contract value resolves to the runtime token in both themes.
|
|
153
|
+
|
|
117
154
|
### Component Tokens
|
|
118
155
|
|
|
119
156
|
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.
|
|
@@ -176,10 +213,10 @@ gets an input with no border and no background.
|
|
|
176
213
|
- Do not create new public `--ds-*` tokens.
|
|
177
214
|
- Do not rename all product `--ds-*` tokens in a broad sweep.
|
|
178
215
|
- During migration, add explicit aliases only when they reduce risk and point toward the accepted `--q1-*` naming.
|
|
179
|
-
- Treat `--ds-*` tokens in
|
|
216
|
+
- Treat `--ds-*` tokens in downstream consumers as legacy product implementation until a dedicated migration plan lands.
|
|
180
217
|
|
|
181
218
|
## Non-Goals
|
|
182
219
|
|
|
183
220
|
- This contract does not publish an npm token package.
|
|
184
|
-
- This contract does not migrate
|
|
221
|
+
- This contract does not migrate downstream consumers.
|
|
185
222
|
- This contract does not require deleting every local or private product CSS variable.
|