@q1travel/design-system 0.15.0 → 0.15.2
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/README.md +1 -1
- package/contracts/context-contrast-migration.md +85 -0
- package/contracts/design.dark.md +1 -1
- package/contracts/design.md +1 -1
- package/contracts/icon-system.md +1 -0
- package/contracts/implementation-map.md +1 -0
- package/contracts/token-naming.md +19 -0
- package/dist-pkg/design-system.js +2096 -2050
- package/dist-pkg/style.css +206 -18
- package/dist-pkg/tokens.css +20 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ q1travel 产品家族的设计权威上游仓,三件事集于一处:`@q1trav
|
|
|
8
8
|
|
|
9
9
|
## Sources
|
|
10
10
|
|
|
11
|
-
- Source contracts(设计契约源,canonical):`contracts/design.md`、`contracts/design.dark.md`、`contracts/token-naming.md`、`contracts/icon-system.md`、`contracts/button-api-compatibility.md`、`contracts/interface-guidelines.md`、`contracts/design-engineering-principles.md`、`contracts/implementation-map.md`、`contracts/overlay-foundation.md`,以及迁移契约 `contracts/status-chip-badge-migration.md`、`contracts/pagination-migration.md`、`contracts/table-migration.md`、`contracts/overlay-shadow-migration.md`。独立 HTML 文档的有界 class 词汇表源为 `contracts/design.css`。
|
|
11
|
+
- Source contracts(设计契约源,canonical):`contracts/design.md`、`contracts/design.dark.md`、`contracts/token-naming.md`、`contracts/icon-system.md`、`contracts/button-api-compatibility.md`、`contracts/interface-guidelines.md`、`contracts/design-engineering-principles.md`、`contracts/implementation-map.md`、`contracts/overlay-foundation.md`,以及迁移契约 `contracts/context-contrast-migration.md`、`contracts/status-chip-badge-migration.md`、`contracts/pagination-migration.md`、`contracts/table-migration.md`、`contracts/overlay-shadow-migration.md`。独立 HTML 文档的有界 class 词汇表源为 `contracts/design.css`。
|
|
12
12
|
- Generated mirrors(生成镜像,勿手改):`public/design.md`、`public/design.dark.md` 由 `scripts/sync-design-contracts.mjs` 从契约源逐字节复制;`public/design.css` 由 `scripts/build-design-css.mjs` 把两份契约 frontmatter 的取值注入 `contracts/design.css` 的类词汇后生成,因而自足、可被独立 HTML 页面直接加载。
|
|
13
13
|
- Runtime tokens:`src/styles/tokens.css`(canonical `--q1-*`,仅 `:root` 与 `:root[data-theme='dark']` 两个扁平 selector)。
|
|
14
14
|
- 发布台账:`contracts/releases/`(仅存于仓库,不进 npm 包)。
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Context and text contrast migration
|
|
2
|
+
|
|
3
|
+
## Scope and approval
|
|
4
|
+
|
|
5
|
+
Issues #246, #245, and #244 share a package ownership boundary. The consumer
|
|
6
|
+
approved implementation on 2026-09-09 after reviewing the source audit and
|
|
7
|
+
correcting the original ramp interpretation. This plan covers the existing
|
|
8
|
+
`text-muted` semantic token, Navigation active text, and the `stacked`
|
|
9
|
+
ContextSwitcher presentation. The consumer accepted the rendered result and authorized commit and release on
|
|
10
|
+
2026-09-11. The target patch release is 0.15.1; the starting consumer version is
|
|
11
|
+
0.15.0. This migration does not include source edits in consuming repositories.
|
|
12
|
+
|
|
13
|
+
## #246: readable supporting text
|
|
14
|
+
|
|
15
|
+
The reference ramps keep their existing values. In particular, gray-700 and
|
|
16
|
+
gray-800 are solid-background steps; they intentionally do not flip by theme.
|
|
17
|
+
There is no global monotonic-ramp requirement.
|
|
18
|
+
|
|
19
|
+
| Semantic token | Before | After | Supported surfaces |
|
|
20
|
+
| --- | --- | --- | --- |
|
|
21
|
+
| Light `--q1-color-text-muted` | gray-700, `#8f8f8f` | `#6b6b6b` | canvas, panel, subtle |
|
|
22
|
+
| Dark `--q1-color-text-muted` | gray-800, `#7d7d7d` | gray-700, `#8f8f8f` | canvas, panel, subtle |
|
|
23
|
+
|
|
24
|
+
Light supporting text needs its own semantic value between gray-800 and
|
|
25
|
+
gray-900: gray-800 misses normal-text AA, while gray-900 would collapse the
|
|
26
|
+
secondary/muted distinction. Dark supporting text can reuse gray-700. All three
|
|
27
|
+
text levels retain descending contrast on the supported surfaces and meet
|
|
28
|
+
WCAG 2 AA normal-text contrast (4.5:1). Arbitrary consumer surfaces, opacity,
|
|
29
|
+
blending, and disabled styling require their own effective-color checks.
|
|
30
|
+
|
|
31
|
+
Regenerate `public/design.md`, `public/design.dark.md`, and `public/design.css`
|
|
32
|
+
through `npm run sync:contracts`; runtime and contract values must agree.
|
|
33
|
+
The regression gate checks named text/surface pairs and button-label/solid
|
|
34
|
+
pairs. It must not treat every color as text or accept unsupported color syntax
|
|
35
|
+
silently. Existing browser checks cover composed component colors.
|
|
36
|
+
|
|
37
|
+
Consumer follow-up after upgrading: q1travel-web PR #998 introduced
|
|
38
|
+
`body.theme-dark .settings-appearance-layout { --text-tertiary: var(--q1-color-gray-700); }`.
|
|
39
|
+
Remove that workaround and resume the normal `--q1-color-text-muted` mapping.
|
|
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.
|
|
43
|
+
|
|
44
|
+
## #245: Navigation active text
|
|
45
|
+
|
|
46
|
+
Both vertical and horizontal active items, including hover, use the existing
|
|
47
|
+
`--q1-color-primary-900` text-capable step (solution A). The label and decorative
|
|
48
|
+
icon inherit the same foreground. Preserve semibold, transparent resting
|
|
49
|
+
background, neutral hover, focus indication, native activation, and route-owned
|
|
50
|
+
`aria-current`. Do not change the action-primary button background.
|
|
51
|
+
|
|
52
|
+
This is a package-only CSS change. Web requires no source adjustment. A new
|
|
53
|
+
brand-text semantic token is not introduced in this migration.
|
|
54
|
+
|
|
55
|
+
## #244: stacked current context
|
|
56
|
+
|
|
57
|
+
The existing `presentation: { type: 'stacked' }` adopts one consistent visual
|
|
58
|
+
behavior, without new props. Grouped and drilldown keep their presentations.
|
|
59
|
+
|
|
60
|
+
- A selected `menuitemradio` retains `aria-checked`, with a subtle full-row fill
|
|
61
|
+
and an inline-start accent rail instead of a trailing check. Pending feedback
|
|
62
|
+
remains visible. Focus and current-context indicators remain distinguishable.
|
|
63
|
+
- `depth: 1` uses a connector to the preceding depth-0 context within the same
|
|
64
|
+
group. The last child ends the branch at its center. Search results keep their
|
|
65
|
+
existing filtering behavior; when the parent is absent, retain indentation
|
|
66
|
+
without a misleading connector. These decorative lines do not create a Tree
|
|
67
|
+
widget or alter the menu keyboard model.
|
|
68
|
+
- Hover fades a background layer via opacity using duration-press (120ms).
|
|
69
|
+
Pointer opening introduces a short, capped list entrance whose last completion
|
|
70
|
+
is no later than duration-fast (150ms). Search, pending changes, and selection
|
|
71
|
+
updates do not replay the entrance. Keyboard opening and reduced motion are
|
|
72
|
+
immediate. Closing unmounts immediately.
|
|
73
|
+
|
|
74
|
+
Consumer follow-up: upgrade and verify the work-place map with real grouped
|
|
75
|
+
data, sparse/search results, pending/error states, long names, RTL, touch,
|
|
76
|
+
keyboard, and reduced motion. No package-private BEM overrides are required.
|
|
77
|
+
API #538 and #539 remain backend work and are not prerequisites for this change.
|
|
78
|
+
|
|
79
|
+
## Acceptance and delivery boundary
|
|
80
|
+
|
|
81
|
+
Require failing-then-passing focused contrast and component assertions, light
|
|
82
|
+
and dark rendered proof, a 390px responsive check, and the full `npm run check`
|
|
83
|
+
on the final source. Keep unrelated baseline failures explicit. Source changes,
|
|
84
|
+
local verification, commit, published version, and consumer adoption are
|
|
85
|
+
separate delivery states.
|
package/contracts/design.dark.md
CHANGED
package/contracts/design.md
CHANGED
package/contracts/icon-system.md
CHANGED
|
@@ -75,3 +75,4 @@ q1travel 的界面图标**目标是**一套自建的线性图标系统:几何
|
|
|
75
75
|
- **颜色**:不为图标单独设色,依赖 `currentColor` 跟随文本。
|
|
76
76
|
- **间距**:图标与文本之间保留一致间距,并与文本基线对齐。
|
|
77
77
|
- **一致性**:同一控件组内不混用不同描边或尺寸。
|
|
78
|
+
- **光学位移**:16px 线性图标贴文字标签时,图标框几何居中不等于看起来居中。位移统一消费 `--q1-optical-icon-shift-cjk-label`,通过独立的 `translate` 属性施加,不改 `transform`,因此不会冲掉 chevron 的旋转。取值按字体栈校准:包默认 `--q1-font-sans` 为 `0px`;拉丁首选字体决定行盒、中文回退 PingFang SC 的字体栈(web 当前字体栈)为 `-1px`,由消费方在自己的根上覆盖。纯英文标签会因此偏高约 1–2px,这是 x-height 的物理位置,不再按脚本细分。已接入:Navigation 分组图标、分组 chevron、链接项图标;ContextSwitcher 单行条目图标与动作图标。Button 前后缀默认不位移,消费方在已知全是中文的场景把 `--q1-button-affix-optical-y` 设为该 token。数值由 `check:browser` 的光学 fixture 锁定,见 `contracts/token-naming.md` 的 Optical Tokens。
|
|
@@ -17,6 +17,7 @@ README owns the repository inventory and generated-file boundary. This file owns
|
|
|
17
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
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
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
|
+
| Optical alignment | Aligned-looking media, icons, labels, and column edges | `ContextSwitcher` two-line rows, `Navigation` icons and chevron, `Table` edge columns and actions column, `Badge` label wrapper, `Button` affix | Optical tokens: `--q1-optical-icon-shift-cjk-label`, `--q1-optical-media-first-line-offset`, `--q1-surface-inset-inline`, `--q1-table-edge-padding-inline`, `--q1-button-hang-inline`, `--q1-badge-optical-shift`, `--q1-button-affix-optical-y` | Shifts use standalone `translate`; rotations and layout stay intact | Integer-pixel values only; locked by the `check:browser` optical fixture | Wrapper and class changes add no accessible names or roles |
|
|
20
21
|
| 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
|
|
|
22
23
|
## Implementation Rules
|
|
@@ -51,6 +51,25 @@ The scale stops at 300ms on purpose. Past that, an interface reads as something
|
|
|
51
51
|
|
|
52
52
|
An `infinite` loop's period is not on this scale. A spinner at 1.2s and a skeleton sweep at 1.6s are component rhythms, not responses to input; forcing them into the response scale either breaks them or manufactures single-use tokens.
|
|
53
53
|
|
|
54
|
+
### Optical Tokens
|
|
55
|
+
|
|
56
|
+
Optical tokens carry the integer-pixel compensations that make an interface look aligned rather than merely measure aligned. They were introduced in 0.15.2 from the 2026-09-17 optical alignment audit.
|
|
57
|
+
|
|
58
|
+
Their values hold only for the font stack they were measured with. The package default is calibrated for `--q1-font-sans`; a consumer that overrides the body font stack re-measures and overrides the value on its own root. `check:browser` locks both the package default font stack and the current web font stack with the optical fixture (`/__browser-fixtures__/optical-alignment`): Chinese and mixed samples stay within 1px (plus half a device pixel of quantization), across light and dark themes at DPR 1 and 2.
|
|
59
|
+
|
|
60
|
+
- `--q1-optical-icon-shift-cjk-label` (`0px`) — vertical shift for a 16px line icon beside a Chinese label. `--q1-font-sans` needs none. The current web stack, whose Latin primary font (Avenir Next) sets the line box while Chinese falls back to PingFang SC, needs `-1px`.
|
|
61
|
+
- `--q1-media-size` (`var(--q1-space-6)`), `--q1-media-first-line-box` (`var(--q1-line-height-label-13)`), and `--q1-optical-media-first-line-offset` (`calc((first-line-box - media-size) / 2)`, `-3px`) — a two-line media row aligns its avatar to the first line's optical center, not to the geometric center of the whole block. The offset resolves once on `:root`, so a surface that changes the media size or first-line box redeclares the offset in the same rule.
|
|
62
|
+
- `--q1-surface-inset-inline` (`var(--q1-space-4)`) — the single content inset that page headers, card content, and table edge columns share as one reference line.
|
|
63
|
+
- `--q1-table-edge-padding-inline` (`var(--q1-surface-inset-inline)`) — outer padding of a table's first and last columns. Inner columns keep `--q1-space-2`.
|
|
64
|
+
- `--q1-button-hang-inline` (`calc(var(--q1-space-3) + 1px)`) — distance from a small button's border edge to its label. Ghost buttons in a table actions column hang by this amount so the label starts on the column line.
|
|
65
|
+
- `--q1-badge-optical-shift` (`0px`) and `--q1-button-affix-optical-y` (`0px`) — opt-in switches for the Badge label and Button affixes. They default to zero because Chinese and Latin labels move in opposite directions; a consumer sets them only where the label script is known.
|
|
66
|
+
|
|
67
|
+
Rules:
|
|
68
|
+
|
|
69
|
+
- Values are whole pixels. A compensation never uses a fractional pixel such as `0.5px`.
|
|
70
|
+
- Components apply a shift through the standalone `translate` property, never through `transform`, so an existing `transform: rotate()` keeps working.
|
|
71
|
+
- Where the compensation must change occupied space, use `margin-block-start` with an integer token instead of `translate`.
|
|
72
|
+
|
|
54
73
|
### Semantic Tokens
|
|
55
74
|
|
|
56
75
|
Semantic tokens describe product meaning. Product surfaces should consume these before reaching for reference tokens.
|