@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
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Badge,
|
|
3
|
+
Card,
|
|
4
|
+
CardContent,
|
|
5
|
+
CardDescription,
|
|
6
|
+
CardHeader,
|
|
7
|
+
CardTitle,
|
|
8
|
+
DataTable,
|
|
9
|
+
type ColumnDef,
|
|
10
|
+
} from "@godxjp/ui/data-display";
|
|
11
|
+
import {
|
|
12
|
+
Checkbox,
|
|
13
|
+
Field,
|
|
14
|
+
Input,
|
|
15
|
+
Select,
|
|
16
|
+
SelectContent,
|
|
17
|
+
SelectItem,
|
|
18
|
+
SelectTrigger,
|
|
19
|
+
SelectValue,
|
|
20
|
+
Switch,
|
|
21
|
+
} from "@godxjp/ui/data-entry";
|
|
22
|
+
import { Button, Text } from "@godxjp/ui/general";
|
|
23
|
+
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Density · design-token foundation. One knob (`<PageContainer density>`) swaps a
|
|
27
|
+
* single CSS class (`.ui-density-compact|default|comfortable`) that retunes
|
|
28
|
+
* --control-height, --control-padding-x, --checkbox-size, --switch-* and the φ
|
|
29
|
+
* unit. The first card renders the SAME real controls inside each density-scoped
|
|
30
|
+
* subtree so the retune is visible at rest. The DataTable owns a separate density
|
|
31
|
+
* prop (--table-row-height / --table-cell-padding-y), shown in its own card.
|
|
32
|
+
* Composed only from real @godxjp/ui components.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
type Line = { id: string; item: string; qty: string };
|
|
36
|
+
|
|
37
|
+
const lines: Line[] = [
|
|
38
|
+
{ id: "L-01", item: "ライセンス", qty: "12" },
|
|
39
|
+
{ id: "L-02", item: "保守費", qty: "1" },
|
|
40
|
+
{ id: "L-03", item: "初期構築", qty: "1" },
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const columns: ColumnDef<Line>[] = [
|
|
44
|
+
{ key: "id", header: "明細", width: "w-20" },
|
|
45
|
+
{ key: "item", header: "品目" },
|
|
46
|
+
{
|
|
47
|
+
key: "qty",
|
|
48
|
+
header: "数量",
|
|
49
|
+
align: "right",
|
|
50
|
+
render: (row) => <Text tabular>{row.qty}</Text>,
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
/** The same real controls, rendered once per density column. */
|
|
55
|
+
function DensitySample({ idPrefix }: { idPrefix: string }) {
|
|
56
|
+
return (
|
|
57
|
+
<Flex direction="col" gap="md">
|
|
58
|
+
<Input defaultValue="株式会社ベトヤ" aria-label="取引先名" />
|
|
59
|
+
<Select defaultValue="paid" name={`${idPrefix}-status`}>
|
|
60
|
+
<SelectTrigger id={`${idPrefix}-status`} aria-label="状態">
|
|
61
|
+
<SelectValue placeholder="状態を選択" />
|
|
62
|
+
</SelectTrigger>
|
|
63
|
+
<SelectContent>
|
|
64
|
+
<SelectItem value="draft">下書き</SelectItem>
|
|
65
|
+
<SelectItem value="sent">送付済</SelectItem>
|
|
66
|
+
<SelectItem value="paid">入金済</SelectItem>
|
|
67
|
+
</SelectContent>
|
|
68
|
+
</Select>
|
|
69
|
+
<Flex direction="row" align="center" gap="md" wrap>
|
|
70
|
+
<Field id={`${idPrefix}-tax`} label="税込表示">
|
|
71
|
+
<Checkbox id={`${idPrefix}-tax`} defaultChecked />
|
|
72
|
+
</Field>
|
|
73
|
+
<Field id={`${idPrefix}-mail`} label="自動送信">
|
|
74
|
+
<Switch id={`${idPrefix}-mail`} defaultChecked />
|
|
75
|
+
</Field>
|
|
76
|
+
</Flex>
|
|
77
|
+
<Flex direction="row" align="center" gap="sm" wrap>
|
|
78
|
+
<Button size="sm">保存</Button>
|
|
79
|
+
<Button size="sm" variant="outline">
|
|
80
|
+
下書き
|
|
81
|
+
</Button>
|
|
82
|
+
<Button size="sm" variant="ghost" disabled>
|
|
83
|
+
ロック中
|
|
84
|
+
</Button>
|
|
85
|
+
</Flex>
|
|
86
|
+
</Flex>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const density = [
|
|
91
|
+
{
|
|
92
|
+
cls: "ui-density-compact",
|
|
93
|
+
label: "compact",
|
|
94
|
+
role: "kintone 風の密なテーブル",
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
cls: "ui-density-default",
|
|
98
|
+
label: "default",
|
|
99
|
+
role: "標準アプリ画面",
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
cls: "ui-density-comfortable",
|
|
103
|
+
label: "comfortable",
|
|
104
|
+
role: "公開 / モバイル · WCAG タッチ floor",
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
export default function Demo() {
|
|
109
|
+
return (
|
|
110
|
+
<PageContainer
|
|
111
|
+
title="Density"
|
|
112
|
+
subtitle="One knob · <PageContainer density> · retunes controls, tables, checkbox/switch, φ unit"
|
|
113
|
+
>
|
|
114
|
+
<Flex direction="col" gap="lg">
|
|
115
|
+
<Card>
|
|
116
|
+
<CardHeader>
|
|
117
|
+
<CardTitle level={2}>Same UI, three densities</CardTitle>
|
|
118
|
+
<CardDescription>
|
|
119
|
+
Set density once per page via {"<PageContainer density>"} · never the .ui-density-*
|
|
120
|
+
classes directly. Flip the one prop and Input, Select, Checkbox, Switch and Button all
|
|
121
|
+
re-tune their height, padding and the φ rhythm together. 44px (comfortable) is the
|
|
122
|
+
WCAG / Digital Agency touch floor.
|
|
123
|
+
</CardDescription>
|
|
124
|
+
</CardHeader>
|
|
125
|
+
<CardContent>
|
|
126
|
+
<Flex direction="row" gap="lg" align="start" wrap>
|
|
127
|
+
{density.map((d) => (
|
|
128
|
+
<Flex key={d.cls} direction="col" gap="sm" className="min-w-0 flex-1 sm:min-w-72">
|
|
129
|
+
<Flex direction="row" align="center" justify="between" gap="sm">
|
|
130
|
+
<Text size="xs" mono>
|
|
131
|
+
density="{d.label}"
|
|
132
|
+
</Text>
|
|
133
|
+
{d.label === "default" && <Badge variant="secondary">default</Badge>}
|
|
134
|
+
</Flex>
|
|
135
|
+
<Text size="xs" tone="muted">
|
|
136
|
+
{d.role}
|
|
137
|
+
</Text>
|
|
138
|
+
<div className={d.cls}>
|
|
139
|
+
<DensitySample idPrefix={d.label} />
|
|
140
|
+
</div>
|
|
141
|
+
</Flex>
|
|
142
|
+
))}
|
|
143
|
+
</Flex>
|
|
144
|
+
</CardContent>
|
|
145
|
+
</Card>
|
|
146
|
+
|
|
147
|
+
<Card>
|
|
148
|
+
<CardHeader>
|
|
149
|
+
<CardTitle level={2}>Table row density (DataTable density)</CardTitle>
|
|
150
|
+
<CardDescription>
|
|
151
|
+
The DataTable owns its own density axis: density="compact" vs
|
|
152
|
+
density="comfortable" swaps --table-row-height and --table-cell-padding-y.
|
|
153
|
+
The density toggle in the table toolbar drives the same prop at runtime.
|
|
154
|
+
</CardDescription>
|
|
155
|
+
</CardHeader>
|
|
156
|
+
<CardContent>
|
|
157
|
+
<Flex direction="row" gap="lg" align="start" wrap>
|
|
158
|
+
<Flex direction="col" gap="sm" className="min-w-0 flex-1 sm:min-w-72">
|
|
159
|
+
<Text size="xs" mono>
|
|
160
|
+
density="compact"
|
|
161
|
+
</Text>
|
|
162
|
+
<Card>
|
|
163
|
+
<CardContent flush>
|
|
164
|
+
<DataTable
|
|
165
|
+
data={lines}
|
|
166
|
+
columns={columns}
|
|
167
|
+
getRowId={(row) => row.id}
|
|
168
|
+
density="compact"
|
|
169
|
+
/>
|
|
170
|
+
</CardContent>
|
|
171
|
+
</Card>
|
|
172
|
+
</Flex>
|
|
173
|
+
<Flex direction="col" gap="sm" className="min-w-0 flex-1 sm:min-w-72">
|
|
174
|
+
<Text size="xs" mono>
|
|
175
|
+
density="comfortable"
|
|
176
|
+
</Text>
|
|
177
|
+
<Card>
|
|
178
|
+
<CardContent flush>
|
|
179
|
+
<DataTable
|
|
180
|
+
data={lines}
|
|
181
|
+
columns={columns}
|
|
182
|
+
getRowId={(row) => row.id}
|
|
183
|
+
density="comfortable"
|
|
184
|
+
/>
|
|
185
|
+
</CardContent>
|
|
186
|
+
</Card>
|
|
187
|
+
</Flex>
|
|
188
|
+
</Flex>
|
|
189
|
+
</CardContent>
|
|
190
|
+
</Card>
|
|
191
|
+
|
|
192
|
+
<Card>
|
|
193
|
+
<CardHeader>
|
|
194
|
+
<CardTitle level={2}>Page-level knob (PageContainer density)</CardTitle>
|
|
195
|
+
<CardDescription>
|
|
196
|
+
In a real screen you pass density to the page shell once; this nested PageContainer is
|
|
197
|
+
the comfortable knob applied to a whole form. Note the taller controls and looser φ
|
|
198
|
+
rhythm versus the compact column above.
|
|
199
|
+
</CardDescription>
|
|
200
|
+
</CardHeader>
|
|
201
|
+
<CardContent>
|
|
202
|
+
<PageContainer
|
|
203
|
+
density="comfortable"
|
|
204
|
+
title="請求書を作成"
|
|
205
|
+
subtitle="comfortable density · login / mobile surfaces"
|
|
206
|
+
>
|
|
207
|
+
<Flex direction="col" gap="md">
|
|
208
|
+
<Input defaultValue="2024-04-12" aria-label="発行日" />
|
|
209
|
+
<Select defaultValue="JPY" name="page-currency">
|
|
210
|
+
<SelectTrigger id="page-currency" aria-label="通貨">
|
|
211
|
+
<SelectValue placeholder="通貨を選択" />
|
|
212
|
+
</SelectTrigger>
|
|
213
|
+
<SelectContent>
|
|
214
|
+
<SelectItem value="JPY">JPY 日本円</SelectItem>
|
|
215
|
+
<SelectItem value="USD">USD 米ドル</SelectItem>
|
|
216
|
+
</SelectContent>
|
|
217
|
+
</Select>
|
|
218
|
+
<Field id="page-terms" label="利用規約に同意する">
|
|
219
|
+
<Checkbox id="page-terms" defaultChecked />
|
|
220
|
+
</Field>
|
|
221
|
+
<Flex direction="row" gap="sm" wrap>
|
|
222
|
+
<Button>発行する</Button>
|
|
223
|
+
<Button variant="outline">下書き保存</Button>
|
|
224
|
+
</Flex>
|
|
225
|
+
</Flex>
|
|
226
|
+
</PageContainer>
|
|
227
|
+
</CardContent>
|
|
228
|
+
</Card>
|
|
229
|
+
</Flex>
|
|
230
|
+
</PageContainer>
|
|
231
|
+
);
|
|
232
|
+
}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Badge,
|
|
3
|
+
Card,
|
|
4
|
+
CardContent,
|
|
5
|
+
CardDescription,
|
|
6
|
+
CardHeader,
|
|
7
|
+
CardTitle,
|
|
8
|
+
} from "@godxjp/ui/data-display";
|
|
9
|
+
import {
|
|
10
|
+
EMAIL_BRAND_MARK,
|
|
11
|
+
EMAIL_COLORS,
|
|
12
|
+
EMAIL_COLOR_SOURCE,
|
|
13
|
+
EMAIL_CTA,
|
|
14
|
+
EMAIL_FOCUS,
|
|
15
|
+
EMAIL_FOOTER,
|
|
16
|
+
EMAIL_MOBILE,
|
|
17
|
+
EMAIL_SHELL,
|
|
18
|
+
EMAIL_TYPOGRAPHY,
|
|
19
|
+
EMAIL_URGENCY,
|
|
20
|
+
type EmailColorToken,
|
|
21
|
+
} from "@godxjp/ui/email";
|
|
22
|
+
import { Text } from "@godxjp/ui/general";
|
|
23
|
+
import { Flex, PageContainer, ResponsiveGrid } from "@godxjp/ui/layout";
|
|
24
|
+
|
|
25
|
+
import { buildEmailSpecimenHtml } from "./_email-specimen";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Email tokens · the `@godxjp/ui/email` contract (issue #227).
|
|
29
|
+
*
|
|
30
|
+
* A transactional email is rendered by Blade/Twig/MJML, by clients that strip `<style>`, ignore
|
|
31
|
+
* CSS custom properties and block remote images — so neither the React components nor the CSS
|
|
32
|
+
* token file are reachable. `@godxjp/ui/email` is the framework-neutral bridge: literal hex and px
|
|
33
|
+
* DERIVED from the same `src/tokens/` files the web reads, plus the canonical brand mark as
|
|
34
|
+
* self-contained markup. Nothing on this page types a colour or a size by hand; the two iframes
|
|
35
|
+
* below render the real specimen document at the 480px desktop width and at a narrow mobile width.
|
|
36
|
+
*/
|
|
37
|
+
const specimen = buildEmailSpecimenHtml();
|
|
38
|
+
|
|
39
|
+
const colorRows = (Object.keys(EMAIL_COLORS) as EmailColorToken[]).map((token) => ({
|
|
40
|
+
token,
|
|
41
|
+
hex: EMAIL_COLORS[token],
|
|
42
|
+
role: EMAIL_COLOR_SOURCE[token].cssVar,
|
|
43
|
+
}));
|
|
44
|
+
|
|
45
|
+
const geometryGroups = [
|
|
46
|
+
{
|
|
47
|
+
title: "Shell (480px)",
|
|
48
|
+
rows: [
|
|
49
|
+
["width", EMAIL_SHELL.width],
|
|
50
|
+
["content column", EMAIL_SHELL.contentWidth],
|
|
51
|
+
["card padding", EMAIL_SHELL.padding],
|
|
52
|
+
["page gutter", EMAIL_SHELL.pagePadding],
|
|
53
|
+
["radius", EMAIL_SHELL.radius],
|
|
54
|
+
["border", EMAIL_SHELL.borderWidth],
|
|
55
|
+
["block gap", EMAIL_SHELL.gap],
|
|
56
|
+
["reference height", EMAIL_SHELL.referenceHeight],
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
title: "Typography",
|
|
61
|
+
rows: [
|
|
62
|
+
["body", `${EMAIL_TYPOGRAPHY.bodyFontSize}/${EMAIL_TYPOGRAPHY.bodyLineHeight}`],
|
|
63
|
+
["body weight", String(EMAIL_TYPOGRAPHY.bodyFontWeight)],
|
|
64
|
+
["heading", `${EMAIL_TYPOGRAPHY.headingFontSize}/${EMAIL_TYPOGRAPHY.headingLineHeight}`],
|
|
65
|
+
["heading weight", String(EMAIL_TYPOGRAPHY.headingFontWeight)],
|
|
66
|
+
["footer", `${EMAIL_FOOTER.fontSize}/${EMAIL_FOOTER.lineHeight}`],
|
|
67
|
+
["mobile heading", EMAIL_MOBILE.headingFontSize],
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
title: "Brand lockup",
|
|
72
|
+
rows: [
|
|
73
|
+
["mark box", `${EMAIL_BRAND_MARK.widthPx} × ${EMAIL_BRAND_MARK.heightPx}px`],
|
|
74
|
+
["viewBox", EMAIL_BRAND_MARK.viewBox],
|
|
75
|
+
["mark · wordmark gap", EMAIL_BRAND_MARK.gap],
|
|
76
|
+
["wordmark", EMAIL_BRAND_MARK.wordmarkFontSize],
|
|
77
|
+
["wordmark weight", String(EMAIL_BRAND_MARK.wordmarkFontWeight)],
|
|
78
|
+
["capsule", EMAIL_COLORS.brand],
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
title: "Primary CTA",
|
|
83
|
+
rows: [
|
|
84
|
+
["height", EMAIL_CTA.height],
|
|
85
|
+
["line-height", EMAIL_CTA.lineHeight],
|
|
86
|
+
["padding-x", EMAIL_CTA.paddingX],
|
|
87
|
+
["radius", EMAIL_CTA.radius],
|
|
88
|
+
["font-size", EMAIL_CTA.fontSize],
|
|
89
|
+
["font-weight", String(EMAIL_CTA.fontWeight)],
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
title: "Legal footer",
|
|
94
|
+
rows: [
|
|
95
|
+
["font-size", EMAIL_FOOTER.fontSize],
|
|
96
|
+
["line-height", String(EMAIL_FOOTER.lineHeight)],
|
|
97
|
+
["link gap", EMAIL_FOOTER.linkGap],
|
|
98
|
+
["padding-top", EMAIL_FOOTER.paddingTop],
|
|
99
|
+
["hairline", EMAIL_FOOTER.borderWidth],
|
|
100
|
+
["focus ring", EMAIL_FOCUS.borderWidth],
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
title: "Mobile reflow",
|
|
105
|
+
rows: [
|
|
106
|
+
["breakpoint", EMAIL_MOBILE.maxWidth],
|
|
107
|
+
["card width", EMAIL_MOBILE.width],
|
|
108
|
+
["card padding", EMAIL_MOBILE.padding],
|
|
109
|
+
["page gutter", EMAIL_MOBILE.pagePadding],
|
|
110
|
+
["heading", EMAIL_MOBILE.headingFontSize],
|
|
111
|
+
["CTA width", EMAIL_MOBILE.ctaWidth],
|
|
112
|
+
],
|
|
113
|
+
},
|
|
114
|
+
] as const;
|
|
115
|
+
|
|
116
|
+
const fontStacks = [
|
|
117
|
+
{ label: "--email-font-family-sans", value: EMAIL_TYPOGRAPHY.fontFamily },
|
|
118
|
+
{ label: "--email-font-family-mono", value: EMAIL_TYPOGRAPHY.monoFontFamily },
|
|
119
|
+
];
|
|
120
|
+
|
|
121
|
+
export default function Demo() {
|
|
122
|
+
return (
|
|
123
|
+
<PageContainer
|
|
124
|
+
title="Email tokens"
|
|
125
|
+
subtitle="@godxjp/ui/email · literal hex + px derived from the web tokens, for templates that cannot run React or resolve var()"
|
|
126
|
+
>
|
|
127
|
+
<Flex direction="col" gap="lg">
|
|
128
|
+
<Card>
|
|
129
|
+
<CardHeader>
|
|
130
|
+
<CardTitle level={2}>Rendered specimen · 480px desktop</CardTitle>
|
|
131
|
+
<CardDescription>
|
|
132
|
+
The real document, built only from the token export: table layout, inline styles, an
|
|
133
|
+
embedded brand mark, a bulletproof CTA and the legal footer. The card is{" "}
|
|
134
|
+
{EMAIL_SHELL.width} wide inside a {EMAIL_SHELL.pagePadding} gutter; the canonical
|
|
135
|
+
invitation reference measures {EMAIL_SHELL.widthPx}×{EMAIL_SHELL.referenceHeightPx}.
|
|
136
|
+
</CardDescription>
|
|
137
|
+
</CardHeader>
|
|
138
|
+
<CardContent>
|
|
139
|
+
<iframe
|
|
140
|
+
title="Transactional email specimen at 480px"
|
|
141
|
+
srcDoc={specimen}
|
|
142
|
+
className="border-border bg-background w-full rounded-md border"
|
|
143
|
+
style={{ height: 560 }}
|
|
144
|
+
/>
|
|
145
|
+
</CardContent>
|
|
146
|
+
</Card>
|
|
147
|
+
|
|
148
|
+
<Card>
|
|
149
|
+
<CardHeader>
|
|
150
|
+
<CardTitle level={2}>Rendered specimen · narrow mobile</CardTitle>
|
|
151
|
+
<CardDescription>
|
|
152
|
+
The same document at 360px. Below the {EMAIL_MOBILE.maxWidth} breakpoint the card goes
|
|
153
|
+
fluid, the inset drops to {EMAIL_MOBILE.padding}, the heading steps down to{" "}
|
|
154
|
+
{EMAIL_MOBILE.headingFontSize} and the CTA goes full-bleed. Every reflow rule has an
|
|
155
|
+
inline fallback, so a client that strips the style block still renders the desktop
|
|
156
|
+
layout rather than a broken one.
|
|
157
|
+
</CardDescription>
|
|
158
|
+
</CardHeader>
|
|
159
|
+
<CardContent>
|
|
160
|
+
<iframe
|
|
161
|
+
title="Transactional email specimen at 360px"
|
|
162
|
+
srcDoc={specimen}
|
|
163
|
+
className="border-border bg-background rounded-md border"
|
|
164
|
+
style={{ width: 360, height: 620 }}
|
|
165
|
+
/>
|
|
166
|
+
</CardContent>
|
|
167
|
+
</Card>
|
|
168
|
+
|
|
169
|
+
<Card>
|
|
170
|
+
<CardHeader>
|
|
171
|
+
<CardTitle level={2}>Brand mark</CardTitle>
|
|
172
|
+
<CardDescription>
|
|
173
|
+
The canonical GoDX mark is the emerald capsule plus the internal glyph. The artwork is
|
|
174
|
+
byte-identical to the <code><Logo mark="godx" /></code> path and to
|
|
175
|
+
the SCR-302 reference raster; only the rendered box is email-specific (
|
|
176
|
+
{EMAIL_BRAND_MARK.width}, against the 32px web box). A capsule alone is the incomplete
|
|
177
|
+
mark. In a header the mark is DECORATIVE and pairs with the readable wordmark{" "}
|
|
178
|
+
{EMAIL_BRAND_MARK.gap} away at {EMAIL_BRAND_MARK.wordmarkFontSize}/
|
|
179
|
+
{EMAIL_BRAND_MARK.wordmarkFontWeight}, so the name is announced once. Three
|
|
180
|
+
deliveries, none of which fetches an asset: inline SVG, the same SVG as a data: URL,
|
|
181
|
+
and a table fallback for clients with no SVG support.
|
|
182
|
+
</CardDescription>
|
|
183
|
+
</CardHeader>
|
|
184
|
+
<CardContent>
|
|
185
|
+
<ResponsiveGrid columns={{ sm: 1, md: 3 }}>
|
|
186
|
+
{[
|
|
187
|
+
{ label: "Inline <svg>", markup: EMAIL_BRAND_MARK.svg },
|
|
188
|
+
{
|
|
189
|
+
// Prose label, not markup: it names the email delivery form. The real delivery
|
|
190
|
+
// on the next line is a self-contained data: URI (email clients block remote
|
|
191
|
+
// images) and it does carry alt="GoDX".
|
|
192
|
+
// ui-audit-disable-next-line img-needs-alt
|
|
193
|
+
label: "data: URL in <img>",
|
|
194
|
+
markup: `<img src="${EMAIL_BRAND_MARK.dataUri}" width="${EMAIL_BRAND_MARK.widthPx}" height="${EMAIL_BRAND_MARK.heightPx}" alt="GoDX">`,
|
|
195
|
+
},
|
|
196
|
+
// Prose label, not markup: a raw <table> is the only brand-mark fallback that
|
|
197
|
+
// renders in email clients without SVG support, so the label names it literally.
|
|
198
|
+
// ui-audit-disable-next-line no-raw-table
|
|
199
|
+
{ label: "<table> fallback", markup: EMAIL_BRAND_MARK.tableHtml },
|
|
200
|
+
].map((item) => (
|
|
201
|
+
<Flex key={item.label} direction="col" gap="sm">
|
|
202
|
+
<div
|
|
203
|
+
// eslint-disable-next-line react/no-danger
|
|
204
|
+
dangerouslySetInnerHTML={{ __html: item.markup }}
|
|
205
|
+
/>
|
|
206
|
+
<Text size="sm" tone="muted">
|
|
207
|
+
{item.label}
|
|
208
|
+
</Text>
|
|
209
|
+
</Flex>
|
|
210
|
+
))}
|
|
211
|
+
</ResponsiveGrid>
|
|
212
|
+
<Flex direction="col" gap="xs" className="mt-4">
|
|
213
|
+
<Text size="sm" tone="muted">
|
|
214
|
+
viewBox {EMAIL_BRAND_MARK.viewBox} · {EMAIL_BRAND_MARK.width}×
|
|
215
|
+
{EMAIL_BRAND_MARK.height} · capsule {EMAIL_COLORS.brand} · glyph{" "}
|
|
216
|
+
{EMAIL_COLORS.brandForeground}
|
|
217
|
+
</Text>
|
|
218
|
+
</Flex>
|
|
219
|
+
</CardContent>
|
|
220
|
+
</Card>
|
|
221
|
+
|
|
222
|
+
<Card>
|
|
223
|
+
<CardHeader>
|
|
224
|
+
<CardTitle level={2}>Palette</CardTitle>
|
|
225
|
+
<CardDescription>
|
|
226
|
+
Each slot is the semantic web role converted HSL→hex at module load. No literal is
|
|
227
|
+
ever copied by hand. Re-theme the role and the email follows. The action-required rail
|
|
228
|
+
uses {EMAIL_URGENCY.accent} from <code>--attention</code>; solid urgency labels use{" "}
|
|
229
|
+
{EMAIL_URGENCY.solidForeground} on {EMAIL_URGENCY.solidBackground} only for icons or
|
|
230
|
+
large/bold text. Body copy remains foreground on surface.
|
|
231
|
+
</CardDescription>
|
|
232
|
+
</CardHeader>
|
|
233
|
+
<CardContent>
|
|
234
|
+
<ResponsiveGrid columns={{ sm: 2, md: 3, lg: 4 }}>
|
|
235
|
+
{colorRows.map((row) => (
|
|
236
|
+
<Flex key={row.token} direction="col" gap="xs">
|
|
237
|
+
<div
|
|
238
|
+
className="border-border h-12 rounded-md border"
|
|
239
|
+
style={{ backgroundColor: row.hex }}
|
|
240
|
+
/>
|
|
241
|
+
<Text size="sm">{row.token}</Text>
|
|
242
|
+
<Flex gap="xs" align="center">
|
|
243
|
+
<Badge tone="neutral" variant="outline">
|
|
244
|
+
{row.role}
|
|
245
|
+
</Badge>
|
|
246
|
+
<Text size="sm" tone="muted">
|
|
247
|
+
{row.hex}
|
|
248
|
+
</Text>
|
|
249
|
+
</Flex>
|
|
250
|
+
</Flex>
|
|
251
|
+
))}
|
|
252
|
+
</ResponsiveGrid>
|
|
253
|
+
</CardContent>
|
|
254
|
+
</Card>
|
|
255
|
+
|
|
256
|
+
<Card>
|
|
257
|
+
<CardHeader>
|
|
258
|
+
<CardTitle level={2}>Geometry & typography</CardTitle>
|
|
259
|
+
<CardDescription>
|
|
260
|
+
Literal px only. No rem, no calc(), no var(). The ramp is the canonical SCR-302 email
|
|
261
|
+
ramp, deliberately looser and quieter than the web one: body{" "}
|
|
262
|
+
{EMAIL_TYPOGRAPHY.bodyFontSize}/{EMAIL_TYPOGRAPHY.bodyLineHeight}, title{" "}
|
|
263
|
+
{EMAIL_TYPOGRAPHY.headingFontSize} at weight {EMAIL_TYPOGRAPHY.headingFontWeight} (a
|
|
264
|
+
transactional title is calm, not bold), legal band {EMAIL_FOOTER.fontSize}/
|
|
265
|
+
{EMAIL_FOOTER.lineHeight}. Font stacks name the canonical Noto Sans JP face FIRST and
|
|
266
|
+
then degrade. No email client honours <code>@font-face</code>, so a reader gets Noto
|
|
267
|
+
Sans JP only where it is already available and otherwise lands on Hiragino
|
|
268
|
+
(macOS/iOS), Yu Gothic (Windows), M PLUS 2, Meiryo, the system UI face, Arial, then{" "}
|
|
269
|
+
<code>sans-serif</code>. Families are single-quoted so the value drops into a
|
|
270
|
+
double-quoted <code>style</code> attribute unescaped.
|
|
271
|
+
</CardDescription>
|
|
272
|
+
</CardHeader>
|
|
273
|
+
<CardContent>
|
|
274
|
+
<Flex direction="col" gap="xs" className="mb-4">
|
|
275
|
+
{fontStacks.map((stack) => (
|
|
276
|
+
<Flex key={stack.label} direction="col" gap="xs">
|
|
277
|
+
<Badge tone="neutral" variant="outline">
|
|
278
|
+
{stack.label}
|
|
279
|
+
</Badge>
|
|
280
|
+
<Text size="sm" tone="muted">
|
|
281
|
+
{stack.value}
|
|
282
|
+
</Text>
|
|
283
|
+
</Flex>
|
|
284
|
+
))}
|
|
285
|
+
</Flex>
|
|
286
|
+
<ResponsiveGrid columns={{ sm: 1, md: 2, lg: 4 }}>
|
|
287
|
+
{geometryGroups.map((group) => (
|
|
288
|
+
<Flex key={group.title} direction="col" gap="xs">
|
|
289
|
+
<Text weight="medium">{group.title}</Text>
|
|
290
|
+
{group.rows.map(([label, value]) => (
|
|
291
|
+
<Flex key={label} justify="between" gap="sm">
|
|
292
|
+
<Text size="sm" tone="muted">
|
|
293
|
+
{label}
|
|
294
|
+
</Text>
|
|
295
|
+
<Text size="sm">{value}</Text>
|
|
296
|
+
</Flex>
|
|
297
|
+
))}
|
|
298
|
+
</Flex>
|
|
299
|
+
))}
|
|
300
|
+
</ResponsiveGrid>
|
|
301
|
+
</CardContent>
|
|
302
|
+
</Card>
|
|
303
|
+
</Flex>
|
|
304
|
+
</PageContainer>
|
|
305
|
+
);
|
|
306
|
+
}
|