@godxjp/ui 19.0.0 → 19.2.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 +25 -128
- package/dist/app/app-provider.d.ts +1 -1
- package/dist/app/app-provider.js +3 -0
- package/dist/app/theme-axes.d.ts +4 -15
- package/dist/app/timezones.d.ts +1 -4
- package/dist/components/charts/area-chart.d.ts +2 -3
- package/dist/components/charts/bar-chart.d.ts +2 -3
- package/dist/components/charts/chart-frame.d.ts +7 -16
- package/dist/components/charts/chart-summary.d.ts +2 -2
- package/dist/components/charts/compact-bar-trend.d.ts +9 -24
- package/dist/components/charts/index.d.ts +1 -6
- package/dist/components/data-display/badge.d.ts +2 -12
- package/dist/components/data-display/card.d.ts +21 -41
- package/dist/components/data-display/carousel.d.ts +1 -2
- package/dist/components/data-display/code-block.d.ts +4 -0
- package/dist/components/data-display/code-block.js +24 -0
- package/dist/components/data-display/data-table.d.ts +15 -37
- package/dist/components/data-display/data-table.js +1 -3
- package/dist/components/data-display/descriptions.d.ts +2 -6
- package/dist/components/data-display/descriptions.js +0 -2
- package/dist/components/data-display/index.d.ts +4 -0
- package/dist/components/data-display/index.js +4 -0
- package/dist/components/data-display/list-row.d.ts +3 -22
- package/dist/components/data-display/permission-matrix.d.ts +7 -20
- package/dist/components/data-display/progress.d.ts +1 -1
- package/dist/components/data-display/prose.d.ts +4 -0
- package/dist/components/data-display/prose.js +20 -0
- package/dist/components/data-display/service-launcher-card.d.ts +3 -10
- package/dist/components/data-display/table.d.ts +20 -80
- package/dist/components/data-display/table.js +0 -3
- package/dist/components/data-display/timeline.d.ts +3 -5
- package/dist/components/data-entry/branch-scope-picker.d.ts +2 -19
- package/dist/components/data-entry/branch-scope-picker.js +0 -1
- package/dist/components/data-entry/calendar.d.ts +3 -2
- package/dist/components/data-entry/calendar.js +58 -3
- package/dist/components/data-entry/cascader.js +3 -1
- package/dist/components/data-entry/checkbox-group.js +12 -5
- package/dist/components/data-entry/checkbox.js +30 -21
- package/dist/components/data-entry/command-palette.d.ts +8 -22
- package/dist/components/data-entry/date-picker.d.ts +4 -5
- package/dist/components/data-entry/date-picker.js +12 -3
- package/dist/components/data-entry/date-range-picker.d.ts +1 -1
- package/dist/components/data-entry/date-range-picker.js +17 -6
- package/dist/components/data-entry/form-errors.d.ts +7 -18
- package/dist/components/data-entry/form-field.d.ts +1 -1
- package/dist/components/data-entry/form-field.js +15 -6
- package/dist/components/data-entry/form.d.ts +1 -9
- package/dist/components/data-entry/input.d.ts +16 -14
- package/dist/components/data-entry/input.js +13 -3
- package/dist/components/data-entry/month-picker.js +6 -4
- package/dist/components/data-entry/month-range-picker.d.ts +4 -6
- package/dist/components/data-entry/month-range-picker.js +11 -5
- package/dist/components/data-entry/number-input.d.ts +1 -5
- package/dist/components/data-entry/number-input.js +1 -0
- package/dist/components/data-entry/radio.js +19 -6
- package/dist/components/data-entry/search-select.d.ts +3 -5
- package/dist/components/data-entry/search-select.js +8 -2
- package/dist/components/data-entry/select.d.ts +15 -2
- package/dist/components/data-entry/select.js +57 -10
- package/dist/components/data-entry/switch.js +9 -2
- package/dist/components/data-entry/textarea.d.ts +10 -16
- package/dist/components/data-entry/textarea.js +8 -1
- package/dist/components/data-entry/time-picker.d.ts +3 -5
- package/dist/components/data-entry/tree-select.js +3 -1
- package/dist/components/data-entry/upload-types.d.ts +1 -5
- package/dist/components/data-entry/use-upload-draft.d.ts +0 -4
- package/dist/components/feedback/dialog.d.ts +6 -15
- package/dist/components/feedback/overlay-header-tone.d.ts +1 -1
- package/dist/components/feedback/sheet.d.ts +3 -10
- package/dist/components/feedback/sheet.js +1 -1
- package/dist/components/feedback/sonner.js +2 -3
- package/dist/components/general/activity.d.ts +4 -30
- package/dist/components/general/button.js +1 -10
- package/dist/components/general/logo.d.ts +6 -28
- package/dist/components/general/reveal.d.ts +3 -9
- package/dist/components/general/typography.d.ts +1 -3
- package/dist/components/layout/account-chip.d.ts +8 -0
- package/dist/components/layout/account-chip.js +45 -0
- package/dist/components/layout/auth-divider.d.ts +2 -9
- package/dist/components/layout/auth-shell.d.ts +1 -14
- package/dist/components/layout/breadcrumb.d.ts +1 -5
- package/dist/components/layout/centered-shell.d.ts +4 -18
- package/dist/components/layout/error-surface.d.ts +11 -28
- package/dist/components/layout/error-surface.js +4 -1
- package/dist/components/layout/index.d.ts +2 -0
- package/dist/components/layout/index.js +2 -0
- package/dist/components/layout/legal-document-shell.d.ts +5 -28
- package/dist/components/layout/master-detail.d.ts +2 -18
- package/dist/components/layout/page-container.js +0 -1
- package/dist/components/layout/responsive-grid.d.ts +6 -1
- package/dist/components/layout/responsive-grid.js +9 -2
- package/dist/components/layout/service-role-panel.d.ts +7 -19
- package/dist/components/layout/sidebar.d.ts +5 -27
- package/dist/components/layout/sidebar.js +0 -1
- package/dist/components/layout/split-pane.d.ts +0 -7
- package/dist/components/layout/topbar.d.ts +1 -14
- package/dist/components/navigation/app-setting-picker.js +1 -3
- package/dist/components/navigation/filter-bar.d.ts +1 -6
- package/dist/components/navigation/pagination-utils.d.ts +2 -12
- package/dist/components/navigation/tabs-scroll.d.ts +2 -36
- package/dist/components/navigation/tabs.js +4 -8
- package/dist/components/query/data-state.d.ts +2 -2
- package/dist/components/ui/credential-reveal.d.ts +1 -4
- package/dist/components/ui/hover-card.d.ts +1 -2
- package/dist/components/ui/separator.d.ts +2 -15
- package/dist/components/ui/toggle-group.d.ts +1 -5
- package/dist/components/ui/toggle.d.ts +6 -31
- package/dist/email/brand-mark.d.ts +6 -34
- package/dist/email/color.d.ts +7 -17
- package/dist/email/geometry.d.ts +4 -8
- package/dist/email/index.d.ts +4 -48
- package/dist/email/inline-style.d.ts +3 -9
- package/dist/email/urgency.d.ts +2 -7
- package/dist/form/form-context.d.ts +2 -5
- package/dist/form/form-root.d.ts +1 -2
- package/dist/i18n/messages/en.json +4 -0
- package/dist/i18n/messages/ja.json +4 -0
- package/dist/i18n/messages/vi.json +4 -0
- package/dist/inertia/index.d.ts +2 -10
- package/dist/lib/control-styles.d.ts +10 -21
- package/dist/lib/control-styles.js +4 -6
- package/dist/lib/datetime/format-date.d.ts +1 -4
- package/dist/lib/field-a11y.d.ts +31 -36
- package/dist/lib/field-a11y.js +16 -2
- package/dist/lib/format.d.ts +4 -8
- package/dist/lib/hooks.d.ts +6 -12
- package/dist/lib/permission-grid.d.ts +3 -18
- package/dist/lib/query-error.d.ts +3 -3
- package/dist/props/components/app.prop.d.ts +19 -27
- package/dist/props/components/charts.prop.d.ts +2 -3
- package/dist/props/components/data-display.prop.d.ts +48 -72
- package/dist/props/components/data-entry.prop.d.ts +41 -30
- package/dist/props/components/form.prop.d.ts +2 -6
- package/dist/props/components/general.prop.d.ts +11 -27
- package/dist/props/components/layout.prop.d.ts +89 -260
- package/dist/props/components/navigation.prop.d.ts +27 -42
- package/dist/props/registry.d.ts +31 -0
- package/dist/props/registry.js +33 -0
- package/dist/props/vocabulary/data.prop.d.ts +18 -49
- package/dist/props/vocabulary/index.d.ts +1 -1
- package/dist/props/vocabulary/interaction.prop.d.ts +10 -12
- package/dist/props/vocabulary/layout.prop.d.ts +8 -30
- package/dist/props/vocabulary/shared.prop.d.ts +3 -2
- package/dist/styles/alert-layout.css +1 -32
- package/dist/styles/badge-layout.css +4 -18
- package/dist/styles/base.css +14 -113
- package/dist/styles/card-layout.css +6 -128
- package/dist/styles/chart-layout.css +2 -17
- package/dist/styles/control.css +380 -458
- package/dist/styles/core.css +21 -0
- package/dist/styles/data-display-layout.css +175 -94
- package/dist/styles/data-entry-layout.css +0 -45
- package/dist/styles/density.css +1 -30
- package/dist/styles/dialog-layout.css +5 -69
- package/dist/styles/focus-ring.css +13 -87
- package/dist/styles/fonts.css +1 -31
- package/dist/styles/form-layout.css +7 -91
- package/dist/styles/index.css +2 -20
- package/dist/styles/layout.css +38 -456
- package/dist/styles/logo-layout.css +1 -35
- package/dist/styles/motion.css +3 -42
- package/dist/styles/navigation-layout.css +3 -50
- package/dist/styles/shell-layout.css +37 -403
- package/dist/styles/table-layout.css +16 -274
- package/dist/styles/text-layout.css +7 -21
- package/dist/styles/toggle.css +1 -23
- package/dist/theme/dxs.canonical.css +1 -55
- package/dist/theme/example.service.css +1 -26
- package/dist/theme/famgia.service.css +5 -15
- package/dist/tokens/axes.css +3 -40
- package/dist/tokens/base.css +1 -4
- package/dist/tokens/components/activity.css +6 -42
- package/dist/tokens/components/badge.css +4 -13
- package/dist/tokens/components/banner.css +4 -9
- package/dist/tokens/components/card.css +32 -88
- package/dist/tokens/components/chart.css +9 -26
- package/dist/tokens/components/control.css +37 -222
- package/dist/tokens/components/data-display.css +28 -79
- package/dist/tokens/components/data-entry.css +5 -19
- package/dist/tokens/components/descriptions.css +7 -27
- package/dist/tokens/components/email.css +38 -84
- package/dist/tokens/components/error-surface.css +2 -18
- package/dist/tokens/components/feedback.css +27 -124
- package/dist/tokens/components/form.css +13 -45
- package/dist/tokens/components/legal-document.css +16 -41
- package/dist/tokens/components/list-row.css +11 -36
- package/dist/tokens/components/logo.css +2 -57
- package/dist/tokens/components/navigation.css +16 -94
- package/dist/tokens/components/scroll-area.css +2 -18
- package/dist/tokens/components/separator.css +8 -30
- package/dist/tokens/components/sheet.css +3 -14
- package/dist/tokens/components/shell.css +53 -307
- package/dist/tokens/components/sidebar.css +5 -22
- package/dist/tokens/components/table.css +19 -140
- package/dist/tokens/components/toggle.css +3 -65
- package/dist/tokens/components/upload.css +7 -43
- package/dist/tokens/foundation.css +108 -383
- package/dist/tokens/semantic/layout.css +33 -207
- package/docs/CANONICAL-CONTRACTS.md +206 -0
- package/docs/COMPONENTS.md +157 -0
- package/docs/COMPOSITION-VS-COMPONENT.md +105 -0
- package/docs/CONSUMER-RULES.md +14 -0
- package/docs/CUSTOMER-THEMING.md +162 -0
- package/docs/DATETIME.md +69 -0
- package/docs/DEVELOPMENT.md +173 -0
- package/docs/FORMS.md +143 -0
- package/docs/FRAME-A11Y-CI.md +267 -0
- package/docs/FRAME-COVERAGE-LEDGER.md +123 -0
- package/docs/FRAME-COVERAGE-REPORT.md +140 -0
- package/docs/FRAME-COVERAGE-STANDARD.md +65 -0
- package/docs/FRAME-COVERAGE.md +29 -0
- package/docs/PROPS-REGISTRY.md +61 -0
- package/docs/PROPS-VOCABULARY.md +100 -0
- package/docs/README.md +60 -0
- package/docs/REGISTRY.md +70 -0
- package/docs/SPACING.md +56 -0
- package/docs/STANDARDS-vocabulary-tokens.md +48 -0
- package/docs/TESTING.md +98 -0
- package/docs/TOKENS.md +347 -0
- package/docs/asset-modules.d.ts +46 -0
- package/docs/assets/cover-terrain.svg +6 -0
- package/docs/assets/portrait-amber.svg +5 -0
- package/docs/assets/portrait-clay.svg +5 -0
- package/docs/assets/portrait-indigo.svg +5 -0
- package/docs/assets/portrait-iris.svg +5 -0
- package/docs/assets/portrait-moss.svg +5 -0
- package/docs/assets/portrait-plum.svg +5 -0
- package/docs/assets/portrait-slate.svg +5 -0
- package/docs/charts/compact-bar-trend.tsx +328 -0
- package/docs/charts/size-tiers.tsx +192 -0
- package/docs/data-display/accordion.tsx +99 -0
- package/docs/data-display/avatar.tsx +355 -0
- package/docs/data-display/badge.tsx +247 -0
- package/docs/data-display/card/examples/detail-panel.tsx +106 -0
- package/docs/data-display/card/index.md +3 -0
- package/docs/data-display/card/index.tsx +285 -0
- package/docs/data-display/carousel.tsx +156 -0
- package/docs/data-display/charts.tsx +198 -0
- package/docs/data-display/code-block.tsx +90 -0
- package/docs/data-display/collapsible.tsx +162 -0
- package/docs/data-display/credential-reveal.tsx +145 -0
- package/docs/data-display/data-table/examples/approval-queue.tsx +212 -0
- package/docs/data-display/data-table/examples/grid-features.tsx +158 -0
- package/docs/data-display/data-table/examples/list-page.tsx +175 -0
- package/docs/data-display/data-table/index.md +5 -0
- package/docs/data-display/data-table/index.tsx +295 -0
- package/docs/data-display/descriptions.tsx +143 -0
- package/docs/data-display/empty-state.tsx +164 -0
- package/docs/data-display/hover-card.tsx +181 -0
- package/docs/data-display/list-row.tsx +420 -0
- package/docs/data-display/permission-matrix.tsx +184 -0
- package/docs/data-display/popover-touch.tsx +27 -0
- package/docs/data-display/popover.tsx +245 -0
- package/docs/data-display/progress.tsx +84 -0
- package/docs/data-display/prose.tsx +105 -0
- package/docs/data-display/qr-code.tsx +68 -0
- package/docs/data-display/scroll-area.tsx +271 -0
- package/docs/data-display/service-launcher-card.tsx +145 -0
- package/docs/data-display/stat-card.tsx +99 -0
- package/docs/data-display/table.tsx +251 -0
- package/docs/data-display/timeline.tsx +112 -0
- package/docs/data-display/touch-actions.tsx +36 -0
- package/docs/data-display/tree-list.tsx +107 -0
- package/docs/data-entry/branch-scope-picker.tsx +123 -0
- package/docs/data-entry/calendar.tsx +180 -0
- package/docs/data-entry/cascader.tsx +378 -0
- package/docs/data-entry/checkbox.tsx +256 -0
- package/docs/data-entry/color-picker.tsx +117 -0
- package/docs/data-entry/command-palette.tsx +179 -0
- package/docs/data-entry/command.tsx +262 -0
- package/docs/data-entry/country-picker-recipe.tsx +170 -0
- package/docs/data-entry/date-picker.tsx +191 -0
- package/docs/data-entry/date-range-picker.tsx +149 -0
- package/docs/data-entry/form/examples/employee-settings.tsx +267 -0
- package/docs/data-entry/form/examples/invoice-form.tsx +387 -0
- package/docs/data-entry/form-field/examples/a11y-contract.tsx +240 -0
- package/docs/data-entry/form-field/examples/create-form.tsx +105 -0
- package/docs/data-entry/form-field/index.md +8 -0
- package/docs/data-entry/form-field/index.tsx +326 -0
- package/docs/data-entry/form-inertia.tsx +80 -0
- package/docs/data-entry/form-root.tsx +102 -0
- package/docs/data-entry/form.tsx +724 -0
- package/docs/data-entry/input-otp.tsx +231 -0
- package/docs/data-entry/input.tsx +114 -0
- package/docs/data-entry/label.tsx +100 -0
- package/docs/data-entry/month-picker.tsx +101 -0
- package/docs/data-entry/month-range-picker.tsx +115 -0
- package/docs/data-entry/number-input.tsx +240 -0
- package/docs/data-entry/password-input.tsx +106 -0
- package/docs/data-entry/password-strength.tsx +97 -0
- package/docs/data-entry/radio-group.tsx +95 -0
- package/docs/data-entry/rating.tsx +87 -0
- package/docs/data-entry/search-input.tsx +120 -0
- package/docs/data-entry/select-async-contracts.tsx +108 -0
- package/docs/data-entry/select-matrix.tsx +204 -0
- package/docs/data-entry/select.tsx +369 -0
- package/docs/data-entry/slider.tsx +130 -0
- package/docs/data-entry/switch.tsx +67 -0
- package/docs/data-entry/tag-input.tsx +108 -0
- package/docs/data-entry/textarea.tsx +209 -0
- package/docs/data-entry/time-picker.tsx +99 -0
- package/docs/data-entry/toggle-count.tsx +293 -0
- package/docs/data-entry/toggle-group.tsx +225 -0
- package/docs/data-entry/toggle.tsx +127 -0
- package/docs/data-entry/transfer.tsx +97 -0
- package/docs/data-entry/tree-select.tsx +204 -0
- package/docs/data-entry/upload.tsx +184 -0
- package/docs/feedback/alert-dialog.tsx +270 -0
- package/docs/feedback/alert.tsx +248 -0
- package/docs/feedback/banner.tsx +183 -0
- package/docs/feedback/danger-confirm.tsx +88 -0
- package/docs/feedback/dialog-touch.tsx +24 -0
- package/docs/feedback/dialog.tsx +193 -0
- package/docs/feedback/sheet.tsx +410 -0
- package/docs/feedback/skeleton.tsx +111 -0
- package/docs/feedback/toast.tsx +135 -0
- package/docs/feedback/tooltip.tsx +171 -0
- package/docs/feedback/two-factor-setup.tsx +68 -0
- package/docs/foundation/_email-specimen.ts +274 -0
- package/docs/foundation/colors.tsx +202 -0
- package/docs/foundation/density.tsx +232 -0
- package/docs/foundation/email-tokens.tsx +306 -0
- package/docs/foundation/radius-shadow.tsx +152 -0
- package/docs/foundation/spacing.tsx +211 -0
- package/docs/foundation/typography.tsx +147 -0
- package/docs/general/activity.tsx +224 -0
- package/docs/general/button/examples/destructive-confirm.tsx +90 -0
- package/docs/general/button/examples/form-actions.tsx +85 -0
- package/docs/general/button/examples/toolbar.tsx +160 -0
- package/docs/general/button/index.md +12 -0
- package/docs/general/button/index.tsx +211 -0
- package/docs/general/logo.tsx +131 -0
- package/docs/general/reveal.tsx +41 -0
- package/docs/general/typography.tsx +152 -0
- package/docs/layout/account-chip.tsx +72 -0
- package/docs/layout/admin-collection.tsx +122 -0
- package/docs/layout/app-shell.tsx +374 -0
- package/docs/layout/aspect-ratio.tsx +119 -0
- package/docs/layout/auth-account-summary.tsx +103 -0
- package/docs/layout/auth-divider.tsx +28 -0
- package/docs/layout/auth-footer.tsx +37 -0
- package/docs/layout/auth-identity.tsx +36 -0
- package/docs/layout/auth-recovery/examples/mfa-challenge.md +41 -0
- package/docs/layout/auth-recovery/examples/mfa-challenge.tsx +254 -0
- package/docs/layout/auth-recovery/examples/mobile-390.md +25 -0
- package/docs/layout/auth-recovery/examples/mobile-390.tsx +82 -0
- package/docs/layout/auth-recovery/examples/password-recovery.md +24 -0
- package/docs/layout/auth-recovery/examples/password-recovery.tsx +197 -0
- package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.md +27 -0
- package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.tsx +156 -0
- package/docs/layout/auth-recovery/index.md +140 -0
- package/docs/layout/auth-recovery/index.tsx +96 -0
- package/docs/layout/auth-shell-context.tsx +103 -0
- package/docs/layout/auth-shell-device.tsx +112 -0
- package/docs/layout/auth-shell-registration.tsx +335 -0
- package/docs/layout/auth-shell-variants.tsx +139 -0
- package/docs/layout/auth-shell.tsx +59 -0
- package/docs/layout/auth-stack.tsx +40 -0
- package/docs/layout/centered-shell.tsx +102 -0
- package/docs/layout/error-surface/examples/application-403.tsx +84 -0
- package/docs/layout/error-surface/examples/application-404.tsx +77 -0
- package/docs/layout/error-surface/examples/system-500.tsx +47 -0
- package/docs/layout/error-surface/examples/system-503.tsx +48 -0
- package/docs/layout/error-surface/index.md +153 -0
- package/docs/layout/error-surface/index.tsx +239 -0
- package/docs/layout/flex.tsx +262 -0
- package/docs/layout/legal-document-shell/_data.ts +110 -0
- package/docs/layout/legal-document-shell/examples/desktop-1440.md +12 -0
- package/docs/layout/legal-document-shell/examples/desktop-1440.tsx +83 -0
- package/docs/layout/legal-document-shell/examples/mobile-390.md +22 -0
- package/docs/layout/legal-document-shell/examples/mobile-390.tsx +70 -0
- package/docs/layout/legal-document-shell/examples/tablet-1024.md +3 -0
- package/docs/layout/legal-document-shell/examples/tablet-1024.tsx +84 -0
- package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.md +18 -0
- package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.tsx +61 -0
- package/docs/layout/legal-document-shell/index.md +51 -0
- package/docs/layout/legal-document-shell/index.tsx +101 -0
- package/docs/layout/master-detail.tsx +387 -0
- package/docs/layout/org-switcher.tsx +131 -0
- package/docs/layout/page-container.tsx +946 -0
- package/docs/layout/resizable-panel.tsx +419 -0
- package/docs/layout/responsive-grid.tsx +235 -0
- package/docs/layout/separator.tsx +327 -0
- package/docs/layout/service-role-panel.tsx +144 -0
- package/docs/layout/sidebar.tsx +586 -0
- package/docs/layout/split-pane.tsx +451 -0
- package/docs/layout/topbar.tsx +347 -0
- package/docs/navigation/app-setting-picker.tsx +141 -0
- package/docs/navigation/breadcrumb.tsx +128 -0
- package/docs/navigation/context-menu.tsx +117 -0
- package/docs/navigation/dropdown-menu.tsx +213 -0
- package/docs/navigation/filter-bar.tsx +227 -0
- package/docs/navigation/menubar.tsx +141 -0
- package/docs/navigation/navigation-menu.tsx +165 -0
- package/docs/navigation/pagination.tsx +241 -0
- package/docs/navigation/steps.tsx +263 -0
- package/docs/navigation/tabs-rtl.tsx +28 -0
- package/docs/navigation/tabs.tsx +308 -0
- package/docs/navigation/toolbar.tsx +339 -0
- package/docs/providers/app-provider.tsx +191 -0
- package/docs/providers/format-date.tsx +230 -0
- package/docs/query/button-refetch.tsx +160 -0
- package/docs/query/data-state.tsx +192 -0
- package/docs/query/infinite-query-state.tsx +93 -0
- package/docs/query/mutation-feedback.tsx +70 -0
- package/docs/query/prefetch-link.tsx +262 -0
- package/docs/query/touch-actions.tsx +68 -0
- package/docs/showcase/acme-portal.tsx +441 -0
- package/docs/showcase/acme-website.tsx +455 -0
- package/docs/showcase/case1-warehouse-dashboard.tsx +343 -0
- package/docs/showcase/case2-employee-me.tsx +441 -0
- package/docs/showcase/case3-approval-workflow.tsx +527 -0
- package/docs/showcase/case4-login.tsx +307 -0
- package/docs/showcase/case5-shift-calendar.tsx +795 -0
- package/docs/showcase/case6-agency-handy.tsx +1072 -0
- package/docs/showcase/futurelastic-web.tsx +390 -0
- package/docs/showcase/org-switcher.tsx +313 -0
- package/docs/showcase/permission-matrix.tsx +343 -0
- package/docs/showcase/public-landing.tsx +210 -0
- package/docs/showcase/settings-account-sections.tsx +559 -0
- package/docs/showcase/settings-security-mfa.tsx +145 -0
- package/docs/showcase/table-approval-queue.tsx +199 -0
- package/docs/showcase/table-bulk-actions.tsx +460 -0
- package/docs/showcase/table-compact-kintone.tsx +438 -0
- package/docs/showcase/table-conditional-format.tsx +367 -0
- package/docs/showcase/table-crud-list.tsx +544 -0
- package/docs/showcase/table-density.tsx +340 -0
- package/docs/showcase/table-expandable-rows.tsx +471 -0
- package/docs/showcase/table-filter-chips.tsx +461 -0
- package/docs/showcase/table-footer-totals.tsx +311 -0
- package/docs/showcase/table-grouped-subtotals.tsx +388 -0
- package/docs/showcase/table-master-detail.tsx +479 -0
- package/docs/showcase/table-pagination.tsx +320 -0
- package/docs/showcase/table-states.tsx +363 -0
- package/docs/showcase/table-sticky-columns.tsx +373 -0
- package/docs/showcase/table-tree-rows.tsx +444 -0
- package/docs/showcase/table-view-tabs.tsx +488 -0
- package/package.json +10 -11
- package/scripts/_agent-setup.mjs +16 -2
- package/scripts/audit-hook.mjs +3 -13
- package/scripts/init-agent-kit.mjs +1 -14
- package/scripts/postinstall.mjs +12 -12
- package/scripts/ui-audit.mjs +93 -31
- package/scripts/visual-audit-rules.mjs +51 -7
- package/scripts/visual-audit.mjs +118 -47
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* APP SHELL — canonical chrome layout for admin surfaces.
|
|
3
|
-
* Slot-based composition: <AppShell sidebar={<Sidebar />} topbar={<Topbar />}>.
|
|
4
|
-
*/
|
|
1
|
+
|
|
5
2
|
|
|
6
3
|
@layer components {
|
|
7
4
|
.app-root {
|
|
@@ -13,8 +10,6 @@
|
|
|
13
10
|
"sidebar topbar"
|
|
14
11
|
"sidebar main"
|
|
15
12
|
"sidebar footer";
|
|
16
|
-
/* Rail width is a knob, never a literal (rule #45) — a service on a different design grid sets
|
|
17
|
-
* --app-shell-sidebar-width once (e.g. 255px) instead of forking this rule. */
|
|
18
13
|
grid-template-columns: var(--app-shell-sidebar-width) minmax(0, 1fr);
|
|
19
14
|
grid-template-rows: var(--app-shell-bar-height) minmax(0, 1fr) auto;
|
|
20
15
|
height: 100vh;
|
|
@@ -25,13 +20,6 @@
|
|
|
25
20
|
grid-template-columns: var(--app-shell-rail-width) minmax(0, 1fr);
|
|
26
21
|
}
|
|
27
22
|
|
|
28
|
-
/* topbarSpan="full" — the bar runs edge to edge and the rail starts beneath it, for products
|
|
29
|
-
* whose bar carries space-level chrome (global search, account, notifications) that outranks the
|
|
30
|
-
* current section instead of belonging to it. Only the row assignment changes: both track sizes
|
|
31
|
-
* stay token-owned, so --app-shell-sidebar-width and the collapsed rail still apply untouched.
|
|
32
|
-
* Below the 900px breakpoint the grid already collapses to a single column, which IS this
|
|
33
|
-
* arrangement, so no narrow override is needed here — only the docked mode, which rebuilds the
|
|
34
|
-
* two-track grid, needs restating (see the breakpoint block). */
|
|
35
23
|
.app-root[data-topbar-span="full"] {
|
|
36
24
|
grid-template-areas:
|
|
37
25
|
"topbar topbar"
|
|
@@ -39,35 +27,10 @@
|
|
|
39
27
|
"sidebar footer";
|
|
40
28
|
}
|
|
41
29
|
|
|
42
|
-
/* NO TOP BAR AT ALL — `topbar`, `topbarLeft`, `topbarRight` and `logo` all undefined. AppShell
|
|
43
|
-
* renders no `<header class="app-topbar">` in that state (the mobile drawer trigger is the one
|
|
44
|
-
* exception, below) and publishes it as ONE attribute here, so the geometry is decided by the
|
|
45
|
-
* grid element itself rather than by `:has()` on whatever the consumer nested inside.
|
|
46
|
-
*
|
|
47
|
-
* The row has to go with the header. An empty --app-shell-bar-height track still costs a fixed
|
|
48
|
-
* 48px, and the header still painted a bottom border over hsl(var(--card)) — so a chat / mail /
|
|
49
|
-
* IDE shell, whose PAGE header is the top row, showed two rows of chrome (~48 + ~60px) over
|
|
50
|
-
* exactly the region that needs the height most.
|
|
51
|
-
*
|
|
52
|
-
* `auto`, not a `0` literal, is what makes one attribute enough for every branch: an absent row
|
|
53
|
-
* measures 0, a `display:none` header measures 0, and at narrow widths — where the header comes
|
|
54
|
-
* back to carry the hamburger — the row sizes itself from that header's own min-height. So the
|
|
55
|
-
* breakpoint block needs no restatement of these rows, which is the trap this file has already
|
|
56
|
-
* paid for once: the deleted 768px block re-declared grid-template-rows with a `3rem` literal
|
|
57
|
-
* and defeated --app-shell-bar-height below 768px only (see the note on the one @media block).
|
|
58
|
-
* `[data-topbar-span="full"]` re-declares grid-template-AREAS only, so it inherits this row
|
|
59
|
-
* template untouched and its named-but-empty "topbar topbar" row is 0 as well. */
|
|
60
30
|
.app-root[data-topbar="none"] {
|
|
61
31
|
grid-template-rows: auto minmax(0, 1fr) auto;
|
|
62
32
|
}
|
|
63
33
|
|
|
64
|
-
/* The one thing that may still live in a bar-less shell: AppShell's OWN hamburger. Below 900px
|
|
65
|
-
* the docked sidebar is hidden, and dropping the bar there too would leave the shell with no
|
|
66
|
-
* reachable navigation at all — a worse failure than the double chrome above (gh#165). So when a
|
|
67
|
-
* drawer exists the header is still rendered, carrying the trigger and nothing else, and it is
|
|
68
|
-
* THIS rule, not the empty row, that keeps it off the wide layout: `display:none` removes its
|
|
69
|
-
* border, its background and its height together. The min-height is inert here and load-bearing
|
|
70
|
-
* at narrow widths, where it is the only thing giving the `auto` row a height. */
|
|
71
34
|
.app-root[data-topbar="none"] > .app-topbar {
|
|
72
35
|
display: none;
|
|
73
36
|
min-height: var(--app-shell-bar-height);
|
|
@@ -80,35 +43,21 @@
|
|
|
80
43
|
min-width: 0;
|
|
81
44
|
min-height: 0;
|
|
82
45
|
flex-direction: column;
|
|
83
|
-
|
|
84
|
-
* flush with the rail's inline edges, so a plain `hidden` clipped their
|
|
85
|
-
* focus ring on three sides. `clip` + margin (the margin is honoured only
|
|
86
|
-
* when BOTH axes clip) lets the ring paint over the rail border, while the
|
|
87
|
-
* rail still contains its content. Inner scroll regions are unaffected —
|
|
88
|
-
* `clip` creates no scroll container, exactly like `hidden`. */
|
|
46
|
+
|
|
89
47
|
overflow: clip;
|
|
90
48
|
overflow-clip-margin: var(--focus-ring-clip-margin);
|
|
91
49
|
border-inline-end: 1px solid hsl(var(--border));
|
|
92
50
|
background: hsl(var(--card));
|
|
93
|
-
|
|
51
|
+
|
|
94
52
|
background-image: var(--sidebar-gradient);
|
|
95
53
|
color: hsl(var(--foreground));
|
|
96
54
|
}
|
|
97
55
|
|
|
98
56
|
.app-topbar {
|
|
99
57
|
grid-area: topbar;
|
|
100
|
-
/* Persistent navigation chrome stays a FIXED size regardless of density — the
|
|
101
|
-
* AppShell adds `.ui-scale-fixed` to this <header> (resets the whole size-token
|
|
102
|
-
* set to baseline; --scaling:1 alone is not enough — see foundation.css). */
|
|
103
58
|
display: flex;
|
|
104
59
|
min-width: 0;
|
|
105
|
-
|
|
106
|
-
* honours overflow-clip-margin ONLY when BOTH axes are `clip` — a
|
|
107
|
-
* single-axis clip silently drops the margin, which would cut a flush
|
|
108
|
-
* control's ring whenever a theme sets --app-shell-bar-inset to 0. The 8px
|
|
109
|
-
* margin also covers the vertical ring of coarse-pointer 44px controls,
|
|
110
|
-
* which the 3.5rem coarse bar height already keeps inside the bar. Safari
|
|
111
|
-
* falls back to `visible` with the .ui-topbar family below. */
|
|
60
|
+
|
|
112
61
|
overflow: clip;
|
|
113
62
|
overflow-clip-margin: var(--focus-ring-clip-margin);
|
|
114
63
|
align-items: center;
|
|
@@ -116,7 +65,7 @@
|
|
|
116
65
|
padding-inline: var(--app-shell-bar-inset);
|
|
117
66
|
border-bottom: 1px solid hsl(var(--border));
|
|
118
67
|
background: hsl(var(--card));
|
|
119
|
-
|
|
68
|
+
|
|
120
69
|
background-image: var(--topbar-gradient);
|
|
121
70
|
}
|
|
122
71
|
|
|
@@ -124,38 +73,16 @@
|
|
|
124
73
|
grid-area: main;
|
|
125
74
|
min-width: 0;
|
|
126
75
|
overflow: auto;
|
|
127
|
-
|
|
128
|
-
* region instead of merely starting at its top. With the default `block`
|
|
129
|
-
* flow a `--fill` container could only be `min-height: 100%`, i.e. it grew
|
|
130
|
-
* past the region and pushed the scroll back out here — which is why a chat
|
|
131
|
-
* transcript slid UNDER its own sticky composer. Ordinary pages are
|
|
132
|
-
* unaffected: their container still has `min-height: 100%`, still grows,
|
|
133
|
-
* and this element still scrolls it. */
|
|
76
|
+
|
|
134
77
|
display: flex;
|
|
135
78
|
flex-direction: column;
|
|
136
|
-
|
|
137
|
-
* radial/linear brand wash behind the whole content area by configuring the token alone. */
|
|
79
|
+
|
|
138
80
|
background-image: var(--gradient-glow);
|
|
139
|
-
|
|
140
|
-
* establish a paint-containment boundary in Chrome: tall nested scrollers (a two-pane
|
|
141
|
-
* `grid` of long lists, a nested `overflow-y:auto` region) — or any absolutely-positioned
|
|
142
|
-
* descendant (Radix form-fallback bubbles, `.sr-only` nodes) — can leak their clipped
|
|
143
|
-
* extent into the DOCUMENT scroll, so the window scrolls past the content into a
|
|
144
|
-
* full-viewport void below the fold even though `.app-root` is exactly 100vh.
|
|
145
|
-
* `contain:paint` makes `.app-main` the real clip boundary + containing block, so its
|
|
146
|
-
* content can never extend the document scroll height (gh#104 — same shell-containment
|
|
147
|
-
* family as the gh#103 body-stretch void). */
|
|
81
|
+
|
|
148
82
|
contain: paint;
|
|
149
83
|
background-color: var(--app-shell-main-background);
|
|
150
84
|
}
|
|
151
85
|
|
|
152
|
-
/* `.app-main` carries tabindex="0" (axe scrollable-region-focusable, dbad118), so keyboard
|
|
153
|
-
* focus can land on the region. The UA default outline is suppressed and the indicator is
|
|
154
|
-
* token-gated (gh#276): `--region-focus-ring-width` defaults to 0 — OFF — because a
|
|
155
|
-
* control-strength frame around the whole content area reads as a glitch (`:focus-visible`
|
|
156
|
-
* promotes on any keypress after a click-focus, so mouse users see it constantly). A service
|
|
157
|
-
* that needs the visible keyboard-scroll affordance (WCAG 2.4.7) opts in via the token;
|
|
158
|
-
* INSET because `.app-main` is the shell's clip boundary (`contain: paint`). */
|
|
159
86
|
.app-main:focus-visible {
|
|
160
87
|
outline: none;
|
|
161
88
|
box-shadow: inset 0 0 0 var(--region-focus-ring-width)
|
|
@@ -173,11 +100,6 @@
|
|
|
173
100
|
max-width: var(--app-shell-page-max-width);
|
|
174
101
|
}
|
|
175
102
|
|
|
176
|
-
/*
|
|
177
|
-
* AUTH SHELL — centred auth/login page shell (brand bar + centred card + footer).
|
|
178
|
-
* Comfortable control density + a larger auth heading are scoped to the shell so login/mfa/reset
|
|
179
|
-
* forms read at the right size without a consumer scope class. Everything reads a token knob.
|
|
180
|
-
*/
|
|
181
103
|
.ui-auth-shell {
|
|
182
104
|
--control-height: var(--auth-shell-control-height);
|
|
183
105
|
--heading-h1: var(--auth-shell-heading-size);
|
|
@@ -220,22 +142,12 @@
|
|
|
220
142
|
--auth-shell-main-padding: var(--auth-shell-canonical-main-padding);
|
|
221
143
|
}
|
|
222
144
|
|
|
223
|
-
/*
|
|
224
|
-
* NAMED FLOW PRESETS (gh#217 / gh#220) — orthogonal to `variant` and declared AFTER it (equal
|
|
225
|
-
* specificity, so source order wins) so a preset re-measures the page while `variant="canonical"`
|
|
226
|
-
* keeps owning control density and heading size. A preset owns the card measure + page gutters,
|
|
227
|
-
* so the consumer never overrides `--auth-shell-card-max-width` by hand.
|
|
228
|
-
*/
|
|
229
145
|
.ui-auth-shell[data-preset] .ui-auth-shell-card {
|
|
230
146
|
display: flex;
|
|
231
147
|
flex-direction: column;
|
|
232
148
|
gap: var(--auth-shell-card-stack-gap);
|
|
233
149
|
}
|
|
234
150
|
|
|
235
|
-
/* Login is an anchored three-part composition: AuthIdentity · Card · AuthFooter. The fixed
|
|
236
|
-
* identity track absorbs absent, one-line and wrapped two-line requester states while its
|
|
237
|
-
* content remains visually adjacent to the Card. This keeps real requester data intact without
|
|
238
|
-
* allowing its line count to move the canonical SCR-001 card anchor (gh#237). */
|
|
239
151
|
.ui-auth-shell[data-preset="login"] {
|
|
240
152
|
--auth-shell-card-max-width: var(--auth-shell-login-card-max-width);
|
|
241
153
|
--auth-shell-main-align: flex-start;
|
|
@@ -277,9 +189,6 @@
|
|
|
277
189
|
text-align: center;
|
|
278
190
|
}
|
|
279
191
|
|
|
280
|
-
/* Device-authorization also owns its CODE FIELD (gh#12): the preset's subject is the code, so
|
|
281
|
-
* the slot box comes from the preset instead of the generic square control tier. Scoped on the
|
|
282
|
-
* shell so every OTP inside the device flow inherits it; a per-instance override still wins. */
|
|
283
192
|
.ui-auth-shell[data-preset="device-authorization"] {
|
|
284
193
|
--auth-shell-card-max-width: var(--auth-shell-device-card-max-width);
|
|
285
194
|
--auth-shell-main-padding: var(--auth-shell-device-main-padding);
|
|
@@ -293,20 +202,11 @@
|
|
|
293
202
|
--auth-shell-card-stack-gap: var(--auth-shell-context-card-stack-gap);
|
|
294
203
|
}
|
|
295
204
|
|
|
296
|
-
/* Account-recovery preset (gh#233) — one 432px measure for BOTH SCR-008 panels (password
|
|
297
|
-
* recovery and the sign-in MFA challenge). Title + description live INSIDE the bordered surface
|
|
298
|
-
* here, so the panel is `Card > CardHeader(CardTitle + CardDescription)` with no `AuthIdentity`
|
|
299
|
-
* mark above it — the preset only re-measures the page, it never dictates content. */
|
|
300
205
|
.ui-auth-shell[data-preset="account-recovery"] {
|
|
301
206
|
--auth-shell-card-max-width: var(--auth-shell-recovery-card-max-width);
|
|
302
207
|
--auth-shell-main-padding: var(--auth-shell-recovery-main-padding);
|
|
303
208
|
}
|
|
304
209
|
|
|
305
|
-
/* Registration preset (gh#256) — the sign-up measure. `flex-start` is the load-bearing line: a
|
|
306
|
-
* registration card is the tallest surface in the hosted-identity set, and a vertically CENTRED
|
|
307
|
-
* tall card overflows ABOVE the scroll origin on a short viewport, putting its first field out of
|
|
308
|
-
* reach. Start-aligned, the block-start inset is ordinary page padding the user scrolls past, and
|
|
309
|
-
* the block-end inset is the footer clearance the form keeps at the end of a long scroll. */
|
|
310
210
|
.ui-auth-shell[data-preset="registration"] {
|
|
311
211
|
--auth-shell-card-max-width: var(--auth-shell-registration-card-max-width);
|
|
312
212
|
--auth-shell-main-align: flex-start;
|
|
@@ -316,11 +216,6 @@
|
|
|
316
216
|
--auth-shell-card-stack-gap: var(--auth-shell-registration-card-stack-gap);
|
|
317
217
|
}
|
|
318
218
|
|
|
319
|
-
/* Fixed identity track — the mechanism `login` proved (gh#237), applied to the identity block
|
|
320
|
-
* wherever it sits in the column rather than through a grid row, so the preset does not constrain
|
|
321
|
-
* how many sections the page stacks. Content aligns to the slot END, so absent / one-line /
|
|
322
|
-
* wrapped two-line identity copy changes only the empty space ABOVE it and never moves the card
|
|
323
|
-
* off its canonical anchor. */
|
|
324
219
|
.ui-auth-shell[data-preset="registration"] .ui-auth-shell-card > .ui-auth-identity {
|
|
325
220
|
block-size: var(--auth-shell-registration-identity-slot-block-size);
|
|
326
221
|
justify-content: flex-end;
|
|
@@ -391,7 +286,6 @@
|
|
|
391
286
|
overflow: hidden;
|
|
392
287
|
color: hsl(var(--foreground));
|
|
393
288
|
font-size: var(--auth-account-summary-email-font-size);
|
|
394
|
-
/* Declares its own line box because it CLIPS — see gh#254. */
|
|
395
289
|
line-height: var(--auth-account-summary-email-line-height);
|
|
396
290
|
font-weight: var(--font-weight-medium);
|
|
397
291
|
text-overflow: ellipsis;
|
|
@@ -430,32 +324,12 @@
|
|
|
430
324
|
}
|
|
431
325
|
}
|
|
432
326
|
|
|
433
|
-
/* INTENTIONALLY UNLAYERED (like density.css) — the Label primitive carries `text-sm leading-none`
|
|
434
|
-
* Tailwind utility classes, and the utilities layer is declared after `components`, so a
|
|
435
|
-
* components-layer declaration of the same properties can NEVER win regardless of specificity.
|
|
436
|
-
* That left `--auth-shell-field-label-font-size` / `--auth-shell-field-label-line-height` dead and
|
|
437
|
-
* the canonical field label rendering as a 14px/1.0 line box instead of the canonical 12px/1.5 =
|
|
438
|
-
* 18px, sitting the email input 4px high (gh#263). Unlayered author CSS out-cascades every layer;
|
|
439
|
-
* the two tokens remain the public tuning knobs. */
|
|
440
327
|
.ui-auth-shell[data-variant="canonical"] [data-slot="form-field-label"] [data-slot="label"] {
|
|
441
328
|
font-size: var(--auth-shell-field-label-font-size);
|
|
442
329
|
line-height: var(--auth-shell-field-label-line-height);
|
|
443
330
|
}
|
|
444
331
|
|
|
445
332
|
@layer components {
|
|
446
|
-
/*
|
|
447
|
-
* Compact auth card density — the two card axes are wired to SEPARATE knobs (gh#232), so a
|
|
448
|
-
* service can shorten the canonical Login card without narrowing its column (or vice versa):
|
|
449
|
-
* inline column ← --auth-shell-compact-card-inset → --card-space-inset
|
|
450
|
-
* block padding ← --auth-shell-card-padding-block-compact → --card-space-shell-y
|
|
451
|
-
* header↔body ← --auth-shell-card-body-gap-compact → --card-space-body-y
|
|
452
|
-
* solo body ← --auth-shell-card-padding-block-compact → --card-space-solo-y
|
|
453
|
-
* The block knob is `initial` at :root, so its default resolves HERE against the live inset —
|
|
454
|
-
* canonical output is byte-identical to pre-gh#232 while the knob is now actually consumed.
|
|
455
|
-
* --card-space-solo-y is mapped EXPLICITLY as well as via the shell-y fallback: a solo body
|
|
456
|
-
* takes both block edges symmetrically, and naming it here keeps that contract legible at the
|
|
457
|
-
* one place a reader looks for the compact card's spacing.
|
|
458
|
-
*/
|
|
459
333
|
.ui-auth-shell[data-density="compact"] .ui-auth-shell-card {
|
|
460
334
|
--card-space-inset: var(--auth-shell-compact-card-inset);
|
|
461
335
|
--card-space-shell-y: var(
|
|
@@ -470,13 +344,6 @@
|
|
|
470
344
|
--card-space-gap: var(--auth-shell-card-gap-compact);
|
|
471
345
|
}
|
|
472
346
|
|
|
473
|
-
/* AuthDivider is the auth-scoped PRESET over the labelled `Separator` (gh#308). It no longer
|
|
474
|
-
* re-implements the grid, the rule or the accessible-name contract — it only re-points
|
|
475
|
-
* Separator's knobs at the `--auth-shell-divider-*` layer, so the auth micro-scale (11px, not
|
|
476
|
-
* the stream's xs) and the auth rule/label colours stay exactly where a service already tunes
|
|
477
|
-
* them, while a day divider in a message stream is no longer coupled to a login form.
|
|
478
|
-
* `--separator-label-font-weight` is pinned to normal because the auth conjunction has always
|
|
479
|
-
* inherited the body weight, whereas the generic labelled rule defaults to medium. */
|
|
480
347
|
.ui-auth-divider {
|
|
481
348
|
--separator-label-gap: var(--auth-shell-divider-gap);
|
|
482
349
|
--separator-label-font-size: var(--auth-shell-divider-label-font-size);
|
|
@@ -497,9 +364,6 @@
|
|
|
497
364
|
var(--auth-shell-login-main-padding-block-end);
|
|
498
365
|
}
|
|
499
366
|
|
|
500
|
-
/* Declared after the canonical mobile inset so a preset's mobile gutter wins at equal
|
|
501
|
-
* specificity: device-authorization = 5px inline (card x=5, width=380 at 390px);
|
|
502
|
-
* context-selection = edge-to-edge (0 inline). */
|
|
503
367
|
.ui-auth-shell[data-preset="device-authorization"] {
|
|
504
368
|
--auth-shell-main-padding: var(--auth-shell-device-main-padding-mobile);
|
|
505
369
|
}
|
|
@@ -508,17 +372,10 @@
|
|
|
508
372
|
--auth-shell-main-padding: var(--auth-shell-context-main-padding-mobile);
|
|
509
373
|
}
|
|
510
374
|
|
|
511
|
-
/* account-recovery = 15px inline at 390 (panel x=15, width=360). This is a DECIDED mobile
|
|
512
|
-
* contract — the supplied 390 canonical reference is a desktop 2x2 composite that overflows
|
|
513
|
-
* horizontally and is not a valid source (gh#233). */
|
|
514
375
|
.ui-auth-shell[data-preset="account-recovery"] {
|
|
515
376
|
--auth-shell-main-padding: var(--auth-shell-recovery-main-padding-mobile);
|
|
516
377
|
}
|
|
517
378
|
|
|
518
|
-
/* registration = 15px inline at 390 (card x=15, width=360 — the same page rhythm as Login, so
|
|
519
|
-
* sign-in → sign-up never jumps on a phone). The block insets tighten but the footer clearance
|
|
520
|
-
* stays deliberately larger than a bare gutter: at 390 the form is at its tallest and the
|
|
521
|
-
* consent/legal footer must not sit flush against the submit button. */
|
|
522
379
|
.ui-auth-shell[data-preset="registration"] {
|
|
523
380
|
--auth-shell-main-padding: var(--auth-shell-registration-main-padding-block-start-mobile)
|
|
524
381
|
var(--auth-shell-registration-main-padding-inline-mobile)
|
|
@@ -526,14 +383,6 @@
|
|
|
526
383
|
}
|
|
527
384
|
}
|
|
528
385
|
|
|
529
|
-
/*
|
|
530
|
-
* CENTERED SHELL — authenticated, no-sidebar, centred-column page shell (hosted-ID "My Page",
|
|
531
|
-
* account / self-service, standalone settings). A flex column over the same brand-wash surface as
|
|
532
|
-
* the app/auth shells: a padded top bar that MIRRORS `.app-topbar` chrome (fixed height + inline
|
|
533
|
-
* padding + border + backdrop) but WITHOUT a sidebar grid, a scrollable `main` whose content is a
|
|
534
|
-
* width-tiered centred column that is TOP-aligned (sections flow + scroll, never vertically
|
|
535
|
-
* centred like the auth card), and an optional footer. Every knob reads a token.
|
|
536
|
-
*/
|
|
537
386
|
.ui-centered-shell {
|
|
538
387
|
display: flex;
|
|
539
388
|
min-height: 100dvh;
|
|
@@ -551,7 +400,7 @@
|
|
|
551
400
|
padding-inline: var(--centered-shell-bar-padding-x);
|
|
552
401
|
border-bottom: 1px solid hsl(var(--border));
|
|
553
402
|
background: hsl(var(--card));
|
|
554
|
-
|
|
403
|
+
|
|
555
404
|
background-image: var(--topbar-gradient);
|
|
556
405
|
}
|
|
557
406
|
|
|
@@ -561,9 +410,9 @@
|
|
|
561
410
|
flex: 1 1 auto;
|
|
562
411
|
flex-direction: column;
|
|
563
412
|
overflow: auto;
|
|
564
|
-
|
|
413
|
+
|
|
565
414
|
background-image: var(--gradient-glow);
|
|
566
|
-
|
|
415
|
+
|
|
567
416
|
contain: paint;
|
|
568
417
|
padding: var(--centered-shell-main-padding);
|
|
569
418
|
}
|
|
@@ -571,9 +420,7 @@
|
|
|
571
420
|
.ui-centered-shell-column {
|
|
572
421
|
width: 100%;
|
|
573
422
|
margin-inline: auto;
|
|
574
|
-
|
|
575
|
-
* surface via `align="center"`). Auto margins absorb the free space of the flex `main`, and
|
|
576
|
-
* collapse to 0 when the content overflows, so tall content still scrolls from the top. */
|
|
423
|
+
|
|
577
424
|
margin-block: var(--centered-shell-column-offset-block);
|
|
578
425
|
max-width: var(--centered-shell-width-md);
|
|
579
426
|
}
|
|
@@ -597,6 +444,20 @@
|
|
|
597
444
|
color: hsl(var(--muted-foreground));
|
|
598
445
|
}
|
|
599
446
|
|
|
447
|
+
@media (max-width: 720px) {
|
|
448
|
+
.ui-centered-shell-bar {
|
|
449
|
+
padding-inline: var(--centered-shell-bar-padding-x-compact);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
.ui-centered-shell-main {
|
|
453
|
+
padding-inline: var(--centered-shell-main-padding-inline-compact);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.ui-centered-shell-footer {
|
|
457
|
+
padding-inline: var(--centered-shell-footer-padding-inline-compact);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
600
461
|
.app-topbar-rail {
|
|
601
462
|
display: flex;
|
|
602
463
|
min-width: 0;
|
|
@@ -617,22 +478,12 @@
|
|
|
617
478
|
display: none;
|
|
618
479
|
}
|
|
619
480
|
|
|
620
|
-
/* AppShell-owned mobile drawer trigger — hidden on desktop, shown once the docked sidebar
|
|
621
|
-
* collapses out at 900px, THE ONE AppShell breakpoint (gh#165, gh#259). NOT Tailwind's `lg`
|
|
622
|
-
* (1024px): this comment said "below lg" for six minors while the shipped rule below and the
|
|
623
|
-
* hamburger's own `max-[900px]:inline-flex` both fired at 900 — see the block comment on the
|
|
624
|
-
* `@media (width <= 56.25rem)` rule for why 900 is the canonical value. The drawer nav itself is
|
|
625
|
-
* a focus-trapped Sheet. */
|
|
626
481
|
.app-mobile-nav-trigger {
|
|
627
482
|
display: none;
|
|
628
483
|
flex: 0 0 auto;
|
|
629
484
|
margin-inline-end: var(--space-1);
|
|
630
485
|
}
|
|
631
486
|
|
|
632
|
-
/* Drawer scrim = a SHARE of the ONE shared semantic scrim (--overlay-background), resolved at the
|
|
633
|
-
* call site so a scoped [data-tenant]/.dark override of --overlay-background reaches the portaled
|
|
634
|
-
* drawer (docs/TOKENS.md · "Role-mirror knobs MUST be `initial`"). Default resolves to the same
|
|
635
|
-
* rgb(0 0 0 / 0.2) it has always been; setting --app-shell-mobile-nav-background still wins. */
|
|
636
487
|
[data-slot="sheet-overlay"].app-mobile-nav-overlay {
|
|
637
488
|
background-color: var(
|
|
638
489
|
--app-shell-mobile-nav-background,
|
|
@@ -648,13 +499,6 @@
|
|
|
648
499
|
overscroll-behavior: contain;
|
|
649
500
|
}
|
|
650
501
|
|
|
651
|
-
/* The drawer nav reuses the docked Sidebar node; its `.sb-root { display: contents }` flattens
|
|
652
|
-
* into the scrollable SheetBody so sections/footer flow naturally in the panel.
|
|
653
|
-
* The body's INLINE inset is tokenized on the component itself
|
|
654
|
-
* (`px-[var(--app-shell-mobile-nav-inset)]` in AppShell, which wins over SheetBody's generic
|
|
655
|
-
* `px-[var(--sheet-pad-x)]` because both are utilities) — the nav owns its edge instead of being
|
|
656
|
-
* double-padded (gh#211). Do NOT set `padding-inline` here: this file is `@layer components`, so
|
|
657
|
-
* a Tailwind utility on the element always wins. */
|
|
658
502
|
.app-mobile-nav-body {
|
|
659
503
|
display: flex;
|
|
660
504
|
flex-direction: column;
|
|
@@ -672,21 +516,6 @@
|
|
|
672
516
|
font-size: var(--font-size-base);
|
|
673
517
|
}
|
|
674
518
|
|
|
675
|
-
/*
|
|
676
|
-
* THE ONE AppShell breakpoint — 900px (56.25rem), the DXS canonical value. It is stated in exactly
|
|
677
|
-
* two places and they must agree: this rule and `max-[900px]:inline-flex` on the hamburger in
|
|
678
|
-
* `app-shell.tsx` (a CSS @media cannot read a custom property, so the trigger's visibility has to
|
|
679
|
-
* repeat the number; making it a public knob needs a `data-shell-mode` attribute — tracked in the
|
|
680
|
-
* #213 audit, out of scope here).
|
|
681
|
-
*
|
|
682
|
-
* There used to be a SECOND, conflicting `@media (max-width: 768px)` block further down that also
|
|
683
|
-
* restructured `.app-root`. It (a) dropped the `"footer"` grid area and set `.app-footer{display:
|
|
684
|
-
* none}`, silently deleting whatever a consumer passed to AppShell's `footer` slot on a phone, and
|
|
685
|
-
* (b) re-declared the grid ROW template with a 3rem literal, overriding --app-shell-bar-height so
|
|
686
|
-
* a themed bar height was ignored below 768px only. Between 768 and 900 the sidebar was hidden by
|
|
687
|
-
* THIS rule while the grid still reserved a sidebar track — incoherent. Both are gone; the
|
|
688
|
-
* footer row and the bar-height token now hold at every width.
|
|
689
|
-
*/
|
|
690
519
|
@media (width <= 56.25rem) {
|
|
691
520
|
.app-root,
|
|
692
521
|
.app-root[data-collapsed="true"] {
|
|
@@ -701,12 +530,6 @@
|
|
|
701
530
|
display: none;
|
|
702
531
|
}
|
|
703
532
|
|
|
704
|
-
/* Bar-less shell (data-topbar="none") at narrow widths: the bar comes back for the hamburger
|
|
705
|
-
* ALONE — the only route to navigation once the docked rail is hidden. The `auto` row picks up
|
|
706
|
-
* its height from the header's min-height, so no grid-template-rows is restated here, and none
|
|
707
|
-
* may be: the one-breakpoint guard forbids a rows declaration inside this block precisely
|
|
708
|
-
* because the last one hard-coded 3rem. Docked mode never reaches this rule — it renders no
|
|
709
|
-
* drawer, so a bar-less docked shell has no header to show. */
|
|
710
533
|
.app-root[data-topbar="none"] > .app-topbar {
|
|
711
534
|
display: flex;
|
|
712
535
|
}
|
|
@@ -719,9 +542,6 @@
|
|
|
719
542
|
display: inline-flex;
|
|
720
543
|
}
|
|
721
544
|
|
|
722
|
-
/* Some approved application contracts retain their navigation rail at narrow widths. This is
|
|
723
|
-
* an explicit AppShell mode, never a consumer media-query fork: the same sidebar node, footer,
|
|
724
|
-
* active items and token-owned rail width remain in the canonical two-track grid. */
|
|
725
545
|
.app-root[data-responsive-navigation="docked"] {
|
|
726
546
|
grid-template-areas:
|
|
727
547
|
"sidebar topbar"
|
|
@@ -734,8 +554,6 @@
|
|
|
734
554
|
grid-template-columns: var(--app-shell-rail-width) minmax(0, 1fr);
|
|
735
555
|
}
|
|
736
556
|
|
|
737
|
-
/* Docked mode rebuilds the two-track grid at narrow widths, which would otherwise undo
|
|
738
|
-
* topbarSpan="full" exactly where the bar's space-level controls matter most. */
|
|
739
557
|
.app-root[data-responsive-navigation="docked"][data-topbar-span="full"] {
|
|
740
558
|
grid-template-areas:
|
|
741
559
|
"topbar topbar"
|
|
@@ -747,24 +565,11 @@
|
|
|
747
565
|
display: flex;
|
|
748
566
|
}
|
|
749
567
|
|
|
750
|
-
/* (There is deliberately no `padding-inline` undo for docked mode any more. It existed to
|
|
751
|
-
* cancel a bar inset that stepped on the SHELL's 900px restructure; since gh#330 the inset
|
|
752
|
-
* steps on the PAGE's 720px step instead, and a docked page tightens its own gutters at that
|
|
753
|
-
* same step — so undoing the bar here would re-open the misalignment the step exists to
|
|
754
|
-
* keep closed.) */
|
|
755
568
|
.app-root[data-responsive-navigation="docked"] .app-mobile-nav-trigger {
|
|
756
569
|
display: none;
|
|
757
570
|
}
|
|
758
571
|
}
|
|
759
572
|
|
|
760
|
-
/* The compact step of the HORIZONTAL PAGE-INSET AXIS (gh#330). It is deliberately NOT the shell's
|
|
761
|
-
* 900px restructure breakpoint: the bar's inset is not a fact about whether a rail is docked, it
|
|
762
|
-
* is a fact about where the page's content edge is — and the page steps its gutters to
|
|
763
|
-
* --space-page-compact-x at exactly `(max-width: 720px)` (see styles/layout.css ·
|
|
764
|
-
* `.ui-page-container`). Stated with the identical condition so the two sides can never drift
|
|
765
|
-
* apart again; the shell's own restructure block above still owns everything that IS about the
|
|
766
|
-
* rail. This block mentions `.app-topbar` only, so the one-breakpoint `.app-root` contract
|
|
767
|
-
* (gh#213) is untouched. */
|
|
768
573
|
@media (max-width: 720px) {
|
|
769
574
|
.app-topbar {
|
|
770
575
|
padding-inline: var(--app-shell-bar-inset-compact);
|
|
@@ -775,10 +580,6 @@
|
|
|
775
580
|
display: contents;
|
|
776
581
|
}
|
|
777
582
|
|
|
778
|
-
/*
|
|
779
|
-
* ORG SWITCHER — shared Console/Admin tenant control. Widths, insets and state geometry stay
|
|
780
|
-
* inside the library so a consumer never needs `w-64` or descendant-selector overrides.
|
|
781
|
-
*/
|
|
782
583
|
.ui-org-switcher {
|
|
783
584
|
width: 100%;
|
|
784
585
|
min-width: 0;
|
|
@@ -920,7 +721,6 @@
|
|
|
920
721
|
background: hsl(var(--accent));
|
|
921
722
|
}
|
|
922
723
|
|
|
923
|
-
/* Non-interactive brand header — no click target, so no pointer/hover affordance and no caret. */
|
|
924
724
|
.sb-product-static,
|
|
925
725
|
.sb-product-static:hover {
|
|
926
726
|
cursor: default;
|
|
@@ -992,16 +792,6 @@
|
|
|
992
792
|
margin-top: var(--sidebar-section-gap);
|
|
993
793
|
}
|
|
994
794
|
|
|
995
|
-
/* The section label is the ONE piece of sidebar text with no colour knob.
|
|
996
|
-
* Every other one has a variable with this same fallback — item, hover,
|
|
997
|
-
* active, icon — and the sidebar is paintable by design (`--sidebar-gradient`
|
|
998
|
-
* is a published knob). So a consumer that paints it can recolour every label
|
|
999
|
-
* except this heading, which stays muted-foreground and lands on whatever
|
|
1000
|
-
* they painted: measured at 1.50 against a mid-tone blue, where 11px text
|
|
1001
|
-
* needs 4.5.
|
|
1002
|
-
*
|
|
1003
|
-
* The fallback is the old value, so nothing changes for a sidebar that does
|
|
1004
|
-
* not paint itself. */
|
|
1005
795
|
.sb-section-label {
|
|
1006
796
|
padding: 0 var(--sidebar-section-label-padding-x) var(--sidebar-section-label-padding-bottom);
|
|
1007
797
|
color: var(--sidebar-section-label-foreground, hsl(var(--muted-foreground)));
|
|
@@ -1030,9 +820,7 @@
|
|
|
1030
820
|
border: 0;
|
|
1031
821
|
border-radius: var(--sidebar-nav-item-radius);
|
|
1032
822
|
background: transparent;
|
|
1033
|
-
|
|
1034
|
-
* icon reads a SEPARATE knob on `.sb-icon` below, so a service can darken 16px nav icons
|
|
1035
|
-
* without re-tinting every muted text. */
|
|
823
|
+
|
|
1036
824
|
color: var(--sidebar-nav-item-foreground, hsl(var(--muted-foreground)));
|
|
1037
825
|
cursor: pointer;
|
|
1038
826
|
font-family: inherit;
|
|
@@ -1041,18 +829,6 @@
|
|
|
1041
829
|
text-align: start;
|
|
1042
830
|
}
|
|
1043
831
|
|
|
1044
|
-
/* Every nav row is a CONTROL, so it owes a visible keyboard indicator (WCAG 2.4.7) — and it
|
|
1045
|
-
* has to be the design system's, not the UA's. Measured in Chromium before this rule: the
|
|
1046
|
-
* first Tab into the shell landed on a rail item drawing Chrome's own
|
|
1047
|
-
* `outline: rgb(0,95,204) auto 1px`, a blue that belongs to no theme and matches nothing else
|
|
1048
|
-
* on the page, while every Button beside it drew the token ring. On a Slack-style shell that
|
|
1049
|
-
* is the FIRST thing a keyboard user sees.
|
|
1050
|
-
*
|
|
1051
|
-
* Same shape as `.app-main:focus-visible` above — suppress the UA outline, draw a token ring —
|
|
1052
|
-
* but NOT gated behind an opt-in width the way the region ring is. A whole-content-area frame
|
|
1053
|
-
* reads as a glitch and defaults off; a 2px ring hugging one 32px row is exactly the
|
|
1054
|
-
* affordance, so it reads the global `--focus-ring-width` and is on by default. `box-shadow`
|
|
1055
|
-
* rather than `outline` so the ring follows `--sidebar-nav-item-radius`. */
|
|
1056
832
|
.sb-nav-item:focus-visible {
|
|
1057
833
|
outline: none;
|
|
1058
834
|
box-shadow: 0 0 0 var(--focus-ring-width) hsl(var(--focus-ring-color, var(--ring)));
|
|
@@ -1063,9 +839,6 @@
|
|
|
1063
839
|
color: var(--sidebar-nav-item-hover-foreground, hsl(var(--foreground)));
|
|
1064
840
|
}
|
|
1065
841
|
|
|
1066
|
-
/* Active item reads its own bg/fg tokens (defaults = the hover look) so a service can give the
|
|
1067
|
-
* selected nav row a brand treatment — e.g. a gold tint + gold text on a navy sidebar — without
|
|
1068
|
-
* forking CSS. Defaults are byte-identical to the hover state. */
|
|
1069
842
|
.sb-nav-item[data-active="true"] {
|
|
1070
843
|
background: var(--sidebar-item-active-background, hsl(var(--accent)));
|
|
1071
844
|
color: var(--sidebar-item-active-foreground, hsl(var(--foreground)));
|
|
@@ -1079,11 +852,7 @@
|
|
|
1079
852
|
flex: 0 0 auto;
|
|
1080
853
|
line-height: 0;
|
|
1081
854
|
place-items: center;
|
|
1082
|
-
|
|
1083
|
-
* row colour, so the resting look is byte-identical to before. A service sets
|
|
1084
|
-
* `--sidebar-nav-icon-foreground` alone to get canonical darker icons beside muted labels — no
|
|
1085
|
-
* page-local selector, no global `--muted-foreground` re-tint. Colour only: size/geometry stay
|
|
1086
|
-
* on --sidebar-nav-icon-size. */
|
|
855
|
+
|
|
1087
856
|
color: var(--sidebar-nav-icon-foreground, currentColor);
|
|
1088
857
|
}
|
|
1089
858
|
|
|
@@ -1098,19 +867,12 @@
|
|
|
1098
867
|
min-width: 0;
|
|
1099
868
|
flex: 1;
|
|
1100
869
|
overflow: hidden;
|
|
1101
|
-
|
|
1102
|
-
* its clip box, and a 1em box is shorter than the font's ascent+descent: every descender and
|
|
1103
|
-
* Vietnamese tone mark below the baseline gets sheared off. Knob, not constant (rule #45). */
|
|
870
|
+
|
|
1104
871
|
line-height: var(--sidebar-nav-item-line-height);
|
|
1105
872
|
text-overflow: ellipsis;
|
|
1106
873
|
white-space: nowrap;
|
|
1107
874
|
}
|
|
1108
875
|
|
|
1109
|
-
/* The nav row's count pill. Its COLOUR is a knob pair, and the resting values are exactly the
|
|
1110
|
-
* literals it carried before (rule #44/#45) — `initial` at the token tier so the role defaults
|
|
1111
|
-
* re-resolve under a scoped theme, resolved here at the call site. Before the knobs the only
|
|
1112
|
-
* way to emphasise a row was to nest a `<Badge>` INSIDE `badge`, which produced two stacked
|
|
1113
|
-
* pills: a 37.11×19.14 `.sb-badge` wrapping a 25.11×19.14 `<Badge>` with its own border. */
|
|
1114
876
|
.sb-badge {
|
|
1115
877
|
display: inline-flex;
|
|
1116
878
|
min-width: 1.125rem;
|
|
@@ -1125,12 +887,6 @@
|
|
|
1125
887
|
padding-inline: 0.375rem;
|
|
1126
888
|
}
|
|
1127
889
|
|
|
1128
|
-
/* `badgeTone="destructive"` — the count is ADDRESSED TO YOU (an @mention, a direct message),
|
|
1129
|
-
* not merely unread. Present-when-on (rule #44): a neutral row emits no `data-tone` at all, so
|
|
1130
|
-
* this rule cannot reach it and the default pill is byte-identical. GEOMETRY IS UNTOUCHED — the
|
|
1131
|
-
* tone moves two colours and nothing else, which is the whole point of the axis: the row's
|
|
1132
|
-
* height, the pill's radius and its 0.375rem inline pad stay on the base rule, so a mention row
|
|
1133
|
-
* and an unread row still line up in the same column. */
|
|
1134
890
|
.sb-badge[data-tone="destructive"] {
|
|
1135
891
|
background: var(--sidebar-badge-destructive-background, hsl(var(--destructive)));
|
|
1136
892
|
color: var(--sidebar-badge-destructive-foreground, hsl(var(--destructive-foreground)));
|
|
@@ -1142,7 +898,6 @@
|
|
|
1142
898
|
padding: var(--space-2);
|
|
1143
899
|
}
|
|
1144
900
|
|
|
1145
|
-
/* Collapsible group trigger chevron (rotates when open). */
|
|
1146
901
|
.sb-nav-group-trigger .sb-chevron {
|
|
1147
902
|
margin-inline-start: auto;
|
|
1148
903
|
flex: 0 0 auto;
|
|
@@ -1154,8 +909,6 @@
|
|
|
1154
909
|
transform: rotate(180deg);
|
|
1155
910
|
}
|
|
1156
911
|
|
|
1157
|
-
/* Nested rows (submenu) — left guide line + dot markers, design `.sb-nest`.
|
|
1158
|
-
* Active child reads as primary-colored text, never a filled block. */
|
|
1159
912
|
.sb-nav-sub {
|
|
1160
913
|
display: flex;
|
|
1161
914
|
flex-direction: column;
|
|
@@ -1168,8 +921,7 @@
|
|
|
1168
921
|
.sb-nav-item--sub {
|
|
1169
922
|
height: 1.75rem;
|
|
1170
923
|
font-size: var(--sidebar-nav-sub-font-size);
|
|
1171
|
-
|
|
1172
|
-
* included. Default unchanged. */
|
|
924
|
+
|
|
1173
925
|
color: var(--sidebar-nav-item-foreground, hsl(var(--muted-foreground)));
|
|
1174
926
|
}
|
|
1175
927
|
|
|
@@ -1199,11 +951,6 @@
|
|
|
1199
951
|
opacity: 1;
|
|
1200
952
|
}
|
|
1201
953
|
|
|
1202
|
-
/* gh#228 — nav ICON state knobs. Declared AFTER the row-state rules so they win at equal
|
|
1203
|
-
* specificity, in the same order the row states resolve (hover → active → disabled). Each falls
|
|
1204
|
-
* back to the base icon knob and finally to `currentColor` (= the row colour for that state), so
|
|
1205
|
-
* the defaults are byte-identical to the pre-gh#228 rendering and setting only
|
|
1206
|
-
* `--sidebar-nav-icon-foreground` themes every state at once. Colour only — no geometry. */
|
|
1207
954
|
.sb-nav-item:hover .sb-icon {
|
|
1208
955
|
color: var(
|
|
1209
956
|
--sidebar-nav-icon-hover-foreground,
|
|
@@ -1218,9 +965,6 @@
|
|
|
1218
965
|
);
|
|
1219
966
|
}
|
|
1220
967
|
|
|
1221
|
-
/* Disabled rows (`aria-disabled="true"`, set by SidebarItem for item.disabled). Defaults resolve
|
|
1222
|
-
* to the RESTING row/icon colour, so a disabled row reads as inert in every state; a service dims
|
|
1223
|
-
* it further with the two disabled knobs. */
|
|
1224
968
|
.sb-nav-item[aria-disabled="true"] {
|
|
1225
969
|
color: var(
|
|
1226
970
|
--sidebar-nav-item-disabled-foreground,
|
|
@@ -1235,8 +979,6 @@
|
|
|
1235
979
|
);
|
|
1236
980
|
}
|
|
1237
981
|
|
|
1238
|
-
/* Collapsed-rail flyout — PORTALED (Radix Popover) so it escapes the sidebar's overflow and is
|
|
1239
|
-
* never clipped: names a leaf item (tooltip) or reveals a group's submenu on hover/focus. */
|
|
1240
982
|
.sb-flyout-pop {
|
|
1241
983
|
display: flex;
|
|
1242
984
|
width: auto;
|
|
@@ -1254,7 +996,6 @@
|
|
|
1254
996
|
white-space: nowrap;
|
|
1255
997
|
}
|
|
1256
998
|
|
|
1257
|
-
/* Footer user — circular avatar with live dot + overflow menu, design `.sb-user`. */
|
|
1258
999
|
.sb-user {
|
|
1259
1000
|
display: flex;
|
|
1260
1001
|
width: 100%;
|
|
@@ -1377,30 +1118,6 @@
|
|
|
1377
1118
|
gap: 2px;
|
|
1378
1119
|
}
|
|
1379
1120
|
|
|
1380
|
-
/* Topbar — a pure slot bar. start (inline-start) · center (grows, centered) · end (inline-end).
|
|
1381
|
-
* The library owns ONLY this positioning; every control inside is the consumer's to compose.
|
|
1382
|
-
*
|
|
1383
|
-
* SHRINK CONTRACT (gh#226) — a hosted console packs an intrinsically wide brand/tenant string
|
|
1384
|
-
* into `start` and a fixed-width search trigger into `center`; at a compact desktop width
|
|
1385
|
-
* (1024px minus a 16rem sidebar) that content used to push `end` (locale picker, user menu) past
|
|
1386
|
-
* the bar and out of the viewport, and leak a horizontal document scroll. The contract is:
|
|
1387
|
-
* root — never wider than its AppShell grid/flex allocation (`max-width:100%` +
|
|
1388
|
-
* `min-width:0`, so it shrinks whether the parent is a grid track or a flex line);
|
|
1389
|
-
* start — shrinks first, its content clipped INSIDE the slot (never spills over center/end);
|
|
1390
|
-
* center — `flex-basis:0`, so it yields all of its box before `start` gives up a pixel;
|
|
1391
|
-
* end — `flex:0 0 auto`, so it keeps its natural width and stays anchored inline-end.
|
|
1392
|
-
* Slots clip with `clip`, NOT `hidden`: a `hidden` box is still a scroll container, so focusing a
|
|
1393
|
-
* clipped control would scroll the slot and shove its leading content out of view. The clip
|
|
1394
|
-
* margin keeps the focus ring of an edge control paintable (WCAG 2.4.11 / 2.4.13).
|
|
1395
|
-
*
|
|
1396
|
-
* BOX KNOBS (rule #45) — --topbar-height / --topbar-inset / --topbar-gap. Their defaults are the
|
|
1397
|
-
* QUIET ones (`auto` / `0` / the previous 8px), i.e. byte-identical rendering to before they
|
|
1398
|
-
* existed: inside AppShell the `.app-topbar` grid row still owns the height and inset. A service
|
|
1399
|
-
* that mounts <Topbar> DIRECTLY on a page (no AppShell) now sizes it from the theme —
|
|
1400
|
-
* `--topbar-height: 3.5rem; --topbar-inset: var(--space-4)` — instead of an app-local class.
|
|
1401
|
-
* `--topbar-gap` re-rhythms the whole bar at once: it is both the gap BETWEEN the three clusters
|
|
1402
|
-
* and the gap INSIDE each of them, so a denser bar stays internally consistent.
|
|
1403
|
-
* The shrink contract above is unaffected — none of these touch flex/overflow. */
|
|
1404
1121
|
.ui-topbar {
|
|
1405
1122
|
display: flex;
|
|
1406
1123
|
height: var(--topbar-height);
|
|
@@ -1411,17 +1128,7 @@
|
|
|
1411
1128
|
align-items: center;
|
|
1412
1129
|
gap: var(--topbar-gap);
|
|
1413
1130
|
padding-inline: var(--topbar-inset);
|
|
1414
|
-
|
|
1415
|
-
* - Chromium honours overflow-clip-margin ONLY when BOTH axes are `clip`;
|
|
1416
|
-
* a single-axis clip silently ignores the margin, and a flush-edge
|
|
1417
|
-
* control's ring vanishes on the clipped axis.
|
|
1418
|
-
* - `hidden` can never work here (no clip-margin, and pairing it with
|
|
1419
|
-
* `visible` computes to `auto`, which still clips).
|
|
1420
|
-
* - The margin must be a bare var() — Chromium drops calc() at parse time.
|
|
1421
|
-
* So: clip BOTH axes and let the margin carry the ring on every side. The
|
|
1422
|
-
* gh#226 shrink/truncation contract is intact (content clips 8px outside
|
|
1423
|
-
* the box). Safari (clip yes, clip-margin no) falls back to `visible`
|
|
1424
|
-
* below. */
|
|
1131
|
+
|
|
1425
1132
|
overflow: clip;
|
|
1426
1133
|
overflow-clip-margin: var(--focus-ring-clip-margin);
|
|
1427
1134
|
}
|
|
@@ -1432,17 +1139,10 @@
|
|
|
1432
1139
|
min-width: 0;
|
|
1433
1140
|
align-items: center;
|
|
1434
1141
|
gap: var(--topbar-gap);
|
|
1435
|
-
/* Same both-axes-clip + margin contract as .ui-topbar above (gh#291): the
|
|
1436
|
-
* 8px margin covers the 3px ring on every side of a flush-edge control;
|
|
1437
|
-
* single-axis clip would silently drop the margin in Chromium. */
|
|
1438
1142
|
overflow: clip;
|
|
1439
1143
|
overflow-clip-margin: var(--focus-ring-clip-margin);
|
|
1440
1144
|
}
|
|
1441
|
-
|
|
1442
|
-
* both-axes clip above would eat every flush-edge focus ring there with no
|
|
1443
|
-
* margin to save it. Trade slot containment for ring visibility on that
|
|
1444
|
-
* engine only — the .app-topbar horizontal clip still prevents bar blowout
|
|
1445
|
-
* and document scroll. */
|
|
1145
|
+
|
|
1446
1146
|
@supports not (overflow-clip-margin: 1px) {
|
|
1447
1147
|
.app-sidebar,
|
|
1448
1148
|
.app-topbar,
|
|
@@ -1461,7 +1161,6 @@
|
|
|
1461
1161
|
min-width: 0;
|
|
1462
1162
|
flex: 0 1 auto;
|
|
1463
1163
|
overflow: hidden;
|
|
1464
|
-
/* Declares its own line box because it CLIPS — see gh#254. */
|
|
1465
1164
|
line-height: var(--topbar-start-truncate-line-height);
|
|
1466
1165
|
text-overflow: ellipsis;
|
|
1467
1166
|
white-space: nowrap;
|
|
@@ -1476,11 +1175,6 @@
|
|
|
1476
1175
|
margin-inline-start: auto;
|
|
1477
1176
|
}
|
|
1478
1177
|
|
|
1479
|
-
/* COLLISION CONTRACT (gh#244) — with a docked 16rem sidebar, 901–1100px viewports do not have
|
|
1480
|
-
* enough room for a breadcrumb/title, full search trigger and end utilities. The center slot is
|
|
1481
|
-
* optional by definition, so remove it before it can cover either owned edge. This also gives
|
|
1482
|
-
* phones the same deterministic allocation. A consumer with a real compact center presentation
|
|
1483
|
-
* can opt it back in through the public token instead of a page-local media query. */
|
|
1484
1178
|
@media (width <= 68.75rem) {
|
|
1485
1179
|
.ui-topbar-center {
|
|
1486
1180
|
display: var(--topbar-center-compact-display);
|
|
@@ -1516,7 +1210,6 @@
|
|
|
1516
1210
|
color: hsl(var(--muted-foreground));
|
|
1517
1211
|
}
|
|
1518
1212
|
|
|
1519
|
-
/* Non-interactive brand chip — no menu/handler, so no pointer/hover affordance and no caret. */
|
|
1520
1213
|
.tb-chip-static,
|
|
1521
1214
|
.tb-chip-static:hover {
|
|
1522
1215
|
border-color: transparent;
|
|
@@ -1540,9 +1233,7 @@
|
|
|
1540
1233
|
min-width: 0;
|
|
1541
1234
|
overflow: hidden;
|
|
1542
1235
|
font-weight: 500;
|
|
1543
|
-
|
|
1544
|
-
* font's descenders. `.tb-chip` uses `font: inherit`, so without this the chip would shear its
|
|
1545
|
-
* glyphs the moment a service set a tight line-height on the bar. */
|
|
1236
|
+
|
|
1546
1237
|
line-height: 1.5;
|
|
1547
1238
|
text-overflow: ellipsis;
|
|
1548
1239
|
white-space: nowrap;
|
|
@@ -1560,11 +1251,7 @@
|
|
|
1560
1251
|
|
|
1561
1252
|
.tb-search {
|
|
1562
1253
|
display: flex;
|
|
1563
|
-
|
|
1564
|
-
* defaults to `none`, so nothing caps it short of `end`. A consumer opting into the older
|
|
1565
|
-
* fixed-width, centered look sets the token to an explicit length instead of overriding this
|
|
1566
|
-
* rule. `width: 100%` + `max-width: none` is the pair that makes both cases work from ONE
|
|
1567
|
-
* token: a set length caps it, an unset one (`none`) doesn't. */
|
|
1254
|
+
|
|
1568
1255
|
width: 100%;
|
|
1569
1256
|
max-width: var(--topbar-search-max-width);
|
|
1570
1257
|
height: var(--control-height-sm);
|
|
@@ -1637,12 +1324,6 @@
|
|
|
1637
1324
|
background: hsl(var(--attention));
|
|
1638
1325
|
}
|
|
1639
1326
|
|
|
1640
|
-
/* TOPBAR CHIP/SEARCH DENSITY ONLY — this is NOT a second shell breakpoint. The `.app-root`
|
|
1641
|
-
* restructure that used to live here (a 768px duplicate of the 900px rule that also deleted the
|
|
1642
|
-
* footer row and re-declared the grid rows with a 3rem literal) is gone; see the note on the one
|
|
1643
|
-
* `@media (width <= 56.25rem)` block above. What remains is purely the optional `.tb-*` console
|
|
1644
|
-
* chrome collapsing to icon-only on a phone, which is independent of where the shell switches to
|
|
1645
|
-
* its drawer. */
|
|
1646
1327
|
@media (max-width: 768px) {
|
|
1647
1328
|
.tb-chip-sep,
|
|
1648
1329
|
.tb-search .kbd {
|
|
@@ -1660,15 +1341,6 @@
|
|
|
1660
1341
|
}
|
|
1661
1342
|
}
|
|
1662
1343
|
|
|
1663
|
-
/*
|
|
1664
|
-
* REDUCED MOTION for the AppShell mobile drawer (WCAG 2.3.3 / 2.2.2). The drawer is a Sheet, so it
|
|
1665
|
-
* animates via Tailwind `data-[state]:animate-in|animate-out` + `slide-in-from-*` utilities.
|
|
1666
|
-
* DELIBERATELY UNLAYERED: Tailwind v4 emits those into `@layer utilities`, which beats any rule in
|
|
1667
|
-
* `@layer components` regardless of specificity — this gate was previously written inside the
|
|
1668
|
-
* components layer above and could never win. Same reasoning as the overlay gate in
|
|
1669
|
-
* dialog-layout.css (which also covers this drawer via [data-slot="sheet-*"]); kept here as well so
|
|
1670
|
-
* a consumer importing only `styles/shell-layout` still gets it.
|
|
1671
|
-
*/
|
|
1672
1344
|
@media (prefers-reduced-motion: reduce) {
|
|
1673
1345
|
.app-mobile-nav-overlay,
|
|
1674
1346
|
.app-mobile-nav-drawer {
|
|
@@ -1677,18 +1349,6 @@
|
|
|
1677
1349
|
}
|
|
1678
1350
|
}
|
|
1679
1351
|
|
|
1680
|
-
/*
|
|
1681
|
-
* ERROR SURFACE — the 403 / 404 / 500 / 503 exception surface (gh#221, gh#251).
|
|
1682
|
-
*
|
|
1683
|
-
* Geometry is PACKAGE-OWNED at 1440 / 1024 / 390: a consumer never writes `min-h-dvh`, a
|
|
1684
|
-
* flex-centring class or a media query for an error page. In `system` mode the viewport centring
|
|
1685
|
-
* comes from `CenteredShell align="center"` (which the component renders itself); this block owns
|
|
1686
|
-
* the surface block that is identical in BOTH modes — measure, rhythm, metadata list.
|
|
1687
|
-
*
|
|
1688
|
-
* The narrow step is a CONTAINER query, not a viewport one (the SplitPane precedent, gh#165): the
|
|
1689
|
-
* surface reads its OWN width, so it compacts correctly whether the shrinking came from a 390px
|
|
1690
|
-
* phone or from an application shell whose sidebar is expanded on a laptop.
|
|
1691
|
-
*/
|
|
1692
1352
|
@layer components {
|
|
1693
1353
|
.ui-error-surface {
|
|
1694
1354
|
container: error-surface / inline-size;
|
|
@@ -1697,7 +1357,7 @@
|
|
|
1697
1357
|
max-width: var(--error-surface-max-width);
|
|
1698
1358
|
flex-direction: column;
|
|
1699
1359
|
align-items: center;
|
|
1700
|
-
|
|
1360
|
+
|
|
1701
1361
|
margin-inline: auto;
|
|
1702
1362
|
gap: var(--error-surface-gap);
|
|
1703
1363
|
padding-block: var(--error-surface-padding-block);
|
|
@@ -1710,9 +1370,6 @@
|
|
|
1710
1370
|
padding-block-end: var(--error-surface-brand-gap);
|
|
1711
1371
|
}
|
|
1712
1372
|
|
|
1713
|
-
/* The EmptyState body already owns its own vertical rhythm and description measure
|
|
1714
|
-
* (--empty-state-*); the surface only removes the duplicated block padding so the two spacing
|
|
1715
|
-
* systems do not stack into a hole between the status code and the icon. */
|
|
1716
1373
|
.ui-error-surface .ui-error-surface-body {
|
|
1717
1374
|
width: 100%;
|
|
1718
1375
|
padding-block: 0;
|
|
@@ -1727,7 +1384,6 @@
|
|
|
1727
1384
|
width: 100%;
|
|
1728
1385
|
flex-direction: column;
|
|
1729
1386
|
gap: var(--error-surface-meta-gap);
|
|
1730
|
-
/* Chrome is a token, default quiet (rule #44) — `none` unless a service opts in. */
|
|
1731
1387
|
border-block-start: var(--error-surface-meta-border);
|
|
1732
1388
|
padding-block-start: var(--error-surface-meta-padding-block);
|
|
1733
1389
|
margin: 0;
|
|
@@ -1749,10 +1405,6 @@
|
|
|
1749
1405
|
max-width: var(--error-surface-progress-max-width);
|
|
1750
1406
|
}
|
|
1751
1407
|
|
|
1752
|
-
/*
|
|
1753
|
-
* NARROW STEP (the 390 case). Reclaim vertical space and stop a long ja / vi metadata row from
|
|
1754
|
-
* wrapping into a ragged two-column shape: each label stacks over its value, centred.
|
|
1755
|
-
*/
|
|
1756
1408
|
@container error-surface (width < 30rem) {
|
|
1757
1409
|
.ui-error-surface {
|
|
1758
1410
|
padding-block: var(--error-surface-padding-block-compact);
|
|
@@ -1766,24 +1418,11 @@
|
|
|
1766
1418
|
}
|
|
1767
1419
|
|
|
1768
1420
|
@layer components {
|
|
1769
|
-
|
|
1770
|
-
* A PUBLIC landing page (marketing header · hero · sections · legal footer) is a COMPOSITION,
|
|
1771
|
-
* not a framework component (docs/COMPOSITION-VS-COMPONENT.md: Hero / Navbar / Footer / Pricing
|
|
1772
|
-
* all FAIL the Framework-Component Test). What the consumer must NOT own is the SHELL geometry —
|
|
1773
|
-
* the content measure, the header/footer measure alignment, the section rhythm and the flat
|
|
1774
|
-
* public-surface chrome. This preset owns all of it through `--centered-shell-landing-*` knobs,
|
|
1775
|
-
* so a landing composes real primitives with ZERO page-local CSS and zero descendant selectors.
|
|
1776
|
-
*
|
|
1777
|
-
* `preset="default"` emits NO `data-preset` attribute at all, so none of this can match and every
|
|
1778
|
-
* existing CenteredShell keeps its exact box (the gh#231 inert-default contract). */
|
|
1421
|
+
|
|
1779
1422
|
.ui-centered-shell[data-preset="public-landing"] {
|
|
1780
1423
|
--centered-shell-main-padding: var(--centered-shell-landing-main-padding-block)
|
|
1781
1424
|
var(--centered-shell-landing-inset-inline);
|
|
1782
|
-
/* The hero title is a real `Heading level={1}`; the preset re-points the h1 tier the same way
|
|
1783
|
-
* `.ui-auth-shell` re-points it — never a consumer font-size. */
|
|
1784
1425
|
--heading-h1: var(--centered-shell-landing-heading-size);
|
|
1785
|
-
/* Flat public surface: every Card in the subtree loses its elevation from ONE knob instead of
|
|
1786
|
-
* a consumer `.landing .card { box-shadow: none }` descendant selector. */
|
|
1787
1426
|
--card-shadow: var(--centered-shell-landing-card-shadow);
|
|
1788
1427
|
background: hsl(var(--centered-shell-landing-background, var(--background)));
|
|
1789
1428
|
}
|
|
@@ -1792,13 +1431,10 @@
|
|
|
1792
1431
|
display: flex;
|
|
1793
1432
|
max-width: var(--centered-shell-landing-max-width);
|
|
1794
1433
|
flex-direction: column;
|
|
1795
|
-
|
|
1434
|
+
|
|
1796
1435
|
gap: var(--centered-shell-landing-section-gap);
|
|
1797
1436
|
}
|
|
1798
1437
|
|
|
1799
|
-
/* Header and footer share the column's measure WITHOUT a consumer max-width wrapper: the inline
|
|
1800
|
-
* padding is the page gutter until the viewport is wider than the measure, then it grows so the
|
|
1801
|
-
* bar content starts on exactly the same inline edge as the centred column. */
|
|
1802
1438
|
.ui-centered-shell[data-preset="public-landing"] .ui-centered-shell-bar,
|
|
1803
1439
|
.ui-centered-shell[data-preset="public-landing"] .ui-centered-shell-footer {
|
|
1804
1440
|
padding-inline: max(
|
|
@@ -1812,8 +1448,6 @@
|
|
|
1812
1448
|
text-align: start;
|
|
1813
1449
|
}
|
|
1814
1450
|
|
|
1815
|
-
/* Compact step (the 390px acceptance width sits here): the gutter, the section rhythm and the
|
|
1816
|
-
* hero tier switch to their compact knobs. One media query, owned by the package. */
|
|
1817
1451
|
@media (width < 40rem) {
|
|
1818
1452
|
.ui-centered-shell[data-preset="public-landing"] {
|
|
1819
1453
|
--centered-shell-landing-inset-inline: var(--centered-shell-landing-inset-inline-compact);
|