@q1travel/design-system 0.31.1 → 0.31.3
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/contracts/design.dark.md +2 -2
- package/contracts/design.md +5 -3
- package/contracts/implementation-map.md +14 -1
- package/contracts/interface-guidelines.md +12 -2
- package/contracts/table-migration.md +23 -2
- package/dist-pkg/design-system.d.ts +37 -9
- package/dist-pkg/design-system.js +6008 -5779
- package/dist-pkg/style.css +204 -31
- package/package.json +1 -1
package/contracts/design.dark.md
CHANGED
|
@@ -540,8 +540,8 @@ CheckCircleFill accepts `tone?: 'default' | 'success'` (default `default`); succ
|
|
|
540
540
|
|
|
541
541
|
**Status and feedback.** Banner, ProjectBanner, Note, ErrorCard, RegionErrorState, ErrorMessage, EmptyState, Badge, Pill, CheckCircleFill, StatusDot, ToastProvider, useToast, Feedback, PageFeedback, Spinner, LoadingDots, Skeleton, StatusPage, SkeletonIllustration, EmptyListIllustration.
|
|
542
542
|
|
|
543
|
-
- 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.
|
|
544
|
-
- 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 a small illustration or icon and regular
|
|
543
|
+
- Banner accepts a string `title` and paragraph-inline `children` (text and inline Link, no block elements). `action: BannerAction` is either `{ label, href }` or `{ label, onClick, loading?, disabled? }`, mutually exclusive. The exported `BannerAction` derives button events and states from ButtonProps. Buttons use `type="button"`, size sm, rounded, primary for announcements and secondary for tone strips, with layout class `banner__button-action`. Loading retains focus with aria-disabled and blocks activation; disabled takes priority and leaves the Tab order. Loading adds no aria-busy; Banner adds no role or live region. Progress ignores either action. Existing links and calls omitting new capabilities retain their complete markup; no existing consumer migration is required. Remove button calls and BannerAction imports before reverting this addition. 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.
|
|
544
|
+
- 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 a small illustration or icon and regular primary-text title row inside a section whose heading and actions belong to the host, without description, actions, or headingLevel. Inline accepts `illustration?: ReactNode`, using `--q1-space-10` (40) for its width and preserving the artwork aspect ratio; illustration takes priority over icon with a development warning when both are supplied. Without illustration, icon-only and title-only calls use the same zero horizontal padding and primary title color. Center limits the decorative illustration slot to `--q1-space-16` (64), with no extra bottom margin: the existing `--q1-space-2` container gap gives 8 between illustration and title. Standalone artwork remains 96 wide; inline built-in scenes use simplified geometry with at most two narrative details, clear strokes, left alignment and vertical centering with the title. Standard inline usage pairs the 40-wide illustration with a visible title on its right in the same row (for example, 「还没有登录记录」). Use titleHidden only in the few contexts where the host already supplies a visible title. All inline variants use zero horizontal padding; illustration, icon and title-only content align with the host section body content edge. Hosts without padding supply their own inset. Inline titles use text-primary at the unchanged copy-14 size. Center accepts a decorative `illustration?: ReactNode` in place of icon; when neither illustration nor icon is supplied, it renders `EmptyListIllustration variant="neutral"` inside the decorative `empty-state__illustration` slot. Explicit icons retain their slot with a transparent background in both themes. Both layouts accept `titleHidden?: boolean`: true adds `empty-state--title-hidden` to the existing root and `q1-sr-only` to the required title, preserving its p or h2–h6 tag, text and accessibility semantics. Center keeps illustration/icon, optional description and actions; inline keeps its small illustration or icon. The hidden title takes no layout space; remaining siblings keep the existing gap and margins, and an illustration/icon alone has no trailing margin. Omitted or false preserves the existing DOM, classes and styles exactly. Built-in `EmptyListIllustration` accepts `scene?: 'list' | 'search' | 'complete' | 'chart' | 'inventory' | 'orders' | 'product' | 'permission' | 'purchase' | 'supplier' | 'team' | 'notification' | 'store' | 'task' | 'session' | 'activity' | 'payment' | 'security' | 'integration'` and the compatible `variant?: 'complete' | 'neutral'`. Explicit scene takes priority; without scene, neutral maps to list and all other calls default to complete. Accepted #830 intentionally changes both standalone default complete and EmptyState default list artwork and internal SVG structure; the outer decorative span, class and 96×104 viewBox remain. Complete draws its own decorative check without depending on CheckCircleFill. The chart, inventory, orders, list, activity, task, product, purchase, supplier, store, team, search, complete, permission, notification, session, integration, payment and security scenes use white or background-100 surface bodies, gray-700 fine outlines, and low-saturation local color fills. Every internal detail contrasts at least 3:1 with each fill it crosses, without reduced opacity. Each illustration uses at most one brand-colored element, at a narrative position. Same-shape, unblurred offset shadows provide depth; rectangle corner radii use authored SVG geometry. Geometry is identical across themes. Both variants have no 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.
|
|
545
545
|
- 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.
|
|
546
546
|
- 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.
|
|
547
547
|
- Toast is for non-blocking confirmation of something that already happened. It is not where an error the reader must act on belongs.
|
package/contracts/design.md
CHANGED
|
@@ -377,7 +377,9 @@ components:
|
|
|
377
377
|
backgroundColor: "{semantic-colors.surface-panel}"
|
|
378
378
|
hoverBackgroundColor: "{semantic-colors.surface-hover}"
|
|
379
379
|
textColor: "{semantic-colors.text-primary}"
|
|
380
|
-
borderColor: "{semantic-colors.border}"
|
|
380
|
+
borderColor: "{semantic-colors.border-strong}"
|
|
381
|
+
hoverBorderColor: "{colors.gray-600}"
|
|
382
|
+
pressBorderColor: "{colors.gray-600}"
|
|
381
383
|
typography: "{typography.label-14}"
|
|
382
384
|
rounded: "{rounded.sm}"
|
|
383
385
|
height: 40px
|
|
@@ -540,8 +542,8 @@ CheckCircleFill accepts `tone?: 'default' | 'success'` (default `default`); succ
|
|
|
540
542
|
|
|
541
543
|
**Status and feedback.** Banner, ProjectBanner, Note, ErrorCard, RegionErrorState, ErrorMessage, EmptyState, Badge, Pill, CheckCircleFill, StatusDot, ToastProvider, useToast, Feedback, PageFeedback, Spinner, LoadingDots, Skeleton, StatusPage, SkeletonIllustration, EmptyListIllustration.
|
|
542
544
|
|
|
543
|
-
- 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.
|
|
544
|
-
- 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 a small illustration or icon and regular
|
|
545
|
+
- Banner accepts a string `title` and paragraph-inline `children` (text and inline Link, no block elements). `action: BannerAction` is either `{ label, href }` or `{ label, onClick, loading?, disabled? }`, mutually exclusive. The exported `BannerAction` derives button events and states from ButtonProps. Buttons use `type="button"`, size sm, rounded, primary for announcements and secondary for tone strips, with layout class `banner__button-action`. Loading retains focus with aria-disabled and blocks activation; disabled takes priority and leaves the Tab order. Loading adds no aria-busy; Banner adds no role or live region. Progress ignores either action. Existing links and calls omitting new capabilities retain their complete markup; no existing consumer migration is required. Remove button calls and BannerAction imports before reverting this addition. 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.
|
|
546
|
+
- 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 a small illustration or icon and regular primary-text title row inside a section whose heading and actions belong to the host, without description, actions, or headingLevel. Inline accepts `illustration?: ReactNode`, using `--q1-space-10` (40) for its width and preserving the artwork aspect ratio; illustration takes priority over icon with a development warning when both are supplied. Without illustration, icon-only and title-only calls use the same zero horizontal padding and primary title color. Center limits the decorative illustration slot to `--q1-space-16` (64), with no extra bottom margin: the existing `--q1-space-2` container gap gives 8 between illustration and title. Standalone artwork remains 96 wide; inline built-in scenes use simplified geometry with at most two narrative details, clear strokes, left alignment and vertical centering with the title. Standard inline usage pairs the 40-wide illustration with a visible title on its right in the same row (for example, 「还没有登录记录」). Use titleHidden only in the few contexts where the host already supplies a visible title. All inline variants use zero horizontal padding; illustration, icon and title-only content align with the host section body content edge. Hosts without padding supply their own inset. Inline titles use text-primary at the unchanged copy-14 size. Center accepts a decorative `illustration?: ReactNode` in place of icon; when neither illustration nor icon is supplied, it renders `EmptyListIllustration variant="neutral"` inside the decorative `empty-state__illustration` slot. Explicit icons retain their slot with a transparent background in both themes. Both layouts accept `titleHidden?: boolean`: true adds `empty-state--title-hidden` to the existing root and `q1-sr-only` to the required title, preserving its p or h2–h6 tag, text and accessibility semantics. Center keeps illustration/icon, optional description and actions; inline keeps its small illustration or icon. The hidden title takes no layout space; remaining siblings keep the existing gap and margins, and an illustration/icon alone has no trailing margin. Omitted or false preserves the existing DOM, classes and styles exactly. Built-in `EmptyListIllustration` accepts `scene?: 'list' | 'search' | 'complete' | 'chart' | 'inventory' | 'orders' | 'product' | 'permission' | 'purchase' | 'supplier' | 'team' | 'notification' | 'store' | 'task' | 'session' | 'activity' | 'payment' | 'security' | 'integration'` and the compatible `variant?: 'complete' | 'neutral'`. Explicit scene takes priority; without scene, neutral maps to list and all other calls default to complete. Accepted #830 intentionally changes both standalone default complete and EmptyState default list artwork and internal SVG structure; the outer decorative span, class and 96×104 viewBox remain. Complete draws its own decorative check without depending on CheckCircleFill. The chart, inventory, orders, list, activity, task, product, purchase, supplier, store, team, search, complete, permission, notification, session, integration, payment and security scenes use white or background-100 surface bodies, gray-700 fine outlines, and low-saturation local color fills. Every internal detail contrasts at least 3:1 with each fill it crosses, without reduced opacity. Each illustration uses at most one brand-colored element, at a narrative position. Same-shape, unblurred offset shadows provide depth; rectangle corner radii use authored SVG geometry. Geometry is identical across themes. Both variants have no 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.
|
|
545
547
|
- 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.
|
|
546
548
|
- 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.
|
|
547
549
|
- Toast is for non-blocking confirmation of something that already happened. It is not where an error the reader must act on belongs.
|
|
@@ -102,6 +102,11 @@ Click, ArrowLeft/ArrowRight, Home, and End notify activation; controlled selecti
|
|
|
102
102
|
changes only when the parent updates `value`. Keyboard navigation follows the
|
|
103
103
|
focused enabled tab while the parent update is pending, and a later value update
|
|
104
104
|
does not pull focus from the activated button. Consumers own URL synchronization.
|
|
105
|
+
Line disabled labels and their icons use `text-muted`, with at least 3:1 contrast
|
|
106
|
+
against the background in both themes and less contrast than enabled labels. Hover
|
|
107
|
+
and press do not strengthen disabled items. A selected-disabled style combination
|
|
108
|
+
keeps a muted underline; unselected disabled items have no underline. Runtime
|
|
109
|
+
selection still falls back to an enabled item as described above.
|
|
105
110
|
|
|
106
111
|
## Record activity (accepted 2026-10-06)
|
|
107
112
|
|
|
@@ -157,4 +162,12 @@ Accepted 2026-11-02 (#761): ThemeSwitcher keeps a single outer group border. Opt
|
|
|
157
162
|
|
|
158
163
|
## EmptyState title visibility
|
|
159
164
|
|
|
160
|
-
Accepted #568: `EmptyState` supports `titleHidden?: boolean` in both center and inline layouts. Both layouts accept `titleHidden?: boolean`: true adds `empty-state--title-hidden` to the existing root and `q1-sr-only` to the required title, preserving its p or h2–h6 tag, text and accessibility semantics. Center keeps illustration/icon, optional description and actions; inline keeps its small illustration or icon. Inline accepts `illustration?: ReactNode` with width `--q1-space-
|
|
165
|
+
Accepted #568: `EmptyState` supports `titleHidden?: boolean` in both center and inline layouts. Both layouts accept `titleHidden?: boolean`: true adds `empty-state--title-hidden` to the existing root and `q1-sr-only` to the required title, preserving its p or h2–h6 tag, text and accessibility semantics. Center keeps illustration/icon, optional description and actions; inline keeps its small illustration or icon. Inline accepts `illustration?: ReactNode` with width `--q1-space-10` (40), with simplified geometry, left alignment and vertical centering with the title, preserving the artwork aspect ratio; illustration takes priority over icon and supplying both emits a development warning. Inline does not accept description, actions or headingLevel. Inline icon-only and title-only calls share zero horizontal padding and primary title color. The hidden title takes no layout space; remaining siblings keep the existing gap and margins, and an illustration/icon alone has no trailing margin. Omitted or false preserves the existing DOM, classes and styles exactly.
|
|
166
|
+
|
|
167
|
+
Standard inline usage pairs the 40-wide illustration with a visible title on its right in the same row (for example, 「还没有登录记录」). Use titleHidden only in the few contexts where the host already supplies a visible title. All inline variants use zero horizontal padding; illustration, icon and title-only content align with the host section body content edge. Hosts without padding supply their own inset. Inline titles use text-primary at the unchanged copy-14 size.
|
|
168
|
+
|
|
169
|
+
### EmptyState panel
|
|
170
|
+
|
|
171
|
+
Accepted #860: `layout="panel"` is a full-width compact surface for empty tab or filter results. It requires a visible `title: string`; optional `description: string`, `actions: ReactNode` and `headingLevel: 2 | 3 | 4 | 5 | 6` (default `p`) retain text and native action semantics. `icon`, `illustration` and `titleHidden` are forbidden only in this branch. Center and inline types and byte-for-byte markup remain unchanged.
|
|
172
|
+
|
|
173
|
+
DOM: `div.empty-state.empty-state--panel > div.empty-state__body` contains the title and optional `p.empty-state__desc`, followed by optional sibling `div.empty-state__actions`. Only `empty-state--panel` and `empty-state__body` are new classes. The static root has no live-region semantics. Existing subtle background, radius-3, space-4/6, copy-14, semibold primary title and regular secondary description tokens provide hierarchy in both themes, with text contrast at least 4.5:1. A one-pixel border uses the existing border-subtle token and space-1 divided by four; the edge remains distinguishable from the page in both themes without darkening the fill. Actions align vertically at the right on wide screens and below the text at the left on narrow screens; no horizontal overflow.
|
|
@@ -243,8 +243,18 @@ Component pages follow one skeleton so a reader who has used one page can find t
|
|
|
243
243
|
|
|
244
244
|
### Empty illustrations
|
|
245
245
|
|
|
246
|
-
Accepted #830: decorative empty illustrations share a 96×104 viewBox
|
|
246
|
+
Accepted #830: decorative empty illustrations share a 96×104 viewBox and ICON_STROKE_WIDTH round strokes. All scene geometry, including half the computed stroke width around each element, stays inside the viewBox. The family specimen uses one site-themed card per scene, four columns on wide screens and two on narrow screens. At most one element uses primary-700 in light and primary-900 in dark, with identical geometry. Scene selects list, search, complete, chart, inventory, orders, product, permission, purchase, supplier, team, notification, store, task, session, activity, payment, security or integration. Scene takes precedence over the compatible variant; absent scene, neutral maps to list and all other calls to complete. Keep the decorative outer span, aria-hidden=true, non-focusable SVG and text-owned state meaning. Complete owns its check; CheckCircleFill semantics are unchanged.
|
|
247
|
+
|
|
248
|
+
Accepted #839: chart, inventory, orders, list, activity, task, product, purchase, supplier, store, team, search, complete, permission, notification, session, integration, payment and security use background-100 surfaces, gray-700 outlines, local teal/amber/green/blue-300 fills and matching hue-900 detail strokes in light; dark uses gray-700 detail strokes, with inventory blue-300 to avoid a brown cast; session and security use blue-300, payment uses green-300. Adjacent documentation gallery cells use distinct hues; reorder the gallery without changing individual scene assets. Every internal detail contrasts at least 3:1 with each fill it crosses, without reduced opacity. Local color covers 20–35% of the main geometric bounding rectangle; no opaque gray body or purple backplate. At most one primary element appears, at a functional narrative position. Same-shape, unblurred shadows offset by two viewBox units use gray-alpha-100 in light and gray-alpha-200 in dark. Internal rectangle radii remain authored SVG geometry. No gradients, blur or particles.
|
|
247
249
|
|
|
248
250
|
### EmptyState illustration-only presentation
|
|
249
251
|
|
|
250
|
-
Accepted #568: `titleHidden` visually hides the required title using `q1-sr-only`, while retaining its original paragraph or heading semantics and accessible text. Illustration/icon remains decorative; description and actions are independent optional center content. Inline accepts a small decorative `illustration?: ReactNode` at `--q1-space-
|
|
252
|
+
Accepted #568: `titleHidden` visually hides the required title using `q1-sr-only`, while retaining its original paragraph or heading semantics and accessible text. Illustration/icon remains decorative; description and actions are independent optional center content. Inline accepts a small decorative `illustration?: ReactNode` at `--q1-space-10` (40) width, preserving its aspect ratio; illustration takes priority over icon, with a development warning when both are supplied. Inline description, actions and headingLevel remain unsupported. Omitted or false leaves the default presentation unchanged; inline calls without illustration share the zero horizontal padding and primary title color.
|
|
253
|
+
|
|
254
|
+
Inline built-in illustrations use space-10 (40), simplified geometry with at most two narrative details, clear strokes and no public size prop. The illustration aligns left and centers vertically with its title. Center geometry, space-16 and spacing remain unchanged. Standard inline usage pairs the 40-wide illustration with a visible title on its right in the same row (for example, 「还没有登录记录」). Use titleHidden only in the few contexts where the host already supplies a visible title. All inline variants use zero horizontal padding; illustration, icon and title-only content align with the host section body content edge. Hosts without padding supply their own inset. Inline titles use text-primary at the unchanged copy-14 size.
|
|
255
|
+
|
|
256
|
+
### EmptyState panel
|
|
257
|
+
|
|
258
|
+
Accepted #860: `layout="panel"` is a full-width compact surface for empty tab or filter results. It requires a visible `title: string`; optional `description: string`, `actions: ReactNode` and `headingLevel: 2 | 3 | 4 | 5 | 6` (default `p`) retain text and native action semantics. `icon`, `illustration` and `titleHidden` are forbidden only in this branch. Center and inline types and byte-for-byte markup remain unchanged.
|
|
259
|
+
|
|
260
|
+
DOM: `div.empty-state.empty-state--panel > div.empty-state__body` contains the title and optional `p.empty-state__desc`, followed by optional sibling `div.empty-state__actions`. Only `empty-state--panel` and `empty-state__body` are new classes. The static root has no live-region semantics. Existing subtle background, radius-3, space-4/6, copy-14, semibold primary title and regular secondary description tokens provide hierarchy in both themes, with text contrast at least 4.5:1. A one-pixel border uses the existing border-subtle token and space-1 divided by four; the edge remains distinguishable from the page in both themes without darkening the fill. Actions align vertically at the right on wide screens and below the text at the left on narrow screens; no horizontal overflow.
|
|
@@ -39,6 +39,11 @@ library, router, or product-side data model.
|
|
|
39
39
|
navigation in this contract.
|
|
40
40
|
- `renderRow` and composed cells may extend row presentation, but they must
|
|
41
41
|
preserve the table's heading, cell, focus, and selection semantics.
|
|
42
|
+
`TableRowRenderContext<T>.selectionCell: ReactNode | null` exposes the exact
|
|
43
|
+
complete selection cell used by default rows, including the library Checkbox,
|
|
44
|
+
accessible name, controlled state, disabled state, and change handler. It is
|
|
45
|
+
`null` without `selection`. Reuse it when composing content cells; `cells`
|
|
46
|
+
remains unchanged and still includes the selection cell, so do not render both.
|
|
42
47
|
- Loading, empty, and error states are explicit consumer-owned surfaces. Table
|
|
43
48
|
must not invent fetch status, error copy, recovery actions, or business
|
|
44
49
|
permissions. An empty result may be rendered as an adjacent Empty State
|
|
@@ -60,9 +65,25 @@ requires each capability.
|
|
|
60
65
|
- Selection is controlled by the consumer. Table receives the selected row keys
|
|
61
66
|
and reports the next selected-key collection through its change callback; it
|
|
62
67
|
does not keep an independent authoritative selection store.
|
|
68
|
+
- `onSelectionChange(selectedKeys, details)` keeps the selected-key array contents
|
|
69
|
+
and ordering unchanged. Existing single-argument callbacks remain assignable.
|
|
70
|
+
The exported `TableSelectionChangeDetails` is `{ type: 'row' | 'page';
|
|
71
|
+
rowKey?: TableRowKey; checked: boolean; shiftKey: boolean }`. Row changes include
|
|
72
|
+
`rowKey`; current-page changes omit the property entirely. `checked` is the
|
|
73
|
+
control's target state. `shiftKey` reads the triggering native event modifier,
|
|
74
|
+
defaulting to `false` when absent, including native Shift-click and Shift-Space.
|
|
75
|
+
These details do not implement range selection or change default selection behavior.
|
|
63
76
|
- A row is selectable only when the consumer exposes it as selectable. Selection
|
|
64
|
-
controls use
|
|
65
|
-
`:focus-visible` state.
|
|
77
|
+
controls use the library `Checkbox` with accessible names and a visible
|
|
78
|
+
`:focus-visible` state. Header and default row selection share the bare
|
|
79
|
+
`span.control-option.control-option--bare` shell, native checkbox input, and
|
|
80
|
+
`span.control-option__visual`. The former `table__checkbox-control` label is
|
|
81
|
+
removed; consumers targeting it must use the selection cell and Checkbox
|
|
82
|
+
structure. Both controls have equal visual dimensions and horizontal centers,
|
|
83
|
+
and their visual centers align vertically with the first text column,
|
|
84
|
+
retain the selection-column width, and use canonical theme tokens. Coarse
|
|
85
|
+
pointers retain the minimum touch target. Header `indeterminate` and
|
|
86
|
+
`aria-checked="mixed"` expose partial selection.
|
|
66
87
|
- The header select-all control operates on the currently rendered/selectable
|
|
67
88
|
page only.
|
|
68
89
|
- Selecting all adds the selectable keys visible on the current page to the
|
|
@@ -151,20 +151,31 @@ export declare type BadgeTone = 'neutral' | 'info' | 'success' | 'warning' | 'da
|
|
|
151
151
|
|
|
152
152
|
export declare function Banner({ title, children, tone, icon, action, onDismiss, progress, className, ...rest }: BannerProps): JSX.Element;
|
|
153
153
|
|
|
154
|
+
export declare type BannerAction = {
|
|
155
|
+
label: string;
|
|
156
|
+
href: string;
|
|
157
|
+
onClick?: never;
|
|
158
|
+
loading?: never;
|
|
159
|
+
disabled?: never;
|
|
160
|
+
} | {
|
|
161
|
+
label: string;
|
|
162
|
+
href?: never;
|
|
163
|
+
onClick: NonNullable<ButtonProps['onClick']>;
|
|
164
|
+
loading?: ButtonProps['loading'];
|
|
165
|
+
disabled?: ButtonProps['disabled'];
|
|
166
|
+
};
|
|
167
|
+
|
|
154
168
|
export declare type BannerProps = {
|
|
155
169
|
/** 粗体导语,一眼点题。 */
|
|
156
170
|
title: string;
|
|
157
|
-
/**
|
|
171
|
+
/** 段落内文本或行内内容,可放 Link;非空白导语用「 — 」衔接,空白导语仅显示正文。 */
|
|
158
172
|
children?: ReactNode;
|
|
159
173
|
/** 未设 = 页顶公告形态;设值 = 页内卡条形态(neutral 为中性卡条)。 */
|
|
160
174
|
tone?: BannerTone;
|
|
161
175
|
/** 卡条形态的前缀图标;纯装饰(组件自动 aria-hidden)。公告形态与进度形态不渲染图标。 */
|
|
162
176
|
icon?: ReactNode;
|
|
163
|
-
/**
|
|
164
|
-
action?:
|
|
165
|
-
label: string;
|
|
166
|
-
href: string;
|
|
167
|
-
};
|
|
177
|
+
/** 主操作链接或按钮;按钮复用 Button 的 loading / disabled。进度形态忽略 action。 */
|
|
178
|
+
action?: BannerAction;
|
|
168
179
|
/** 关闭回调;设置后渲染关闭按钮。公告形态无关闭;进度形态渲染在进度头右侧。 */
|
|
169
180
|
onDismiss?: () => void;
|
|
170
181
|
/** 进度形态(自有扩展):value 为 0–100 的百分比(非法值归 0),label 供读屏。进度恒为卡条形态。 */
|
|
@@ -1107,9 +1118,9 @@ export declare type EmptyListIllustrationProps = {
|
|
|
1107
1118
|
variant?: 'complete' | 'neutral';
|
|
1108
1119
|
};
|
|
1109
1120
|
|
|
1110
|
-
export declare type EmptyListIllustrationScene = 'list' | 'search' | 'complete' | 'chart' | 'inventory' | 'orders' | 'product' | 'permission';
|
|
1121
|
+
export declare type EmptyListIllustrationScene = 'list' | 'search' | 'complete' | 'chart' | 'inventory' | 'orders' | 'product' | 'permission' | 'purchase' | 'supplier' | 'team' | 'notification' | 'store' | 'task' | 'session' | 'activity' | 'payment' | 'security' | 'integration';
|
|
1111
1122
|
|
|
1112
|
-
export declare function EmptyState({ icon, illustration, title, titleHidden, description, actions, headingLevel, layout, }: {
|
|
1123
|
+
export declare function EmptyState({ icon, illustration, title, titleHidden, description, actions, headingLevel, layout, }: ({
|
|
1113
1124
|
icon?: ReactNode;
|
|
1114
1125
|
title: string;
|
|
1115
1126
|
/** 仅视觉隐藏标题,保留原标签与可访问文本。 */
|
|
@@ -1128,6 +1139,15 @@ export declare function EmptyState({ icon, illustration, title, titleHidden, des
|
|
|
1128
1139
|
description?: never;
|
|
1129
1140
|
actions?: never;
|
|
1130
1141
|
headingLevel?: never;
|
|
1142
|
+
}) | {
|
|
1143
|
+
layout: 'panel';
|
|
1144
|
+
title: string;
|
|
1145
|
+
description?: string;
|
|
1146
|
+
actions?: ReactNode;
|
|
1147
|
+
headingLevel?: 2 | 3 | 4 | 5 | 6;
|
|
1148
|
+
icon?: never;
|
|
1149
|
+
illustration?: never;
|
|
1150
|
+
titleHidden?: never;
|
|
1131
1151
|
})): JSX.Element;
|
|
1132
1152
|
|
|
1133
1153
|
/** Public host for consumer-owned sibling portals. Package overlays share this Foundation root. */
|
|
@@ -2691,16 +2711,24 @@ export declare type TableRowRenderContext<T> = {
|
|
|
2691
2711
|
rowKey: TableRowKey;
|
|
2692
2712
|
rowProps: TableHTMLAttributes<HTMLTableRowElement>;
|
|
2693
2713
|
cells: ReactNode;
|
|
2714
|
+
selectionCell: ReactNode | null;
|
|
2694
2715
|
};
|
|
2695
2716
|
|
|
2696
2717
|
export declare type TableSelection<T> = {
|
|
2697
2718
|
selectedKeys: readonly TableRowKey[];
|
|
2698
|
-
onSelectionChange: (selectedKeys: TableRowKey[]) => void;
|
|
2719
|
+
onSelectionChange: (selectedKeys: TableRowKey[], details: TableSelectionChangeDetails) => void;
|
|
2699
2720
|
getRowLabel: (row: T, rowIndex: number) => string;
|
|
2700
2721
|
getRowDisabled?: (row: T, rowIndex: number) => boolean;
|
|
2701
2722
|
selectAllLabel?: string;
|
|
2702
2723
|
};
|
|
2703
2724
|
|
|
2725
|
+
export declare type TableSelectionChangeDetails = {
|
|
2726
|
+
type: 'row' | 'page';
|
|
2727
|
+
rowKey?: TableRowKey;
|
|
2728
|
+
checked: boolean;
|
|
2729
|
+
shiftKey: boolean;
|
|
2730
|
+
};
|
|
2731
|
+
|
|
2704
2732
|
export declare type TableSortDirection = 'asc' | 'desc';
|
|
2705
2733
|
|
|
2706
2734
|
export declare function Tabs({ tabs, ariaLabel, variant, value, defaultValue, onValueChange, }: {
|