@eifi1/ui-kit 0.31.1 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +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/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 +74 -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/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 +4 -3
- 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 +32 -0
- package/dist/components/appearance-labels.js +18 -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/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 +47 -21
- package/dist/components/chip.js.map +1 -1
- package/dist/components/choice-card.d.ts +1 -1
- package/dist/components/choice-card.js +8 -7
- 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 +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 +7 -5
- 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 +6 -3
- 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 +9 -5
- 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 +2 -2
- 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 +165 -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 +51 -6
- package/dist/components/settings-fields.js +37 -0
- package/dist/components/settings-fields.js.map +1 -1
- package/dist/components/share-card.d.ts +11 -6
- package/dist/components/share-card.js +2 -0
- 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/swipeable-row.js +2 -1
- 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 +16 -1
- 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-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 +202 -114
- 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/{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-BvdQdbv3.d.ts} +605 -58
- 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 +77 -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 +89 -2
- 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 +84 -2
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +8 -3
- package/dist/i18n/locales/fr.js +86 -2
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +8 -3
- package/dist/i18n/locales/hu.js +86 -2
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +8 -3
- package/dist/i18n/locales/it.js +87 -2
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +8 -3
- package/dist/i18n/locales/zh.js +84 -2
- 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 +75 -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/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 +109 -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 +157 -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.d.ts +8 -3
- package/package.json +1 -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 +224 -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/components/account-chips.tsx +36 -10
- package/src/components/alert-banner.tsx +11 -6
- package/src/components/amount-input.tsx +5 -5
- package/src/components/appearance-labels.ts +40 -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/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 +105 -24
- package/src/components/choice-card.tsx +15 -10
- 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.tsx +160 -43
- package/src/components/date-picker.tsx +12 -9
- 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 +6 -3
- 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 +9 -5
- 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 +2 -2
- package/src/components/pie-chart.tsx +19 -9
- package/src/components/popover.tsx +22 -5
- package/src/components/row-actions.tsx +344 -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 +81 -2
- package/src/components/share-card.tsx +10 -0
- 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/swipeable-row.tsx +2 -1
- 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 +99 -12
- package/src/components/toggle-legend.tsx +53 -8
- package/src/components/translation-review.tsx +10 -5
- package/src/components/tree-view.tsx +3 -2
- package/src/components/treemap.tsx +27 -10
- package/src/components/ui.tsx +331 -145
- package/src/components/user-avatar.tsx +1 -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 +121 -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 +103 -0
- package/src/i18n/kit-labels.tsx +12 -0
- package/src/i18n/locales/es.ts +94 -0
- package/src/i18n/locales/fr.ts +98 -0
- package/src/i18n/locales/hu.ts +96 -0
- package/src/i18n/locales/it.ts +99 -0
- package/src/i18n/locales/zh.ts +90 -0
- package/src/i18n/review.ts +14 -0
- package/src/index.ts +74 -6
- 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 +224 -0
- package/src/theme/palette-presets.ts +24 -4
- package/src/theme/palette-store.ts +6 -1
- package/src/theme/text-size.ts +267 -0
- package/tokens.css +143 -1
|
@@ -70,32 +70,45 @@ export function fromLogPosition(position: number, min: number, max: number, zero
|
|
|
70
70
|
// runs the other way too. Firefox draws the fill itself with `::-moz-range-progress`,
|
|
71
71
|
// which follows the direction on its own.
|
|
72
72
|
//
|
|
73
|
-
// The thumb's `-mt-[
|
|
74
|
-
//
|
|
73
|
+
// The thumb's `-mt-[0.3125rem]` centres a 1rem thumb on a 0.375rem track — half the
|
|
74
|
+
// difference — in rem since 0.32 (§3.2): the thumb and track grow with the text, and the
|
|
75
|
+
// 5px it was left the thumb low of the track at 125 % and further at 150 %. WebKit lays
|
|
76
|
+
// the thumb out from the track's top edge, Firefox centres it, so only one carries the
|
|
77
|
+
// offset.
|
|
75
78
|
//
|
|
76
79
|
// The focus ring goes on the THUMB, not the box: the box is the full width of the
|
|
77
80
|
// row, and a ring round all of it says "this row is focused" rather than "the handle
|
|
78
81
|
// you are about to move is". Offset in the surface colour, because the thumb is
|
|
79
|
-
// --brand and a --brand ring touching it would be invisible.
|
|
82
|
+
// --brand and a --brand ring touching it would be invisible. Its width is the kit's
|
|
83
|
+
// focus frame (`--focus-ring-width`, §5) — spelt out per engine, since `FOCUS_RING`'s
|
|
84
|
+
// classes cannot carry the pseudo-element.
|
|
85
|
+
//
|
|
86
|
+
// At Large the box is the 48 px touch target (§4) — the track stays centred in it, and
|
|
87
|
+
// the marks row below is pulled up by as much (see `MARKS_LARGE`).
|
|
80
88
|
const TRACK = [
|
|
81
|
-
"block h-6 w-full cursor-pointer appearance-none bg-transparent focus:outline-none disabled:cursor-not-allowed",
|
|
89
|
+
"block h-6 large:h-[48px] w-full cursor-pointer appearance-none bg-transparent focus:outline-none disabled:cursor-not-allowed",
|
|
82
90
|
// WebKit / Blink
|
|
83
91
|
"[&::-webkit-slider-runnable-track]:h-1.5 [&::-webkit-slider-runnable-track]:rounded-full",
|
|
84
92
|
"[&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,var(--brand)_var(--slider-fill),var(--border-strong)_var(--slider-fill))]",
|
|
85
93
|
"rtl:[&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_left,var(--brand)_var(--slider-fill),var(--border-strong)_var(--slider-fill))]",
|
|
86
|
-
"[&::-webkit-slider-thumb]:-mt-[
|
|
94
|
+
"[&::-webkit-slider-thumb]:-mt-[0.3125rem] [&::-webkit-slider-thumb]:size-4 [&::-webkit-slider-thumb]:appearance-none",
|
|
87
95
|
"[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-[var(--brand)] [&::-webkit-slider-thumb]:shadow",
|
|
88
|
-
"focus-visible:[&::-webkit-slider-thumb]:ring-
|
|
96
|
+
"focus-visible:[&::-webkit-slider-thumb]:ring-[length:var(--focus-ring-width)] focus-visible:[&::-webkit-slider-thumb]:ring-[var(--brand)]",
|
|
89
97
|
"focus-visible:[&::-webkit-slider-thumb]:ring-offset-2 focus-visible:[&::-webkit-slider-thumb]:ring-offset-[var(--bg-surface)]",
|
|
90
98
|
// Firefox
|
|
91
99
|
"[&::-moz-range-track]:h-1.5 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-[var(--border-strong)]",
|
|
92
100
|
"[&::-moz-range-progress]:h-1.5 [&::-moz-range-progress]:rounded-full [&::-moz-range-progress]:bg-[var(--brand)]",
|
|
93
101
|
"[&::-moz-range-thumb]:size-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-0",
|
|
94
102
|
"[&::-moz-range-thumb]:bg-[var(--brand)] [&::-moz-range-thumb]:shadow",
|
|
95
|
-
"focus-visible:[&::-moz-range-thumb]:ring-
|
|
103
|
+
"focus-visible:[&::-moz-range-thumb]:ring-[length:var(--focus-ring-width)] focus-visible:[&::-moz-range-thumb]:ring-[var(--brand)]",
|
|
96
104
|
"focus-visible:[&::-moz-range-thumb]:ring-offset-2 focus-visible:[&::-moz-range-thumb]:ring-offset-[var(--bg-surface)]",
|
|
97
105
|
].join(" ");
|
|
98
106
|
|
|
107
|
+
// The marks row sits `-mt-1.5` under a 1.5rem box, tucked against the track. In the 48 px
|
|
108
|
+
// box at Large the track's lower edge is `(48px + 0.375rem) / 2` down, so the row comes
|
|
109
|
+
// up by `(48px − 0.375rem) / 2` less the same 0.1875rem gap: `24px − 0.375rem`.
|
|
110
|
+
const MARKS_LARGE = "large:-mt-[calc(24px-0.375rem)]";
|
|
111
|
+
|
|
99
112
|
/** A tick under the track. A bare number is a tick with no words. */
|
|
100
113
|
export interface SliderMark {
|
|
101
114
|
value: number;
|
|
@@ -293,7 +306,7 @@ export const Slider = forwardRef<HTMLInputElement, SliderProps>(function Slider(
|
|
|
293
306
|
// without a `translate` that would need flipping for right-to-left.
|
|
294
307
|
<div
|
|
295
308
|
aria-hidden
|
|
296
|
-
className={cn("relative mx-2 -mt-1.5", hasMarkLabels ? "h-5" : "h-1.5")}
|
|
309
|
+
className={cn("relative mx-2 -mt-1.5", MARKS_LARGE, hasMarkLabels ? "h-5" : "h-1.5")}
|
|
297
310
|
>
|
|
298
311
|
{normalizedMarks.map((m) => (
|
|
299
312
|
<span
|
|
@@ -303,7 +316,7 @@ export const Slider = forwardRef<HTMLInputElement, SliderProps>(function Slider(
|
|
|
303
316
|
>
|
|
304
317
|
<span className="h-1.5 w-px shrink-0 bg-[var(--border-strong)]" />
|
|
305
318
|
{m.label !== undefined && (
|
|
306
|
-
<span className="mt-0.5 select-none whitespace-nowrap text-
|
|
319
|
+
<span className="mt-0.5 select-none whitespace-nowrap text-caption leading-tight text-[var(--text-muted)]">
|
|
307
320
|
{m.label}
|
|
308
321
|
</span>
|
|
309
322
|
)}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef } from "react";
|
|
2
2
|
import { cn } from "../lib/cn";
|
|
3
3
|
import { useKitLabels, useKitLocale } from "../i18n/kit-labels";
|
|
4
|
+
import { useTextSize } from "../theme/text-size";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* The words a sparkline speaks. It has no axes, no tooltip and no legend, so its
|
|
@@ -78,8 +79,12 @@ export interface SparklineProps
|
|
|
78
79
|
/** The series, oldest first. `null`/`undefined`/`NaN` is a GAP — the line breaks
|
|
79
80
|
* there rather than drawing a zero or bridging across the missing point. */
|
|
80
81
|
data: ReadonlyArray<number | null | undefined>;
|
|
81
|
-
/** Width in px. Ignored under `fluid`.
|
|
82
|
+
/** Width in px at Normal. Ignored under `fluid`. The drawn box is this × the text
|
|
83
|
+
* size's scale (0.32, docs/text-size-harmonization.md §3.2): a sparkline stands beside
|
|
84
|
+
* a figure, and a 72 × 24 trend under a 150 % number reads as a speck. The strokes
|
|
85
|
+
* stay px (`non-scaling-stroke`), as every chart's do. */
|
|
82
86
|
width?: number;
|
|
87
|
+
/** Height in px at Normal, × the scale likewise. */
|
|
83
88
|
height?: number;
|
|
84
89
|
/** Fill the container's width instead of a fixed one (the height stays fixed). */
|
|
85
90
|
fluid?: boolean;
|
|
@@ -182,6 +187,7 @@ export function Sparkline({
|
|
|
182
187
|
...rest
|
|
183
188
|
}: SparklineProps) {
|
|
184
189
|
const text = useKitLabels("sparkline", DEFAULT_SPARKLINE_LABELS, labels);
|
|
190
|
+
const { scale } = useTextSize();
|
|
185
191
|
const kitLocale = useKitLocale(locale);
|
|
186
192
|
const format = formatValue ?? defaultFormat(kitLocale);
|
|
187
193
|
|
|
@@ -252,8 +258,10 @@ export function Sparkline({
|
|
|
252
258
|
role="img"
|
|
253
259
|
aria-label={name}
|
|
254
260
|
{...rest}
|
|
255
|
-
|
|
256
|
-
|
|
261
|
+
// The drawing stays in its own units (the viewBox); only the box it is shown in
|
|
262
|
+
// grows, uniformly, so nothing is distorted and the strokes keep their px width.
|
|
263
|
+
width={fluid ? "100%" : W * scale}
|
|
264
|
+
height={H * scale}
|
|
257
265
|
viewBox={`0 0 ${W} ${H}`}
|
|
258
266
|
preserveAspectRatio="none"
|
|
259
267
|
className={cn(fluid ? "block w-full" : "inline-block shrink-0 align-middle", "overflow-visible", className)}
|
|
@@ -5,6 +5,7 @@ import { cn } from "../lib/cn";
|
|
|
5
5
|
import { useKitLabels, useKitLink, useKitLocale } from "../i18n/kit-labels";
|
|
6
6
|
import { pickLinkRenderer, RenderedKitLink } from "./text-link";
|
|
7
7
|
import { Card, FieldHint } from "./ui";
|
|
8
|
+
import { useInlineFacts, useLargeText } from "../hooks/use-large-text";
|
|
8
9
|
import { Sparkline } from "./sparkline";
|
|
9
10
|
import { Tooltip } from "./tooltip";
|
|
10
11
|
// The kit's one placeholder look, so a loading tile and the Skeleton list beside it
|
|
@@ -151,7 +152,11 @@ export interface StatTileProps
|
|
|
151
152
|
/** The explanation behind a "?" beside the label (a {@link FieldHint}) — hidden
|
|
152
153
|
* until asked for, so it is for what a reader MIGHT want to know ("excludes
|
|
153
154
|
* transfers between your own accounts"). For a line everyone should read, use
|
|
154
|
-
* {@link StatTileProps.description} instead.
|
|
155
|
+
* {@link StatTileProps.description} instead.
|
|
156
|
+
*
|
|
157
|
+
* 0.32 (docs/text-size-harmonization.md §4 "No fact only in a tooltip"): at Large
|
|
158
|
+
* and Extra large, and on a touch screen, the words are shown under the label
|
|
159
|
+
* instead of behind the "?". */
|
|
155
160
|
hint?: string;
|
|
156
161
|
/**
|
|
157
162
|
* Keep the label to ONE line, cut with an ellipsis, and show the whole of it in a
|
|
@@ -169,6 +174,9 @@ export interface StatTileProps
|
|
|
169
174
|
* your own `<Tooltip>` for the full text (keksdose's admin metrics-panel.tsx:134
|
|
170
175
|
* does, from before this prop). A wrapped label shows a bubble even when nothing is
|
|
171
176
|
* cut, and nests its trigger inside this one's.
|
|
177
|
+
*
|
|
178
|
+
* Ignored at Large and Extra large (0.32, §4): nothing truncates there, and the full
|
|
179
|
+
* label would otherwise be a fact only in a tooltip.
|
|
172
180
|
*/
|
|
173
181
|
truncateLabel?: boolean;
|
|
174
182
|
/**
|
|
@@ -199,6 +207,15 @@ export interface StatTileProps
|
|
|
199
207
|
* Withheld while `loading`, like the sub-values.
|
|
200
208
|
*/
|
|
201
209
|
projection?: StatTileSubValue;
|
|
210
|
+
/**
|
|
211
|
+
* Smaller figures under the headline, label left and figure right.
|
|
212
|
+
*
|
|
213
|
+
* At Large and Extra large (0.32, §4 "StatTile shows its one big number; the sparkline
|
|
214
|
+
* and sub-values move below"): the tile leads with the headline and its delta, and the
|
|
215
|
+
* projection, these rows and the sparkline follow beneath the description, each row's
|
|
216
|
+
* label over its figure — a 2-up tile at 150 % is 120 px of text wide, and a label
|
|
217
|
+
* beside a figure there squeezed both.
|
|
218
|
+
*/
|
|
202
219
|
subValues?: StatTileSubValue[];
|
|
203
220
|
/** Shorthand for a fluid {@link Sparkline} named after the tile and speaking in
|
|
204
221
|
* the tile's number format. The name is the label's text; see
|
|
@@ -310,6 +327,11 @@ export function StatTile({
|
|
|
310
327
|
...rest
|
|
311
328
|
}: StatTileProps) {
|
|
312
329
|
const text = useKitLabels("statTile", DEFAULT_STAT_TILE_LABELS, labels);
|
|
330
|
+
// §4: at Large the one big number leads and the rest follows below it; the label
|
|
331
|
+
// never truncates; on touch or at Large the hint is words, not a "?".
|
|
332
|
+
const large = useLargeText();
|
|
333
|
+
const inlineHint = useInlineFacts() && !!hint;
|
|
334
|
+
if (large) truncateLabel = false;
|
|
313
335
|
// A loading StatTileGrid puts every tile in it into the loading state and says
|
|
314
336
|
// "Loading…" ONCE for all of them; the tile then keeps its own sentence to itself
|
|
315
337
|
// (see StatTileGrid's `loading`).
|
|
@@ -342,7 +364,9 @@ export function StatTile({
|
|
|
342
364
|
const stretched = cn(
|
|
343
365
|
"text-start uppercase tracking-wide",
|
|
344
366
|
"after:absolute after:inset-0 after:rounded-lg after:content-['']",
|
|
345
|
-
|
|
367
|
+
// The kit's focus frame (0.32, §5), on the overlay — `FOCUS_RING`'s classes cannot
|
|
368
|
+
// carry the `after:`, so its width is spelt out.
|
|
369
|
+
"focus-visible:outline-none focus-visible:after:ring-[length:var(--focus-ring-width)] focus-visible:after:ring-inset focus-visible:after:ring-[var(--brand)]",
|
|
346
370
|
);
|
|
347
371
|
const describedBy = d ? `${valueId} ${deltaId}` : valueId;
|
|
348
372
|
let labelNode: ReactNode = label;
|
|
@@ -417,7 +441,7 @@ export function StatTile({
|
|
|
417
441
|
{!gridLoading && <span className="sr-only">{text.loading}</span>}
|
|
418
442
|
</span>
|
|
419
443
|
) : hasValue ? (
|
|
420
|
-
<span id={valueId} data-private={priv} className={cn(valueClass, valueLabel != null && "ms-auto")}>
|
|
444
|
+
<span id={valueId} data-private={priv} className={cn(valueClass, valueLabel != null && !large && "ms-auto")}>
|
|
421
445
|
{show(value)}
|
|
422
446
|
{unit != null && (
|
|
423
447
|
<span className="ms-1 text-[0.7em] font-medium text-[var(--text-muted)]">{unit}</span>
|
|
@@ -480,7 +504,7 @@ export function StatTile({
|
|
|
480
504
|
</span>
|
|
481
505
|
)}
|
|
482
506
|
{/* Above the stretched link's overlay, so it stays hoverable and focusable. */}
|
|
483
|
-
{hint && <FieldHint label={hint} side="top" className="relative z-10 shrink-0" />}
|
|
507
|
+
{hint && !inlineHint && <FieldHint label={hint} side="top" className="relative z-10 shrink-0" />}
|
|
484
508
|
</div>
|
|
485
509
|
{icon != null && (
|
|
486
510
|
<span aria-hidden className="shrink-0 text-[var(--text-muted)] [&_svg]:size-4">
|
|
@@ -489,10 +513,19 @@ export function StatTile({
|
|
|
489
513
|
)}
|
|
490
514
|
</div>
|
|
491
515
|
|
|
516
|
+
{inlineHint && (
|
|
517
|
+
// §4: the hint as words under the label — the same muted type as `description`,
|
|
518
|
+
// in the reading case of a sentence rather than the label's capitals.
|
|
519
|
+
<p data-slot="stat-tile-hint" className="mt-0.5 text-xs text-[var(--text-muted)]">
|
|
520
|
+
{hint}
|
|
521
|
+
</p>
|
|
522
|
+
)}
|
|
523
|
+
|
|
492
524
|
{valueLabel != null ? (
|
|
493
525
|
// Period-left / value-right, matching the sub-rows below it. flex-wrap lets a
|
|
494
|
-
// too-long amount drop to its own end-aligned line instead of overflowing.
|
|
495
|
-
|
|
526
|
+
// too-long amount drop to its own end-aligned line instead of overflowing. At
|
|
527
|
+
// Large the period goes over the figure, which then has the tile's width.
|
|
528
|
+
<div className={cn("mt-1 flex items-baseline gap-x-1.5", large ? "flex-col items-start" : "flex-wrap")}>
|
|
496
529
|
<span className="shrink-0 text-xs uppercase tracking-wide text-[var(--text-muted)]">{valueLabel}</span>
|
|
497
530
|
{headline}
|
|
498
531
|
</div>
|
|
@@ -500,7 +533,9 @@ export function StatTile({
|
|
|
500
533
|
<div className="mt-1">{headline}</div>
|
|
501
534
|
)}
|
|
502
535
|
|
|
503
|
-
{
|
|
536
|
+
{/* At Large the delta and description follow the figure at once, and the
|
|
537
|
+
projection moves down with the other figures (see `subValues`). */}
|
|
538
|
+
{!large && !loading && projection && (
|
|
504
539
|
<dl className="mt-0.5">
|
|
505
540
|
<FigureRow figure={projection} tileTone={tone} show={show} priv={priv} />
|
|
506
541
|
</dl>
|
|
@@ -508,16 +543,25 @@ export function StatTile({
|
|
|
508
543
|
|
|
509
544
|
{deltaNode}
|
|
510
545
|
{description != null && <div className="mt-1 text-xs text-[var(--text-muted)]">{description}</div>}
|
|
511
|
-
{graphic && <div className="mt-2">{graphic}</div>}
|
|
546
|
+
{!large && graphic && <div className="mt-2">{graphic}</div>}
|
|
512
547
|
|
|
513
|
-
{!loading && subValues && subValues.length > 0 && (
|
|
514
|
-
<dl className="mt-1.5 space-y-0.5">
|
|
515
|
-
{
|
|
516
|
-
<FigureRow
|
|
548
|
+
{!loading && ((large && projection) || (subValues && subValues.length > 0)) && (
|
|
549
|
+
<dl data-slot="stat-tile-figures" className={cn("mt-1.5", large ? "space-y-1.5" : "space-y-0.5")}>
|
|
550
|
+
{large && projection && (
|
|
551
|
+
<FigureRow figure={projection} tileTone={tone} show={show} priv={priv} stacked />
|
|
552
|
+
)}
|
|
553
|
+
{subValues?.map((sv, i) => (
|
|
554
|
+
<FigureRow key={i} figure={sv} tileTone={tone} show={show} priv={priv} stacked={large} />
|
|
517
555
|
))}
|
|
518
556
|
</dl>
|
|
519
557
|
)}
|
|
520
558
|
|
|
559
|
+
{large && graphic && (
|
|
560
|
+
<div data-slot="stat-tile-graphic" className="mt-2">
|
|
561
|
+
{graphic}
|
|
562
|
+
</div>
|
|
563
|
+
)}
|
|
564
|
+
|
|
521
565
|
{footer != null && <div className="mt-2">{footer}</div>}
|
|
522
566
|
</Card>
|
|
523
567
|
);
|
|
@@ -529,11 +573,14 @@ function FigureRow({
|
|
|
529
573
|
tileTone,
|
|
530
574
|
show,
|
|
531
575
|
priv,
|
|
576
|
+
stacked = false,
|
|
532
577
|
}: {
|
|
533
578
|
figure: StatTileSubValue;
|
|
534
579
|
tileTone: StatTileTone;
|
|
535
580
|
show: (v: ReactNode) => ReactNode;
|
|
536
581
|
priv: "" | undefined;
|
|
582
|
+
/** The label over the figure (Large, §4) instead of beside it. */
|
|
583
|
+
stacked?: boolean;
|
|
537
584
|
}) {
|
|
538
585
|
const own = figure.tone ?? (tileTone === "neutral" ? undefined : tileTone);
|
|
539
586
|
const svTone = own === "none" ? undefined : own;
|
|
@@ -543,11 +590,20 @@ function FigureRow({
|
|
|
543
590
|
// the period it belongs to. Now the label breaks within itself and the amount stays
|
|
544
591
|
// on the label's first line, end-aligned like every other row.
|
|
545
592
|
return (
|
|
546
|
-
<div
|
|
593
|
+
<div
|
|
594
|
+
className={cn(
|
|
595
|
+
"flex text-xs tabular-nums text-[var(--text-muted)]",
|
|
596
|
+
stacked ? "flex-col items-start" : "items-baseline gap-x-2",
|
|
597
|
+
)}
|
|
598
|
+
>
|
|
547
599
|
<dt className="min-w-0 uppercase tracking-wide [overflow-wrap:anywhere]">{figure.label}</dt>
|
|
548
600
|
<dd
|
|
549
601
|
data-private={priv}
|
|
550
|
-
className={cn(
|
|
602
|
+
className={cn(
|
|
603
|
+
"shrink-0 whitespace-nowrap",
|
|
604
|
+
!stacked && "ms-auto",
|
|
605
|
+
svTone && [toneClass(svTone, figure.value), "opacity-75"],
|
|
606
|
+
)}
|
|
551
607
|
>
|
|
552
608
|
{show(figure.value)}
|
|
553
609
|
</dd>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from "react";
|
|
2
2
|
import type { ReactNode } from "react";
|
|
3
3
|
import { cn } from "../lib/cn";
|
|
4
|
+
import { FOCUS_RING } from "./focus-ring";
|
|
4
5
|
import { useRowSwipe, type SwipeStage } from "../hooks/use-row-swipe";
|
|
5
6
|
import { DEFAULT_SWIPEABLE_ROW_LABELS, useKitLabels } from "../i18n/kit-labels";
|
|
6
7
|
|
|
@@ -270,7 +271,7 @@ export function SwipeableRow({
|
|
|
270
271
|
className={cn(
|
|
271
272
|
"sr-only whitespace-nowrap rounded-md border border-[var(--border)] bg-[var(--bg-surface)] px-2 py-1 text-xs font-medium text-[var(--text-primary)] shadow-sm",
|
|
272
273
|
"focus:not-sr-only focus:pointer-events-auto focus:inline-flex focus:items-center focus:gap-1.5",
|
|
273
|
-
|
|
274
|
+
FOCUS_RING,
|
|
274
275
|
)}
|
|
275
276
|
>
|
|
276
277
|
{/* The label is the button's accessible name, so the caller's icon is
|
|
@@ -2,7 +2,14 @@ import { forwardRef, useId } from "react";
|
|
|
2
2
|
import type { ChangeEvent, InputHTMLAttributes, ReactNode } from "react";
|
|
3
3
|
import { cn } from "../lib/cn";
|
|
4
4
|
import { hasMessage, mergeDescribedBy } from "./choice-parts";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
DISABLED_REASON_LINE_CLASS,
|
|
7
|
+
LockedReason,
|
|
8
|
+
useDisabledReasonLine,
|
|
9
|
+
useLockReason,
|
|
10
|
+
type DisabledReasonDisplay,
|
|
11
|
+
} from "./field-parts";
|
|
12
|
+
import { FOCUS_RING } from "./focus-ring";
|
|
6
13
|
|
|
7
14
|
/**
|
|
8
15
|
* An on/off switch that is still `<input type="checkbox">`, with `role="switch"`.
|
|
@@ -14,16 +21,20 @@ import { LockedReason, useLockReason } from "./field-parts";
|
|
|
14
21
|
* the moment it is flipped; a choice that waits for a Save button is a checkbox.
|
|
15
22
|
*/
|
|
16
23
|
|
|
17
|
-
/** Geometry per size. The thumb sits `
|
|
18
|
-
* checked offset is `track width − thumb −
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
24
|
+
/** Geometry per size. The thumb sits `start-0.5` (0.125rem, 2 px at Normal) in from
|
|
25
|
+
* each end of the track, so its checked offset is `track width − thumb − 0.125rem`.
|
|
26
|
+
* All of it in rem since 0.32 (docs/text-size-harmonization.md §3.2, §4): the track
|
|
27
|
+
* and thumb already grew with the text, and a checked offset left in px (14 / 18) put
|
|
28
|
+
* the thumb short of the end at 125 % and in the middle at 150 %. `start-*`, never
|
|
29
|
+
* `left-*` or a `translate-x`: an inline-start offset follows the writing direction,
|
|
30
|
+
* so in a right-to-left form the thumb travels right-to-left with no `rtl:` override
|
|
31
|
+
* to keep in step. */
|
|
22
32
|
const SIZES = {
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
// 1.75 × 1rem track, 0.75rem thumb (28×16 / 12 at Normal): the dense setting rows in
|
|
34
|
+
// Kastlan's tables. Checked: 1.75 − 0.75 − 0.125 = 0.875rem.
|
|
35
|
+
sm: { track: "h-4 w-7", thumb: "size-3 peer-checked:start-3.5" },
|
|
36
|
+
// 2.25 × 1.25rem track, 1rem thumb (36×20 / 16). Checked: 2.25 − 1 − 0.125 = 1.125rem.
|
|
37
|
+
md: { track: "h-5 w-9", thumb: "size-4 peer-checked:start-4.5" },
|
|
27
38
|
} as const;
|
|
28
39
|
|
|
29
40
|
export type SwitchSize = keyof typeof SIZES;
|
|
@@ -38,7 +49,8 @@ export type SwitchSize = keyof typeof SIZES;
|
|
|
38
49
|
const TRACK =
|
|
39
50
|
"peer block shrink-0 cursor-pointer appearance-none rounded-full bg-[var(--border-strong)] transition-colors " +
|
|
40
51
|
"checked:bg-[var(--brand)] " +
|
|
41
|
-
|
|
52
|
+
// The kit's focus frame (§5), stood off the track so it never merges with the fill.
|
|
53
|
+
`focus:outline-none ${FOCUS_RING} focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--bg-surface)] ` +
|
|
42
54
|
"disabled:cursor-not-allowed";
|
|
43
55
|
|
|
44
56
|
// The thumb, laid over the input and ignoring the pointer so every click still reaches
|
|
@@ -93,6 +105,13 @@ export interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>,
|
|
|
93
105
|
* switch anew (it moves in or out of the Tooltip), as a locked Button is.
|
|
94
106
|
*/
|
|
95
107
|
disabledReason?: ReactNode;
|
|
108
|
+
/**
|
|
109
|
+
* Where `disabledReason` shows (0.32, §4 "No fact only in a tooltip"): by default, at
|
|
110
|
+
* Large and on a touch screen, as a line in the words column under the description (a
|
|
111
|
+
* bare switch: under the track), and in the tooltip otherwise. See
|
|
112
|
+
* {@link DisabledReasonDisplay}.
|
|
113
|
+
*/
|
|
114
|
+
disabledReasonDisplay?: DisabledReasonDisplay;
|
|
96
115
|
/**
|
|
97
116
|
* This switch COMMITS — flipping it saves. Under a locked {@link WriteLockProvider} it
|
|
98
117
|
* is locked the `disabledReason` way with the lock's reason (which wins over its
|
|
@@ -122,6 +141,7 @@ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(function Switch(
|
|
|
122
141
|
disabled,
|
|
123
142
|
required,
|
|
124
143
|
disabledReason,
|
|
144
|
+
disabledReasonDisplay,
|
|
125
145
|
commit,
|
|
126
146
|
onClick,
|
|
127
147
|
...rest
|
|
@@ -132,6 +152,7 @@ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(function Switch(
|
|
|
132
152
|
const inputId = id ?? generated;
|
|
133
153
|
const lock = useLockReason(commit, disabledReason);
|
|
134
154
|
const locked = lock.locked;
|
|
155
|
+
const reasonLine = useDisabledReasonLine(disabledReasonDisplay);
|
|
135
156
|
// Locked is disabled the focusable way — the row fades and the words stop inviting a
|
|
136
157
|
// click, as for `disabled`.
|
|
137
158
|
const looksDisabled = Boolean(disabled) || locked;
|
|
@@ -177,21 +198,28 @@ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(function Switch(
|
|
|
177
198
|
</span>
|
|
178
199
|
);
|
|
179
200
|
// The Tooltip goes round the track, not the row — the row is the caller's layout. A
|
|
180
|
-
// bare switch hands its `className` to the wrapper, then the outermost element.
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
201
|
+
// bare switch hands its `className` to the wrapper, then the outermost element. With
|
|
202
|
+
// words beside it, the reason LINE goes under them instead (below), so the track
|
|
203
|
+
// stays where the row puts it.
|
|
204
|
+
const lineInWords = locked && reasonLine && !bare;
|
|
205
|
+
const control =
|
|
206
|
+
locked && !lineInWords ? (
|
|
207
|
+
<LockedReason lock={lock} line={reasonLine} className={cn("shrink-0", bare && className)}>
|
|
208
|
+
{track}
|
|
209
|
+
</LockedReason>
|
|
210
|
+
) : (
|
|
211
|
+
track
|
|
212
|
+
);
|
|
188
213
|
|
|
189
214
|
if (bare) return control;
|
|
190
215
|
|
|
191
|
-
// The switch's cell is one label line tall (text-sm,
|
|
216
|
+
// The switch's cell is one label line tall (text-sm, 1.25rem) so it centres on the
|
|
192
217
|
// FIRST line of a label that wraps, and a description underneath does not drag it
|
|
193
218
|
// down to the middle of the paragraph.
|
|
194
|
-
|
|
219
|
+
// With the reason line in the words, the row's fade moves onto its parts: the line is
|
|
220
|
+
// the one thing on the row still to be read, and at 60 % it would not be.
|
|
221
|
+
const dimParts = lineInWords;
|
|
222
|
+
const cell = <span className={cn("flex h-5 shrink-0 items-center", dimParts && "opacity-60")}>{control}</span>;
|
|
195
223
|
const words = (
|
|
196
224
|
<span className="min-w-0 flex-1">
|
|
197
225
|
{label !== undefined && (
|
|
@@ -200,6 +228,7 @@ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(function Switch(
|
|
|
200
228
|
className={cn(
|
|
201
229
|
"block text-sm leading-5 text-[var(--text-primary)]",
|
|
202
230
|
looksDisabled ? "cursor-not-allowed" : "cursor-pointer select-none",
|
|
231
|
+
dimParts && "opacity-60",
|
|
203
232
|
)}
|
|
204
233
|
>
|
|
205
234
|
{label}
|
|
@@ -211,15 +240,20 @@ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(function Switch(
|
|
|
211
240
|
</label>
|
|
212
241
|
)}
|
|
213
242
|
{showDescription && (
|
|
214
|
-
<span id={descriptionId} className="mt-0.5 block text-xs text-[var(--text-muted)]">
|
|
243
|
+
<span id={descriptionId} className={cn("mt-0.5 block text-xs text-[var(--text-muted)]", dimParts && "opacity-60")}>
|
|
215
244
|
{description}
|
|
216
245
|
</span>
|
|
217
246
|
)}
|
|
247
|
+
{lineInWords && (
|
|
248
|
+
<span id={lock.reasonId} className={DISABLED_REASON_LINE_CLASS}>
|
|
249
|
+
{lock.reason}
|
|
250
|
+
</span>
|
|
251
|
+
)}
|
|
218
252
|
</span>
|
|
219
253
|
);
|
|
220
254
|
|
|
221
255
|
return (
|
|
222
|
-
<div className={cn("flex items-start gap-3", looksDisabled && "opacity-60", className)}>
|
|
256
|
+
<div className={cn("flex items-start gap-3", looksDisabled && !dimParts && "opacity-60", className)}>
|
|
223
257
|
{switchPosition === "end" ? (
|
|
224
258
|
<>
|
|
225
259
|
{words}
|
package/src/components/table.tsx
CHANGED
|
@@ -242,7 +242,7 @@ const STACK_PHONE_CLASSES = cn(
|
|
|
242
242
|
"max-sm:[&_tbody_td]:block max-sm:[&_tbody_td]:px-0 max-sm:[&_tbody_td]:py-0.5 max-sm:[&_tbody_td]:text-start",
|
|
243
243
|
"max-sm:[&_tfoot_td]:block max-sm:[&_tfoot_td]:px-0 max-sm:[&_tfoot_td]:py-0.5",
|
|
244
244
|
"max-sm:[&_tbody_td:first-child]:font-medium",
|
|
245
|
-
"max-sm:[&_td[data-label]]:before:block max-sm:[&_td[data-label]]:before:text-
|
|
245
|
+
"max-sm:[&_td[data-label]]:before:block max-sm:[&_td[data-label]]:before:text-caption max-sm:[&_td[data-label]]:before:font-medium max-sm:[&_td[data-label]]:before:text-[var(--text-muted)] max-sm:[&_td[data-label]]:before:content-[attr(data-label)]",
|
|
246
246
|
);
|
|
247
247
|
|
|
248
248
|
/**
|
|
@@ -353,7 +353,7 @@ export function Table({
|
|
|
353
353
|
// rounded corners.
|
|
354
354
|
framed && "rounded-md border border-[var(--border)]",
|
|
355
355
|
THIN_SCROLLBAR_CLASS,
|
|
356
|
-
"focus-visible:outline-
|
|
356
|
+
"focus-visible:outline-[length:var(--focus-ring-width)] focus-visible:-outline-offset-2 focus-visible:outline-[var(--brand)]",
|
|
357
357
|
wrapperClassName,
|
|
358
358
|
)}
|
|
359
359
|
>
|
|
@@ -288,7 +288,7 @@ export function TextLink({
|
|
|
288
288
|
|
|
289
289
|
const look = cn(
|
|
290
290
|
"rounded-sm underline-offset-2 transition-colors",
|
|
291
|
-
"focus-visible:outline-
|
|
291
|
+
"focus-visible:outline-[length:var(--focus-ring-width)] focus-visible:outline-offset-2 focus-visible:outline-[var(--brand)]",
|
|
292
292
|
TONE[tone],
|
|
293
293
|
UNDERLINE[underline],
|
|
294
294
|
ariaCurrent && "font-semibold",
|
package/src/components/text.tsx
CHANGED
|
@@ -35,10 +35,14 @@ export type SectionLabelSize = "xs" | "md" | "sm";
|
|
|
35
35
|
* reached as a string than wrapped in a component that only takes a `className`. The
|
|
36
36
|
* uppercase is CSS, so a screen reader reads the text as written: write it in normal
|
|
37
37
|
* case.
|
|
38
|
+
*
|
|
39
|
+
* The sizes are the kit's named rem steps since 0.32 (`text-micro` 0.625rem,
|
|
40
|
+
* `text-caption` 0.6875rem — 10 and 11 px at Normal), so a label grows with the text
|
|
41
|
+
* size like everything around it (docs/text-size-harmonization.md §3.2).
|
|
38
42
|
*/
|
|
39
43
|
export const SECTION_LABEL_CLASS: Record<SectionLabelSize, string> = {
|
|
40
|
-
xs: "text-
|
|
41
|
-
md: "text-
|
|
44
|
+
xs: "text-micro font-semibold uppercase tracking-wide text-[var(--text-muted)]",
|
|
45
|
+
md: "text-caption font-semibold uppercase tracking-wide text-[var(--text-muted)]",
|
|
42
46
|
sm: "text-xs font-semibold uppercase tracking-wide text-[var(--text-muted)]",
|
|
43
47
|
};
|
|
44
48
|
|
|
@@ -61,8 +65,8 @@ export type SectionLabelVariant = "plain" | "band";
|
|
|
61
65
|
* a font-size arbitrary `text-` value from a colour one. (Not spelt out as class
|
|
62
66
|
* names here: Tailwind scans comments, and a literal one broke the showcase CSS.) */
|
|
63
67
|
const SECTION_LABEL_BAND_CLASS: Record<SectionLabelSize, string> = {
|
|
64
|
-
xs: "text-
|
|
65
|
-
md: "text-
|
|
68
|
+
xs: "text-micro",
|
|
69
|
+
md: "text-caption",
|
|
66
70
|
sm: "text-xs",
|
|
67
71
|
};
|
|
68
72
|
const BAND =
|
|
@@ -112,14 +116,15 @@ export function SectionLabel({
|
|
|
112
116
|
/* ── Caption ──────────────────────────────────────────────────────────────── */
|
|
113
117
|
|
|
114
118
|
/**
|
|
115
|
-
* The caption type as a class string:
|
|
119
|
+
* The caption type as a class string: `text-caption` (0.6875rem, 11 px at Normal, §3.2),
|
|
120
|
+
* snug, muted. lenkbank's `CAPTION`
|
|
116
121
|
* (shared/ui/caption.ts:23) — written out 31 times before it was a constant — as a
|
|
117
122
|
* token colour rather than `slate-500 dark:slate-400`, so it follows the palette.
|
|
118
123
|
* Exported for the same reason lenkbank's is a string: every caller positions it
|
|
119
124
|
* differently (`mt-1`, `self-end pb-2`, `border-t`), and what must be one thing is the
|
|
120
125
|
* type, not the box.
|
|
121
126
|
*/
|
|
122
|
-
export const CAPTION_CLASS = "text-
|
|
127
|
+
export const CAPTION_CLASS = "text-caption leading-snug text-[var(--text-muted)]";
|
|
123
128
|
|
|
124
129
|
export interface CaptionProps extends ComponentPropsWithoutRef<"p"> {
|
|
125
130
|
/** Default `p`; `span` for a caption inside a line of other content. */
|
|
@@ -2,6 +2,7 @@ import { useId, useRef } from "react";
|
|
|
2
2
|
import type { KeyboardEvent, ReactNode } from "react";
|
|
3
3
|
import { Ban, Check } from "lucide-react";
|
|
4
4
|
import { cn } from "../lib/cn";
|
|
5
|
+
import { FOCUS_RING } from "./focus-ring";
|
|
5
6
|
import { horizontalStep } from "../lib/direction";
|
|
6
7
|
import { Tooltip } from "./tooltip";
|
|
7
8
|
|
|
@@ -133,7 +134,9 @@ export interface TileRadioGroupProps<T extends string> {
|
|
|
133
134
|
*/
|
|
134
135
|
const TILE_BASE =
|
|
135
136
|
"relative inline-flex shrink-0 items-center justify-center rounded-md border transition-colors " +
|
|
136
|
-
"focus:outline-none
|
|
137
|
+
"focus:outline-none " +
|
|
138
|
+
FOCUS_RING +
|
|
139
|
+
" focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--bg-surface)] " +
|
|
137
140
|
"disabled:cursor-not-allowed disabled:opacity-50";
|
|
138
141
|
const TILE_IDLE =
|
|
139
142
|
"border-[var(--border)] bg-[var(--bg-surface)] hover:border-[var(--border-strong)] hover:bg-[var(--bg-hover)]";
|
package/src/components/toast.tsx
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { useEffect, useState, useSyncExternalStore } from "react";
|
|
2
2
|
import type { CSSProperties, MouseEvent, ReactElement, ReactNode } from "react";
|
|
3
3
|
import { useKitLabels } from "../i18n/kit-labels";
|
|
4
|
-
import {
|
|
5
|
-
import { PHONE_QUERY } from "./ui";
|
|
4
|
+
import { usePhoneLayout } from "../hooks/use-breakpoint";
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* The kit's toast layer: a `toast` API and a `<Toaster>`, over sonner.
|
|
@@ -298,7 +297,9 @@ export type ToastPosition =
|
|
|
298
297
|
|
|
299
298
|
export type ToastSwipeDirection = "top" | "right" | "bottom" | "left";
|
|
300
299
|
|
|
301
|
-
/** sonner's offset: one value for every edge, or per edge. Numbers are px
|
|
300
|
+
/** sonner's offset: one value for every edge, or per edge. Numbers are px, which do not
|
|
301
|
+
* follow the text size — prefer a CSS length (rem, or a `calc()` on
|
|
302
|
+
* {@link TOASTER_OFFSET_TOP} / {@link TOASTER_OFFSET_BOTTOM}). */
|
|
302
303
|
export type ToasterOffset =
|
|
303
304
|
| string
|
|
304
305
|
| number
|
|
@@ -397,6 +398,22 @@ function subscribeDocumentTheme(onChange: () => void): () => void {
|
|
|
397
398
|
|
|
398
399
|
const px = (v: string | number) => (typeof v === "number" ? `${v}px` : v);
|
|
399
400
|
|
|
401
|
+
/**
|
|
402
|
+
* The Toaster's default distance from the top edge (desktop), as a CSS length (0.32,
|
|
403
|
+
* docs/text-size-harmonization.md §10.11): below a 3rem top bar with 1rem to spare, and
|
|
404
|
+
* the safe area. In rem, so it moves with the text size along with the top bar — an
|
|
405
|
+
* app's `offset={{ top: 64 }}` (keksdose) did not. Pass it, or a `calc()` built on it,
|
|
406
|
+
* instead of a px number.
|
|
407
|
+
*/
|
|
408
|
+
export const TOASTER_OFFSET_TOP = "calc(env(safe-area-inset-top, 0px) + 4rem)";
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* The Toaster's default distance from the bottom edge (phone), as a CSS length: above
|
|
412
|
+
* AppShell's measured bottom nav (`--app-nav-h`) or the home indicator, whichever is
|
|
413
|
+
* taller, with 0.75rem to spare.
|
|
414
|
+
*/
|
|
415
|
+
export const TOASTER_OFFSET_BOTTOM = "calc(max(var(--app-nav-h, 0px), env(safe-area-inset-bottom, 0px)) + 0.75rem)";
|
|
416
|
+
|
|
400
417
|
/**
|
|
401
418
|
* Where the toasts appear, with the kit's defaults — mount ONE, near the root and
|
|
402
419
|
* inside `<UiKitProvider>` (it reads the `toast` labels) and inside the router if a
|
|
@@ -480,14 +497,17 @@ export function Toaster({
|
|
|
480
497
|
}, [dismissOnMiddleClick, mod]);
|
|
481
498
|
|
|
482
499
|
const documentTheme = useSyncExternalStore(subscribeDocumentTheme, readDocumentTheme, () => "light" as const);
|
|
483
|
-
const phone =
|
|
500
|
+
const phone = usePhoneLayout();
|
|
484
501
|
const resolved: ToastPosition = position ?? (phone ? "bottom-center" : "top-center");
|
|
485
502
|
|
|
486
503
|
// Above the bottom nav and the home indicator: whichever is taller, since the nav
|
|
487
504
|
// already pads itself by the safe area (the same sum BulkActionBar floats on).
|
|
488
|
-
const bottom =
|
|
489
|
-
|
|
490
|
-
|
|
505
|
+
const bottom =
|
|
506
|
+
navOffset === undefined
|
|
507
|
+
? TOASTER_OFFSET_BOTTOM
|
|
508
|
+
: `calc(max(${px(navOffset)}, env(safe-area-inset-bottom, 0px)) + 0.75rem)`;
|
|
509
|
+
// Below a 3rem TopBar with the same 1rem clearance.
|
|
510
|
+
const top = TOASTER_OFFSET_TOP;
|
|
491
511
|
const computed = resolved.startsWith("bottom") ? { bottom } : { top };
|
|
492
512
|
|
|
493
513
|
if (!mod) return null;
|