@q1travel/design-system 0.11.0 → 0.12.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/README.md +5 -3
- package/contracts/design.dark.md +208 -4
- package/contracts/design.md +208 -4
- package/contracts/token-naming.md +8 -0
- package/dist-pkg/design-system.d.ts +47 -4
- package/dist-pkg/design-system.js +3170 -2763
- package/dist-pkg/style.css +225 -45
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,8 +8,8 @@ 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`。
|
|
12
|
-
- Generated mirrors(生成镜像,勿手改):`public/design.md`、`public/design.dark.md
|
|
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`。
|
|
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 包)。
|
|
15
15
|
|
|
@@ -58,6 +58,8 @@ docs/ review/ 架构骨架、agent 规范、历史决策记录
|
|
|
58
58
|
## Documentation & AI Guidelines
|
|
59
59
|
|
|
60
60
|
- **AI Agent 必须遵循根目录 `AGENTS.md`**(Claude Code 与 Codex 共用的 canonical 入口:命令速查、红线约束、工作闭环与知识索引);`CLAUDE.md` 仅为其薄包装。
|
|
61
|
-
- `docs/architecture.md` —
|
|
61
|
+
- `docs/architecture.md` — 双构建管线、契约生成与下游消费模型、文档站托管与公开契约的缓存策略(含 Cloudflare Cache Rule 与 Purge 运维备忘)、发布溯源链路。
|
|
62
62
|
- `docs/adr/template.md` — 新 ADR 从此模板开始;早期已接受决策存于 `review/decision-log/`。
|
|
63
|
+
- `docs/token-coverage-gaps.md` — 下游有真实消费需求但本仓未导出的 `--q1-*` 能力缺口登记(待决清单,非契约)。
|
|
64
|
+
- `docs/research/design-md-eval/` — design.md 有/无 对照评测:固定场景、确定性检查、修正队列(研究记录,非契约)。
|
|
63
65
|
- 下游消费方式:安装 `@q1travel/design-system` 后 import 组件与 `style.css` / `tokens.css`;`npx q1-design sync` 把包内 skill 与契约物化为只读缓存,`q1-design verify` 校验缓存未被改动,`q1-design lint` 执行 `Q1-DS-*` 机械规则;`q1-design ls` 列出随包组件,`q1-design doc <组件名>` 打印其公共 API(两者现推自随包的 `.d.ts`,不另存清单);`q1-design overrides` 统计并分类消费方对组件外观的覆写。
|
package/contracts/design.dark.md
CHANGED
|
@@ -313,13 +313,46 @@ components:
|
|
|
313
313
|
activeTextColor: "{semantic-colors.text-primary}"
|
|
314
314
|
borderColor: "{semantic-colors.border}"
|
|
315
315
|
---
|
|
316
|
-
|
|
317
316
|
# q1travel Design System
|
|
318
317
|
|
|
319
318
|
## Overview
|
|
320
319
|
|
|
321
320
|
This is the dark-theme source contract. It keeps token names aligned with the light contract and changes values only where the theme requires a different surface, text, border, or status value.
|
|
322
321
|
|
|
322
|
+
## Scope and Reader
|
|
323
|
+
|
|
324
|
+
This file is the public entry point to q1travel design authority. It is written to be loaded whole, by an agent that may have no access to this repository and no other q1travel context.
|
|
325
|
+
|
|
326
|
+
It covers: which decisions are already made, which components exist, how space and hierarchy are composed, and which recognizable failures to avoid.
|
|
327
|
+
|
|
328
|
+
It does not cover: per-component API surfaces, per-surface interaction detail, or migration state. Inside this repository those live in `contracts/interface-guidelines.md` (surface rules), `contracts/implementation-map.md` (reference-to-implementation mapping), `contracts/token-naming.md` (token layers and migration), and `contracts/icon-system.md`. Where this file and those contracts disagree, the narrower contract wins and this file should be corrected.
|
|
329
|
+
|
|
330
|
+
Reference systems provide intent, never implementation source. Do not copy markup, class names, computed styles, or measurements taken from a screenshot.
|
|
331
|
+
|
|
332
|
+
## Priority Order
|
|
333
|
+
|
|
334
|
+
When requirements conflict, protect in this order. A lower item never justifies breaking a higher one.
|
|
335
|
+
|
|
336
|
+
1. Supplied facts: amounts, units, currencies, time zones, identifiers, and every qualifier attached to them.
|
|
337
|
+
2. Accessibility contracts for the component tier in use. A Tier A keyboard model is not negotiable.
|
|
338
|
+
3. Registered components and semantic tokens over new local structure.
|
|
339
|
+
4. The reader's question, and the shortest honest path to its answer.
|
|
340
|
+
5. q1travel authorship being unmistakable.
|
|
341
|
+
6. Composition chosen for this particular material.
|
|
342
|
+
7. Responsive refinement and motion detail.
|
|
343
|
+
|
|
344
|
+
## Working Method
|
|
345
|
+
|
|
346
|
+
Four passes. Do not start at pass three.
|
|
347
|
+
|
|
348
|
+
**Frame the task.** Name the person deciding, what they decide, and the strongest supported answer. Separate observation from projection. Support two paths through the same page: a fast path that reaches the conclusion, and an audit path that exposes the evidence behind it.
|
|
349
|
+
|
|
350
|
+
**Choose composition.** Reject the obvious template for the document category. Map the material to visual variables: magnitude to length, time to sequence, alternatives to aligned rows. Use a table for exact lookup, prose for a single conclusion, a chart only where a relationship reads faster as a shape than as numbers.
|
|
351
|
+
|
|
352
|
+
**Apply the system.** Compose from the inventory below. Consume semantic tokens, not source values. Stay monochrome unless colour carries meaning that also survives without colour.
|
|
353
|
+
|
|
354
|
+
**Inspect before delivery.** Run the Verification section. Check the first viewport, the peer alignment, the theme pair, and the keyboard path before calling the work done.
|
|
355
|
+
|
|
323
356
|
## Token Layers
|
|
324
357
|
|
|
325
358
|
- Core tokens define source design values such as color, spacing, radius, and typography.
|
|
@@ -328,6 +361,177 @@ This is the dark-theme source contract. It keeps token names aligned with the li
|
|
|
328
361
|
|
|
329
362
|
## Usage
|
|
330
363
|
|
|
331
|
-
- Product code
|
|
332
|
-
-
|
|
333
|
-
-
|
|
364
|
+
- Product code consumes semantic tokens and component mappings before core values, and never literal colour values.
|
|
365
|
+
- New public tokens use the `--q1-*` prefix. Token names stay stable across the light and dark contracts; only values differ.
|
|
366
|
+
- Consume token names, never the resolved values printed by an inspector. A resolved value is inspection output, not an API.
|
|
367
|
+
- Every reference must resolve. `var(--x)` naming a token that does not exist fails silently: the declaration is dropped and the surface quietly loses a radius, a colour, or a border.
|
|
368
|
+
|
|
369
|
+
## Primitives Inventory
|
|
370
|
+
|
|
371
|
+
These components ship in the package. Compose from this list before writing new structure. If a needed capability is missing from a component, extend that component rather than adding another local pattern beside it.
|
|
372
|
+
|
|
373
|
+
`q1-design ls` prints this list from the installed package, and `q1-design doc <name>` prints one component's public API. Use those when the package is installed; use this section when it is not.
|
|
374
|
+
|
|
375
|
+
**Actions.** Button, ButtonLink, IconButton, SplitButton, LoadMoreButton, ClearButton, CopyButton, Link, Toolbar.
|
|
376
|
+
|
|
377
|
+
- Button carries the action. ButtonLink navigates but reads as a button, for a page-level call to action. Link reads as text, inside a sentence. Substituting one for another makes the page read wrong.
|
|
378
|
+
- SplitButton is a primary action with an adjacent menu whose first entry mirrors it. Do not use it to hide unrelated actions behind a chevron.
|
|
379
|
+
- IconButton requires an accessible name. An icon-only control without one is not deliverable.
|
|
380
|
+
|
|
381
|
+
**Text fields.** FormField, Label, Input, ClearableInput, SearchInput, Textarea, Select, Fieldset, ErrorMessage.
|
|
382
|
+
|
|
383
|
+
- FormField owns the label, help text, and error slot. Do not assemble those three around a bare Input.
|
|
384
|
+
- Select is for a short, fixed list. Anything searchable, or longer than roughly seven entries, is a Combobox.
|
|
385
|
+
|
|
386
|
+
**Option fields.** ControlOption, Checkbox, Radio, Choicebox, Combobox, MultiSelect, Switch, Toggle, Slider, RangeSlider.
|
|
387
|
+
|
|
388
|
+
- Switch commits immediately. Checkbox stages a change that a submit applies. Choosing the wrong one misstates when the change takes effect.
|
|
389
|
+
- Toggle selects among mutually exclusive views. It is not a Switch with more entries.
|
|
390
|
+
- RangeSlider is two thumbs over one interval, paired with numeric inputs; Slider is a single value.
|
|
391
|
+
|
|
392
|
+
**Dates and ranges.** CalendarGrid, RangeInputs, RangeField, PeriodCombobox, addDays.
|
|
393
|
+
|
|
394
|
+
**Overlays.** Modal, ModalInset, DestructiveActionModal, Drawer, Sheet, Menu, ContextMenu, DotsMenu, Tooltip, ContextCard, SearchDialog, CommandMenu.
|
|
395
|
+
|
|
396
|
+
- Modal blocks and demands an answer. Use it for confirmation, not for a long form; a long form belongs in a Drawer or its own route.
|
|
397
|
+
- DestructiveActionModal is the required shape for irreversible actions. Do not rebuild that confirmation from a plain Modal.
|
|
398
|
+
- Sheet slides in from an edge with a focus trap; Drawer is the wider panel form. Menu is anchored and flips on collision; ContextMenu and DotsMenu share its keyboard engine.
|
|
399
|
+
- Tooltip carries a short label for a control. Anything a reader must read to decide belongs in the page or in a ContextCard.
|
|
400
|
+
|
|
401
|
+
**Data and evidence.** Table, Pagination, DocsPagination, ShowMore, Chart, Gauge, Progress, JsonView, Entity, Description, RelativeTimeCard.
|
|
402
|
+
|
|
403
|
+
- Table owns tabular semantics, selection, sorting, and density. Never assemble rows out of divs.
|
|
404
|
+
- Pagination paginates a data set with known or unknown totals. DocsPagination is previous/next reading order and is not interchangeable with it.
|
|
405
|
+
- Gauge is one ratio as a ring. Progress is advancement along a task, and takes segment stops.
|
|
406
|
+
- RelativeTimeCard reveals the absolute time behind a relative one. Prefer it to printing both.
|
|
407
|
+
|
|
408
|
+
**Status and feedback.** Banner, ProjectBanner, Note, ErrorCard, ErrorMessage, EmptyState, Badge, Pill, StatusDot, ToastProvider, useToast, Feedback, Spinner, LoadingDots, Skeleton.
|
|
409
|
+
|
|
410
|
+
- Banner announces at page scope. Note is an inline aside. ErrorMessage sits against one field. ErrorCard replaces a region that failed to load. Picking the widest one available overstates the problem.
|
|
411
|
+
- Toast is for non-blocking confirmation of something that already happened. It is not where an error the reader must act on belongs.
|
|
412
|
+
- Badge and Pill label a state drawn from a known set. Ordinary metadata is text, not a badge. StatusDot is the smallest form, and needs a text label beside it.
|
|
413
|
+
- Skeleton holds the shape of content that is coming. Spinner and LoadingDots say only that something is happening.
|
|
414
|
+
|
|
415
|
+
**Structure and navigation.** Card, AuthCard, Sidebar, SidebarDrawer, Navigation, NavigationSection, NavigationItem, NavigationGroup, ContextSwitcher, Breadcrumb, CollapsibleBreadcrumb, Tabs, Collapse, CollapseGroup, Separator, Scroller, ScrollerWithButtons, FileTree.
|
|
416
|
+
|
|
417
|
+
- Card is a surface you have earned, not a default wrapper. Reach for spacing and alignment first.
|
|
418
|
+
- Tabs switch between peer views of the same subject. They are not a way to shorten a page.
|
|
419
|
+
- ContextSwitcher is the two-level selection model; the consumer owns the state behind it.
|
|
420
|
+
|
|
421
|
+
**Identity and media.** Avatar, AvatarGroup, Book, Browser, BrowserDots, BrowserControls, BrowserAddress, BrowserTabs, BrowserPlaceholder, Phone, Video, ThemeSwitcher.
|
|
422
|
+
|
|
423
|
+
**Text utilities.** Code, CodeInline, CodeTokens, CodeBlock, Snippet, Kbd, MiddleTruncate, TextWithCopyButton.
|
|
424
|
+
|
|
425
|
+
- Kbd holds one key or one modifier per element.
|
|
426
|
+
- MiddleTruncate preserves both ends of an identifier. Do not truncate identifiers with a trailing ellipsis.
|
|
427
|
+
|
|
428
|
+
**Hooks.** useToast, useCopy, useRadio.
|
|
429
|
+
|
|
430
|
+
## Document Stylesheet
|
|
431
|
+
|
|
432
|
+
The inventory above needs a React application. When the page is a standalone HTML document — a report, a proposal, a brief — produced outside that application, load the published stylesheet instead and compose from its class vocabulary.
|
|
433
|
+
|
|
434
|
+
```html
|
|
435
|
+
<link rel="stylesheet" href="https://design.q1lx.com/design.css">
|
|
436
|
+
<body class="q1-doc">
|
|
437
|
+
<div class="q1-shell">…</div>
|
|
438
|
+
</body>
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
The stylesheet is self-contained: it carries the token values it needs, so no other file has to load first. It resolves the light and dark palettes from the reader's system setting, and accepts an explicit `data-theme` of `light` or `dark` on the root element. Do not add a visible theme control.
|
|
442
|
+
|
|
443
|
+
**The vocabulary is bounded.** Treat the names below as the entire public surface. Do not invent class names, do not guess at undocumented ones, and do not write page-level `style` attributes or a second stylesheet beside it — typography, spacing, and rhythm are decided here precisely so they are not decided again per page. If something is missing, add it to the vocabulary rather than working around it.
|
|
444
|
+
|
|
445
|
+
Never load this stylesheet together with the component stylesheet that ships in the package. They serve different worlds, and loading both creates two answers to the same question.
|
|
446
|
+
|
|
447
|
+
Shell: `q1-doc`, `q1-shell`, `q1-skip-link`, `q1-header`, `q1-masthead`, `q1-footer`.
|
|
448
|
+
|
|
449
|
+
Composition: `q1-grid`, `q1-span-4`, `q1-span-6`, `q1-span-8`, `q1-span-12`, `q1-stack`, `q1-cluster`, `q1-split`, `q1-section`, `q1-reading`.
|
|
450
|
+
|
|
451
|
+
Typography: `q1-display`, `q1-title`, `q1-heading-24`, `q1-heading-20`, `q1-heading-16`, `q1-lede`, `q1-body`, `q1-label`, `q1-meta`, `q1-caption`, `q1-mono`, `q1-numeric`.
|
|
452
|
+
|
|
453
|
+
Evidence: `q1-stat-strip`, `q1-stat`, `q1-stat-label`, `q1-stat-value`, `q1-stat-detail`, `q1-table-wrap`, `q1-note`, `q1-formula`, `q1-sources`.
|
|
454
|
+
|
|
455
|
+
Comparison: `q1-bar-list`, `q1-bar`, `q1-bar-label`, `q1-bar-value`, `q1-bar-track`, `q1-bar-fill`.
|
|
456
|
+
|
|
457
|
+
Utility: `q1-sr-only`.
|
|
458
|
+
|
|
459
|
+
Rules that the classes alone do not carry:
|
|
460
|
+
|
|
461
|
+
- `q1-table-wrap` owns exactly one semantic `table`. Mark numeric headers and cells with `q1-numeric` so the column aligns and its digits share a width. `q1-numeric` belongs on table cells only; `q1-stat-value` already sets tabular figures and must not carry it.
|
|
462
|
+
- `q1-note` takes its meaning from `data-tone` of `info`, `success`, `warning`, or `danger`. The wording must carry that meaning too; the colour is a second cue, never the only one.
|
|
463
|
+
- Every `q1-bar-fill` in one list sets `--q1-bar-ratio` against the same maximum. Bars drawn without a shared scale compare nothing.
|
|
464
|
+
- A `q1-stat-strip` holds peer figures. Label, value, and detail are present or absent consistently across the whole strip.
|
|
465
|
+
- Reading prose sits in `q1-reading` or a six-to-seven column span, not across the full twelve.
|
|
466
|
+
|
|
467
|
+
## Composition Rules
|
|
468
|
+
|
|
469
|
+
**Grid.** Twelve columns on desktop, six on tablet, four on mobile. Reading prose occupies six to seven desktop columns. Tables, charts, and major comparisons take the full twelve. Grid children set a zero minimum width so content reflows instead of overflowing.
|
|
470
|
+
|
|
471
|
+
**Spacing expresses grouping, not decoration.** Choose the step from the relationship, then keep it identical across peers.
|
|
472
|
+
|
|
473
|
+
- Within a group: `space-1` to `space-3`.
|
|
474
|
+
- Between groups: `space-4` to `space-6`.
|
|
475
|
+
- Between major sections: `space-8` to `space-10`.
|
|
476
|
+
- A true chapter break: `space-16`. Reserved; not a default.
|
|
477
|
+
|
|
478
|
+
Label, value, and detail spacing is identical across every peer in a set. One paragraph rhythm throughout the body.
|
|
479
|
+
|
|
480
|
+
**Hierarchy comes from type, weight, and space before it comes from surfaces.** Earn every border and every filled surface. Align every object to a shared edge, baseline, or grid line.
|
|
481
|
+
|
|
482
|
+
**Colour.** Monochrome by default. Add colour only where it encodes state, action, or a data series, and always with a second cue that is not colour. The light and dark themes are equivalent in meaning and hierarchy; neither is the primary one.
|
|
483
|
+
|
|
484
|
+
**Copy.** Sentence case headings that state the claim rather than name the section. Simplify the language, never the claim. Keep every qualifier attached to the number it qualifies.
|
|
485
|
+
|
|
486
|
+
## DO
|
|
487
|
+
|
|
488
|
+
- Answer the reader's question in the first viewport, together with the one relationship the page turns on.
|
|
489
|
+
- Give the page exactly one `h1`, and descend heading levels without skipping.
|
|
490
|
+
- Consume semantic tokens; let the theme resolve the value.
|
|
491
|
+
- Use a registered component; extend it when it falls short.
|
|
492
|
+
- Right-align numeric columns and keep their decimal places consistent down the column.
|
|
493
|
+
- Let a table occupy the full width of the region that owns it.
|
|
494
|
+
- Keep peer values, baselines, and label positions aligned across a set.
|
|
495
|
+
- Name every icon-only control, and keep focus visible on every interactive element.
|
|
496
|
+
- Preserve uncertainty: a projection is labelled as one, and a caveat travels with its figure.
|
|
497
|
+
- Honour reduced-motion preferences.
|
|
498
|
+
|
|
499
|
+
## DON'T
|
|
500
|
+
|
|
501
|
+
Do not ship any of these. Each is a recognizable generated-page default, and several are already blocked by gates in consuming repositories.
|
|
502
|
+
|
|
503
|
+
- Literal colour values in product code. Use tokens.
|
|
504
|
+
- A token reference with no definition behind it, or a component token with no fallback to the semantic token it replaces.
|
|
505
|
+
- A native `select` where the list is searchable or long.
|
|
506
|
+
- A hand-built Button, Badge, Table, Input, or Textarea beside the registered one.
|
|
507
|
+
- Reaching into another component's class names to adjust its appearance.
|
|
508
|
+
- All-caps eyebrows, overlines, and decorative numbered section labels.
|
|
509
|
+
- Decorative gradients, glows, blobs, stripes, glass effects, and shadows that carry no elevation meaning.
|
|
510
|
+
- A centred hero followed by a grid of equal cards.
|
|
511
|
+
- Repeated metric boxes standing in for a composed relationship.
|
|
512
|
+
- Badges or pills used for ordinary metadata.
|
|
513
|
+
- Nested cards, or a second border, added to repair a hierarchy that type and spacing should have carried.
|
|
514
|
+
- A dark rounded rectangle drawn around every chart.
|
|
515
|
+
- Tiny muted prose, inconsistent peer values, and misaligned baselines.
|
|
516
|
+
- A narrow table floating in a wide section, or a wide table compressed until words break.
|
|
517
|
+
- A legend where a direct label would do, or colour used without meaning.
|
|
518
|
+
- Bars at full width without a shared scale.
|
|
519
|
+
- Summary, conclusion, and recommendation sections that all restate the same sentence.
|
|
520
|
+
- Narration of how the page was produced.
|
|
521
|
+
- A visible theme switcher on a delivered page, or decorative brand marks.
|
|
522
|
+
|
|
523
|
+
## Verification
|
|
524
|
+
|
|
525
|
+
Before delivery, confirm each of these. They are observable; none of them is a matter of taste.
|
|
526
|
+
|
|
527
|
+
- Every `var(--token)` resolves to a defined token, or carries an explicit fallback.
|
|
528
|
+
- No literal colour value appears outside the token definition layer.
|
|
529
|
+
- Every interactive element is reachable by keyboard, in a sensible order, with a visible focus style.
|
|
530
|
+
- Tier A components follow their WAI-ARIA APG keyboard model; Tier B controls use native semantics with an associated name; Tier C hides decorative visuals from assistive technology and names every icon-only control.
|
|
531
|
+
- The page carries one `h1`, ordered headings, and landmark regions.
|
|
532
|
+
- Text and its background meet WCAG AA, and no state is signalled by colour alone.
|
|
533
|
+
- Light and dark render the same hierarchy, with no missing surface or invisible border in either.
|
|
534
|
+
- Peer spacing, alignment, and numeric formatting are identical across each set.
|
|
535
|
+
- Nothing scrolls horizontally at the page level.
|
|
536
|
+
|
|
537
|
+
In this repository, `npm run check` is the full gate; a partial run is not a pass. In consuming repositories, run their design and token gates before reporting completion.
|
package/contracts/design.md
CHANGED
|
@@ -313,13 +313,46 @@ components:
|
|
|
313
313
|
activeTextColor: "{semantic-colors.text-primary}"
|
|
314
314
|
borderColor: "{semantic-colors.border}"
|
|
315
315
|
---
|
|
316
|
-
|
|
317
316
|
# q1travel Design System
|
|
318
317
|
|
|
319
318
|
## Overview
|
|
320
319
|
|
|
321
320
|
This is the light-theme source contract. It defines token names, semantic roles, and component mappings before documentation examples are rendered.
|
|
322
321
|
|
|
322
|
+
## Scope and Reader
|
|
323
|
+
|
|
324
|
+
This file is the public entry point to q1travel design authority. It is written to be loaded whole, by an agent that may have no access to this repository and no other q1travel context.
|
|
325
|
+
|
|
326
|
+
It covers: which decisions are already made, which components exist, how space and hierarchy are composed, and which recognizable failures to avoid.
|
|
327
|
+
|
|
328
|
+
It does not cover: per-component API surfaces, per-surface interaction detail, or migration state. Inside this repository those live in `contracts/interface-guidelines.md` (surface rules), `contracts/implementation-map.md` (reference-to-implementation mapping), `contracts/token-naming.md` (token layers and migration), and `contracts/icon-system.md`. Where this file and those contracts disagree, the narrower contract wins and this file should be corrected.
|
|
329
|
+
|
|
330
|
+
Reference systems provide intent, never implementation source. Do not copy markup, class names, computed styles, or measurements taken from a screenshot.
|
|
331
|
+
|
|
332
|
+
## Priority Order
|
|
333
|
+
|
|
334
|
+
When requirements conflict, protect in this order. A lower item never justifies breaking a higher one.
|
|
335
|
+
|
|
336
|
+
1. Supplied facts: amounts, units, currencies, time zones, identifiers, and every qualifier attached to them.
|
|
337
|
+
2. Accessibility contracts for the component tier in use. A Tier A keyboard model is not negotiable.
|
|
338
|
+
3. Registered components and semantic tokens over new local structure.
|
|
339
|
+
4. The reader's question, and the shortest honest path to its answer.
|
|
340
|
+
5. q1travel authorship being unmistakable.
|
|
341
|
+
6. Composition chosen for this particular material.
|
|
342
|
+
7. Responsive refinement and motion detail.
|
|
343
|
+
|
|
344
|
+
## Working Method
|
|
345
|
+
|
|
346
|
+
Four passes. Do not start at pass three.
|
|
347
|
+
|
|
348
|
+
**Frame the task.** Name the person deciding, what they decide, and the strongest supported answer. Separate observation from projection. Support two paths through the same page: a fast path that reaches the conclusion, and an audit path that exposes the evidence behind it.
|
|
349
|
+
|
|
350
|
+
**Choose composition.** Reject the obvious template for the document category. Map the material to visual variables: magnitude to length, time to sequence, alternatives to aligned rows. Use a table for exact lookup, prose for a single conclusion, a chart only where a relationship reads faster as a shape than as numbers.
|
|
351
|
+
|
|
352
|
+
**Apply the system.** Compose from the inventory below. Consume semantic tokens, not source values. Stay monochrome unless colour carries meaning that also survives without colour.
|
|
353
|
+
|
|
354
|
+
**Inspect before delivery.** Run the Verification section. Check the first viewport, the peer alignment, the theme pair, and the keyboard path before calling the work done.
|
|
355
|
+
|
|
323
356
|
## Token Layers
|
|
324
357
|
|
|
325
358
|
- Core tokens define source design values such as color, spacing, radius, and typography.
|
|
@@ -328,6 +361,177 @@ This is the light-theme source contract. It defines token names, semantic roles,
|
|
|
328
361
|
|
|
329
362
|
## Usage
|
|
330
363
|
|
|
331
|
-
- Product code
|
|
332
|
-
-
|
|
333
|
-
-
|
|
364
|
+
- Product code consumes semantic tokens and component mappings before core values, and never literal colour values.
|
|
365
|
+
- New public tokens use the `--q1-*` prefix. Token names stay stable across the light and dark contracts; only values differ.
|
|
366
|
+
- Consume token names, never the resolved values printed by an inspector. A resolved value is inspection output, not an API.
|
|
367
|
+
- Every reference must resolve. `var(--x)` naming a token that does not exist fails silently: the declaration is dropped and the surface quietly loses a radius, a colour, or a border.
|
|
368
|
+
|
|
369
|
+
## Primitives Inventory
|
|
370
|
+
|
|
371
|
+
These components ship in the package. Compose from this list before writing new structure. If a needed capability is missing from a component, extend that component rather than adding another local pattern beside it.
|
|
372
|
+
|
|
373
|
+
`q1-design ls` prints this list from the installed package, and `q1-design doc <name>` prints one component's public API. Use those when the package is installed; use this section when it is not.
|
|
374
|
+
|
|
375
|
+
**Actions.** Button, ButtonLink, IconButton, SplitButton, LoadMoreButton, ClearButton, CopyButton, Link, Toolbar.
|
|
376
|
+
|
|
377
|
+
- Button carries the action. ButtonLink navigates but reads as a button, for a page-level call to action. Link reads as text, inside a sentence. Substituting one for another makes the page read wrong.
|
|
378
|
+
- SplitButton is a primary action with an adjacent menu whose first entry mirrors it. Do not use it to hide unrelated actions behind a chevron.
|
|
379
|
+
- IconButton requires an accessible name. An icon-only control without one is not deliverable.
|
|
380
|
+
|
|
381
|
+
**Text fields.** FormField, Label, Input, ClearableInput, SearchInput, Textarea, Select, Fieldset, ErrorMessage.
|
|
382
|
+
|
|
383
|
+
- FormField owns the label, help text, and error slot. Do not assemble those three around a bare Input.
|
|
384
|
+
- Select is for a short, fixed list. Anything searchable, or longer than roughly seven entries, is a Combobox.
|
|
385
|
+
|
|
386
|
+
**Option fields.** ControlOption, Checkbox, Radio, Choicebox, Combobox, MultiSelect, Switch, Toggle, Slider, RangeSlider.
|
|
387
|
+
|
|
388
|
+
- Switch commits immediately. Checkbox stages a change that a submit applies. Choosing the wrong one misstates when the change takes effect.
|
|
389
|
+
- Toggle selects among mutually exclusive views. It is not a Switch with more entries.
|
|
390
|
+
- RangeSlider is two thumbs over one interval, paired with numeric inputs; Slider is a single value.
|
|
391
|
+
|
|
392
|
+
**Dates and ranges.** CalendarGrid, RangeInputs, RangeField, PeriodCombobox, addDays.
|
|
393
|
+
|
|
394
|
+
**Overlays.** Modal, ModalInset, DestructiveActionModal, Drawer, Sheet, Menu, ContextMenu, DotsMenu, Tooltip, ContextCard, SearchDialog, CommandMenu.
|
|
395
|
+
|
|
396
|
+
- Modal blocks and demands an answer. Use it for confirmation, not for a long form; a long form belongs in a Drawer or its own route.
|
|
397
|
+
- DestructiveActionModal is the required shape for irreversible actions. Do not rebuild that confirmation from a plain Modal.
|
|
398
|
+
- Sheet slides in from an edge with a focus trap; Drawer is the wider panel form. Menu is anchored and flips on collision; ContextMenu and DotsMenu share its keyboard engine.
|
|
399
|
+
- Tooltip carries a short label for a control. Anything a reader must read to decide belongs in the page or in a ContextCard.
|
|
400
|
+
|
|
401
|
+
**Data and evidence.** Table, Pagination, DocsPagination, ShowMore, Chart, Gauge, Progress, JsonView, Entity, Description, RelativeTimeCard.
|
|
402
|
+
|
|
403
|
+
- Table owns tabular semantics, selection, sorting, and density. Never assemble rows out of divs.
|
|
404
|
+
- Pagination paginates a data set with known or unknown totals. DocsPagination is previous/next reading order and is not interchangeable with it.
|
|
405
|
+
- Gauge is one ratio as a ring. Progress is advancement along a task, and takes segment stops.
|
|
406
|
+
- RelativeTimeCard reveals the absolute time behind a relative one. Prefer it to printing both.
|
|
407
|
+
|
|
408
|
+
**Status and feedback.** Banner, ProjectBanner, Note, ErrorCard, ErrorMessage, EmptyState, Badge, Pill, StatusDot, ToastProvider, useToast, Feedback, Spinner, LoadingDots, Skeleton.
|
|
409
|
+
|
|
410
|
+
- Banner announces at page scope. Note is an inline aside. ErrorMessage sits against one field. ErrorCard replaces a region that failed to load. Picking the widest one available overstates the problem.
|
|
411
|
+
- Toast is for non-blocking confirmation of something that already happened. It is not where an error the reader must act on belongs.
|
|
412
|
+
- Badge and Pill label a state drawn from a known set. Ordinary metadata is text, not a badge. StatusDot is the smallest form, and needs a text label beside it.
|
|
413
|
+
- Skeleton holds the shape of content that is coming. Spinner and LoadingDots say only that something is happening.
|
|
414
|
+
|
|
415
|
+
**Structure and navigation.** Card, AuthCard, Sidebar, SidebarDrawer, Navigation, NavigationSection, NavigationItem, NavigationGroup, ContextSwitcher, Breadcrumb, CollapsibleBreadcrumb, Tabs, Collapse, CollapseGroup, Separator, Scroller, ScrollerWithButtons, FileTree.
|
|
416
|
+
|
|
417
|
+
- Card is a surface you have earned, not a default wrapper. Reach for spacing and alignment first.
|
|
418
|
+
- Tabs switch between peer views of the same subject. They are not a way to shorten a page.
|
|
419
|
+
- ContextSwitcher is the two-level selection model; the consumer owns the state behind it.
|
|
420
|
+
|
|
421
|
+
**Identity and media.** Avatar, AvatarGroup, Book, Browser, BrowserDots, BrowserControls, BrowserAddress, BrowserTabs, BrowserPlaceholder, Phone, Video, ThemeSwitcher.
|
|
422
|
+
|
|
423
|
+
**Text utilities.** Code, CodeInline, CodeTokens, CodeBlock, Snippet, Kbd, MiddleTruncate, TextWithCopyButton.
|
|
424
|
+
|
|
425
|
+
- Kbd holds one key or one modifier per element.
|
|
426
|
+
- MiddleTruncate preserves both ends of an identifier. Do not truncate identifiers with a trailing ellipsis.
|
|
427
|
+
|
|
428
|
+
**Hooks.** useToast, useCopy, useRadio.
|
|
429
|
+
|
|
430
|
+
## Document Stylesheet
|
|
431
|
+
|
|
432
|
+
The inventory above needs a React application. When the page is a standalone HTML document — a report, a proposal, a brief — produced outside that application, load the published stylesheet instead and compose from its class vocabulary.
|
|
433
|
+
|
|
434
|
+
```html
|
|
435
|
+
<link rel="stylesheet" href="https://design.q1lx.com/design.css">
|
|
436
|
+
<body class="q1-doc">
|
|
437
|
+
<div class="q1-shell">…</div>
|
|
438
|
+
</body>
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
The stylesheet is self-contained: it carries the token values it needs, so no other file has to load first. It resolves the light and dark palettes from the reader's system setting, and accepts an explicit `data-theme` of `light` or `dark` on the root element. Do not add a visible theme control.
|
|
442
|
+
|
|
443
|
+
**The vocabulary is bounded.** Treat the names below as the entire public surface. Do not invent class names, do not guess at undocumented ones, and do not write page-level `style` attributes or a second stylesheet beside it — typography, spacing, and rhythm are decided here precisely so they are not decided again per page. If something is missing, add it to the vocabulary rather than working around it.
|
|
444
|
+
|
|
445
|
+
Never load this stylesheet together with the component stylesheet that ships in the package. They serve different worlds, and loading both creates two answers to the same question.
|
|
446
|
+
|
|
447
|
+
Shell: `q1-doc`, `q1-shell`, `q1-skip-link`, `q1-header`, `q1-masthead`, `q1-footer`.
|
|
448
|
+
|
|
449
|
+
Composition: `q1-grid`, `q1-span-4`, `q1-span-6`, `q1-span-8`, `q1-span-12`, `q1-stack`, `q1-cluster`, `q1-split`, `q1-section`, `q1-reading`.
|
|
450
|
+
|
|
451
|
+
Typography: `q1-display`, `q1-title`, `q1-heading-24`, `q1-heading-20`, `q1-heading-16`, `q1-lede`, `q1-body`, `q1-label`, `q1-meta`, `q1-caption`, `q1-mono`, `q1-numeric`.
|
|
452
|
+
|
|
453
|
+
Evidence: `q1-stat-strip`, `q1-stat`, `q1-stat-label`, `q1-stat-value`, `q1-stat-detail`, `q1-table-wrap`, `q1-note`, `q1-formula`, `q1-sources`.
|
|
454
|
+
|
|
455
|
+
Comparison: `q1-bar-list`, `q1-bar`, `q1-bar-label`, `q1-bar-value`, `q1-bar-track`, `q1-bar-fill`.
|
|
456
|
+
|
|
457
|
+
Utility: `q1-sr-only`.
|
|
458
|
+
|
|
459
|
+
Rules that the classes alone do not carry:
|
|
460
|
+
|
|
461
|
+
- `q1-table-wrap` owns exactly one semantic `table`. Mark numeric headers and cells with `q1-numeric` so the column aligns and its digits share a width. `q1-numeric` belongs on table cells only; `q1-stat-value` already sets tabular figures and must not carry it.
|
|
462
|
+
- `q1-note` takes its meaning from `data-tone` of `info`, `success`, `warning`, or `danger`. The wording must carry that meaning too; the colour is a second cue, never the only one.
|
|
463
|
+
- Every `q1-bar-fill` in one list sets `--q1-bar-ratio` against the same maximum. Bars drawn without a shared scale compare nothing.
|
|
464
|
+
- A `q1-stat-strip` holds peer figures. Label, value, and detail are present or absent consistently across the whole strip.
|
|
465
|
+
- Reading prose sits in `q1-reading` or a six-to-seven column span, not across the full twelve.
|
|
466
|
+
|
|
467
|
+
## Composition Rules
|
|
468
|
+
|
|
469
|
+
**Grid.** Twelve columns on desktop, six on tablet, four on mobile. Reading prose occupies six to seven desktop columns. Tables, charts, and major comparisons take the full twelve. Grid children set a zero minimum width so content reflows instead of overflowing.
|
|
470
|
+
|
|
471
|
+
**Spacing expresses grouping, not decoration.** Choose the step from the relationship, then keep it identical across peers.
|
|
472
|
+
|
|
473
|
+
- Within a group: `space-1` to `space-3`.
|
|
474
|
+
- Between groups: `space-4` to `space-6`.
|
|
475
|
+
- Between major sections: `space-8` to `space-10`.
|
|
476
|
+
- A true chapter break: `space-16`. Reserved; not a default.
|
|
477
|
+
|
|
478
|
+
Label, value, and detail spacing is identical across every peer in a set. One paragraph rhythm throughout the body.
|
|
479
|
+
|
|
480
|
+
**Hierarchy comes from type, weight, and space before it comes from surfaces.** Earn every border and every filled surface. Align every object to a shared edge, baseline, or grid line.
|
|
481
|
+
|
|
482
|
+
**Colour.** Monochrome by default. Add colour only where it encodes state, action, or a data series, and always with a second cue that is not colour. The light and dark themes are equivalent in meaning and hierarchy; neither is the primary one.
|
|
483
|
+
|
|
484
|
+
**Copy.** Sentence case headings that state the claim rather than name the section. Simplify the language, never the claim. Keep every qualifier attached to the number it qualifies.
|
|
485
|
+
|
|
486
|
+
## DO
|
|
487
|
+
|
|
488
|
+
- Answer the reader's question in the first viewport, together with the one relationship the page turns on.
|
|
489
|
+
- Give the page exactly one `h1`, and descend heading levels without skipping.
|
|
490
|
+
- Consume semantic tokens; let the theme resolve the value.
|
|
491
|
+
- Use a registered component; extend it when it falls short.
|
|
492
|
+
- Right-align numeric columns and keep their decimal places consistent down the column.
|
|
493
|
+
- Let a table occupy the full width of the region that owns it.
|
|
494
|
+
- Keep peer values, baselines, and label positions aligned across a set.
|
|
495
|
+
- Name every icon-only control, and keep focus visible on every interactive element.
|
|
496
|
+
- Preserve uncertainty: a projection is labelled as one, and a caveat travels with its figure.
|
|
497
|
+
- Honour reduced-motion preferences.
|
|
498
|
+
|
|
499
|
+
## DON'T
|
|
500
|
+
|
|
501
|
+
Do not ship any of these. Each is a recognizable generated-page default, and several are already blocked by gates in consuming repositories.
|
|
502
|
+
|
|
503
|
+
- Literal colour values in product code. Use tokens.
|
|
504
|
+
- A token reference with no definition behind it, or a component token with no fallback to the semantic token it replaces.
|
|
505
|
+
- A native `select` where the list is searchable or long.
|
|
506
|
+
- A hand-built Button, Badge, Table, Input, or Textarea beside the registered one.
|
|
507
|
+
- Reaching into another component's class names to adjust its appearance.
|
|
508
|
+
- All-caps eyebrows, overlines, and decorative numbered section labels.
|
|
509
|
+
- Decorative gradients, glows, blobs, stripes, glass effects, and shadows that carry no elevation meaning.
|
|
510
|
+
- A centred hero followed by a grid of equal cards.
|
|
511
|
+
- Repeated metric boxes standing in for a composed relationship.
|
|
512
|
+
- Badges or pills used for ordinary metadata.
|
|
513
|
+
- Nested cards, or a second border, added to repair a hierarchy that type and spacing should have carried.
|
|
514
|
+
- A dark rounded rectangle drawn around every chart.
|
|
515
|
+
- Tiny muted prose, inconsistent peer values, and misaligned baselines.
|
|
516
|
+
- A narrow table floating in a wide section, or a wide table compressed until words break.
|
|
517
|
+
- A legend where a direct label would do, or colour used without meaning.
|
|
518
|
+
- Bars at full width without a shared scale.
|
|
519
|
+
- Summary, conclusion, and recommendation sections that all restate the same sentence.
|
|
520
|
+
- Narration of how the page was produced.
|
|
521
|
+
- A visible theme switcher on a delivered page, or decorative brand marks.
|
|
522
|
+
|
|
523
|
+
## Verification
|
|
524
|
+
|
|
525
|
+
Before delivery, confirm each of these. They are observable; none of them is a matter of taste.
|
|
526
|
+
|
|
527
|
+
- Every `var(--token)` resolves to a defined token, or carries an explicit fallback.
|
|
528
|
+
- No literal colour value appears outside the token definition layer.
|
|
529
|
+
- Every interactive element is reachable by keyboard, in a sensible order, with a visible focus style.
|
|
530
|
+
- Tier A components follow their WAI-ARIA APG keyboard model; Tier B controls use native semantics with an associated name; Tier C hides decorative visuals from assistive technology and names every icon-only control.
|
|
531
|
+
- The page carries one `h1`, ordered headings, and landmark regions.
|
|
532
|
+
- Text and its background meet WCAG AA, and no state is signalled by colour alone.
|
|
533
|
+
- Light and dark render the same hierarchy, with no missing surface or invisible border in either.
|
|
534
|
+
- Peer spacing, alignment, and numeric formatting are identical across each set.
|
|
535
|
+
- Nothing scrolls horizontally at the page level.
|
|
536
|
+
|
|
537
|
+
In this repository, `npm run check` is the full gate; a partial run is not a pass. In consuming repositories, run their design and token gates before reporting completion.
|
|
@@ -80,6 +80,14 @@ Examples:
|
|
|
80
80
|
- `--q1-button-bg-hover`
|
|
81
81
|
- `--q1-input-border-focus`
|
|
82
82
|
|
|
83
|
+
Shipped today for the `.form-control` skin: `--q1-input-bg`, `--q1-input-border`,
|
|
84
|
+
`--q1-input-fg`, `--q1-input-border-focus`, `--q1-input-focus-ring`.
|
|
85
|
+
|
|
86
|
+
Every component token MUST declare a fallback to the semantic token it replaces, so a
|
|
87
|
+
consumer that defines none of them sees no change. A component token without a fallback
|
|
88
|
+
turns an opt-in customisation surface into a required one: the first consumer to upgrade
|
|
89
|
+
gets an input with no border and no background.
|
|
90
|
+
|
|
83
91
|
## Usage Rules
|
|
84
92
|
|
|
85
93
|
- Product code should use semantic tokens first.
|
|
@@ -582,7 +582,7 @@ export declare type ContextMenuEntry = {
|
|
|
582
582
|
type: 'separator';
|
|
583
583
|
};
|
|
584
584
|
|
|
585
|
-
export declare function ContextSwitcher({ currentContext, groups, open, defaultOpen, onOpenChange, onSelect, pendingId, errorMessage, footerActions, onFooterAction, label, presentation, }: ContextSwitcherProps): JSX.Element;
|
|
585
|
+
export declare function ContextSwitcher({ currentContext, groups, open, defaultOpen, onOpenChange, onSelect, pendingId, errorMessage, footerActions, header, headerActions, onFooterAction, label, presentation, }: ContextSwitcherProps): JSX.Element;
|
|
586
586
|
|
|
587
587
|
export declare type ContextSwitcherAction = {
|
|
588
588
|
id: string;
|
|
@@ -612,6 +612,7 @@ export declare type ContextSwitcherGroup = {
|
|
|
612
612
|
items: ContextSwitcherItem[];
|
|
613
613
|
search?: ContextSwitcherSearch;
|
|
614
614
|
emptyState?: ContextSwitcherEmptyState;
|
|
615
|
+
divider?: boolean;
|
|
615
616
|
};
|
|
616
617
|
|
|
617
618
|
export declare type ContextSwitcherItem = {
|
|
@@ -622,10 +623,14 @@ export declare type ContextSwitcherItem = {
|
|
|
622
623
|
description?: ReactNode;
|
|
623
624
|
avatar?: ReactNode;
|
|
624
625
|
disabled?: boolean;
|
|
626
|
+
depth?: 0 | 1;
|
|
627
|
+
kind?: 'context' | 'action';
|
|
625
628
|
};
|
|
626
629
|
|
|
627
630
|
export declare type ContextSwitcherPresentation = {
|
|
628
631
|
type?: 'grouped';
|
|
632
|
+
} | {
|
|
633
|
+
type: 'stacked';
|
|
629
634
|
} | {
|
|
630
635
|
type: 'drilldown';
|
|
631
636
|
primaryGroupId: string;
|
|
@@ -642,6 +647,8 @@ export declare type ContextSwitcherProps = {
|
|
|
642
647
|
pendingId?: string;
|
|
643
648
|
errorMessage?: ReactNode;
|
|
644
649
|
footerActions?: ContextSwitcherAction[];
|
|
650
|
+
header?: ContextSwitcherCurrent;
|
|
651
|
+
headerActions?: ContextSwitcherAction[];
|
|
645
652
|
onFooterAction?: (action: ContextSwitcherAction) => void;
|
|
646
653
|
label?: string;
|
|
647
654
|
presentation?: ContextSwitcherPresentation;
|
|
@@ -1389,18 +1396,47 @@ export declare const Sidebar: typeof SidebarRoot & {
|
|
|
1389
1396
|
|
|
1390
1397
|
declare function SidebarContent({ className, ...props }: SidebarSlotProps): JSX.Element;
|
|
1391
1398
|
|
|
1399
|
+
export declare function SidebarDrawer({ 'aria-label': ariaLabel, open, onOpenChange, trigger, header, footer, children, collapseBelow, drawerWidth, variant, }: SidebarDrawerProps): JSX.Element;
|
|
1400
|
+
|
|
1401
|
+
export declare type SidebarDrawerProps = {
|
|
1402
|
+
'aria-label': string;
|
|
1403
|
+
open: boolean;
|
|
1404
|
+
onOpenChange: (open: boolean) => void;
|
|
1405
|
+
trigger: (props: SidebarDrawerTriggerProps) => ReactNode;
|
|
1406
|
+
header?: ReactNode;
|
|
1407
|
+
footer?: ReactNode;
|
|
1408
|
+
children: ReactNode;
|
|
1409
|
+
collapseBelow?: number;
|
|
1410
|
+
drawerWidth?: SidebarDrawerWidth;
|
|
1411
|
+
variant?: SidebarVariant;
|
|
1412
|
+
};
|
|
1413
|
+
|
|
1414
|
+
export declare type SidebarDrawerTriggerProps = {
|
|
1415
|
+
ref: Ref<HTMLButtonElement>;
|
|
1416
|
+
type: 'button';
|
|
1417
|
+
onClick: NonNullable<ButtonHTMLAttributes<HTMLButtonElement>['onClick']>;
|
|
1418
|
+
'aria-controls': string;
|
|
1419
|
+
'aria-expanded': boolean;
|
|
1420
|
+
'aria-haspopup': 'dialog';
|
|
1421
|
+
};
|
|
1422
|
+
|
|
1423
|
+
export declare type SidebarDrawerWidth = 'compact' | 'default' | 'wide';
|
|
1424
|
+
|
|
1392
1425
|
declare function SidebarFooter({ className, ...props }: SidebarSlotProps): JSX.Element;
|
|
1393
1426
|
|
|
1394
1427
|
declare function SidebarHeader({ className, ...props }: SidebarSlotProps): JSX.Element;
|
|
1395
1428
|
|
|
1396
1429
|
export declare type SidebarProps = HTMLAttributes<HTMLElement> & {
|
|
1397
1430
|
'aria-label': string;
|
|
1431
|
+
variant?: SidebarVariant;
|
|
1398
1432
|
};
|
|
1399
1433
|
|
|
1400
|
-
declare function SidebarRoot({ className, ...props }: SidebarProps): JSX.Element;
|
|
1434
|
+
declare function SidebarRoot({ className, variant, ...props }: SidebarProps): JSX.Element;
|
|
1401
1435
|
|
|
1402
1436
|
export declare type SidebarSlotProps = HTMLAttributes<HTMLDivElement>;
|
|
1403
1437
|
|
|
1438
|
+
export declare type SidebarVariant = 'panel' | 'plain';
|
|
1439
|
+
|
|
1404
1440
|
export declare function Skeleton({ shape, animated, show, className, children, }: {
|
|
1405
1441
|
shape?: SkeletonShape;
|
|
1406
1442
|
animated?: boolean;
|
|
@@ -1612,8 +1648,15 @@ export declare function ThemeSwitcher({ small, disabled }: {
|
|
|
1612
1648
|
|
|
1613
1649
|
export declare type ThresholdTone = 'primary' | 'success' | 'warning' | 'danger';
|
|
1614
1650
|
|
|
1651
|
+
declare type ToastAction = {
|
|
1652
|
+
label: string;
|
|
1653
|
+
/** 点击后先执行回调再关闭该提示。 */
|
|
1654
|
+
onClick?: () => void;
|
|
1655
|
+
};
|
|
1656
|
+
|
|
1615
1657
|
declare type ToastContextValue = {
|
|
1616
|
-
|
|
1658
|
+
/** 返回提示 id,可交给 dismiss 提前关闭(如异步流程完成后收起 preserve 提示)。 */
|
|
1659
|
+
push: (toast: ToastOptions) => number;
|
|
1617
1660
|
dismiss: (id: number) => void;
|
|
1618
1661
|
};
|
|
1619
1662
|
|
|
@@ -1622,7 +1665,7 @@ export declare type ToastOptions = {
|
|
|
1622
1665
|
/** 支持纯文本或富文本(如加粗/行内链接);aria-live 区域会播报文本内容,行内链接仍可被 Tab 到并激活。 */
|
|
1623
1666
|
title: ReactNode;
|
|
1624
1667
|
description?: ReactNode;
|
|
1625
|
-
|
|
1668
|
+
action?: ToastAction;
|
|
1626
1669
|
preserve?: boolean;
|
|
1627
1670
|
duration?: number;
|
|
1628
1671
|
};
|