@q1travel/design-system 0.30.5 → 0.30.7

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.
@@ -528,13 +528,12 @@ CheckCircleFill accepts `tone?: 'default' | 'success'` (default `default`); succ
528
528
 
529
529
  **Images and proportions.** AspectRatio requires a finite positive width/height ratio (invalid values render as 1 with one development warning) and only reserves layout space. Image requires alt (empty for decoration), defaults to contain and eager, accepts optional src, fit, loading, sm/md/lg square sizes (32/40/48), onError and root className; omitted size follows host width and natural image ratio. Loading keeps img mounted under a decorative Skeleton; missing and failed sources show a single named image fallback, and source changes isolate stale events. Decorative states are hidden from assistive technology; neither Image nor its host becomes inert. Inside AspectRatio, omit size: the Image root and img fill the ratio frame and object-fit controls complete centered containment or cropping. No new tokens or existing-consumer migration; remove new usages before reverting the additive exports.
530
530
 
531
- **Status and feedback.** Banner, ProjectBanner, Note, ErrorCard, RegionErrorState, ErrorMessage, EmptyState, Badge, Pill, CheckCircleFill, StatusDot, ToastProvider, useToast, Feedback, PageFeedback, Spinner, LoadingDots, Skeleton.
532
531
  **Status and feedback.** Banner, ProjectBanner, Note, ErrorCard, RegionErrorState, ErrorMessage, EmptyState, Badge, Pill, CheckCircleFill, StatusDot, ToastProvider, useToast, Feedback, PageFeedback, Spinner, LoadingDots, Skeleton, StatusPage, SkeletonIllustration, EmptyListIllustration.
533
532
 
534
533
  - 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.
535
- - RegionErrorState replaces only the failed region in place (table body under a kept header, card body, page section) while the rest of the page stays usable: neutral surface, danger color on the icon only, polite `role=status` by default, built-in retry that keeps focus while `retrying`. ErrorCard is for a failure that blocks the current task (danger card, assertive `role=alert`). EmptyState is a successful load with no data: default `layout="center"` keeps the full empty view; `layout="inline"` is an icon and regular secondary title row inside a section whose heading and actions belong to the host, without description, actions, headingLevel, or illustration. Center accepts a decorative `illustration?: ReactNode` in place of icon; built-in `EmptyListIllustration` depicts a fully processed list or inbox, without an icon backplate. See `implementation-map.md` for the retry and announcement boundary.
536
- - StatusPage defaults to a whole unavailable page with a caller-owned title, decorative SkeletonIllustration, plain-text description rendered as a paragraph, and actions. Its size="region" variant centers an icon or small illustration, title, description, and up to two actions inside a substantial content region, with a transparent background and content-driven height. ErrorCard covers a blocking compact failure; RegionErrorState is a compact retryable region message with its own status announcement; EmptyState means loading succeeded without content. StatusPage creates no live region; its host owns focus and announcements. StatusPage code is metadata only, never a message or spoken number.
537
- - RegionErrorState replaces only the failed region in place (table body under a kept header, card body, page section) while the rest of the page stays usable: neutral surface, danger color on the icon only, polite `role=status` by default, built-in retry that keeps focus while `retrying`. ErrorCard is for a failure that blocks the current task (danger card, assertive `role=alert`). EmptyState is a successful load with no data. See `implementation-map.md` for the retry and announcement boundary.
534
+ - RegionErrorState replaces only the failed region in place (table body under a kept header, card body, page section) while the rest of the page stays usable: neutral surface, danger color on the icon only, polite `role=status` by default, built-in retry that keeps focus while `retrying`. ErrorCard is for a failure that blocks the current task (danger card, assertive `role=alert`). EmptyState is a successful load with no data: default `layout="center"` keeps the full empty view; `layout="inline"` is an icon and regular secondary title row inside a section whose heading and actions belong to the host, without description, actions, headingLevel, or illustration. Center accepts a decorative `illustration?: ReactNode` in place of icon; built-in `EmptyListIllustration` depicts a fully processed list or inbox, without an icon backplate. `layout="strip"` adds a full-width neutral strip for list failures and load-more rows, with retry always inside its right edge. See `implementation-map.md` for the retry and announcement boundary.
535
+ - StatusPage defaults to a whole unavailable page with a caller-owned title, decorative SkeletonIllustration, plain-text description rendered as a paragraph, and actions. Its size="region" variant centers an icon or small illustration, title, description, and up to two actions inside a substantial content region, with a transparent background and content-driven height. ErrorCard covers a blocking compact failure; RegionErrorState is a compact retryable region message with its own status announcement; EmptyState means loading succeeded without content. StatusPage headingLevel accepts 1–6 (default 1); choose the next heading level under the host section. Existing omitted, 1 and 2 calls need no migration. StatusPage creates no live region; its host owns focus and announcements. StatusPage code is metadata only, never a message or spoken number.
536
+ - RegionErrorState replaces only the failed region in place (table body under a kept header, card body, page section) while the rest of the page stays usable: neutral surface, danger color on the icon only, polite `role=status` by default, built-in retry that keeps focus while `retrying`. ErrorCard is for a failure that blocks the current task (danger card, assertive `role=alert`). EmptyState is a successful load with no data. `layout="strip"` adds a full-width neutral strip for list failures and load-more rows, with retry always inside its right edge. See `implementation-map.md` for the retry and announcement boundary.
538
537
  - Toast is for non-blocking confirmation of something that already happened. It is not where an error the reader must act on belongs.
539
538
  - 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.
540
539
  - Skeleton holds the shape of content that is coming. Spinner and LoadingDots say only that something is happening.
@@ -528,13 +528,12 @@ CheckCircleFill accepts `tone?: 'default' | 'success'` (default `default`); succ
528
528
 
529
529
  **Images and proportions.** AspectRatio requires a finite positive width/height ratio (invalid values render as 1 with one development warning) and only reserves layout space. Image requires alt (empty for decoration), defaults to contain and eager, accepts optional src, fit, loading, sm/md/lg square sizes (32/40/48), onError and root className; omitted size follows host width and natural image ratio. Loading keeps img mounted under a decorative Skeleton; missing and failed sources show a single named image fallback, and source changes isolate stale events. Decorative states are hidden from assistive technology; neither Image nor its host becomes inert. Inside AspectRatio, omit size: the Image root and img fill the ratio frame and object-fit controls complete centered containment or cropping. No new tokens or existing-consumer migration; remove new usages before reverting the additive exports.
530
530
 
531
- **Status and feedback.** Banner, ProjectBanner, Note, ErrorCard, RegionErrorState, ErrorMessage, EmptyState, Badge, Pill, CheckCircleFill, StatusDot, ToastProvider, useToast, Feedback, PageFeedback, Spinner, LoadingDots, Skeleton.
532
531
  **Status and feedback.** Banner, ProjectBanner, Note, ErrorCard, RegionErrorState, ErrorMessage, EmptyState, Badge, Pill, CheckCircleFill, StatusDot, ToastProvider, useToast, Feedback, PageFeedback, Spinner, LoadingDots, Skeleton, StatusPage, SkeletonIllustration, EmptyListIllustration.
533
532
 
534
533
  - 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.
535
- - RegionErrorState replaces only the failed region in place (table body under a kept header, card body, page section) while the rest of the page stays usable: neutral surface, danger color on the icon only, polite `role=status` by default, built-in retry that keeps focus while `retrying`. ErrorCard is for a failure that blocks the current task (danger card, assertive `role=alert`). EmptyState is a successful load with no data: default `layout="center"` keeps the full empty view; `layout="inline"` is an icon and regular secondary title row inside a section whose heading and actions belong to the host, without description, actions, headingLevel, or illustration. Center accepts a decorative `illustration?: ReactNode` in place of icon; built-in `EmptyListIllustration` depicts a fully processed list or inbox, without an icon backplate. See `implementation-map.md` for the retry and announcement boundary.
536
- - StatusPage defaults to a whole unavailable page with a caller-owned title, decorative SkeletonIllustration, plain-text description rendered as a paragraph, and actions. Its size="region" variant centers an icon or small illustration, title, description, and up to two actions inside a substantial content region, with a transparent background and content-driven height. ErrorCard covers a blocking compact failure; RegionErrorState is a compact retryable region message with its own status announcement; EmptyState means loading succeeded without content. StatusPage creates no live region; its host owns focus and announcements. StatusPage code is metadata only, never a message or spoken number.
537
- - RegionErrorState replaces only the failed region in place (table body under a kept header, card body, page section) while the rest of the page stays usable: neutral surface, danger color on the icon only, polite `role=status` by default, built-in retry that keeps focus while `retrying`. ErrorCard is for a failure that blocks the current task (danger card, assertive `role=alert`). EmptyState is a successful load with no data. See `implementation-map.md` for the retry and announcement boundary.
534
+ - RegionErrorState replaces only the failed region in place (table body under a kept header, card body, page section) while the rest of the page stays usable: neutral surface, danger color on the icon only, polite `role=status` by default, built-in retry that keeps focus while `retrying`. ErrorCard is for a failure that blocks the current task (danger card, assertive `role=alert`). EmptyState is a successful load with no data: default `layout="center"` keeps the full empty view; `layout="inline"` is an icon and regular secondary title row inside a section whose heading and actions belong to the host, without description, actions, headingLevel, or illustration. Center accepts a decorative `illustration?: ReactNode` in place of icon; built-in `EmptyListIllustration` depicts a fully processed list or inbox, without an icon backplate. `layout="strip"` adds a full-width neutral strip for list failures and load-more rows, with retry always inside its right edge. See `implementation-map.md` for the retry and announcement boundary.
535
+ - StatusPage defaults to a whole unavailable page with a caller-owned title, decorative SkeletonIllustration, plain-text description rendered as a paragraph, and actions. Its size="region" variant centers an icon or small illustration, title, description, and up to two actions inside a substantial content region, with a transparent background and content-driven height. ErrorCard covers a blocking compact failure; RegionErrorState is a compact retryable region message with its own status announcement; EmptyState means loading succeeded without content. StatusPage headingLevel accepts 1–6 (default 1); choose the next heading level under the host section. Existing omitted, 1 and 2 calls need no migration. StatusPage creates no live region; its host owns focus and announcements. StatusPage code is metadata only, never a message or spoken number.
536
+ - RegionErrorState replaces only the failed region in place (table body under a kept header, card body, page section) while the rest of the page stays usable: neutral surface, danger color on the icon only, polite `role=status` by default, built-in retry that keeps focus while `retrying`. ErrorCard is for a failure that blocks the current task (danger card, assertive `role=alert`). EmptyState is a successful load with no data. `layout="strip"` adds a full-width neutral strip for list failures and load-more rows, with retry always inside its right edge. See `implementation-map.md` for the retry and announcement boundary.
538
537
  - Toast is for non-blocking confirmation of something that already happened. It is not where an error the reader must act on belongs.
539
538
  - 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.
540
539
  - Skeleton holds the shape of content that is coming. Spinner and LoadingDots say only that something is happening.
@@ -37,6 +37,10 @@ README owns the repository inventory and generated-file boundary. This file owns
37
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
+ ## Breadcrumb Route Links — Accepted 2026-10-25 (#563)
41
+
42
+ Breadcrumb and CollapsibleBreadcrumb accept an optional `linkComponent` for single-page routing. It replaces only items with a destination that are neither current nor disabled; static items and the collapse button keep their native behavior. Collapsible endpoints, middle levels and short paths use the same adapter. The adapter must render exactly one native `a` root and forward all received anchor properties, including `ref`, `className` and `children`. `LinkComponentProps` keeps a required string `href`. Omitting the adapter preserves native anchors, markup, classes, attributes, focus order and appearance. Consumers opt in per component; existing calls need no migration. Roll back by removing the optional prop before reverting the addition.
43
+
40
44
  ## Documentation Section Ownership
41
45
 
42
46
  Two component-page sections are q1travel supersets with no external counterpart, so their scope is defined here rather than inferred page by page.
@@ -138,6 +142,6 @@ Accepted 2026-10-08: explicitly sized single-line Button, ButtonLink, Input, Sea
138
142
 
139
143
  ## RegionErrorState retry and announcement boundary
140
144
 
141
- Owner approved 2026-10-15 (#455): public `RegionErrorState` replaces only a region whose data request failed, while the host keeps its frame (table header, card title, section heading). Props: `title` (required), `description`, `layout` `center` (default; table bodies and large regions, block padding `--q1-space-16` keeps roughly five table rows of height) or `inline` (cards and page sections; the retry button wraps under the description when the component's own container is narrower than 30rem), `headingLevel` 2–6 (default renders `p`, matching EmptyState), `onRetry`, `retrying`, and `live` `polite` (default, `role=status`) or `assertive` (`role=alert`). There is no `size` prop; the two layouts cover the observed hosts.
145
+ Owner approved 2026-10-15 (#455): public `RegionErrorState` replaces only a region whose data request failed, while the host keeps its frame (table header, card title, section heading). Props: `title` (required), `description`, `layout` `center` (default; table bodies and large regions, block padding `--q1-space-16` keeps roughly five table rows of height) or `inline` (cards and page sections; the retry button wraps under the description when the component's own container is narrower than 30rem), `headingLevel` 2–6 (default renders `p`, matching EmptyState), `onRetry`, `retrying`, and `live` `polite` (default, `role=status`) or `assertive` (`role=alert`). Accepted 2026-10-25 (#659): `strip` adds `.region-error-state--strip`, a full-width neutral strip with `--q1-color-bg-hover`, `--q1-radius-2`, block padding `--q1-space-2`, inline padding `--q1-space-4`, and minimum block size twice `--q1-space-6`. It shares inline typography and announcements, but its retry always stays inside the right edge without the narrow-container wrap. There is no `size` prop.
142
146
 
143
147
  The announcement region wraps only the icon, the `q1-sr-only` 「错误:」 prefix, the title and the description, and carries `aria-busy` while `retrying`. The retry Button sits outside that region so its loading status never nests inside another live region. Retry uses Button `loading` (focusable, `aria-disabled`, polite 「正在重试」 status) rather than `busy` (native disabled drops focus); the component stays mounted while retrying, and the visible label swaps 「重试」 to 「正在重试」 (hidden from assistive technology because the loading status already announces it). Icons are rendered internally from the existing icon set (AlertCircle, RotateCcw); no icon is exported. Copy is caller-owned; field errors, 403/404 and backend messages are out of scope. After a successful retry the caller moves focus to the restored content. Existing tokens only; the danger color appears only on the icon.
@@ -211,6 +211,10 @@ Theming owns tokens and `color-scheme`; the interaction-contrast rule lives in D
211
211
 
212
212
  These copy clauses keep reader address and empty states consistent with a formal business console: address the reader as 「您」, omit trailing punctuation from empty-state titles, and explain when content will appear in the description.
213
213
 
214
+ ### Second-Line Text
215
+
216
+ - [both] SHOULD keep second-line text in options and list rows — option descriptions, row subtitles, and secondary labels — empty unless it adds information nothing else provides. Add it only when it carries information the label cannot: items at the same level share the same or easily confused labels and the primary text cannot explain itself, or choosing the item has a result the user cannot see from the label, such as ordering, scope, reach, or timing. Translations, restatements of the label, and decorative notes are not information. The pull request must give the reason. Treat second-line text as an exception patch for the primary message, not as standard layout. Severe consequences such as high-risk, irreversible, or data-overwriting actions are stated in the DestructiveActionModal confirmation, not in option or row second lines. When an external product is used as a reference, its second-line information is not carried over. Body descriptions of panels such as empty states, error states, and dialogs are the main message and are not second-line text; field helper text follows the existing note and tooltip rules.
217
+
214
218
  ### Component Naming
215
219
 
216
220
  - [repo] SHOULD use the industry-common component name when one exists. Invent a name only when no established name fits. Name what the component is, not how it is built.
@@ -202,10 +202,12 @@ export declare type BookProps = {
202
202
  width?: number | string;
203
203
  } & Omit<HTMLAttributes<HTMLDivElement>, 'children'>;
204
204
 
205
- export declare function Breadcrumb({ items, label, type, }: {
205
+ export declare function Breadcrumb({ items, label, type, linkComponent, }: {
206
206
  items: BreadcrumbCrumb[];
207
207
  label: string;
208
208
  type?: 'text' | 'menu';
209
+ /** 用于单页应用内路由跳转;省略时渲染原生 a */
210
+ linkComponent?: LinkComponent;
209
211
  }): JSX.Element;
210
212
 
211
213
  export declare type BreadcrumbCrumb = {
@@ -586,9 +588,11 @@ export declare function CollapseGroup({ multiple, children }: {
586
588
  children: ReactNode;
587
589
  }): JSX.Element;
588
590
 
589
- export declare function CollapsibleBreadcrumb({ items, label }: {
591
+ export declare function CollapsibleBreadcrumb({ items, label, linkComponent }: {
590
592
  items: BreadcrumbCrumb[];
591
593
  label: string;
594
+ /** 用于单页应用内路由跳转;省略时渲染原生 a */
595
+ linkComponent?: LinkComponent;
592
596
  }): JSX.Element;
593
597
 
594
598
  export declare function Combobox({ options, searchPlacement, searchPlaceholder, footer, value, onChange, onSearch, isLoading, placeholder, size, disabled, readOnly, invalid, errorId, error, emptyText, clearable, id, className, name, inputMode, spellCheck, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, ref, ...rest }: ComboboxProps): JSX.Element;
@@ -1410,6 +1414,13 @@ export declare function Label({ htmlFor, required, hint, children, }: {
1410
1414
 
1411
1415
  export declare function Link({ href, tone, external, className, children, ref, ...rest }: LinkProps): JSX.Element;
1412
1416
 
1417
+ export declare type LinkComponent = (props: LinkComponentProps) => ReactElement | null;
1418
+
1419
+ /** 注入的链接组件收到的属性:原生 a 属性 + 必填字符串 href;实现必须渲染且只渲染一个原生 a,并透传全部属性(含 ref、className、children)。 */
1420
+ export declare type LinkComponentProps = Omit<ComponentPropsWithRef<'a'>, 'href'> & {
1421
+ href: string;
1422
+ };
1423
+
1413
1424
  export declare type LinkProps = {
1414
1425
  /** 目标地址。省略时渲染为静态文本,不表示 disabled 链接。 */
1415
1426
  href?: string;
@@ -2090,14 +2101,14 @@ export declare type RangeValue = {
2090
2101
 
2091
2102
  export declare function RegionErrorState({ title, description, layout, headingLevel, onRetry, retrying, live, }: RegionErrorStateProps): JSX.Element;
2092
2103
 
2093
- export declare type RegionErrorStateLayout = 'center' | 'inline';
2104
+ export declare type RegionErrorStateLayout = 'center' | 'inline' | 'strip';
2094
2105
 
2095
2106
  export declare type RegionErrorStateProps = {
2096
2107
  /** 失败的是哪块内容,点名资源;必填。 */
2097
2108
  title: string;
2098
2109
  /** 原因或下一步,一句话;可省略。 */
2099
2110
  description?: string;
2100
- /** center:居中占位,用于表格主体与大区块;inline:左对齐紧凑行,用于卡片与页面分区。默认 center。 */
2111
+ /** center:居中占位,用于表格主体与大区块;inline:左对齐紧凑行,用于卡片与页面分区。strip:整宽中性底条,用于列表位与「加载更多」行,重试始终在条内右侧。默认 center。 */
2101
2112
  layout?: RegionErrorStateLayout;
2102
2113
  /** 标题层级:缺省渲染 p(不进标题树);作为页面区块时传 2-6 渲染对应 h 标签。 */
2103
2114
  headingLevel?: 2 | 3 | 4 | 5 | 6;
@@ -2445,7 +2456,7 @@ export declare type StatusPageProps = {
2445
2456
  secondaryAction?: ReactNode;
2446
2457
  illustration?: ReactNode;
2447
2458
  icon?: ReactNode;
2448
- headingLevel?: 1 | 2;
2459
+ headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;
2449
2460
  };
2450
2461
 
2451
2462
  export declare function Switch({ options, ariaLabel, name, defaultValue, value, onChange, size, variant, fullWidth, iconOnly, }: {