@eifi1/ui-kit 0.31.1 → 0.32.1
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 +51 -28
- package/dist/account/delete-account-setting.d.ts +8 -3
- package/dist/admin/admin-action-confirm.d.ts +8 -3
- package/dist/admin/admin-action-log.d.ts +1 -1
- package/dist/admin/admin-action-log.js +4 -2
- package/dist/admin/admin-action-log.js.map +1 -1
- package/dist/admin/invitations-panel.d.ts +8 -3
- package/dist/admin/invitations-panel.js +29 -26
- package/dist/admin/invitations-panel.js.map +1 -1
- package/dist/admin/reviewer-scope-editor.d.ts +8 -3
- package/dist/admin/role-select.d.ts +10 -5
- package/dist/admin/transfer-ownership-dialog.d.ts +8 -3
- package/dist/admin/user-roster.d.ts +10 -5
- package/dist/admin/user-roster.js +8 -47
- package/dist/admin/user-roster.js.map +1 -1
- package/dist/auth/auth-errors.d.ts +43 -8
- package/dist/auth/auth-errors.js +24 -1
- package/dist/auth/auth-errors.js.map +1 -1
- package/dist/auth/register-form.d.ts +8 -3
- package/dist/billing/billing-banner.d.ts +184 -0
- package/dist/billing/billing-banner.js +98 -0
- package/dist/billing/billing-banner.js.map +1 -0
- package/dist/billing/billing-labels.d.ts +100 -0
- package/dist/billing/billing-labels.js +76 -0
- package/dist/billing/billing-labels.js.map +1 -0
- package/dist/billing/billing-lock.d.ts +158 -0
- package/dist/billing/billing-lock.js +17 -0
- package/dist/billing/billing-lock.js.map +1 -0
- package/dist/billing/billing-standing.d.ts +149 -0
- package/dist/billing/billing-standing.js +28 -0
- package/dist/billing/billing-standing.js.map +1 -0
- package/dist/billing/plan-card.d.ts +248 -0
- package/dist/billing/plan-card.js +248 -0
- package/dist/billing/plan-card.js.map +1 -0
- package/dist/billing/plan-limit-notice.d.ts +156 -0
- package/dist/billing/plan-limit-notice.js +76 -0
- package/dist/billing/plan-limit-notice.js.map +1 -0
- package/dist/billing/plan-limit.d.ts +34 -0
- package/dist/billing/plan-limit.js +20 -0
- package/dist/billing/plan-limit.js.map +1 -0
- package/dist/billing/plan-price.d.ts +61 -0
- package/dist/billing/plan-price.js +45 -0
- package/dist/billing/plan-price.js.map +1 -0
- package/dist/billing/subscription-actions.d.ts +133 -0
- package/dist/billing/subscription-actions.js +28 -0
- package/dist/billing/subscription-actions.js.map +1 -0
- package/dist/billing/subscription-status-chip.d.ts +149 -0
- package/dist/billing/subscription-status-chip.js +48 -0
- package/dist/billing/subscription-status-chip.js.map +1 -0
- package/dist/chart.d.ts +9 -3
- package/dist/chart.js.map +1 -1
- package/dist/components/account-chips.d.ts +16 -4
- package/dist/components/account-chips.js +21 -3
- package/dist/components/account-chips.js.map +1 -1
- package/dist/components/alert-banner.d.ts +6 -1
- package/dist/components/alert-banner.js +5 -4
- package/dist/components/alert-banner.js.map +1 -1
- package/dist/components/amount-input.d.ts +8 -3
- package/dist/components/amount-input.js +5 -5
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/appearance-labels.d.ts +38 -0
- package/dist/components/appearance-labels.js +19 -0
- package/dist/components/appearance-labels.js.map +1 -0
- package/dist/components/autocomplete.js +2 -2
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/breadcrumbs.js +3 -2
- package/dist/components/breadcrumbs.js.map +1 -1
- package/dist/components/bulk-action-bar.d.ts +2 -2
- package/dist/components/bulk-action-bar.js +7 -12
- package/dist/components/bulk-action-bar.js.map +1 -1
- package/dist/components/button-group.d.ts +8 -3
- package/dist/components/button-group.js +7 -1
- package/dist/components/button-group.js.map +1 -1
- package/dist/components/calculator.d.ts +8 -3
- package/dist/components/calculator.js +4 -3
- package/dist/components/calculator.js.map +1 -1
- package/dist/components/calendar-heatmap.js +5 -5
- package/dist/components/calendar-heatmap.js.map +1 -1
- package/dist/components/chart-height.d.ts +23 -0
- package/dist/components/chart-height.js +15 -0
- package/dist/components/chart-height.js.map +1 -0
- package/dist/components/chart-zoom.js +6 -1
- package/dist/components/chart-zoom.js.map +1 -1
- package/dist/components/checkbox-group.js +2 -2
- package/dist/components/checkbox-group.js.map +1 -1
- package/dist/components/checkbox.d.ts +10 -0
- package/dist/components/checkbox.js +25 -10
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/chip.d.ts +19 -3
- package/dist/components/chip.js +54 -23
- package/dist/components/chip.js.map +1 -1
- package/dist/components/choice-card.d.ts +1 -1
- package/dist/components/choice-card.js +9 -8
- package/dist/components/choice-card.js.map +1 -1
- package/dist/components/column-mapper.js +1 -1
- package/dist/components/column-mapper.js.map +1 -1
- package/dist/components/combobox-core.js +8 -7
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.js +8 -8
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/confirm-dialog.d.ts +8 -3
- package/dist/components/copy-button.d.ts +10 -5
- package/dist/components/country-select.js +1 -1
- package/dist/components/country-select.js.map +1 -1
- package/dist/components/currency-select.js +3 -3
- package/dist/components/currency-select.js.map +1 -1
- package/dist/components/danger-confirm.d.ts +8 -3
- package/dist/components/data-table-cells.d.ts +1 -1
- package/dist/components/data-table-filter-popover.d.ts +1 -1
- package/dist/components/data-table-filter-popover.js +4 -1
- package/dist/components/data-table-filter-popover.js.map +1 -1
- package/dist/components/data-table-filters.d.ts +1 -1
- package/dist/components/data-table-labels.d.ts +1 -1
- package/dist/components/data-table-pagination.d.ts +3 -2
- package/dist/components/data-table-pagination.js +15 -6
- package/dist/components/data-table-pagination.js.map +1 -1
- package/dist/components/data-table.d.ts +1 -1
- package/dist/components/data-table.js +123 -52
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.d.ts +1 -1
- package/dist/components/date-picker.js +18 -6
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/description-list.js +2 -2
- package/dist/components/description-list.js.map +1 -1
- package/dist/components/dialog-frame.js +2 -1
- package/dist/components/dialog-frame.js.map +1 -1
- package/dist/components/disclosure.js +3 -2
- package/dist/components/disclosure.js.map +1 -1
- package/dist/components/dropdown.d.ts +1 -1
- package/dist/components/dropdown.js +7 -1
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/facing-pair.d.ts +19 -6
- package/dist/components/facing-pair.js +3 -2
- package/dist/components/facing-pair.js.map +1 -1
- package/dist/components/field-parts.d.ts +102 -6
- package/dist/components/field-parts.js +81 -6
- package/dist/components/field-parts.js.map +1 -1
- package/dist/components/field-sync.d.ts +4 -1
- package/dist/components/field-sync.js +12 -2
- package/dist/components/field-sync.js.map +1 -1
- package/dist/components/field.js +2 -2
- package/dist/components/field.js.map +1 -1
- package/dist/components/file-button.d.ts +8 -3
- package/dist/components/file-dropzone.d.ts +8 -3
- package/dist/components/floating-panel.js +7 -4
- package/dist/components/floating-panel.js.map +1 -1
- package/dist/components/focus-ring.d.ts +12 -0
- package/dist/components/focus-ring.js +8 -0
- package/dist/components/focus-ring.js.map +1 -0
- package/dist/components/form-actions.d.ts +8 -3
- package/dist/components/form-actions.js +33 -19
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/full-bleed-dialog.d.ts +11 -1
- package/dist/components/full-bleed-dialog.js +3 -1
- package/dist/components/full-bleed-dialog.js.map +1 -1
- package/dist/components/iban-input.d.ts +8 -3
- package/dist/components/image-grid.js +1 -1
- package/dist/components/image-grid.js.map +1 -1
- package/dist/components/inline-edit-field.js +10 -4
- package/dist/components/inline-edit-field.js.map +1 -1
- package/dist/components/language-select.d.ts +8 -3
- package/dist/components/legal-page.d.ts +26 -5
- package/dist/components/legal-page.js +3 -1
- package/dist/components/legal-page.js.map +1 -1
- package/dist/components/legal.d.ts +8 -3
- package/dist/components/legal.js +2 -1
- package/dist/components/legal.js.map +1 -1
- package/dist/components/lightbox.js +24 -2
- package/dist/components/lightbox.js.map +1 -1
- package/dist/components/line-items.js +2 -1
- package/dist/components/line-items.js.map +1 -1
- package/dist/components/list.d.ts +5 -0
- package/dist/components/list.js +13 -9
- package/dist/components/list.js.map +1 -1
- package/dist/components/measured-grid.d.ts +3 -1
- package/dist/components/measured-grid.js +38 -20
- package/dist/components/measured-grid.js.map +1 -1
- package/dist/components/menu-item.js +2 -1
- package/dist/components/menu-item.js.map +1 -1
- package/dist/components/mini-calendar.js +8 -4
- package/dist/components/mini-calendar.js.map +1 -1
- package/dist/components/money-field.d.ts +8 -3
- package/dist/components/month-picker.js +50 -39
- package/dist/components/month-picker.js.map +1 -1
- package/dist/components/nav-pills.js +1 -1
- package/dist/components/nav-pills.js.map +1 -1
- package/dist/components/number-field.d.ts +8 -3
- package/dist/components/number-input.d.ts +11 -4
- package/dist/components/number-input.js +8 -6
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/numpad-sheet.d.ts +8 -3
- package/dist/components/numpad-sheet.js +2 -1
- package/dist/components/numpad-sheet.js.map +1 -1
- package/dist/components/one-time-code-input.js +2 -2
- package/dist/components/one-time-code-input.js.map +1 -1
- package/dist/components/page-contents.js +2 -2
- package/dist/components/page-contents.js.map +1 -1
- package/dist/components/phone-input.d.ts +8 -3
- package/dist/components/phone-input.js +4 -4
- package/dist/components/phone-input.js.map +1 -1
- package/dist/components/pie-chart.d.ts +8 -2
- package/dist/components/pie-chart.js +11 -7
- package/dist/components/pie-chart.js.map +1 -1
- package/dist/components/popover.d.ts +9 -1
- package/dist/components/popover.js +8 -4
- package/dist/components/popover.js.map +1 -1
- package/dist/components/row-actions.d.ts +100 -0
- package/dist/components/row-actions.js +231 -0
- package/dist/components/row-actions.js.map +1 -0
- package/dist/components/scroll-area.js +1 -1
- package/dist/components/scroll-area.js.map +1 -1
- package/dist/components/search-field.js +3 -2
- package/dist/components/search-field.js.map +1 -1
- package/dist/components/series-chart-budget.d.ts +30 -7
- package/dist/components/series-chart-budget.js +12 -4
- package/dist/components/series-chart-budget.js.map +1 -1
- package/dist/components/series-chart-ticks.d.ts +7 -1
- package/dist/components/series-chart-ticks.js +6 -0
- package/dist/components/series-chart-ticks.js.map +1 -1
- package/dist/components/series-chart.d.ts +58 -28
- package/dist/components/series-chart.js +42 -32
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/settings-fields.d.ts +57 -8
- package/dist/components/settings-fields.js +39 -1
- package/dist/components/settings-fields.js.map +1 -1
- package/dist/components/share-card.d.ts +11 -6
- package/dist/components/share-card.js +8 -2
- package/dist/components/share-card.js.map +1 -1
- package/dist/components/sign-chip.d.ts +4 -0
- package/dist/components/sign-chip.js +17 -4
- package/dist/components/sign-chip.js.map +1 -1
- package/dist/components/signature-pad.d.ts +3 -1
- package/dist/components/signature-pad.js +8 -5
- package/dist/components/signature-pad.js.map +1 -1
- package/dist/components/slider.js +7 -6
- package/dist/components/slider.js.map +1 -1
- package/dist/components/sparkline.d.ts +5 -1
- package/dist/components/sparkline.js +4 -2
- package/dist/components/sparkline.js.map +1 -1
- package/dist/components/stat-tile.d.ts +17 -1
- package/dist/components/stat-tile.js +48 -20
- package/dist/components/stat-tile.js.map +1 -1
- package/dist/components/status-dot.d.ts +4 -0
- package/dist/components/status-dot.js +9 -2
- package/dist/components/status-dot.js.map +1 -1
- package/dist/components/swipeable-row.js +10 -2
- package/dist/components/swipeable-row.js.map +1 -1
- package/dist/components/switch.d.ts +21 -7
- package/dist/components/switch.js +24 -11
- package/dist/components/switch.js.map +1 -1
- package/dist/components/table.js +2 -2
- package/dist/components/table.js.map +1 -1
- package/dist/components/text-link.d.ts +8 -3
- package/dist/components/text-link.js +1 -1
- package/dist/components/text-link.js.map +1 -1
- package/dist/components/text.d.ts +7 -2
- package/dist/components/text.js +5 -5
- package/dist/components/text.js.map +1 -1
- package/dist/components/tile-radio.js +2 -1
- package/dist/components/tile-radio.js.map +1 -1
- package/dist/components/time-input.d.ts +8 -3
- package/dist/components/toast.d.ts +18 -2
- package/dist/components/toast.js +8 -5
- package/dist/components/toast.js.map +1 -1
- package/dist/components/toggle-group.d.ts +25 -3
- package/dist/components/toggle-group.js +40 -11
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/toggle-legend.d.ts +10 -1
- package/dist/components/toggle-legend.js +21 -7
- package/dist/components/toggle-legend.js.map +1 -1
- package/dist/components/translation-review-editor.js +1 -1
- package/dist/components/translation-review-editor.js.map +1 -1
- package/dist/components/translation-review-parts.d.ts +4 -0
- package/dist/components/translation-review.d.ts +4 -0
- package/dist/components/translation-review.js +3 -3
- package/dist/components/translation-review.js.map +1 -1
- package/dist/components/tree-view.js +3 -2
- package/dist/components/tree-view.js.map +1 -1
- package/dist/components/treemap.d.ts +5 -2
- package/dist/components/treemap.js +33 -16
- package/dist/components/treemap.js.map +1 -1
- package/dist/components/ui.d.ts +8 -3
- package/dist/components/ui.js +207 -119
- package/dist/components/ui.js.map +1 -1
- package/dist/components/use-table-state.d.ts +1 -1
- package/dist/components/user-avatar.d.ts +5 -1
- package/dist/components/user-avatar.js +1 -1
- package/dist/components/user-avatar.js.map +1 -1
- package/dist/components/wizard-stepper.js +20 -14
- package/dist/components/wizard-stepper.js.map +1 -1
- package/dist/{data-table-labels-DUELeXpa.d.ts → data-table-labels-kpAAVi6g.d.ts} +26 -2
- package/dist/data-table.d.ts +1 -1
- package/dist/{delete-account-setting-CpIhzxxZ.d.ts → delete-account-setting-FLyJf-kZ.d.ts} +642 -60
- package/dist/demo/demo-banner.js +1 -0
- package/dist/demo/demo-banner.js.map +1 -1
- package/dist/feedback/feedback-attachment.d.ts +8 -3
- package/dist/feedback/feedback-context.d.ts +8 -3
- package/dist/feedback/feedback-crash.d.ts +8 -3
- package/dist/feedback/feedback-dialog.d.ts +8 -3
- package/dist/feedback/feedback-dialog.js +3 -3
- package/dist/feedback/feedback-dialog.js.map +1 -1
- package/dist/feedback/feedback-inbox.d.ts +8 -3
- package/dist/feedback/feedback-inbox.js +2 -2
- package/dist/feedback/feedback-inbox.js.map +1 -1
- package/dist/feedback/feedback-labels.d.ts +8 -3
- package/dist/feedback/feedback-menu.d.ts +9 -4
- package/dist/feedback/feedback-record.d.ts +8 -3
- package/dist/feedback/feedback-row-detail.d.ts +8 -3
- package/dist/feedback/feedback-status-undo.d.ts +8 -3
- package/dist/feedback/feedback-submit.d.ts +8 -3
- package/dist/feedback/feedback-swipe.d.ts +8 -3
- package/dist/feedback/feedback-table.d.ts +8 -3
- package/dist/feedback/feedback-thread.d.ts +8 -3
- package/dist/feedback/feedback-thread.js +3 -3
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/feedback.d.ts +8 -3
- package/dist/hooks/use-anchored-panel.d.ts +32 -3
- package/dist/hooks/use-anchored-panel.js +21 -3
- package/dist/hooks/use-anchored-panel.js.map +1 -1
- package/dist/hooks/use-breakpoint.d.ts +88 -0
- package/dist/hooks/use-breakpoint.js +50 -0
- package/dist/hooks/use-breakpoint.js.map +1 -0
- package/dist/hooks/use-file-drop.d.ts +8 -3
- package/dist/hooks/use-large-text.d.ts +29 -0
- package/dist/hooks/use-large-text.js +20 -0
- package/dist/hooks/use-large-text.js.map +1 -0
- package/dist/hooks/use-windowed-rows.d.ts +52 -8
- package/dist/hooks/use-windowed-rows.js +94 -5
- package/dist/hooks/use-windowed-rows.js.map +1 -1
- package/dist/i18n/defaults.d.ts +8 -3
- package/dist/i18n/defaults.js +8 -0
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.d.ts +8 -3
- package/dist/i18n/german.js +94 -3
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +8 -3
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/languages.d.ts +10 -5
- package/dist/i18n/locales/de-CH.d.ts +8 -3
- package/dist/i18n/locales/en.d.ts +8 -3
- package/dist/i18n/locales/es.d.ts +8 -3
- package/dist/i18n/locales/es.js +89 -3
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +8 -3
- package/dist/i18n/locales/fr.js +91 -3
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +8 -3
- package/dist/i18n/locales/hu.js +91 -3
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +8 -3
- package/dist/i18n/locales/it.js +92 -3
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +8 -3
- package/dist/i18n/locales/zh.js +89 -3
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.d.ts +8 -3
- package/dist/i18n/review.js +15 -1
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +27 -11
- package/dist/index.js +77 -4
- package/dist/index.js.map +1 -1
- package/dist/landing/landing-actions.d.ts +8 -3
- package/dist/landing/landing-sections.d.ts +8 -3
- package/dist/landing/landing-sections.js +7 -3
- package/dist/landing/landing-sections.js.map +1 -1
- package/dist/landing/public-header.d.ts +9 -4
- package/dist/landing/public-header.js +3 -3
- package/dist/landing/public-header.js.map +1 -1
- package/dist/landing/routing.d.ts +8 -3
- package/dist/lib/cn.js +3 -2
- package/dist/lib/cn.js.map +1 -1
- package/dist/rhf/fields.d.ts +8 -3
- package/dist/rhf/fields.js +1 -1
- package/dist/rhf/fields.js.map +1 -1
- package/dist/rhf/form.d.ts +8 -3
- package/dist/rhf/form.js +2 -2
- package/dist/rhf/form.js.map +1 -1
- package/dist/rhf.d.ts +8 -3
- package/dist/search/command-palette.d.ts +1 -1
- package/dist/search/command-palette.js +9 -8
- package/dist/search/command-palette.js.map +1 -1
- package/dist/settings/settings-layout.js +2 -1
- package/dist/settings/settings-layout.js.map +1 -1
- package/dist/settings/settings-section.d.ts +8 -3
- package/dist/settings/use-account-appearance.d.ts +92 -0
- package/dist/settings/use-account-appearance.js +63 -0
- package/dist/settings/use-account-appearance.js.map +1 -0
- package/dist/settings/use-settings-route.d.ts +1 -1
- package/dist/settings/use-settings-route.js +2 -3
- package/dist/settings/use-settings-route.js.map +1 -1
- package/dist/shell/app-shell.d.ts +12 -171
- package/dist/shell/app-shell.js +144 -28
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/auth-layout.js +1 -1
- package/dist/shell/auth-layout.js.map +1 -1
- package/dist/shell/option-switcher-menu.js +1 -1
- package/dist/shell/option-switcher-menu.js.map +1 -1
- package/dist/shell/top-bar-brand.d.ts +8 -3
- package/dist/shell/top-bar-brand.js +3 -1
- package/dist/shell/top-bar-brand.js.map +1 -1
- package/dist/shell/topbar-action-menu.d.ts +4 -0
- package/dist/shell/topbar-action-menu.js +3 -3
- package/dist/shell/topbar-action-menu.js.map +1 -1
- package/dist/shell/topbar-controls.js +4 -4
- package/dist/shell/topbar-controls.js.map +1 -1
- package/dist/shell.d.ts +9 -5
- package/dist/theme/contrast-tokens.d.ts +41 -0
- package/dist/theme/contrast-tokens.js +59 -0
- package/dist/theme/contrast-tokens.js.map +1 -0
- package/dist/theme/contrast.d.ts +110 -0
- package/dist/theme/contrast.js +128 -0
- package/dist/theme/contrast.js.map +1 -0
- package/dist/theme/palette-presets.d.ts +12 -1
- package/dist/theme/palette-presets.js +9 -4
- package/dist/theme/palette-presets.js.map +1 -1
- package/dist/theme/palette-store.js.map +1 -1
- package/dist/theme/text-size.d.ts +173 -0
- package/dist/theme/text-size.js +121 -0
- package/dist/theme/text-size.js.map +1 -0
- package/dist/wizard/stepper-nav.d.ts +8 -3
- package/dist/wizard/wizard-summary.js +1 -1
- package/dist/wizard/wizard-summary.js.map +1 -1
- package/dist/wizard.d.ts +8 -3
- package/package.json +1 -1
- package/src/admin/admin-action-log.tsx +6 -1
- package/src/admin/invitations-panel.tsx +36 -29
- package/src/admin/user-roster.tsx +17 -72
- package/src/auth/auth-errors.ts +68 -7
- package/src/billing/billing-banner.tsx +205 -0
- package/src/billing/billing-labels.ts +240 -0
- package/src/billing/billing-lock.ts +75 -0
- package/src/billing/billing-standing.ts +72 -0
- package/src/billing/plan-card.tsx +458 -0
- package/src/billing/plan-limit-notice.tsx +145 -0
- package/src/billing/plan-limit.ts +53 -0
- package/src/billing/plan-price.ts +101 -0
- package/src/billing/subscription-actions.tsx +76 -0
- package/src/billing/subscription-status-chip.tsx +95 -0
- package/src/chart.ts +2 -0
- package/src/components/account-chips.tsx +36 -10
- package/src/components/alert-banner.tsx +16 -7
- package/src/components/amount-input.tsx +5 -5
- package/src/components/appearance-labels.ts +47 -0
- package/src/components/autocomplete.tsx +2 -2
- package/src/components/breadcrumbs.tsx +3 -3
- package/src/components/bulk-action-bar.tsx +11 -14
- package/src/components/button-group.tsx +21 -0
- package/src/components/calculator.tsx +4 -3
- package/src/components/calendar-heatmap.tsx +5 -5
- package/src/components/chart-height.ts +30 -0
- package/src/components/chart-zoom.tsx +6 -1
- package/src/components/checkbox-group.tsx +2 -2
- package/src/components/checkbox.tsx +62 -20
- package/src/components/chip.tsx +139 -30
- package/src/components/choice-card.tsx +16 -11
- package/src/components/column-mapper.tsx +1 -1
- package/src/components/combobox-core.tsx +8 -7
- package/src/components/combobox.tsx +8 -8
- package/src/components/country-select.tsx +1 -1
- package/src/components/currency-select.tsx +3 -3
- package/src/components/data-table-filter-popover.tsx +7 -1
- package/src/components/data-table-pagination.tsx +60 -31
- package/src/components/data-table.tsx +164 -43
- package/src/components/date-picker.tsx +44 -10
- package/src/components/description-list.tsx +2 -2
- package/src/components/dialog-frame.tsx +2 -1
- package/src/components/disclosure.tsx +3 -2
- package/src/components/dropdown.tsx +10 -2
- package/src/components/facing-pair.ts +12 -5
- package/src/components/field-parts.tsx +190 -7
- package/src/components/field-sync.tsx +17 -3
- package/src/components/field.tsx +2 -2
- package/src/components/floating-panel.tsx +7 -4
- package/src/components/focus-ring.ts +12 -0
- package/src/components/form-actions.tsx +55 -18
- package/src/components/full-bleed-dialog.tsx +18 -4
- package/src/components/image-grid.tsx +1 -1
- package/src/components/inline-edit-field.tsx +26 -4
- package/src/components/legal-page.tsx +28 -2
- package/src/components/legal.tsx +19 -1
- package/src/components/lightbox.tsx +24 -2
- package/src/components/line-items.tsx +7 -1
- package/src/components/list.tsx +36 -10
- package/src/components/measured-grid.tsx +49 -24
- package/src/components/menu-item.tsx +2 -2
- package/src/components/mini-calendar.tsx +8 -4
- package/src/components/month-picker.tsx +15 -6
- package/src/components/nav-pills.tsx +1 -1
- package/src/components/number-input.tsx +14 -7
- package/src/components/numpad-sheet.tsx +2 -2
- package/src/components/one-time-code-input.tsx +2 -2
- package/src/components/page-contents.tsx +2 -2
- package/src/components/phone-input.tsx +9 -4
- package/src/components/pie-chart.tsx +19 -9
- package/src/components/popover.tsx +22 -5
- package/src/components/row-actions.tsx +450 -0
- package/src/components/scroll-area.tsx +1 -1
- package/src/components/search-field.tsx +4 -2
- package/src/components/series-chart-budget.ts +40 -8
- package/src/components/series-chart-ticks.ts +10 -0
- package/src/components/series-chart.tsx +123 -72
- package/src/components/settings-fields.tsx +89 -5
- package/src/components/share-card.tsx +31 -2
- package/src/components/sign-chip.tsx +28 -4
- package/src/components/signature-pad.tsx +13 -7
- package/src/components/slider.tsx +22 -9
- package/src/components/sparkline.tsx +11 -3
- package/src/components/stat-tile.tsx +70 -14
- package/src/components/status-dot.tsx +25 -2
- package/src/components/swipeable-row.tsx +10 -2
- package/src/components/switch.tsx +57 -23
- package/src/components/table.tsx +2 -2
- package/src/components/text-link.tsx +1 -1
- package/src/components/text.tsx +11 -6
- package/src/components/tile-radio.tsx +4 -1
- package/src/components/toast.tsx +27 -7
- package/src/components/toggle-group.tsx +115 -14
- package/src/components/toggle-legend.tsx +53 -8
- package/src/components/translation-review-editor.tsx +1 -1
- package/src/components/translation-review.tsx +11 -5
- package/src/components/tree-view.tsx +3 -2
- package/src/components/treemap.tsx +27 -10
- package/src/components/ui.tsx +353 -153
- package/src/components/user-avatar.tsx +1 -1
- package/src/components/wizard-stepper.tsx +5 -1
- package/src/demo/demo-banner.tsx +5 -0
- package/src/feedback/feedback-dialog.tsx +3 -3
- package/src/feedback/feedback-inbox.tsx +2 -2
- package/src/feedback/feedback-thread.tsx +3 -3
- package/src/hooks/use-anchored-panel.ts +67 -5
- package/src/hooks/use-breakpoint.ts +132 -0
- package/src/hooks/use-large-text.ts +41 -0
- package/src/hooks/use-windowed-rows.ts +168 -12
- package/src/i18n/defaults.ts +8 -0
- package/src/i18n/german.ts +107 -0
- package/src/i18n/kit-labels.tsx +12 -0
- package/src/i18n/locales/es.ts +98 -0
- package/src/i18n/locales/fr.ts +102 -0
- package/src/i18n/locales/hu.ts +100 -0
- package/src/i18n/locales/it.ts +103 -0
- package/src/i18n/locales/zh.ts +94 -0
- package/src/i18n/review.ts +14 -0
- package/src/index.ts +76 -6
- package/src/landing/landing-sections.tsx +7 -3
- package/src/landing/public-header.tsx +4 -4
- package/src/lib/cn.ts +13 -2
- package/src/rhf/fields.tsx +1 -1
- package/src/rhf/form.tsx +2 -2
- package/src/search/command-palette.tsx +10 -9
- package/src/settings/settings-layout.tsx +2 -1
- package/src/settings/use-account-appearance.ts +148 -0
- package/src/settings/use-settings-route.ts +3 -4
- package/src/shell/app-shell.tsx +278 -54
- package/src/shell/auth-layout.tsx +1 -1
- package/src/shell/option-switcher-menu.tsx +1 -1
- package/src/shell/top-bar-brand.tsx +3 -1
- package/src/shell/topbar-action-menu.tsx +3 -3
- package/src/shell/topbar-controls.tsx +4 -4
- package/src/theme/contrast-tokens.ts +112 -0
- package/src/theme/contrast.ts +225 -0
- package/src/theme/palette-presets.ts +24 -4
- package/src/theme/palette-store.ts +6 -1
- package/src/theme/text-size.ts +283 -0
- package/src/wizard/wizard-summary.tsx +4 -2
- package/tokens.css +158 -8
|
@@ -2,6 +2,7 @@ import { useEffect, useMemo, useRef, useState } from "react";
|
|
|
2
2
|
import { Calculator as CalculatorIcon, Delete } from "lucide-react";
|
|
3
3
|
import { Popover } from "./popover";
|
|
4
4
|
import { cn } from "../lib/cn";
|
|
5
|
+
import { FIELD_TOUCH_TEXT } from "./ui";
|
|
5
6
|
import { evaluateExpression, formatResult, isBareAmount, splitLeadingSign } from "../lib/calc";
|
|
6
7
|
import {
|
|
7
8
|
DEFAULT_CALCULATOR_LABELS,
|
|
@@ -70,7 +71,7 @@ const KEYS: Key[] = [
|
|
|
70
71
|
];
|
|
71
72
|
|
|
72
73
|
const KEY_BASE =
|
|
73
|
-
"flex h-9 items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-
|
|
74
|
+
"flex h-9 items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-[length:var(--focus-ring-width)] focus:ring-[var(--border-strong)]";
|
|
74
75
|
// Two key families, two fills: digits sit on the inset surface and darken on
|
|
75
76
|
// hover, operators sit a step down on `--border` and lift toward that surface —
|
|
76
77
|
// the same split `NumberPadSheet` uses for this keypad on a phone. The tokens
|
|
@@ -151,7 +152,7 @@ function CalculatorPanel({
|
|
|
151
152
|
// is right-aligned in every script too — so both stay physical, pinned
|
|
152
153
|
// with `dir="ltr"` rather than mirrored in a right-to-left form.
|
|
153
154
|
dir="ltr"
|
|
154
|
-
className="block w-full rounded-md border border-[var(--border)] bg-[var(--bg-surface)] px-2 py-1.5 text-right font-mono text-sm text-[var(--text-primary)] focus:border-[var(--border-strong)] focus:ring-[var(--border-strong)]"
|
|
155
|
+
className={cn("block w-full rounded-md border border-[var(--border)] bg-[var(--bg-surface)] px-2 py-1.5 text-right font-mono text-sm text-[var(--text-primary)] focus:border-[var(--border-strong)] focus:ring-[var(--border-strong)]", FIELD_TOUCH_TEXT)}
|
|
155
156
|
/>
|
|
156
157
|
<div dir="ltr" className="h-4 pr-1 text-right font-mono text-xs text-[var(--text-placeholder)]">
|
|
157
158
|
{result !== null && formatResult(result) !== text.trim() ? `= ${formatResult(result)}` : ""}
|
|
@@ -231,7 +232,7 @@ export function CalculatorButton({
|
|
|
231
232
|
const labels = useKitLabels("calculator", DEFAULT_CALCULATOR_LABELS, fromProps);
|
|
232
233
|
return (
|
|
233
234
|
<Popover
|
|
234
|
-
width=
|
|
235
|
+
width="14rem"
|
|
235
236
|
labels={{ panel: labels.panel }}
|
|
236
237
|
trigger={({ open, toggle, ref }) => (
|
|
237
238
|
<button
|
|
@@ -478,7 +478,7 @@ export function CalendarHeatmap({
|
|
|
478
478
|
),
|
|
479
479
|
} as const;
|
|
480
480
|
const inner = withNumber ? (
|
|
481
|
-
<span aria-hidden className="text-
|
|
481
|
+
<span aria-hidden className="text-caption leading-none tabular-nums">
|
|
482
482
|
{numberFormat.format(d.getDate())}
|
|
483
483
|
</span>
|
|
484
484
|
) : null;
|
|
@@ -515,7 +515,7 @@ export function CalendarHeatmap({
|
|
|
515
515
|
<div ref={scrollerRef} className="overflow-x-auto pb-1">
|
|
516
516
|
<div ref={gridRef} role="grid" aria-label={gridName} className="inline-grid gap-0.5">
|
|
517
517
|
{/* Decoration: every cell's name already carries its month. */}
|
|
518
|
-
<div aria-hidden className="grid gap-0.5 text-
|
|
518
|
+
<div aria-hidden className="grid gap-0.5 text-micro leading-3 text-[var(--text-muted)]" style={columns}>
|
|
519
519
|
<span />
|
|
520
520
|
{monthLabels.map((m, w) => (
|
|
521
521
|
<span key={w} className="overflow-visible whitespace-nowrap">
|
|
@@ -528,7 +528,7 @@ export function CalendarHeatmap({
|
|
|
528
528
|
<div
|
|
529
529
|
role="rowheader"
|
|
530
530
|
aria-label={weekdayLabels[r].long}
|
|
531
|
-
className="overflow-hidden pe-1 text-
|
|
531
|
+
className="overflow-hidden pe-1 text-micro leading-3 text-[var(--text-muted)]"
|
|
532
532
|
>
|
|
533
533
|
{/* Every other weekday, as a contribution graph does: seven labels
|
|
534
534
|
at this size are a smear. The name is there for all seven. */}
|
|
@@ -557,7 +557,7 @@ export function CalendarHeatmap({
|
|
|
557
557
|
key={i}
|
|
558
558
|
role="columnheader"
|
|
559
559
|
aria-label={w.long}
|
|
560
|
-
className="pb-0.5 text-center text-
|
|
560
|
+
className="pb-0.5 text-center text-micro uppercase tracking-wide text-[var(--text-muted)]"
|
|
561
561
|
>
|
|
562
562
|
{w.short}
|
|
563
563
|
</div>
|
|
@@ -586,7 +586,7 @@ export function CalendarHeatmap({
|
|
|
586
586
|
)}
|
|
587
587
|
{body}
|
|
588
588
|
{legend && (
|
|
589
|
-
<div aria-hidden className="mt-2 flex items-center justify-end gap-1 text-
|
|
589
|
+
<div aria-hidden className="mt-2 flex items-center justify-end gap-1 text-micro text-[var(--text-muted)]">
|
|
590
590
|
<span className="me-0.5">{labels.less}</span>
|
|
591
591
|
{legendLevels.map((l) => (
|
|
592
592
|
<span
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A chart's height as the kit's charts take it (docs/text-size-harmonization.md §10.10):
|
|
5
|
+
*
|
|
6
|
+
* - a CSS length — `"20rem"`, `"min(20rem, 60dvh)"`, `"clamp(14rem, 40vh, 28rem)"` —
|
|
7
|
+
* set inline, so a height can grow with the text size AND stop at the screen: scaled
|
|
8
|
+
* px would make a 480 px chart 720 px at Extra large, more than a phone shows;
|
|
9
|
+
* - a Tailwind class (`"h-72"`, `"h-64 md:h-80"`), as before;
|
|
10
|
+
* - a number of px, set inline, as before — kept for the callers that hold their height
|
|
11
|
+
* as a number, but it does not follow the text size.
|
|
12
|
+
*/
|
|
13
|
+
export type ChartHeight = string | number;
|
|
14
|
+
|
|
15
|
+
/** A number with an optional unit, or one of the CSS functions a length is written with.
|
|
16
|
+
* A Tailwind class never starts with a digit or `min(`, so the two cannot be confused. */
|
|
17
|
+
const CSS_LENGTH = /^(?:[-+]?(?:\d+\.?\d*|\.\d+)(?:%|[a-z]+)?|(?:min|max|clamp|calc|var)\(.*\))$/i;
|
|
18
|
+
|
|
19
|
+
/** Whether a string `height` is a CSS length rather than a class. */
|
|
20
|
+
export function isCssLength(value: string): boolean {
|
|
21
|
+
return CSS_LENGTH.test(value.trim());
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** The class or the inline style a {@link ChartHeight} becomes — one of the two, or
|
|
25
|
+
* neither for `undefined`. */
|
|
26
|
+
export function chartHeightProps(height: ChartHeight | undefined): { className?: string; style?: CSSProperties } {
|
|
27
|
+
if (height === undefined) return {};
|
|
28
|
+
if (typeof height === "number") return { style: { height } };
|
|
29
|
+
return isCssLength(height) ? { style: { height: height.trim() } } : { className: height };
|
|
30
|
+
}
|
|
@@ -29,6 +29,8 @@ import {
|
|
|
29
29
|
type InverseScaleFunction,
|
|
30
30
|
} from "recharts";
|
|
31
31
|
import { X } from "lucide-react";
|
|
32
|
+
import { cn } from "../lib/cn";
|
|
33
|
+
import { FOCUS_RING } from "./focus-ring";
|
|
32
34
|
import { useKitLabels } from "../i18n/kit-labels";
|
|
33
35
|
import { DEFAULT_SERIES_CHART_LABELS, type SeriesChartLabels } from "./series-chart-labels";
|
|
34
36
|
|
|
@@ -492,7 +494,10 @@ export function withChartZoom<P extends ZoomTarget>(Chart: ComponentType<P>) {
|
|
|
492
494
|
<button
|
|
493
495
|
type="button"
|
|
494
496
|
onClick={clear}
|
|
495
|
-
className=
|
|
497
|
+
className={cn(
|
|
498
|
+
"absolute end-1 top-1 z-10 inline-flex items-center gap-1 rounded border border-[var(--border)] bg-[var(--bg-surface)]/90 px-1.5 py-0.5 text-micro text-[var(--text-muted)] backdrop-blur transition-colors hover:text-[var(--text-primary)]",
|
|
499
|
+
FOCUS_RING,
|
|
500
|
+
)}
|
|
496
501
|
>
|
|
497
502
|
<X aria-hidden className="size-3" /> {labels.resetZoom}
|
|
498
503
|
</button>
|
|
@@ -215,12 +215,12 @@ export function CheckboxGroup<T extends string = string>({
|
|
|
215
215
|
</RequiredStarOnLegend.Provider>
|
|
216
216
|
{showHint && (
|
|
217
217
|
// A `div`, not a `p`: a hint may be a node with a link in it.
|
|
218
|
-
<div id={hintId} className="mt-1.5 text-
|
|
218
|
+
<div id={hintId} className="mt-1.5 text-caption leading-tight text-[var(--text-muted)]">
|
|
219
219
|
{hint}
|
|
220
220
|
</div>
|
|
221
221
|
)}
|
|
222
222
|
{showError && (
|
|
223
|
-
<p id={errorId} className="mt-1 text-
|
|
223
|
+
<p id={errorId} className="mt-1 text-caption leading-tight text-[var(--danger)]">
|
|
224
224
|
{error}
|
|
225
225
|
</p>
|
|
226
226
|
)}
|
|
@@ -3,7 +3,15 @@ import { Check, Minus } from "lucide-react";
|
|
|
3
3
|
import type { ChangeEvent, InputHTMLAttributes, ReactNode } from "react";
|
|
4
4
|
import { cn } from "../lib/cn";
|
|
5
5
|
import { assignRef, hasMessage, mergeDescribedBy } from "./choice-parts";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
DISABLED_REASON_LINE_CLASS,
|
|
8
|
+
LockedReason,
|
|
9
|
+
RequiredStarOnLegend,
|
|
10
|
+
useDisabledReasonLine,
|
|
11
|
+
useLockReason,
|
|
12
|
+
type DisabledReasonDisplay,
|
|
13
|
+
} from "./field-parts";
|
|
14
|
+
import { FOCUS_RING } from "./focus-ring";
|
|
7
15
|
|
|
8
16
|
/**
|
|
9
17
|
* A checkbox that is still `<input type="checkbox">`.
|
|
@@ -21,17 +29,31 @@ import { LockedReason, RequiredStarOnLegend, useLockReason } from "./field-parts
|
|
|
21
29
|
* browser's own grey outline in both themes.
|
|
22
30
|
*/
|
|
23
31
|
|
|
24
|
-
// The box. 16px, like every raw checkbox it replaces, so a migration
|
|
32
|
+
// The box. 1rem (16px at Normal), like every raw checkbox it replaces, so a migration
|
|
33
|
+
// moves nothing; its corner `rounded` (0.25rem) rather than a fixed 4px, so it keeps its
|
|
34
|
+
// shape as it grows with the text (0.32, §3.2).
|
|
25
35
|
//
|
|
26
|
-
//
|
|
27
|
-
// --brand-filled (checked) box would be a ring painted in the colour it sits
|
|
28
|
-
// present in the DOM and invisible on screen. The offset is what separates the two.
|
|
36
|
+
// The kit's focus frame (§5), with an offset in the surface colour: a --brand ring
|
|
37
|
+
// touching a --brand-filled (checked) box would be a ring painted in the colour it sits
|
|
38
|
+
// on — present in the DOM and invisible on screen. The offset is what separates the two.
|
|
29
39
|
const BOX =
|
|
30
|
-
"peer size-4 shrink-0 cursor-pointer appearance-none rounded
|
|
40
|
+
"peer size-4 shrink-0 cursor-pointer appearance-none rounded border border-[var(--border-strong)] bg-[var(--bg-surface)] shadow-sm transition-colors " +
|
|
31
41
|
"checked:border-[var(--brand)] checked:bg-[var(--brand)] " +
|
|
32
|
-
|
|
42
|
+
`focus:outline-none ${FOCUS_RING} focus-visible:ring-offset-1 focus-visible:ring-offset-[var(--bg-surface)] ` +
|
|
33
43
|
"disabled:cursor-not-allowed";
|
|
34
44
|
|
|
45
|
+
/**
|
|
46
|
+
* The 48 px touch target at Large (0.32, §4) for a LABELLED box: the label's own hit
|
|
47
|
+
* area, an invisible `::after` that is part of the `<label>` — so a tap on it ticks the
|
|
48
|
+
* box through `for` — reaching back over the box and its gap (`-start-6`: 1rem + 0.5rem)
|
|
49
|
+
* and out to 48 px tall on a one-line label. It changes no layout; a label already taller
|
|
50
|
+
* than 48 px keeps its own box (`max(0px, …)`). A bare box has no label to grow, and
|
|
51
|
+
* takes its target from where it stands (a table row's tap, the caller's own label).
|
|
52
|
+
*/
|
|
53
|
+
const LABEL_TOUCH_LARGE =
|
|
54
|
+
"large:relative large:after:absolute large:after:-start-6 large:after:end-0 " +
|
|
55
|
+
"large:after:-inset-y-[max(0px,calc((48px-100%)/2))] large:after:content-['']";
|
|
56
|
+
|
|
35
57
|
// A mixed box wears the checked fill whether or not the underlying input is checked:
|
|
36
58
|
// `indeterminate` is a property the browser keeps separately from `checked`, and the
|
|
37
59
|
// dash means "some", which is neither answer.
|
|
@@ -43,7 +65,7 @@ const BOX_MIXED = "border-[var(--brand)] bg-[var(--brand)]";
|
|
|
43
65
|
const BOX_INVALID =
|
|
44
66
|
"border-[var(--danger-border-strong)] ring-1 ring-[var(--danger-border-strong)] checked:border-[var(--danger-border-strong)] focus-visible:ring-[var(--danger)]";
|
|
45
67
|
|
|
46
|
-
const ERROR_CLASS = "mt-1 text-
|
|
68
|
+
const ERROR_CLASS = "mt-1 text-caption leading-tight text-[var(--danger)]";
|
|
47
69
|
|
|
48
70
|
export interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type"> {
|
|
49
71
|
/**
|
|
@@ -101,6 +123,12 @@ export interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement
|
|
|
101
123
|
* moves in or out of the Tooltip), as a locked Button is.
|
|
102
124
|
*/
|
|
103
125
|
disabledReason?: ReactNode;
|
|
126
|
+
/**
|
|
127
|
+
* Where `disabledReason` shows (0.32, §4 "No fact only in a tooltip"): by default, at
|
|
128
|
+
* Large and on a touch screen, as a line under the label (a bare box: under the box),
|
|
129
|
+
* and in the tooltip otherwise. See {@link DisabledReasonDisplay}.
|
|
130
|
+
*/
|
|
131
|
+
disabledReasonDisplay?: DisabledReasonDisplay;
|
|
104
132
|
/**
|
|
105
133
|
* This box COMMITS — ticking it saves. Under a locked {@link WriteLockProvider} it is
|
|
106
134
|
* locked the `disabledReason` way with the lock's reason (which wins over its own).
|
|
@@ -134,6 +162,7 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Che
|
|
|
134
162
|
disabled,
|
|
135
163
|
required,
|
|
136
164
|
disabledReason,
|
|
165
|
+
disabledReasonDisplay,
|
|
137
166
|
commit,
|
|
138
167
|
onClick,
|
|
139
168
|
...rest
|
|
@@ -144,6 +173,7 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Che
|
|
|
144
173
|
const inputId = id ?? generated;
|
|
145
174
|
const lock = useLockReason(commit, disabledReason);
|
|
146
175
|
const locked = lock.locked;
|
|
176
|
+
const reasonLine = useDisabledReasonLine(disabledReasonDisplay);
|
|
147
177
|
// Locked is disabled the focusable way: the row fades and the words stop inviting a
|
|
148
178
|
// click exactly as they do for `disabled`.
|
|
149
179
|
const looksDisabled = Boolean(disabled) || locked;
|
|
@@ -242,30 +272,35 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Che
|
|
|
242
272
|
// The reason's Tooltip goes round the BOX, not the row: the row is the caller's
|
|
243
273
|
// layout (`className`), and a wrapper round it would move that into a span. A bare
|
|
244
274
|
// box hands its `className` to the wrapper, which is then the outermost element.
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
275
|
+
// With words beside it, the reason LINE goes under them instead (Switch's shape).
|
|
276
|
+
const lineInWords = locked && reasonLine && !bare;
|
|
277
|
+
const box =
|
|
278
|
+
locked && !lineInWords ? (
|
|
279
|
+
<LockedReason lock={lock} line={reasonLine} className={cn("shrink-0", bare && className)}>
|
|
280
|
+
{control}
|
|
281
|
+
</LockedReason>
|
|
282
|
+
) : (
|
|
283
|
+
control
|
|
284
|
+
);
|
|
285
|
+
// The row's fade moves onto its parts while the reason line is in it, as on Switch.
|
|
286
|
+
const dimParts = lineInWords;
|
|
252
287
|
|
|
253
288
|
if (bare) return box;
|
|
254
289
|
|
|
255
290
|
return (
|
|
256
291
|
<div
|
|
257
292
|
className={cn(
|
|
258
|
-
// `items-start` + a
|
|
259
|
-
// line (text-sm is
|
|
293
|
+
// `items-start` + a 1.25rem cell for the box: the box centres on the label's FIRST
|
|
294
|
+
// line (text-sm's line is 1.25rem), so a label that wraps keeps the box at the top
|
|
260
295
|
// rather than floating to the middle of a paragraph.
|
|
261
296
|
"flex items-start gap-2",
|
|
262
297
|
// The whole row fades, the way ToggleGroup and the fields do, so the label does
|
|
263
298
|
// not stay at full strength beside a box you cannot change.
|
|
264
|
-
looksDisabled && "opacity-60",
|
|
299
|
+
looksDisabled && !dimParts && "opacity-60",
|
|
265
300
|
className,
|
|
266
301
|
)}
|
|
267
302
|
>
|
|
268
|
-
<span className="flex h-5 shrink-0 items-center">{box}</span>
|
|
303
|
+
<span className={cn("flex h-5 shrink-0 items-center", dimParts && "opacity-60")}>{box}</span>
|
|
269
304
|
<span className="min-w-0">
|
|
270
305
|
{label !== undefined && (
|
|
271
306
|
<label
|
|
@@ -275,6 +310,8 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Che
|
|
|
275
310
|
// `select-none`: a double-click to toggle twice would otherwise select the
|
|
276
311
|
// words, and a drag that starts on them starts a native text drag.
|
|
277
312
|
looksDisabled ? "cursor-not-allowed" : "cursor-pointer select-none",
|
|
313
|
+
LABEL_TOUCH_LARGE,
|
|
314
|
+
dimParts && "opacity-60",
|
|
278
315
|
)}
|
|
279
316
|
>
|
|
280
317
|
{label}
|
|
@@ -286,10 +323,15 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Che
|
|
|
286
323
|
</label>
|
|
287
324
|
)}
|
|
288
325
|
{showDescription && (
|
|
289
|
-
<span id={descriptionId} className="mt-0.5 block text-xs text-[var(--text-muted)]">
|
|
326
|
+
<span id={descriptionId} className={cn("mt-0.5 block text-xs text-[var(--text-muted)]", dimParts && "opacity-60")}>
|
|
290
327
|
{description}
|
|
291
328
|
</span>
|
|
292
329
|
)}
|
|
330
|
+
{lineInWords && (
|
|
331
|
+
<span id={lock.reasonId} className={DISABLED_REASON_LINE_CLASS}>
|
|
332
|
+
{lock.reason}
|
|
333
|
+
</span>
|
|
334
|
+
)}
|
|
293
335
|
{showError && (
|
|
294
336
|
<span id={errorId} className={cn("block", ERROR_CLASS)}>
|
|
295
337
|
{error}
|
package/src/components/chip.tsx
CHANGED
|
@@ -4,7 +4,9 @@ import { Check, X } from "lucide-react";
|
|
|
4
4
|
import type { LucideIcon } from "lucide-react";
|
|
5
5
|
import { cn } from "../lib/cn";
|
|
6
6
|
import { horizontalStep } from "../lib/direction";
|
|
7
|
-
import { FIELD_INVALID } from "./ui";
|
|
7
|
+
import { FIELD_INVALID, FIELD_TOUCH_TEXT, TOUCH_TARGET_LARGE } from "./ui";
|
|
8
|
+
import { FOCUS_RING } from "./focus-ring";
|
|
9
|
+
import { DisabledReasonLine, useDisabledReasonLine, type DisabledReasonDisplay } from "./field-parts";
|
|
8
10
|
import { DEFAULT_COMMON_LABELS, useKitLabels, useKitLink, useKitLocale } from "../i18n/kit-labels";
|
|
9
11
|
import { pickLinkRenderer } from "./text-link";
|
|
10
12
|
import { Tooltip } from "./tooltip";
|
|
@@ -196,9 +198,9 @@ const DOT_SIZE: Record<ChipSize, string> = { xs: "size-1.5", sm: "size-2", md: "
|
|
|
196
198
|
* capitals at body size shout and capitals untracked run together. Per size, so it
|
|
197
199
|
* replaces the size's own `text-*` through tailwind-merge. */
|
|
198
200
|
const CAPS: Record<ChipSize, string> = {
|
|
199
|
-
xs: "text-
|
|
200
|
-
sm: "text-
|
|
201
|
-
md: "text-
|
|
201
|
+
xs: "text-micro font-semibold uppercase tracking-wider",
|
|
202
|
+
sm: "text-micro font-semibold uppercase tracking-wider",
|
|
203
|
+
md: "text-caption font-semibold uppercase tracking-wider",
|
|
202
204
|
lg: "text-xs font-semibold uppercase tracking-wider",
|
|
203
205
|
};
|
|
204
206
|
|
|
@@ -255,8 +257,8 @@ const SIZE: Record<
|
|
|
255
257
|
{ body: string; split: string; tail: string; icon: string; remove: string }
|
|
256
258
|
> = {
|
|
257
259
|
xs: {
|
|
258
|
-
body: "gap-1 px-1.5 py-0 text-
|
|
259
|
-
split: "gap-1 ps-1.5 pe-0.5 py-0 text-
|
|
260
|
+
body: "gap-1 px-1.5 py-0 text-caption leading-4",
|
|
261
|
+
split: "gap-1 ps-1.5 pe-0.5 py-0 text-caption leading-4",
|
|
260
262
|
tail: "pe-1",
|
|
261
263
|
icon: "size-3",
|
|
262
264
|
remove: "size-2.5",
|
|
@@ -380,8 +382,10 @@ export function refreshChipEdges(): void {
|
|
|
380
382
|
const r = el.getBoundingClientRect();
|
|
381
383
|
const label = el.querySelector<HTMLElement>(".truncate");
|
|
382
384
|
// Not laid out (a hidden ancestor, jsdom), or truncated at its container's edge,
|
|
383
|
-
// where a wider chip would overflow: leave it alone.
|
|
384
|
-
|
|
385
|
+
// where a wider chip would overflow: leave it alone. So too a label wrapped onto
|
|
386
|
+
// a second line at Large (0.32.1): the chip is already as wide as its row lets it
|
|
387
|
+
// be, and a min-width past that would push it over the edge just the same.
|
|
388
|
+
if (!r.width || (label && (label.scrollWidth > label.clientWidth || labelWraps(label)))) return null;
|
|
385
389
|
const width = Math.round(r.width * 64) / 64;
|
|
386
390
|
const target = snappedChipEdgeWidth(width, r.left + window.scrollX, dpr);
|
|
387
391
|
return target === width ? null : target;
|
|
@@ -404,6 +408,13 @@ export function refreshChipEdges(): void {
|
|
|
404
408
|
}
|
|
405
409
|
}
|
|
406
410
|
|
|
411
|
+
/** Whether a chip's label runs to more than one line — taller than one and a half of
|
|
412
|
+
* its line height. A line height of `normal` (no number to compare) counts as one line. */
|
|
413
|
+
function labelWraps(label: HTMLElement): boolean {
|
|
414
|
+
const line = Number.parseFloat(getComputedStyle(label).lineHeight);
|
|
415
|
+
return line > 0 && label.clientHeight > 1.5 * line;
|
|
416
|
+
}
|
|
417
|
+
|
|
407
418
|
function scheduleChipEdges() {
|
|
408
419
|
if (snapFrame || typeof requestAnimationFrame === "undefined") return;
|
|
409
420
|
snapFrame = requestAnimationFrame(() => {
|
|
@@ -487,13 +498,48 @@ function assignRef<T>(target: Ref<T> | undefined, value: T | null) {
|
|
|
487
498
|
}
|
|
488
499
|
|
|
489
500
|
const CHIP_PILL = "inline-flex max-w-full items-center rounded-full border transition-colors";
|
|
501
|
+
|
|
490
502
|
// `focus-visible`, not `focus`: a chip commonly receives focus programmatically (the
|
|
491
503
|
// ChipInput moves focus onto one after a removal) and a ring that appears on a
|
|
492
504
|
// pointer click reads as a stuck selection.
|
|
493
|
-
const CHIP_RING =
|
|
494
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--brand)] focus-visible:ring-offset-1 focus-visible:ring-offset-[var(--bg-surface)]";
|
|
505
|
+
const CHIP_RING = `${FOCUS_RING} focus-visible:ring-offset-1 focus-visible:ring-offset-[var(--bg-surface)]`;
|
|
495
506
|
const CHIP_BASE = `${CHIP_PILL} ${CHIP_RING}`;
|
|
496
507
|
|
|
508
|
+
/**
|
|
509
|
+
* A text chip's label at Large and Extra large (0.32.1, keksdose's 0.32 report;
|
|
510
|
+
* docs/text-size-harmonization.md §4 "nothing truncates"): it wraps instead of ending in
|
|
511
|
+
* "…". keksdose's "Zur Prüfung zurücklegen" read "Zur Prüfung zu…" on a phone at Extra
|
|
512
|
+
* large, which is a different instruction. No size has a fixed height (padding and
|
|
513
|
+
* `min-h-*` only), so the pill grows with its lines; the mark before the text stays
|
|
514
|
+
* centred on them, as in a pill. A `large:` class, so Normal keeps its one-line chip.
|
|
515
|
+
*
|
|
516
|
+
* `break-words`, not `[overflow-wrap:anywhere]`: a status chip often sits in a table
|
|
517
|
+
* cell, and `anywhere` lowers the label's min-content width to one letter, so an
|
|
518
|
+
* auto-sized column can squeeze it to a letter per line (StatusDot's label did, in the
|
|
519
|
+
* showcase's tone table at 360 px, Extra large). `break-word` keeps each word whole
|
|
520
|
+
* wherever the width is the content's to choose, and still breaks one that cannot fit
|
|
521
|
+
* the row at all.
|
|
522
|
+
*/
|
|
523
|
+
const CHIP_LABEL_WRAP_AT_LARGE = "large:whitespace-normal large:break-words";
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* An interactive chip's touch target at Large and Extra large (docs/text-size-harmonization.md
|
|
527
|
+
* §4: "touch targets at least 48 px … for buttons, inputs, chips"): a link or toggle chip
|
|
528
|
+
* grows its pill to 48 px, as Button `sm` does, and centres what is in it once the
|
|
529
|
+
* minimum width is what sizes it. An inert chip (a tag on a row) is no target and keeps
|
|
530
|
+
* its size; a disabled one is no target either.
|
|
531
|
+
*/
|
|
532
|
+
const CHIP_TOUCH_LARGE = `${TOUCH_TARGET_LARGE} large:justify-center`;
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* The ×'s 48 px hit area at Large (§4) — IconButton's `2xs` pattern: a box that cannot
|
|
536
|
+
* grow without growing the chip around it keeps its size and gets an invisible
|
|
537
|
+
* `::after`, 48 px square and centred on it, which takes the taps a finger lands round
|
|
538
|
+
* the glyph. On an inert removable chip (ChipInput's values) the × is the only target.
|
|
539
|
+
*/
|
|
540
|
+
const REMOVE_HIT_AREA_LARGE =
|
|
541
|
+
"relative large:after:absolute large:after:inset-[calc((100%-48px)/2)] large:after:content-['']";
|
|
542
|
+
|
|
497
543
|
interface ChipBaseProps {
|
|
498
544
|
children: ReactNode;
|
|
499
545
|
tone?: ChipTone;
|
|
@@ -627,6 +673,7 @@ export type ChipProps = ChipBaseProps &
|
|
|
627
673
|
renderLink?: (props: ChipLinkProps) => ReactElement;
|
|
628
674
|
commit?: never;
|
|
629
675
|
disabledReason?: never;
|
|
676
|
+
disabledReasonDisplay?: never;
|
|
630
677
|
}
|
|
631
678
|
| {
|
|
632
679
|
/** The link shape again, with an `onClick`. `href` is a required string here,
|
|
@@ -642,6 +689,7 @@ export type ChipProps = ChipBaseProps &
|
|
|
642
689
|
renderLink?: (props: ChipLinkProps) => ReactElement;
|
|
643
690
|
commit?: never;
|
|
644
691
|
disabledReason?: never;
|
|
692
|
+
disabledReasonDisplay?: never;
|
|
645
693
|
}
|
|
646
694
|
| {
|
|
647
695
|
href?: never;
|
|
@@ -654,11 +702,21 @@ export type ChipProps = ChipBaseProps &
|
|
|
654
702
|
* `disabledReason`, on the chip's button shape (keksdose K3: a filter or flag
|
|
655
703
|
* chip that saves on press, under a read-only lock). The chip stays focusable
|
|
656
704
|
* and `aria-disabled`, a press (and its `onRemove` ×) does nothing, and the
|
|
657
|
-
* reason
|
|
658
|
-
*
|
|
659
|
-
*
|
|
705
|
+
* reason describes the chip — as a line under it at Large and on a touch
|
|
706
|
+
* screen, in the kit {@link Tooltip} otherwise (see `disabledReasonDisplay`).
|
|
707
|
+
* Wins over `disabled`. A link chip navigates rather than commits, so it takes
|
|
708
|
+
* neither this nor `commit`; an inert chip has nothing to refuse.
|
|
660
709
|
*/
|
|
661
710
|
disabledReason?: ReactNode;
|
|
711
|
+
/**
|
|
712
|
+
* Where `disabledReason` shows (0.32, docs/text-size-harmonization.md §4 "No fact
|
|
713
|
+
* only in a tooltip") — {@link Button}'s `disabledReasonDisplay`: by default a line
|
|
714
|
+
* under the chip at Large and Extra large and on a touch screen, where a bubble
|
|
715
|
+
* cannot be hovered open, and the tooltip otherwise and inside
|
|
716
|
+
* `CompactControls`. `"line"` / `"tooltip"` force one. See
|
|
717
|
+
* {@link DisabledReasonDisplay}.
|
|
718
|
+
*/
|
|
719
|
+
disabledReasonDisplay?: DisabledReasonDisplay;
|
|
662
720
|
/** This chip COMMITS — pressing it saves. Under a locked
|
|
663
721
|
* {@link WriteLockProvider} it takes the `disabledReason` path with the lock's
|
|
664
722
|
* reason, as {@link Button}'s `commit` does. */
|
|
@@ -699,6 +757,7 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
|
|
|
699
757
|
onFocus,
|
|
700
758
|
snapEdges = false,
|
|
701
759
|
disabledReason: ownDisabledReason,
|
|
760
|
+
disabledReasonDisplay,
|
|
702
761
|
commit,
|
|
703
762
|
...rest
|
|
704
763
|
},
|
|
@@ -726,6 +785,9 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
|
|
|
726
785
|
locked && "cursor-not-allowed opacity-50",
|
|
727
786
|
);
|
|
728
787
|
const snap = snapEdges && !dot;
|
|
788
|
+
// A finger's target at Large (§4): what can be pressed, refused or not — see
|
|
789
|
+
// CHIP_TOUCH_LARGE. A disabled link renders as the inert span below and is none.
|
|
790
|
+
const target = interactive && (!disabled || locked);
|
|
729
791
|
const snapRef = useSnapEdges(snap);
|
|
730
792
|
// The visible pill carries the snap: the whole chip, or the wrapper of a split one
|
|
731
793
|
// (whose body gets the forwarded ref instead).
|
|
@@ -743,6 +805,9 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
|
|
|
743
805
|
radius,
|
|
744
806
|
surface,
|
|
745
807
|
interactive && !disabled && !locked && "cursor-pointer hover:brightness-[0.97] dark:hover:brightness-110",
|
|
808
|
+
// §4: a link or toggle is a 48 px target at Large — a locked one too, since it is
|
|
809
|
+
// still focusable and still says why when pressed.
|
|
810
|
+
target && CHIP_TOUCH_LARGE,
|
|
746
811
|
// An inert dot chip is text in a column: no inset, so it aligns with the header.
|
|
747
812
|
dot && !interactive && "px-0",
|
|
748
813
|
// The under-4px a snap adds is split between the two sides, not stacked at the end.
|
|
@@ -776,14 +841,15 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
|
|
|
776
841
|
) : (
|
|
777
842
|
<Icon className={cn(s.icon, "shrink-0")} aria-hidden />
|
|
778
843
|
))}
|
|
779
|
-
{/* Text truncates
|
|
780
|
-
|
|
781
|
-
text (keksdose live
|
|
844
|
+
{/* Text truncates at Normal and wraps at Large (CHIP_LABEL_WRAP_AT_LARGE). Mixed
|
|
845
|
+
children (an icon and a word) sit in a row instead: as a plain span, the svg —
|
|
846
|
+
a block under Tailwind's preflight — stacked above the text (keksdose live
|
|
847
|
+
#358). */}
|
|
782
848
|
<span
|
|
783
849
|
className={cn(
|
|
784
850
|
"min-w-0",
|
|
785
851
|
typeof children === "string" || typeof children === "number"
|
|
786
|
-
? "truncate"
|
|
852
|
+
? cn("truncate", CHIP_LABEL_WRAP_AT_LARGE)
|
|
787
853
|
: "inline-flex items-center gap-1 [&>svg]:size-[1em] [&>svg]:shrink-0",
|
|
788
854
|
)}
|
|
789
855
|
>
|
|
@@ -821,7 +887,9 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
|
|
|
821
887
|
// Logical margins: the × sits at the END of the pill, which is the left in RTL.
|
|
822
888
|
"-me-0.5 ms-0.5 shrink-0 p-0.5 transition-colors",
|
|
823
889
|
shape === "square" ? "rounded-sm" : "rounded-full",
|
|
824
|
-
|
|
890
|
+
FOCUS_RING,
|
|
891
|
+
// §4: the × is a 48 px target at Large without growing the chip around it.
|
|
892
|
+
REMOVE_HIT_AREA_LARGE,
|
|
825
893
|
!locked && "hover:bg-[var(--bg-active)]",
|
|
826
894
|
locked && "cursor-not-allowed",
|
|
827
895
|
((disabled && !locked) || removeDisabled) && "pointer-events-none",
|
|
@@ -836,7 +904,11 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
|
|
|
836
904
|
|
|
837
905
|
// ── The combined shape: one pill, two interactive siblings inside it.
|
|
838
906
|
const pill = (inner: ReactNode) => (
|
|
839
|
-
<span
|
|
907
|
+
<span
|
|
908
|
+
ref={snap ? snapRef : undefined}
|
|
909
|
+
// The pill is the target's box here (§4): the body inside stretches to its height.
|
|
910
|
+
className={cn(CHIP_PILL, s.tail, radius, surface, target && CHIP_TOUCH_LARGE, snap && "justify-center", className)}
|
|
911
|
+
>
|
|
840
912
|
{inner}
|
|
841
913
|
{remove}
|
|
842
914
|
</span>
|
|
@@ -929,16 +1001,9 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
|
|
|
929
1001
|
const shaped = remove ? pill(button) : button;
|
|
930
1002
|
if (!locked) return shaped;
|
|
931
1003
|
return (
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
<>
|
|
936
|
-
{shaped}
|
|
937
|
-
<span id={reasonId} hidden>
|
|
938
|
-
{disabledReason}
|
|
939
|
-
</span>
|
|
940
|
-
</>
|
|
941
|
-
</Tooltip>
|
|
1004
|
+
<ChipReasonFrame reason={disabledReason} reasonId={reasonId} display={disabledReasonDisplay}>
|
|
1005
|
+
{shaped}
|
|
1006
|
+
</ChipReasonFrame>
|
|
942
1007
|
);
|
|
943
1008
|
}
|
|
944
1009
|
|
|
@@ -961,6 +1026,47 @@ export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
|
|
|
961
1026
|
);
|
|
962
1027
|
});
|
|
963
1028
|
|
|
1029
|
+
/**
|
|
1030
|
+
* A locked chip and its reason (0.32, docs/text-size-harmonization.md §4): a line under
|
|
1031
|
+
* the chip at Large and on touch, else the kit {@link Tooltip} — Button's `ReasonFrame`,
|
|
1032
|
+
* see {@link DisabledReasonDisplay}. A component of its own so only a LOCKED chip asks
|
|
1033
|
+
* the text size and the pointer; the unlocked chips of a filter row subscribe to nothing.
|
|
1034
|
+
*
|
|
1035
|
+
* Tooltip form: the chip in a FRAGMENT, as a locked Button is — the bubble is visual, and
|
|
1036
|
+
* the hidden copy beside it is what the chip (and its ×) is described by. Line form: the
|
|
1037
|
+
* line is that description, under the chip, and no bubble repeats it.
|
|
1038
|
+
*/
|
|
1039
|
+
function ChipReasonFrame({
|
|
1040
|
+
reason,
|
|
1041
|
+
reasonId,
|
|
1042
|
+
display,
|
|
1043
|
+
children,
|
|
1044
|
+
}: {
|
|
1045
|
+
reason: ReactNode;
|
|
1046
|
+
reasonId: string;
|
|
1047
|
+
display: DisabledReasonDisplay | undefined;
|
|
1048
|
+
children: ReactNode;
|
|
1049
|
+
}) {
|
|
1050
|
+
const line = useDisabledReasonLine(display);
|
|
1051
|
+
if (line) {
|
|
1052
|
+
return (
|
|
1053
|
+
<DisabledReasonLine id={reasonId} reason={reason}>
|
|
1054
|
+
{children}
|
|
1055
|
+
</DisabledReasonLine>
|
|
1056
|
+
);
|
|
1057
|
+
}
|
|
1058
|
+
return (
|
|
1059
|
+
<Tooltip label={reason}>
|
|
1060
|
+
<>
|
|
1061
|
+
{children}
|
|
1062
|
+
<span id={reasonId} hidden>
|
|
1063
|
+
{reason}
|
|
1064
|
+
</span>
|
|
1065
|
+
</>
|
|
1066
|
+
</Tooltip>
|
|
1067
|
+
);
|
|
1068
|
+
}
|
|
1069
|
+
|
|
964
1070
|
/** `null`, `false` and `""` are what a `cond && reason` gives on the happy path — no
|
|
965
1071
|
* reason, so no lock. */
|
|
966
1072
|
function hasReason(node: ReactNode): boolean {
|
|
@@ -1304,7 +1410,10 @@ export function ChipInput({
|
|
|
1304
1410
|
aria-label={label ? undefined : (ariaLabelAttr ?? ariaLabel)}
|
|
1305
1411
|
aria-describedby={describedBy || undefined}
|
|
1306
1412
|
aria-invalid={isInvalid || !!rejected || undefined}
|
|
1307
|
-
|
|
1413
|
+
// `w-0` with flex-1: without a width the browser's default input size (20
|
|
1414
|
+
// characters) became the field's minimum width and pushed it past a 240 px
|
|
1415
|
+
// phone at 150 % (0.32's screenshot run).
|
|
1416
|
+
className={cn("w-0 min-w-[6rem] flex-1 bg-transparent py-0.5 text-sm text-[var(--text-primary)] outline-none placeholder:text-[var(--text-placeholder)] disabled:cursor-default", FIELD_TOUCH_TEXT)}
|
|
1308
1417
|
/>
|
|
1309
1418
|
{/* Additions, removals and rejections move no focus, so nothing would announce
|
|
1310
1419
|
them. `sr-only-fixed` rather than `sr-only`: this sits inside a consumer's
|