@godxjp/ui 31.31.8 → 32.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -121
- package/agent/START-HERE.md +10 -10
- package/agent/components/Accordion.json +2 -2
- package/agent/components/AccountChip.json +1 -1
- package/agent/components/Actions.json +1 -1
- package/agent/components/Activity.json +2 -2
- package/agent/components/Affix.json +1 -1
- package/agent/components/Alert.json +22 -6
- package/agent/components/AlertDialog.json +8 -1
- package/agent/components/Anchor.json +4 -3
- package/agent/components/AppLauncher.json +2 -2
- package/agent/components/AppProvider.json +19 -11
- package/agent/components/AppSettingPicker.json +18 -2
- package/agent/components/AppShell.json +4 -5
- package/agent/components/AreaChart.json +0 -1
- package/agent/components/AspectRatio.json +2 -2
- package/agent/components/Attachments.json +3 -3
- package/agent/components/AuthAccountSummary.json +1 -1
- package/agent/components/AuthDivider.json +1 -1
- package/agent/components/AuthExpiryProvider.json +0 -1
- package/agent/components/AuthFooter.json +2 -2
- package/agent/components/AuthIdentity.json +3 -3
- package/agent/components/AuthStack.json +1 -1
- package/agent/components/Avatar.json +2 -12
- package/agent/components/Badge.json +1 -1
- package/agent/components/BarChart.json +0 -1
- package/agent/components/BranchScopePicker.json +1 -1
- package/agent/components/Breadcrumb.json +1 -1
- package/agent/components/Button.json +3 -3
- package/agent/components/Calendar.json +1 -1
- package/agent/components/Card.json +2 -2
- package/agent/components/CardBar.json +0 -1
- package/agent/components/CardContent.json +0 -1
- package/agent/components/Carousel.json +4 -3
- package/agent/components/Cascader.json +1 -1
- package/agent/components/CenteredShell.json +78 -17
- package/agent/components/ChatBubble.json +3 -3
- package/agent/components/ChatBubbleList.json +3 -3
- package/agent/components/ChatComposer.json +3 -3
- package/agent/components/ChatSuggestion.json +3 -3
- package/agent/components/Checkbox.json +1 -1
- package/agent/components/CheckboxGroup.json +0 -1
- package/agent/components/CodeBlock.json +1 -1
- package/agent/components/Collapsible.json +4 -4
- package/agent/components/ColorPicker.json +1 -1
- package/agent/components/Command.json +5 -5
- package/agent/components/CommandPalette.json +1 -1
- package/agent/components/CompactBarTrend.json +1 -1
- package/agent/components/Conversations.json +3 -3
- package/agent/components/CredentialReveal.json +1 -1
- package/agent/components/DataState.json +2 -2
- package/agent/components/DataTable.json +1 -1
- package/agent/components/DatePicker.json +1 -1
- package/agent/components/Descriptions.json +1 -1
- package/agent/components/Dialog.json +2 -2
- package/agent/components/DraggablePanel.json +5 -4
- package/agent/components/DropdownMenu.json +1 -1
- package/agent/components/EmojiPicker.json +3 -2
- package/agent/components/EmptyState.json +1 -1
- package/agent/components/ErrorSurface.json +3 -3
- package/agent/components/FeatureList.json +1 -1
- package/agent/components/Field.json +0 -1
- package/agent/components/Flex.json +34 -4
- package/agent/components/FloatButton.json +6 -5
- package/agent/components/Form.json +1 -1
- package/agent/components/FormErrors.json +0 -1
- package/agent/components/FormField.json +6 -6
- package/agent/components/FormFieldArray.json +0 -1
- package/agent/components/FormFieldControl.json +0 -1
- package/agent/components/FormRoot.json +1 -1
- package/agent/components/Heading.json +3 -0
- package/agent/components/Icon.json +1 -1
- package/agent/components/Image.json +7 -4
- package/agent/components/InfiniteQueryState.json +1 -1
- package/agent/components/Input.json +1 -1
- package/agent/components/InputOTP.json +2 -2
- package/agent/components/Label.json +3 -3
- package/agent/components/LegalDocumentShell.json +5 -4
- package/agent/components/Legend.json +1 -1
- package/agent/components/LineChart.json +0 -1
- package/agent/components/Link.json +0 -1
- package/agent/components/ListRow.json +1 -1
- package/agent/components/Logo.json +5 -4
- package/agent/components/Marquee.json +4 -3
- package/agent/components/Masonry.json +4 -3
- package/agent/components/MasterDetail.json +1 -1
- package/agent/components/MegaMenu.json +4 -3
- package/agent/components/MobileShell.json +4 -4
- package/agent/components/NavList.json +1 -1
- package/agent/components/NumberInput.json +1 -1
- package/agent/components/OrgChart.json +4 -3
- package/agent/components/OrgSwitcher.json +1 -1
- package/agent/components/OverlayPortalProvider.json +0 -1
- package/agent/components/PageContainer.json +3 -3
- package/agent/components/PageCover.json +3 -2
- package/agent/components/Pagination.json +1 -1
- package/agent/components/PasswordInput.json +1 -1
- package/agent/components/PasswordStrength.json +1 -1
- package/agent/components/PermissionMatrix.json +1 -1
- package/agent/components/PieChart.json +0 -1
- package/agent/components/Popover.json +31 -6
- package/agent/components/PrefetchLink.json +1 -1
- package/agent/components/Progress.json +1 -1
- package/agent/components/Prose.json +1 -1
- package/agent/components/QrCode.json +1 -1
- package/agent/components/Radio.json +0 -1
- package/agent/components/RadioGroup.json +2 -2
- package/agent/components/RangeTimeline.json +2 -1
- package/agent/components/Rating.json +1 -1
- package/agent/components/RecordPicker.json +1 -1
- package/agent/components/ResizablePanel.json +1 -1
- package/agent/components/ResponsiveGrid.json +2 -2
- package/agent/components/Reveal.json +3 -3
- package/agent/components/ScrollArea.json +2 -2
- package/agent/components/SearchInput.json +1 -1
- package/agent/components/Segmented.json +1 -1
- package/agent/components/Select.json +7 -5
- package/agent/components/Separator.json +1 -1
- package/agent/components/ServiceCatalogCta.json +0 -1
- package/agent/components/ServiceLauncherCard.json +1 -1
- package/agent/components/ServiceRolePanel.json +1 -1
- package/agent/components/Sheet.json +5 -5
- package/agent/components/Sidebar.json +1 -1
- package/agent/components/Skeleton.json +26 -12
- package/agent/components/Slider.json +2 -2
- package/agent/components/SortableList.json +3 -2
- package/agent/components/SplitPane.json +1 -1
- package/agent/components/StatCard.json +1 -1
- package/agent/components/Steps.json +1 -1
- package/agent/components/Swatch.json +1 -1
- package/agent/components/Switch.json +1 -1
- package/agent/components/Table.json +1 -1
- package/agent/components/Tabs.json +3 -3
- package/agent/components/Text.json +5 -1
- package/agent/components/TextDiff.json +5 -4
- package/agent/components/Textarea.json +1 -1
- package/agent/components/ThemeScope.json +1 -1
- package/agent/components/ThoughtChain.json +3 -3
- package/agent/components/TimePicker.json +1 -1
- package/agent/components/Timeline.json +1 -1
- package/agent/components/TimelineGrid.json +5 -4
- package/agent/components/Toaster.json +0 -1
- package/agent/components/Toggle.json +3 -3
- package/agent/components/ToggleGroup.json +1 -1
- package/agent/components/Toolbar.json +10 -3
- package/agent/components/Tooltip.json +9 -9
- package/agent/components/Topbar.json +1 -1
- package/agent/components/TopbarItem.json +1 -1
- package/agent/components/Transfer.json +2 -2
- package/agent/components/Tree.json +1 -1
- package/agent/components/TreeSelect.json +1 -1
- package/agent/components/TwoFactorSetup.json +1 -1
- package/agent/components/Upload.json +1 -1
- package/agent/components/UploadCropDialog.json +1 -1
- package/agent/components/Welcome.json +3 -3
- package/agent/components/formatDate.json +2 -2
- package/agent/components/inertiaUpload.json +0 -1
- package/agent/components/useZodForm.json +0 -1
- package/agent/components-index.json +80 -154
- package/agent/components.json +541 -1737
- package/agent/index.json +10 -10
- package/agent/llms.txt +9 -9
- package/agent/patterns/account-recovery-settings.json +1 -1
- package/agent/patterns/auth-recovery-panels.json +2 -2
- package/agent/patterns/error-pages.json +1 -1
- package/agent/patterns/pricing-plans.json +17 -0
- package/agent/patterns-index.json +17 -1
- package/agent/patterns.json +21 -4
- package/agent/rules.json +30 -65
- package/agent/tokens.json +27 -57
- package/agent/vocabulary.json +3 -3
- package/dist/app/app-provider.d.ts +5 -3
- package/dist/app/app-provider.js +47 -12
- package/dist/app/date-format-labels.d.ts +3 -1
- package/dist/app/date-format-labels.js +2 -4
- package/dist/app/date-formats.d.ts +21 -2
- package/dist/app/date-formats.js +51 -2
- package/dist/app/index.d.ts +3 -1
- package/dist/app/index.js +5 -0
- package/dist/app/locales.d.ts +58 -3
- package/dist/app/locales.js +134 -8
- package/dist/app/preset.d.ts +25 -0
- package/dist/app/preset.js +10 -0
- package/dist/app/request-headers.d.ts +3 -3
- package/dist/app/request-headers.js +19 -10
- package/dist/app/settings-scope.d.ts +54 -0
- package/dist/app/settings-scope.js +46 -0
- package/dist/app/tenant-theme.js +8 -3
- package/dist/app/time-format-labels.d.ts +4 -1
- package/dist/app/time-format-labels.js +7 -1
- package/dist/app/types.d.ts +10 -2
- package/dist/app/use-formatting.d.ts +1 -1
- package/dist/components/admin/index.d.ts +1 -1
- package/dist/components/admin/index.js +1 -1
- package/dist/components/data-display/accordion.d.ts +51 -1
- package/dist/components/data-display/accordion.js +247 -1
- package/dist/components/data-display/avatar.d.ts +16 -1
- package/dist/components/data-display/avatar.js +109 -1
- package/dist/components/data-display/credential-reveal.d.ts +9 -2
- package/dist/components/data-display/credential-reveal.js +156 -1
- package/dist/components/data-display/image.js +5 -3
- package/dist/components/data-display/index.d.ts +0 -21
- package/dist/components/data-display/index.js +1 -43
- package/dist/components/data-display/popover.d.ts +15 -3
- package/dist/components/data-display/popover.js +168 -2
- package/dist/components/data-entry/branch-scope-picker.d.ts +1 -1
- package/dist/components/data-entry/index.d.ts +5 -12
- package/dist/components/data-entry/index.js +11 -12
- package/dist/components/data-entry/input-otp.d.ts +48 -2
- package/dist/components/data-entry/input-otp.js +94 -1
- package/dist/components/data-entry/number-input.d.ts +1 -1
- package/dist/components/data-entry/password-input.d.ts +38 -2
- package/dist/components/data-entry/password-input.js +56 -1
- package/dist/components/data-entry/rating.d.ts +38 -2
- package/dist/components/data-entry/rating.js +127 -1
- package/dist/components/data-entry/segmented.d.ts +94 -2
- package/dist/components/data-entry/segmented.js +104 -1
- package/dist/components/{ui/tag-input.d.ts → data-entry/select-tags-inline.d.ts} +7 -4
- package/dist/components/{ui/tag-input.js → data-entry/select-tags-inline.js} +4 -4
- package/dist/components/data-entry/select.js +4 -0
- package/dist/components/data-entry/toggle-group.d.ts +108 -2
- package/dist/components/data-entry/toggle-group.js +189 -1
- package/dist/components/data-entry/toggle.d.ts +86 -2
- package/dist/components/data-entry/toggle.js +153 -2
- package/dist/components/feedback/alert.d.ts +5 -3
- package/dist/components/feedback/alert.js +14 -2
- package/dist/components/feedback/index.d.ts +2 -6
- package/dist/components/feedback/index.js +1 -13
- package/dist/components/feedback/skeleton.d.ts +4 -17
- package/dist/components/feedback/skeleton.js +3 -40
- package/dist/components/general/index.d.ts +2 -4
- package/dist/components/general/index.js +1 -6
- package/dist/components/general/typography.d.ts +4 -58
- package/dist/components/general/typography.js +7 -141
- package/dist/components/layout/aspect-ratio.d.ts +24 -1
- package/dist/components/layout/aspect-ratio.js +18 -1
- package/dist/components/layout/auth-divider.js +1 -1
- package/dist/components/layout/auth-identity.js +6 -2
- package/dist/components/layout/centered-shell.d.ts +13 -8
- package/dist/components/layout/centered-shell.js +43 -1
- package/dist/components/layout/flex.d.ts +1 -1
- package/dist/components/layout/flex.js +73 -1
- package/dist/components/layout/index.d.ts +1 -13
- package/dist/components/layout/index.js +0 -12
- package/dist/components/layout/separator.d.ts +25 -2
- package/dist/components/layout/separator.js +71 -1
- package/dist/components/navigation/{app-setting-toggle.d.ts → app-setting-cycle.d.ts} +3 -4
- package/dist/components/navigation/{app-setting-toggle.js → app-setting-cycle.js} +3 -3
- package/dist/components/navigation/app-setting-picker.d.ts +6 -2
- package/dist/components/navigation/app-setting-picker.js +20 -2
- package/dist/components/navigation/index.d.ts +3 -11
- package/dist/components/navigation/index.js +1 -9
- package/dist/components/navigation/tabs.js +1 -1
- package/dist/components/ui/carousel.d.ts +1 -1
- package/dist/components/ui/carousel.js +1 -1
- package/dist/components/ui/index.d.ts +11 -5
- package/dist/components/ui/index.js +5 -5
- package/dist/contracts/measurement.json +2 -2
- package/dist/email/brand-mark.d.ts +3 -2
- package/dist/email/brand-mark.js +1 -1
- package/dist/email/color.d.ts +7 -0
- package/dist/email/color.js +14 -1
- package/dist/email/index.d.ts +10 -2
- package/dist/email/index.js +23 -2
- package/dist/email/tokens.generated.d.ts +120 -2
- package/dist/email/tokens.generated.js +119 -1
- package/dist/i18n/locale-tags.d.ts +25 -0
- package/dist/i18n/locale-tags.js +59 -0
- package/dist/i18n/translate.d.ts +20 -3
- package/dist/i18n/translate.js +25 -14
- package/dist/i18n/use-translation.d.ts +3 -3
- package/dist/i18n/use-translation.js +4 -2
- package/dist/{components/navigation → lab}/anchor.d.ts +2 -2
- package/dist/{components/navigation → lab}/anchor.js +5 -5
- package/dist/{components/data-display → lab}/carousel.js +2 -2
- package/dist/{components/layout → lab}/draggable-panel.d.ts +8 -8
- package/dist/{components/layout → lab}/draggable-panel.js +2 -2
- package/dist/{components/data-entry → lab}/emoji-picker.d.ts +2 -2
- package/dist/{components/data-entry → lab}/emoji-picker.js +6 -6
- package/dist/{components/general → lab}/float-button.d.ts +8 -8
- package/dist/{components/general → lab}/float-button.js +7 -7
- package/dist/lab/index.d.ts +39 -0
- package/dist/lab/index.js +48 -0
- package/dist/{components/layout → lab}/legal-document-shell.d.ts +2 -2
- package/dist/{components/layout → lab}/legal-document-shell.js +4 -4
- package/dist/{components/data-display → lab}/marquee.d.ts +5 -5
- package/dist/{components/data-display → lab}/marquee.js +5 -5
- package/dist/{components/layout → lab}/masonry.d.ts +2 -2
- package/dist/{components/layout → lab}/masonry.js +3 -3
- package/dist/{components/navigation → lab}/mega-menu.d.ts +4 -4
- package/dist/{components/navigation → lab}/mega-menu.js +2 -2
- package/dist/{components/data-display → lab}/org-chart.d.ts +2 -2
- package/dist/{components/data-display → lab}/org-chart.js +4 -4
- package/dist/{components/layout → lab}/page-cover.d.ts +2 -2
- package/dist/{components/layout → lab}/page-cover.js +2 -2
- package/dist/{components/data-display → lab}/range-timeline.d.ts +1 -1
- package/dist/{components/data-display → lab}/range-timeline.js +6 -6
- package/dist/{components/data-entry → lab}/sortable-list.d.ts +2 -2
- package/dist/{components/data-entry → lab}/sortable-list.js +3 -3
- package/dist/{components/data-display → lab}/text-diff.d.ts +3 -3
- package/dist/{components/data-display → lab}/text-diff.js +4 -4
- package/dist/{components/data-display → lab}/timeline-grid.d.ts +2 -2
- package/dist/{components/data-display → lab}/timeline-grid.js +1 -1
- package/dist/lib/control-styles.js +1 -1
- package/dist/lib/datetime/format.js +20 -6
- package/dist/lib/datetime/sync.d.ts +6 -2
- package/dist/lib/datetime/sync.js +14 -18
- package/dist/lib/platform.d.ts +1 -1
- package/dist/props/components/app.prop.d.ts +28 -13
- package/dist/props/components/data-display.prop.d.ts +19 -29
- package/dist/props/components/feedback.prop.d.ts +15 -44
- package/dist/props/components/general.prop.d.ts +2 -64
- package/dist/props/components/index.d.ts +9 -1
- package/dist/props/components/layout.prop.d.ts +41 -57
- package/dist/props/registry.d.ts +48 -101
- package/dist/props/registry.js +45 -129
- package/dist/props/vocabulary/index.d.ts +1 -1
- package/dist/props/vocabulary/interaction.prop.d.ts +3 -12
- package/dist/styles/alert-layout.css +0 -29
- package/dist/styles/data-display-layout.css +14 -22
- package/dist/styles/fonts/OFL.txt +93 -0
- package/dist/styles/form-layout.css +4 -0
- package/dist/styles/index.css +0 -2
- package/dist/styles/layers.json +44 -179
- package/dist/styles/text-layout.css +0 -15
- package/dist/styles.css +2 -0
- package/dist/themes/godx-tokens.css +41 -0
- package/dist/themes/godx.css +3 -0
- package/dist/themes/godx.d.ts +16 -0
- package/dist/themes/godx.js +12 -0
- package/dist/tokens/components/feedback.css +0 -6
- package/dist/tokens/derived.css +23 -22
- package/dist/tokens/foundation.css +4 -6
- package/docs/COMPOSITION-VS-COMPONENT.md +58 -33
- package/docs/CONSUMER-RULES.md +1 -1
- package/docs/CUSTOMER-THEMING.md +17 -53
- package/docs/migrations/v32.md +105 -0
- package/package.json +59 -19
- package/scripts/_agent-setup.mjs +54 -3
- package/scripts/brand-accent.generated.mjs +15 -2
- package/scripts/cli.mjs +36 -11
- package/scripts/codemod.mjs +542 -0
- package/scripts/consumer-rule.md +21 -43
- package/scripts/postinstall.mjs +10 -47
- package/scripts/prune-css.mjs +1 -1
- package/scripts/ui-audit.mjs +5 -2
- package/dist/components/data-display/chat-bubble.d.ts +0 -30
- package/dist/components/data-display/chat-bubble.js +0 -229
- package/dist/components/data-display/hover-card.d.ts +0 -1
- package/dist/components/data-display/hover-card.js +0 -7
- package/dist/components/data-display/thought-chain.d.ts +0 -42
- package/dist/components/data-display/thought-chain.js +0 -177
- package/dist/components/data-display/thumbnail.d.ts +0 -37
- package/dist/components/data-display/thumbnail.js +0 -20
- package/dist/components/data-display/welcome.d.ts +0 -26
- package/dist/components/data-display/welcome.js +0 -37
- package/dist/components/data-entry/attachments.d.ts +0 -19
- package/dist/components/data-entry/attachments.js +0 -366
- package/dist/components/data-entry/chat-composer.d.ts +0 -51
- package/dist/components/data-entry/chat-composer.js +0 -200
- package/dist/components/data-entry/chat-suggestion.d.ts +0 -28
- package/dist/components/data-entry/chat-suggestion.js +0 -309
- package/dist/components/data-entry/tag-input.d.ts +0 -2
- package/dist/components/data-entry/tag-input.js +0 -5
- package/dist/components/feedback/banner.d.ts +0 -21
- package/dist/components/feedback/banner.js +0 -19
- package/dist/components/feedback/callout.d.ts +0 -23
- package/dist/components/feedback/callout.js +0 -42
- package/dist/components/layout/auth-shell.d.ts +0 -10
- package/dist/components/layout/auth-shell.js +0 -42
- package/dist/components/layout/space-compact.d.ts +0 -65
- package/dist/components/layout/space-compact.js +0 -52
- package/dist/components/navigation/conversations.d.ts +0 -39
- package/dist/components/navigation/conversations.js +0 -371
- package/dist/components/ui/accordion.d.ts +0 -51
- package/dist/components/ui/accordion.js +0 -254
- package/dist/components/ui/aspect-ratio.d.ts +0 -24
- package/dist/components/ui/aspect-ratio.js +0 -21
- package/dist/components/ui/avatar.d.ts +0 -16
- package/dist/components/ui/avatar.js +0 -115
- package/dist/components/ui/credential-reveal.d.ts +0 -9
- package/dist/components/ui/credential-reveal.js +0 -160
- package/dist/components/ui/hover-card.d.ts +0 -47
- package/dist/components/ui/hover-card.js +0 -205
- package/dist/components/ui/input-otp.d.ts +0 -48
- package/dist/components/ui/input-otp.js +0 -101
- package/dist/components/ui/password-input.d.ts +0 -38
- package/dist/components/ui/password-input.js +0 -60
- package/dist/components/ui/rating.d.ts +0 -38
- package/dist/components/ui/rating.js +0 -131
- package/dist/components/ui/segmented.d.ts +0 -94
- package/dist/components/ui/segmented.js +0 -108
- package/dist/components/ui/separator.d.ts +0 -25
- package/dist/components/ui/separator.js +0 -74
- package/dist/components/ui/toggle-group.d.ts +0 -108
- package/dist/components/ui/toggle-group.js +0 -194
- package/dist/components/ui/toggle.d.ts +0 -86
- package/dist/components/ui/toggle.js +0 -156
- package/docs/CANONICAL-CONTRACTS.md +0 -206
- package/docs/COMPONENTS.md +0 -163
- package/docs/DATETIME.md +0 -78
- package/docs/DEVELOPMENT.md +0 -269
- package/docs/FRAME-A11Y-CI.md +0 -287
- package/docs/FRAME-COVERAGE-LEDGER.md +0 -123
- package/docs/FRAME-COVERAGE-REPORT.md +0 -228
- package/docs/FRAME-COVERAGE-STANDARD.md +0 -65
- package/docs/FRAME-COVERAGE.md +0 -29
- package/docs/MEASUREMENT-CONTRACT.md +0 -109
- package/docs/PROPS-REGISTRY.md +0 -61
- package/docs/PROPS-VOCABULARY.md +0 -100
- package/docs/REGISTRY.md +0 -70
- package/docs/TESTING.md +0 -107
- package/docs/THEME-API-COVERAGE.md +0 -538
- package/docs/WHAT-BELONGS-HERE.md +0 -179
- package/docs/asset-modules.d.ts +0 -53
- package/docs/assets/cover-terrain.svg +0 -6
- package/docs/assets/portrait-amber.svg +0 -5
- package/docs/assets/portrait-clay.svg +0 -5
- package/docs/assets/portrait-indigo.svg +0 -5
- package/docs/assets/portrait-iris.svg +0 -5
- package/docs/assets/portrait-moss.svg +0 -5
- package/docs/assets/portrait-plum.svg +0 -5
- package/docs/assets/portrait-slate.svg +0 -5
- package/docs/assets/service-mark-rose.svg +0 -6
- package/docs/assets/service-mark-teal.svg +0 -5
- package/docs/assets/shot-landscape.svg +0 -12
- package/docs/assets/shot-portrait.svg +0 -10
- package/docs/assets/tcgm/card-1.svg +0 -1
- package/docs/assets/tcgm/card-2.svg +0 -1
- package/docs/assets/tcgm/card-3.svg +0 -1
- package/docs/assets/tcgm/card-4.svg +0 -1
- package/docs/assets/tcgm/card-5.svg +0 -1
- package/docs/assets/tcgm/card-6.svg +0 -1
- package/docs/assets/tcgm/hero-prism.svg +0 -1
- package/docs/assets/tcgm/scene-1.svg +0 -1
- package/docs/assets/tcgm/scene-2.svg +0 -1
- package/docs/assets/tcgm/scene-3.svg +0 -1
- package/docs/assets/tcgm/scene-4.svg +0 -1
- package/docs/assets/tcgm/scene-5.svg +0 -1
- package/docs/assets/tcgm/tcgm-lockup-color.svg +0 -1
- package/docs/assets/tcgm/tcgm-symbol-color.svg +0 -1
- package/docs/charts/cjk-category-axis.tsx +0 -81
- package/docs/charts/compact-bar-trend.tsx +0 -327
- package/docs/charts/size-tiers.tsx +0 -192
- package/docs/data-display/accordion.tsx +0 -99
- package/docs/data-display/avatar.tsx +0 -502
- package/docs/data-display/badge.tsx +0 -335
- package/docs/data-display/card/examples/detail-panel.tsx +0 -106
- package/docs/data-display/card/examples/tab-list.tsx +0 -97
- package/docs/data-display/card/index.md +0 -3
- package/docs/data-display/card/index.tsx +0 -390
- package/docs/data-display/carousel.tsx +0 -160
- package/docs/data-display/charts.tsx +0 -278
- package/docs/data-display/chat-bubble.tsx +0 -397
- package/docs/data-display/code-block.tsx +0 -188
- package/docs/data-display/collapsible.tsx +0 -162
- package/docs/data-display/credential-reveal.tsx +0 -148
- package/docs/data-display/data-table/examples/antd-parity.tsx +0 -257
- package/docs/data-display/data-table/examples/approval-queue.tsx +0 -212
- package/docs/data-display/data-table/examples/grid-features.tsx +0 -158
- package/docs/data-display/data-table/examples/list-page.tsx +0 -175
- package/docs/data-display/data-table/examples/selectable-inbox.tsx +0 -113
- package/docs/data-display/data-table/examples/server-paged.tsx +0 -179
- package/docs/data-display/data-table/examples/striped-list.tsx +0 -173
- package/docs/data-display/data-table/index.md +0 -9
- package/docs/data-display/data-table/index.tsx +0 -407
- package/docs/data-display/descriptions.tsx +0 -263
- package/docs/data-display/empty-state.tsx +0 -164
- package/docs/data-display/feature-list.tsx +0 -159
- package/docs/data-display/hover-card.tsx +0 -181
- package/docs/data-display/image.tsx +0 -170
- package/docs/data-display/legend.tsx +0 -158
- package/docs/data-display/list-row.tsx +0 -441
- package/docs/data-display/markdown.tsx +0 -86
- package/docs/data-display/marquee.tsx +0 -254
- package/docs/data-display/org-chart.tsx +0 -165
- package/docs/data-display/permission-matrix.tsx +0 -188
- package/docs/data-display/popover-touch.tsx +0 -27
- package/docs/data-display/popover.tsx +0 -331
- package/docs/data-display/progress.tsx +0 -162
- package/docs/data-display/prose.tsx +0 -169
- package/docs/data-display/qr-code.tsx +0 -68
- package/docs/data-display/scroll-area.tsx +0 -420
- package/docs/data-display/service-launcher-card.tsx +0 -445
- package/docs/data-display/stat-card.tsx +0 -354
- package/docs/data-display/swatch.tsx +0 -107
- package/docs/data-display/table.tsx +0 -362
- package/docs/data-display/text-diff.tsx +0 -89
- package/docs/data-display/thought-chain.tsx +0 -176
- package/docs/data-display/thumbnail.tsx +0 -128
- package/docs/data-display/timeline-grid.tsx +0 -119
- package/docs/data-display/timeline.tsx +0 -671
- package/docs/data-display/touch-actions.tsx +0 -36
- package/docs/data-display/tree.tsx +0 -724
- package/docs/data-display/welcome.tsx +0 -115
- package/docs/data-entry/attachments.tsx +0 -160
- package/docs/data-entry/block-editor.tsx +0 -105
- package/docs/data-entry/branch-scope-picker.tsx +0 -128
- package/docs/data-entry/calendar.tsx +0 -226
- package/docs/data-entry/cascader.tsx +0 -380
- package/docs/data-entry/chat-composer.tsx +0 -619
- package/docs/data-entry/chat-suggestion.tsx +0 -301
- package/docs/data-entry/checkbox.tsx +0 -256
- package/docs/data-entry/color-picker.tsx +0 -189
- package/docs/data-entry/command-palette.tsx +0 -179
- package/docs/data-entry/command.tsx +0 -341
- package/docs/data-entry/country-picker-recipe.tsx +0 -175
- package/docs/data-entry/date-picker.tsx +0 -452
- package/docs/data-entry/emoji-picker.tsx +0 -35
- package/docs/data-entry/form/examples/employee-settings.tsx +0 -267
- package/docs/data-entry/form/examples/invoice-form.tsx +0 -387
- package/docs/data-entry/form-dynamic-fields.tsx +0 -199
- package/docs/data-entry/form-field/examples/a11y-contract.tsx +0 -242
- package/docs/data-entry/form-field/examples/create-form.tsx +0 -107
- package/docs/data-entry/form-field/index.md +0 -8
- package/docs/data-entry/form-field/index.tsx +0 -337
- package/docs/data-entry/form-inertia.tsx +0 -80
- package/docs/data-entry/form-root.tsx +0 -112
- package/docs/data-entry/form.tsx +0 -1498
- package/docs/data-entry/input-otp.tsx +0 -258
- package/docs/data-entry/input.tsx +0 -796
- package/docs/data-entry/label.tsx +0 -102
- package/docs/data-entry/markdown-editor.tsx +0 -69
- package/docs/data-entry/number-input.tsx +0 -279
- package/docs/data-entry/password-input.tsx +0 -102
- package/docs/data-entry/password-strength.tsx +0 -99
- package/docs/data-entry/radio-group.tsx +0 -316
- package/docs/data-entry/rating.tsx +0 -91
- package/docs/data-entry/record-picker.tsx +0 -209
- package/docs/data-entry/search-input.tsx +0 -121
- package/docs/data-entry/segmented-in-filter-row.tsx +0 -60
- package/docs/data-entry/segmented.tsx +0 -300
- package/docs/data-entry/select-async-contracts.tsx +0 -108
- package/docs/data-entry/select-matrix.tsx +0 -209
- package/docs/data-entry/select.tsx +0 -547
- package/docs/data-entry/slider.tsx +0 -212
- package/docs/data-entry/sortable-list.tsx +0 -76
- package/docs/data-entry/switch.tsx +0 -314
- package/docs/data-entry/tag-input.tsx +0 -145
- package/docs/data-entry/textarea.tsx +0 -249
- package/docs/data-entry/time-picker.tsx +0 -187
- package/docs/data-entry/time-range-picker.tsx +0 -55
- package/docs/data-entry/toggle-count.tsx +0 -348
- package/docs/data-entry/toggle-group.tsx +0 -438
- package/docs/data-entry/toggle.tsx +0 -217
- package/docs/data-entry/transfer.tsx +0 -115
- package/docs/data-entry/tree-select.tsx +0 -204
- package/docs/data-entry/upload-crop-dialog.tsx +0 -109
- package/docs/data-entry/upload.tsx +0 -310
- package/docs/feedback/alert-dialog.tsx +0 -270
- package/docs/feedback/alert.tsx +0 -248
- package/docs/feedback/auth-expiry.tsx +0 -104
- package/docs/feedback/banner.tsx +0 -183
- package/docs/feedback/callout.tsx +0 -220
- package/docs/feedback/danger-confirm.tsx +0 -91
- package/docs/feedback/dialog-touch.tsx +0 -24
- package/docs/feedback/dialog.tsx +0 -373
- package/docs/feedback/sheet.tsx +0 -510
- package/docs/feedback/skeleton.tsx +0 -168
- package/docs/feedback/toast.tsx +0 -135
- package/docs/feedback/tooltip.tsx +0 -171
- package/docs/feedback/two-factor-setup.tsx +0 -68
- package/docs/foundation/_email-specimen.ts +0 -274
- package/docs/foundation/_theme-editor-scope.ts +0 -222
- package/docs/foundation/colors.tsx +0 -207
- package/docs/foundation/density.tsx +0 -242
- package/docs/foundation/email-tokens.tsx +0 -323
- package/docs/foundation/radius-shadow.tsx +0 -154
- package/docs/foundation/spacing.tsx +0 -216
- package/docs/foundation/theme-editor.tsx +0 -654
- package/docs/foundation/typography.tsx +0 -147
- package/docs/general/actions.tsx +0 -175
- package/docs/general/activity.tsx +0 -289
- package/docs/general/button/examples/destructive-confirm.tsx +0 -90
- package/docs/general/button/examples/form-actions.tsx +0 -87
- package/docs/general/button/examples/toolbar.tsx +0 -160
- package/docs/general/button/index.md +0 -16
- package/docs/general/button/index.tsx +0 -236
- package/docs/general/float-button.tsx +0 -133
- package/docs/general/icon.tsx +0 -217
- package/docs/general/logo.tsx +0 -194
- package/docs/general/reveal.tsx +0 -309
- package/docs/general/typography.tsx +0 -542
- package/docs/i18n/messages/en.json +0 -1715
- package/docs/i18n/messages/ja.json +0 -1708
- package/docs/i18n/messages/vi.json +0 -1708
- package/docs/layout/account-chip.tsx +0 -72
- package/docs/layout/admin-collection.tsx +0 -122
- package/docs/layout/affix.tsx +0 -209
- package/docs/layout/app-launcher.tsx +0 -211
- package/docs/layout/app-shell-arrangements.tsx +0 -225
- package/docs/layout/app-shell-narrow-bar.tsx +0 -205
- package/docs/layout/app-shell-states.tsx +0 -171
- package/docs/layout/app-shell.tsx +0 -395
- package/docs/layout/aspect-ratio.tsx +0 -135
- package/docs/layout/auth-account-summary.tsx +0 -103
- package/docs/layout/auth-divider.tsx +0 -28
- package/docs/layout/auth-footer.tsx +0 -37
- package/docs/layout/auth-identity.tsx +0 -70
- package/docs/layout/auth-recovery/examples/mfa-challenge.md +0 -41
- package/docs/layout/auth-recovery/examples/mfa-challenge.tsx +0 -254
- package/docs/layout/auth-recovery/examples/mobile-390.md +0 -25
- package/docs/layout/auth-recovery/examples/mobile-390.tsx +0 -82
- package/docs/layout/auth-recovery/examples/password-recovery.md +0 -24
- package/docs/layout/auth-recovery/examples/password-recovery.tsx +0 -197
- package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.md +0 -27
- package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.tsx +0 -156
- package/docs/layout/auth-recovery/index.md +0 -140
- package/docs/layout/auth-recovery/index.tsx +0 -96
- package/docs/layout/auth-shell-context.tsx +0 -103
- package/docs/layout/auth-shell-device.tsx +0 -112
- package/docs/layout/auth-shell-registration.tsx +0 -338
- package/docs/layout/auth-shell-variants.tsx +0 -143
- package/docs/layout/auth-shell.tsx +0 -59
- package/docs/layout/auth-stack.tsx +0 -40
- package/docs/layout/centered-shell.tsx +0 -102
- package/docs/layout/draggable-panel.tsx +0 -127
- package/docs/layout/error-surface/examples/application-403.tsx +0 -84
- package/docs/layout/error-surface/examples/application-404.tsx +0 -77
- package/docs/layout/error-surface/examples/system-500.tsx +0 -47
- package/docs/layout/error-surface/examples/system-503.tsx +0 -48
- package/docs/layout/error-surface/index.md +0 -153
- package/docs/layout/error-surface/index.tsx +0 -239
- package/docs/layout/flex.tsx +0 -444
- package/docs/layout/legal-document-shell/_data.ts +0 -110
- package/docs/layout/legal-document-shell/examples/desktop-1440.md +0 -12
- package/docs/layout/legal-document-shell/examples/desktop-1440.tsx +0 -83
- package/docs/layout/legal-document-shell/examples/mobile-390.md +0 -22
- package/docs/layout/legal-document-shell/examples/mobile-390.tsx +0 -70
- package/docs/layout/legal-document-shell/examples/tablet-1024.md +0 -3
- package/docs/layout/legal-document-shell/examples/tablet-1024.tsx +0 -84
- package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.md +0 -18
- package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.tsx +0 -61
- package/docs/layout/legal-document-shell/index.md +0 -51
- package/docs/layout/legal-document-shell/index.tsx +0 -101
- package/docs/layout/masonry.tsx +0 -291
- package/docs/layout/master-detail.tsx +0 -390
- package/docs/layout/mobile-shell.tsx +0 -106
- package/docs/layout/nav-list.tsx +0 -584
- package/docs/layout/org-switcher.tsx +0 -131
- package/docs/layout/page-container.tsx +0 -1020
- package/docs/layout/page-cover.tsx +0 -56
- package/docs/layout/resizable-panel.tsx +0 -419
- package/docs/layout/responsive-grid.tsx +0 -403
- package/docs/layout/separator.tsx +0 -327
- package/docs/layout/service-role-panel.tsx +0 -144
- package/docs/layout/sidebar.tsx +0 -689
- package/docs/layout/space-compact.tsx +0 -202
- package/docs/layout/split-pane.tsx +0 -532
- package/docs/layout/topbar-item.tsx +0 -233
- package/docs/layout/topbar.tsx +0 -360
- package/docs/navigation/anchor.tsx +0 -295
- package/docs/navigation/app-setting-picker.tsx +0 -178
- package/docs/navigation/app-setting-toggle.tsx +0 -111
- package/docs/navigation/breadcrumb.tsx +0 -207
- package/docs/navigation/card-tabs.tsx +0 -344
- package/docs/navigation/conversations.tsx +0 -176
- package/docs/navigation/dropdown-menu.tsx +0 -345
- package/docs/navigation/filter-bar.tsx +0 -247
- package/docs/navigation/mega-menu-panel.tsx +0 -86
- package/docs/navigation/mega-menu.tsx +0 -254
- package/docs/navigation/pagination.tsx +0 -293
- package/docs/navigation/steps.tsx +0 -315
- package/docs/navigation/tabs-rtl.tsx +0 -28
- package/docs/navigation/tabs.tsx +0 -755
- package/docs/navigation/toolbar.tsx +0 -347
- package/docs/providers/app-provider.tsx +0 -191
- package/docs/providers/format-date.tsx +0 -230
- package/docs/providers/theme-scope.tsx +0 -186
- package/docs/query/button-refetch.tsx +0 -161
- package/docs/query/data-state.tsx +0 -262
- package/docs/query/infinite-query-state.tsx +0 -97
- package/docs/query/mutation-feedback.tsx +0 -128
- package/docs/query/touch-actions.tsx +0 -68
- package/docs/react-router/prefetch-link.tsx +0 -262
- package/docs/roadmap/ai-chat-components.md +0 -206
- package/docs/roadmap/antd-parity.md +0 -155
- package/docs/roadmap/badge-tag-chip-count.md +0 -172
- package/docs/roadmap/list-masonry.md +0 -159
- package/docs/roadmap/parity-audit-data-display-feedback.md +0 -567
- package/docs/roadmap/parity-audit-data-entry.md +0 -368
- package/docs/roadmap/parity-audit-layout-navigation-general.md +0 -459
- package/docs/roadmap/parity-backlog.md +0 -77
- package/docs/roadmap/tree-components.md +0 -151
- package/docs/roadmap/website-components.md +0 -813
- package/docs/showcase/acme-portal.tsx +0 -461
- package/docs/showcase/acme-website.tsx +0 -499
- package/docs/showcase/caimono-price-comparison.tsx +0 -919
- package/docs/showcase/case1-warehouse-dashboard.tsx +0 -358
- package/docs/showcase/case2-employee-me.tsx +0 -438
- package/docs/showcase/case3-approval-workflow.tsx +0 -531
- package/docs/showcase/case4-login.tsx +0 -312
- package/docs/showcase/case5-shift-calendar.tsx +0 -702
- package/docs/showcase/case6-agency-handy.tsx +0 -1120
- package/docs/showcase/futurelastic-web.tsx +0 -441
- package/docs/showcase/marketing-page.tsx +0 -895
- package/docs/showcase/org-switcher.tsx +0 -320
- package/docs/showcase/permission-matrix.tsx +0 -354
- package/docs/showcase/public-landing.tsx +0 -210
- package/docs/showcase/settings-account-sections.tsx +0 -559
- package/docs/showcase/settings-security-mfa.tsx +0 -145
- package/docs/showcase/table-approval-queue.tsx +0 -199
- package/docs/showcase/table-bulk-actions.tsx +0 -468
- package/docs/showcase/table-compact-kintone.tsx +0 -438
- package/docs/showcase/table-conditional-format.tsx +0 -367
- package/docs/showcase/table-crud-list.tsx +0 -544
- package/docs/showcase/table-density.tsx +0 -349
- package/docs/showcase/table-expandable-rows.tsx +0 -496
- package/docs/showcase/table-filter-chips.tsx +0 -468
- package/docs/showcase/table-footer-totals.tsx +0 -328
- package/docs/showcase/table-grouped-subtotals.tsx +0 -398
- package/docs/showcase/table-master-detail.tsx +0 -482
- package/docs/showcase/table-pagination.tsx +0 -409
- package/docs/showcase/table-states.tsx +0 -371
- package/docs/showcase/table-sticky-columns.tsx +0 -377
- package/docs/showcase/table-tree-rows.tsx +0 -451
- package/docs/showcase/table-view-tabs.tsx +0 -488
- package/docs/showcase/tcgm-website.tsx +0 -1047
- package/docs/showcase/tenant-brand-color.tsx +0 -338
- package/docs/showcase/theme-customization.tsx +0 -1292
- package/docs/showcase/theme-lab.tsx +0 -2125
- package/docs/themes/flat.css +0 -466
- package/docs/themes/glassmorphism.css +0 -960
- package/docs/themes/index.ts +0 -219
- package/docs/themes/neubrutalism.css +0 -481
- /package/dist/components/navigation/{filter-bar.d.ts → toolbar.d.ts} +0 -0
- /package/dist/components/navigation/{filter-bar.js → toolbar.js} +0 -0
- /package/dist/{components/data-display → lab}/carousel.d.ts +0 -0
- /package/dist/{components/data-entry → lab}/emoji-data.d.ts +0 -0
- /package/dist/{components/data-entry → lab}/emoji-data.js +0 -0
- /package/dist/{components/data-display → lab}/marquee-reveal.d.ts +0 -0
- /package/dist/{components/data-display → lab}/marquee-reveal.js +0 -0
package/docs/DATETIME.md
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
# formatDate — mandatory datetime display
|
|
2
|
-
|
|
3
|
-
Package: `@godxjp/ui/datetime`
|
|
4
|
-
|
|
5
|
-
## Import
|
|
6
|
-
|
|
7
|
-
```tsx
|
|
8
|
-
import { formatDate } from "@godxjp/ui/datetime";
|
|
9
|
-
import { useDateTime } from "@godxjp/ui/app";
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
## Rules
|
|
13
|
-
|
|
14
|
-
1. **Never** use `date-fns/format`, `toLocaleString`, or raw ISO slices for UI.
|
|
15
|
-
2. **Always** wrap apps in `<AppProvider>` so defaults apply.
|
|
16
|
-
3. **Optional** per-call `timezone` override — global prefs unchanged.
|
|
17
|
-
|
|
18
|
-
## Defaults
|
|
19
|
-
|
|
20
|
-
Omit `locale`, `timezone`, `timeFormat`, `dateFormat` → synced from AppProvider.
|
|
21
|
-
|
|
22
|
-
## dateFormat presets
|
|
23
|
-
|
|
24
|
-
| value | Pattern | Default locale |
|
|
25
|
-
| ----- | ------------ | -------------- |
|
|
26
|
-
| `iso` | `yyyy-MM-dd` | — |
|
|
27
|
-
| `ymd` | `yyyy/MM/dd` | ja |
|
|
28
|
-
| `dmy` | `dd/MM/yyyy` | vi |
|
|
29
|
-
| `mdy` | `MM/dd/yyyy` | en |
|
|
30
|
-
|
|
31
|
-
`ymd` and `iso` are both year-first and are NOT interchangeable: a Japanese business document
|
|
32
|
-
(請求書, 申請書) is written `2026/05/01`, never `2026-05-01`. `ja` defaulted to `iso` until a
|
|
33
|
-
Japanese-first consumer shipped its own date formatter as an explicit stopgap purely to get the
|
|
34
|
-
slashes — rule 1 above broken by this package's own default. Only the DEFAULT moved: a stored
|
|
35
|
-
preference still wins, `defaultDateFormat` still pins any value, and `iso` is one option away in
|
|
36
|
-
`<DateFormatPicker />`.
|
|
37
|
-
|
|
38
|
-
Sent to backend as `x-date-format`. Pick with `<DateFormatPicker />`.
|
|
39
|
-
|
|
40
|
-
## kind presets
|
|
41
|
-
|
|
42
|
-
| kind | Use |
|
|
43
|
-
| ---------- | ---------------------------------------- |
|
|
44
|
-
| `auto` | Default — detects date / time / datetime |
|
|
45
|
-
| `datetime` | Audit logs, `created_at` |
|
|
46
|
-
| `date` | `"2026-05-01"` fields |
|
|
47
|
-
| `calendar` | `Date` from DatePicker |
|
|
48
|
-
| `time` | `"14:30"` HH:mm |
|
|
49
|
-
| `long` | Detail headings (PPP) |
|
|
50
|
-
| `relative` | Activity feeds |
|
|
51
|
-
|
|
52
|
-
## ISO 8601 patterns
|
|
53
|
-
|
|
54
|
-
Date order follows `dateFormat` from AppProvider (`iso` | `ymd` | `dmy` | `mdy`):
|
|
55
|
-
|
|
56
|
-
- `iso`: `yyyy-MM-dd` + `yyyy-MM-dd HH:mm`
|
|
57
|
-
- `ymd`: `yyyy/MM/dd` + `yyyy/MM/dd HH:mm`
|
|
58
|
-
- `dmy`: `dd/MM/yyyy` + `dd/MM/yyyy HH:mm`
|
|
59
|
-
- `mdy`: `MM/dd/yyyy` + `MM/dd/yyyy HH:mm`
|
|
60
|
-
|
|
61
|
-
Time portion still follows `timeFormat` (24h vs 12h).
|
|
62
|
-
|
|
63
|
-
## Examples
|
|
64
|
-
|
|
65
|
-
```tsx
|
|
66
|
-
formatDate("2026-05-01T14:30:00Z");
|
|
67
|
-
formatDate("2026-05-01");
|
|
68
|
-
formatDate("17:30", { kind: "time" });
|
|
69
|
-
formatDate(pickedDate, { kind: "calendar" });
|
|
70
|
-
formatDate(iso, { timezone: "Asia/Tokyo" });
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## React
|
|
74
|
-
|
|
75
|
-
```tsx
|
|
76
|
-
const { format } = useDateTime();
|
|
77
|
-
return <td>{format(row.createdAt)}</td>;
|
|
78
|
-
```
|
package/docs/DEVELOPMENT.md
DELETED
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
# Development Guideline — `@godxjp/ui`
|
|
2
|
-
|
|
3
|
-
How to work **on** the design system (not just with it). If you only consume the framework from the app, read [the ten consumer rules](./CONSUMER-RULES.md) instead — this file is for people **editing `packages/godx-ui/`**.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 0. What this package IS — and the boundary it must keep
|
|
8
|
-
|
|
9
|
-
`@godxjp/ui` is **the** UI framework for every godx surface (admin, agency portal, handheld). It is shared, versioned infrastructure: one change here ripples to every screen and every consumer. Two consequences:
|
|
10
|
-
|
|
11
|
-
1. **Editing it needs explicit session permission** — the hard gate in [CLAUDE.md](../CLAUDE.md) (MANDATORY: read the component skill before touching UI). Treat the package as off-limits by default. 2. **It is generic and presentational only.** The framework knows about _tokens, layout, accessibility, and interaction_ — never about the app's data, routes, language files, or business rules.
|
|
12
|
-
|
|
13
|
-
### The hard boundary — consumer-layer concerns MUST NOT leak in
|
|
14
|
-
|
|
15
|
-
A component in this package may **not** import or assume any of the following. These belong to the **consumer** (the app), which composes framework primitives around them:
|
|
16
|
-
|
|
17
|
-
| ❌ Never inside `packages/godx-ui/` | ✅ Where it belongs |
|
|
18
|
-
| ---------------------------------------------------------------- | ------------------------------------------------------------------- |
|
|
19
|
-
| App i18n — `useTranslation`, `t()`, `resources/js/i18n` | App passes already-translated strings in as props |
|
|
20
|
-
| Inertia — `router`, `usePage`, `<Form>`, `@inertiajs/*` | App wires navigation/submit; pass `onClick`/`href`/`onSubmit` props |
|
|
21
|
-
| Wayfinder routes — `@/routes`, `@/actions`, `.url()` | App resolves the URL, passes a plain string |
|
|
22
|
-
| Business entities / domain logic (Item, Packing, shipment rules) | App-level component in `resources/js/components/**` |
|
|
23
|
-
| App copy / labels / placeholder text baked into the component | Comes in via props; framework ships no product wording |
|
|
24
|
-
| Raw colors / hex / `hsl(...)` literals, `dark:` overrides | Semantic tokens (`var(--…)`, `bg-primary`, …) — see §3 |
|
|
25
|
-
| A consumer's theme values redefined inside a component | Theme lives in `src/tokens/` (the framework default ships it) |
|
|
26
|
-
|
|
27
|
-
> **Litmus test:** if a component can't render in a Storybook-style preview with
|
|
28
|
-
> plain props and zero app context, it does **not** belong in this package. Keep it
|
|
29
|
-
> app-level (`resources/js/components/admin/…`) and have it _compose_ framework
|
|
30
|
-
> primitives. See the **`godx-ui-component-placement`** skill for the full decision.
|
|
31
|
-
|
|
32
|
-
The framework ships its **own theme** (colors, fonts, type scale, wa-iro palette) in `src/tokens/foundation.css`, so consumers import `@godxjp/ui/styles` and need **zero** extra theme config. Do not push theme decisions back onto the consumer.
|
|
33
|
-
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
## 1. Architecture — the layers, bottom-up
|
|
37
|
-
|
|
38
|
-
```
|
|
39
|
-
src/tokens/ Design tokens (the single source of values)
|
|
40
|
-
foundation.css :root + .dark — colors, fonts, type scale, spacing, radius, wa-iro
|
|
41
|
-
primitives/*.css Per-domain primitive tokens (card, table, control, badge, …)
|
|
42
|
-
base.css Coordinates the token layer
|
|
43
|
-
src/styles/ CSS that styles components by [data-slot] + density.css (the density knob)
|
|
44
|
-
index.css Entry: @import fontsource → tailwindcss → @theme (token→utility map) → layout css
|
|
45
|
-
src/components/ React components, grouped (data-display, data-entry, layout, …)
|
|
46
|
-
src/props/ Prop type system — vocabulary/ (atomic) + components/ + registry.ts
|
|
47
|
-
src/lib/ cn(), control-styles, variants — shared helpers
|
|
48
|
-
examples/ *.preview.tsx — Storybook-style stories (preview app)
|
|
49
|
-
docs/primitives/ <component>/index.tsx demo + examples/ + generated .md
|
|
50
|
-
preview/ The preview app (vite) on :6008 that renders examples + docs
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
**Token → utility flow:** a value is defined once as a CSS var in `tokens/foundation.css` (e.g. `--primary`), mapped to a Tailwind utility in the `@theme` block of `styles/index.css` (`--color-primary: hsl(var(--primary))`), and consumed as `bg-primary` / `hsl(var(--primary))`. Never skip a layer with a literal.
|
|
54
|
-
|
|
55
|
-
### The component pattern — markup emits slots, CSS owns styling
|
|
56
|
-
|
|
57
|
-
Components render semantic structure and `data-slot` / `data-*` flags; **the spacing, padding, and chrome live in `src/styles/*-layout.css`**, keyed on those slots. This keeps density and theming centralized.
|
|
58
|
-
|
|
59
|
-
```tsx
|
|
60
|
-
// component: emits slots + flags only
|
|
61
|
-
<div data-slot="card" data-variant={variant} data-density={density} />
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
```css
|
|
65
|
-
/* styles/card-layout.css: owns the look */
|
|
66
|
-
[data-slot="card"] {
|
|
67
|
-
border: 1px solid hsl(var(--card-border));
|
|
68
|
-
border-radius: var(--card-radius);
|
|
69
|
-
}
|
|
70
|
-
[data-slot="card"][data-density="tight"] {
|
|
71
|
-
--card-space-inset: var(--space-3);
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
Prefer this over hardcoding Tailwind padding inside the component. Use Tailwind utility classes for **one-off layout** (flex/grid/gap), not for re-theming.
|
|
76
|
-
|
|
77
|
-
### Density
|
|
78
|
-
|
|
79
|
-
One knob — `.ui-density-{compact,default,comfortable}` in `styles/density.css` — retunes `--phi-unit`, control heights, and table row heights together. Components read the resulting tokens; never branch on density in component JS.
|
|
80
|
-
|
|
81
|
-
### The `ui/` layer
|
|
82
|
-
|
|
83
|
-
`src/components/ui/*` are thin **re-exports** of the canonical implementation (`export * from "../data-display/card"`). They exist for shadcn-style import paths. Edit the canonical file under its group; the `ui/` path follows automatically.
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
## 2. Adding or changing a component (after you have §0 permission)
|
|
88
|
-
|
|
89
|
-
Work in this order; only advance when the previous step genuinely can't express the need:
|
|
90
|
-
|
|
91
|
-
1. **Use** an existing primitive. 2. **Compose** primitives (Card + FormField + Flex…). 3. **Extend** an existing component — add a prop/slot (e.g. `labelAddon`, `accent`). Prefer this: one more prop beats one more component. 4. **Create** a new component — last resort.
|
|
92
|
-
|
|
93
|
-
Document the decision (which promotion criteria it met) so review can check it — see [COMPOSITION-VS-COMPONENT.md](./COMPOSITION-VS-COMPONENT.md).
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
## 3. Rules for framework code
|
|
98
|
-
|
|
99
|
-
- **Semantic tokens only.** No raw hex / `rgb()` / `hsl()` literals, no palette utilities (`bg-blue-500`), no `dark:` overrides — tokens adapt automatically. Structural literals (a `3px` accent stripe, `1px` borders) are fine; _color/size scale_ values come from tokens. - **No app coupling** (the §0 boundary table above). - **Props live in `src/props/`** — atomic concepts in `vocabulary/`, per-component interfaces in `components/`. Check `registry.ts` + `PROP_ALIASES_FORBIDDEN` before inventing a prop name.
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
## 4. Every component change ships its story + docs
|
|
104
|
-
|
|
105
|
-
A change isn't done until its documentation reflects it:
|
|
106
|
-
|
|
107
|
-
1. **Preview story** — `examples/<group>/<Component>.preview.tsx` (Storybook-style). New props get a story (see `examples/data-display/Card.preview.tsx`: Surfaces / Density / AccentEdges). 2. **Docs demo** — `docs/primitives/<group>/<component>/index.tsx` shows the new capability; `examples/` holds focused per-feature demos. 3. **Regenerate props docs** — `pnpm docs:sync-primitives` regenerates the `.md` from source. Run it after prop changes so the tables stay accurate.
|
|
108
|
-
|
|
109
|
-
> Docs are mid-migration to the `<component>/index.tsx (+ examples/)` shape. Do **not**
|
|
110
|
-
> resurrect flat `docs/primitives/<component>.tsx` demos — they were dead orphans and
|
|
111
|
-
> were removed.
|
|
112
|
-
|
|
113
|
-
---
|
|
114
|
-
|
|
115
|
-
## 5. Verify before finishing — scope the checks to the DIFF
|
|
116
|
-
|
|
117
|
-
> **Read §5.0 before you run anything.** This section was rewritten after the owner watched a
|
|
118
|
-
> two-file change take six minutes of gates and asked, correctly, _"bản chất chỉ sửa rất ít, check
|
|
119
|
-
> diff đéo được hay sao? có phải release đâu mà run hết thế?"_ — it is not a release, so stop
|
|
120
|
-
> running a release's worth of checks.
|
|
121
|
-
|
|
122
|
-
### 5.0 MEASURE FIRST, THEN COMPLAIN — the real cost table
|
|
123
|
-
|
|
124
|
-
Every number below was measured on this repo, on an M-series Mac, warm. **Measure again before you
|
|
125
|
-
believe them; a cost you assumed is how you end up optimising the wrong thing.**
|
|
126
|
-
|
|
127
|
-
| command | cost | scope |
|
|
128
|
-
| -------------------------- | --------------- | ------------------------------------------ |
|
|
129
|
-
| `check:token-tiers` | **0.2s** | whole repo |
|
|
130
|
-
| `audit` | **0.5s** | whole repo (~600 files) |
|
|
131
|
-
| `typecheck:docs` | **0.7s** | whole `docs/` program |
|
|
132
|
-
| `typecheck` | **1.3s** | whole `src/` program |
|
|
133
|
-
| `build` | **1.5s** | whole package |
|
|
134
|
-
| `preview:build` | **1.9s** | whole preview |
|
|
135
|
-
| `lint` | **12.9s** | whole repo |
|
|
136
|
-
| **`check:frame-overflow`** | **52s** (was 339s before it was parallelised, gh#851) | **199 frames x 2 viewports, in a browser** |
|
|
137
|
-
|
|
138
|
-
**The lesson is the opposite of the intuition.** "Typecheck the whole system" sounds wasteful and
|
|
139
|
-
costs **1.3 seconds** — typescript-7 is the native compiler, there is nothing to save there, and
|
|
140
|
-
scoping it to changed files would cost more in ceremony than it saves in wall clock. Meanwhile the
|
|
141
|
-
one command that _does_ cost real time is the browser sweep, and it is the one that looks innocent
|
|
142
|
-
in a shell script.
|
|
143
|
-
|
|
144
|
-
`check:frame-overflow` alone was **~96% of the wall clock** of a full local pass. It ran all 398
|
|
145
|
-
navigations down a SINGLE page, in series. It now runs a pool of one page per core (capped at 8):
|
|
146
|
-
**339s -> 52.3s, 6.5x**, byte-identical output, and a planted overflow is still caught at both
|
|
147
|
-
viewports by both. `FRAME_CONCURRENCY=1` restores the serial run for debugging.
|
|
148
|
-
|
|
149
|
-
> **Never argue about the cost of a gate you have not timed.** Time it:
|
|
150
|
-
> `st=$(date +%s); pnpm <gate> >/dev/null 2>&1; echo $(( $(date +%s) - st ))s`
|
|
151
|
-
|
|
152
|
-
### 5.1 What to run, by what you touched
|
|
153
|
-
|
|
154
|
-
Find the row that matches your diff. Run that row. Do not run the rows below it.
|
|
155
|
-
|
|
156
|
-
| you changed | run | why |
|
|
157
|
-
| ---------------------------------- | ------------------------------------------------------------------------------------------------ | --------------------------------------------------------- |
|
|
158
|
-
| a `.css` file only | `audit` · `check:token-tiers` · the component's own tests · `check:frame-overflow --only <slug>` | no TS changed, so `typecheck` has nothing to say |
|
|
159
|
-
| a `.tsx`/`.ts` in `src/` | `typecheck` · `lint` · `audit` · that group's tests | 1.3s + 12.9s, both worth it |
|
|
160
|
-
| a file in `docs/` | `typecheck:docs` · `audit` · `check:example-imports` | `typecheck` covers `src/`, not `docs/` |
|
|
161
|
-
| a token in `src/tokens/` | + `check:token-tiers` · `src/tokens/__tests__` · `pnpm regen` twice (gh#847) | frozen tier tables go stale instantly |
|
|
162
|
-
| a public export / prop | + `pnpm ship:surface` | 8 stacked generators; the list is derived, not remembered |
|
|
163
|
-
| anything that moves LAYOUT | `check:frame-overflow --only <slug>` while you work; the FULL sweep once, before the PR | 17.5s vs 339s |
|
|
164
|
-
| opening the PR / cutting a release | the full sweep, `verify:ci:static`, the full suite in CI | the only place "run everything" is right |
|
|
165
|
-
|
|
166
|
-
### 5.2 `--only` — the diff-scoped browser sweep
|
|
167
|
-
|
|
168
|
-
Added in gh#851 for exactly this. The sweep had no filter at all: 199 frames or nothing.
|
|
169
|
-
|
|
170
|
-
```bash
|
|
171
|
-
pnpm check:frame-overflow --only table # 9 frames, 17.5s
|
|
172
|
-
pnpm check:frame-overflow --only '/^data-entry-(switch|segmented)/' # 3 frames
|
|
173
|
-
pnpm check:frame-overflow # all 199, 52s
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
Measured: `--only table` is **17.5s against the full sweep's 52.3s**. Both matter — the pool cut
|
|
177
|
-
the full sweep 6.5x, and `--only` cuts what is left to the frames a diff can actually reach.
|
|
178
|
-
|
|
179
|
-
Two guards, both deliberate:
|
|
180
|
-
|
|
181
|
-
- **`--only` refuses `--update-baseline`.** A partial sweep does not know whether the frames it
|
|
182
|
-
skipped are still clean, and recording that as the whole truth is how a baseline stops meaning
|
|
183
|
-
anything. Rebaselining needs the full sweep.
|
|
184
|
-
- **Its success line says `PARTIAL, not a release gate`** and prints how many frames it skipped, so
|
|
185
|
-
a filtered green can never be pasted into a PR as if it were the real thing.
|
|
186
|
-
|
|
187
|
-
### 5.3 The commands, for reference
|
|
188
|
-
|
|
189
|
-
```bash
|
|
190
|
-
pnpm lint # eslint — self-contained flat config 12.9s
|
|
191
|
-
pnpm typecheck # tsc --noEmit over src/ 1.3s
|
|
192
|
-
pnpm typecheck:docs # tsc --noEmit over docs/ 0.7s
|
|
193
|
-
pnpm audit # godxjp-ui-audit — 0 errors for touched files 0.5s
|
|
194
|
-
pnpm check:mcp-sync # MCP registry <-> library export drift guard
|
|
195
|
-
pnpm vitest run src/components/<group>/__tests__ --maxWorkers=2 # ONLY what you touched
|
|
196
|
-
pnpm check:frame-overflow --only <slug> # the frames your change can reach ~18s
|
|
197
|
-
pnpm check:frame-overflow # all 199 — pre-PR and CI only 52s
|
|
198
|
-
pnpm preview:build # integration test: examples + docs must build 1.9s
|
|
199
|
-
pnpm test # FULL suite — CI only, never from an agent loop
|
|
200
|
-
pnpm check:frame-axe # WCAG 2.2 AA over every frame — LOCAL ONLY, never in CI (FRAME-A11Y-CI.md)
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
`pnpm verify` and `pnpm verify:release` run these together (verify:release also builds) — **both include the full suite, so both belong to CI.** Locally, run them at most once immediately before opening a PR, never inside an edit loop and never while other agents are working on the same machine. It needs `pnpm exec playwright install chromium` once locally; see [FRAME-A11Y-CI.md](./FRAME-A11Y-CI.md) for how to run/scope it, read the evidence, and regenerate its baseline after an accessibility fix.
|
|
204
|
-
|
|
205
|
-
### Reproducing one screen at one width — the frame routes
|
|
206
|
-
|
|
207
|
-
Three gates and every bug report start here, so the addressing is written down rather than guessed
|
|
208
|
-
(godx-jp/id#639 burned three attempts on `?frame=…`, which is not a thing):
|
|
209
|
-
|
|
210
|
-
```
|
|
211
|
-
pnpm preview # :6008
|
|
212
|
-
http://localhost:6008/isolate/<id> # the demo ALONE, at the real viewport — measure here
|
|
213
|
-
http://localhost:6008/frame/<id> # the same demo inside the device-preset chrome
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
`<id>` is the demo's path under `docs/`, minus `.tsx`, with `/` turned into `-`:
|
|
217
|
-
`docs/layout/topbar.tsx` → `layout-topbar`, `docs/data-entry/date-picker.tsx` → `data-entry-date-picker`.
|
|
218
|
-
A file may override it with a `slug` in its frontmatter. Both routes accept
|
|
219
|
-
`?dir=rtl&density=compact&theme=dark&locale=ja`; `/frame/**` additionally takes `?preset=`/`?w=`/`?h=`/`?zoom=`.
|
|
220
|
-
|
|
221
|
-
For an axe measurement at a given width, drive `/isolate/<id>` with Playwright at that viewport —
|
|
222
|
-
that is what `scripts/topbar-collision-visual.mjs` and the other `test:visual:*` gates do.
|
|
223
|
-
|
|
224
|
-
All gates are **self-contained** — no internal/external tooling package required. The eslint, prettier, and vitest setup live in the package (`eslint.config.js`, `prettier.config.mjs`, `vitest.config.ts`, `src/test/`), so a fresh checkout can lint/type-check/test without anything beyond the declared devDependencies.
|
|
225
|
-
|
|
226
|
-
The app side additionally runs **`npm run ui:audit`** (the design-system linter) and must report 0 errors for touched files.
|
|
227
|
-
|
|
228
|
-
---
|
|
229
|
-
|
|
230
|
-
## 6. Releasing — the lib and its MCP, in lockstep
|
|
231
|
-
|
|
232
|
-
This repo publishes **two packages** that must agree: `@godxjp/ui` (the browser component library, root `package.json`) and `@godxjp/ui-mcp` (the Node MCP server that tells agents how to use it, `mcp/`).
|
|
233
|
-
|
|
234
|
-
### The lockstep contract (issue #140)
|
|
235
|
-
|
|
236
|
-
A consumer that installs `@godxjp/ui@16.10.x` but points its agent at `@godxjp/ui-mcp@16.7.x` gets prop/token/pattern guidance for a build it never installed. To make that impossible, the two packages carry **mutual, machine-readable compatibility metadata**:
|
|
237
|
-
|
|
238
|
-
- root `package.json` → `"godxUiMcp": "<mcp version>"` — the catalog version this library ships with.
|
|
239
|
-
- `mcp/package.json` → `"version"` (identical to the library) **and** `"godxUiCompatibility": "<maj>.<min>.x"` — the UI minor this catalog describes.
|
|
240
|
-
- the MCP exposes it at runtime: `serverInfo.version` == package version, the `godx-ui://compatibility` resource, and the `check_compatibility` tool (an agent calls it with the app's installed `@godxjp/ui` version to get a match/mismatch verdict).
|
|
241
|
-
|
|
242
|
-
- **Lockstep guard** (`pnpm check:mcp-lockstep` → `scripts/check-release-lockstep.mjs`) — asserts ui.version == mcp.version, ui.godxUiMcp == mcp.version, and mcp.godxUiCompatibility covers the UI version. Any split fails CI. - **Catalog drift guard** (`pnpm check:mcp-sync` / `check:mcp-orphans`) — every component the MCP catalogs must still be a real library export, and vice-versa. - **Packed-artifact guard** (`release-integrity` CI, step 4) — packs both tarballs and re-asserts lockstep on the **packed** manifests, i.e. the bytes that would actually ship.
|
|
243
|
-
|
|
244
|
-
### Coordinated release (`pnpm release`)
|
|
245
|
-
|
|
246
|
-
```bash
|
|
247
|
-
pnpm release --ui minor --mcp sync # bump ui, republish mcp at the SAME new version — the norm
|
|
248
|
-
pnpm release --mcp sync # mcp-only fix at the current ui version
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
`--ui <bump>` **requires** `--mcp sync` (the tool refuses a ui-only release) so the two packages can never split. On a bump the tool refreshes both compatibility fields, runs `verify:release` (incl. all three guards) before publishing the lib, `npm publish`es each package, re-runs the lockstep check as a final fail-closed gate, then commits the version bumps.
|
|
252
|
-
|
|
253
|
-
### Recovery from a partial publish
|
|
254
|
-
|
|
255
|
-
If a run publishes `@godxjp/ui` but the `@godxjp/ui-mcp` publish fails (npm hiccup, expired token), the two are momentarily split on npm. Recover:
|
|
256
|
-
|
|
257
|
-
1. Fix the cause (e.g. re-auth `npm whoami`), keep the working tree at the just-published version. 2. Re-run **only** the MCP half at that same version: `pnpm --dir mcp build && npm --prefix mcp version <ui-version> --allow-same-version && npm --prefix mcp publish --access public`. 3.
|
|
258
|
-
|
|
259
|
-
npm versions are immutable, so you can never "fix" a bad published version in place — you can only publish the matching partner at the same number, or move both forward with a fresh `pnpm release --ui patch --mcp sync`. Never hand-publish one package and forget the other.
|
|
260
|
-
|
|
261
|
-
---
|
|
262
|
-
|
|
263
|
-
## See also
|
|
264
|
-
|
|
265
|
-
- [README](../README.md) — overview, component groups, consumer setup.
|
|
266
|
-
- [CONSUMER-RULES.md](./CONSUMER-RULES.md) — the ten rules every consumer follows (the audit enforces them).
|
|
267
|
-
- `docs/TOKENS.md`, `docs/SPACING.md`, `docs/PROPS-VOCABULARY.md`, `docs/PROPS-REGISTRY.md`.
|
|
268
|
-
- [FRAME-A11Y-CI.md](./FRAME-A11Y-CI.md) — per-frame axe a11y (**local only, never in CI**) + geometry + coverage gates.
|
|
269
|
-
- **`godx-ui-component-placement`** skill — decide whether a component belongs here.
|
package/docs/FRAME-A11Y-CI.md
DELETED
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
# Per-frame accessibility — `check:frame-axe` (LOCAL ONLY)
|
|
2
|
-
|
|
3
|
-
One ruler, run in the repository that owns the CSS — **on a developer machine, never in CI/CD.**
|
|
4
|
-
|
|
5
|
-
> **Owner's standing rule (2026-09-17): axe must not run in any GitHub Actions workflow.** It is a
|
|
6
|
-
> local measurement only. gh#643 had wired it into `ci-browser.yml` (four shards on every merge) and
|
|
7
|
-
> `ci-browser-full.yml` (nightly); both jobs are removed. `check:gate-coverage` lists
|
|
8
|
-
> `check:frame-axe` as EXEMPT with this reason, so its absence from the workflows is a declaration,
|
|
9
|
-
> not a dead gate. **Do not re-wire it into a workflow.** The file keeps its historical name so
|
|
10
|
-
> existing links still resolve.
|
|
11
|
-
|
|
12
|
-
## Why it exists (gh#643)
|
|
13
|
-
|
|
14
|
-
`scripts/visual-audit.mjs` carries **eight** rules. A consumer's nightly runs `@axe-core/playwright`
|
|
15
|
-
with **68**. Six of our eight are design-language opinions with no axe equivalent —
|
|
16
|
-
`oversaturated-accent`, `sibling-card-gap`, `row-content-starved`, `emoji-rendered`,
|
|
17
|
-
`alert-controls-misplaced`, `css-layers-missing` — and a design system **should** own those. The
|
|
18
|
-
other sixty (names, roles, `aria-*`, contrast, focus order, target size) were checked **nowhere in
|
|
19
|
-
this repository**, and only in a consumer that cannot fix the CSS, because the CSS is here.
|
|
20
|
-
|
|
21
|
-
gh#639 is what that costs. A topbar shipped; every gate here said green; `target-size` failed in
|
|
22
|
-
`godx-jp/id`'s nightly at 320px. And our own `target-size-min` could not have caught it at any
|
|
23
|
-
threshold — it measures a **painted box**, and that failure was an **obscured** target (axe:
|
|
24
|
-
`partiallyObscured`, 8×28). Two rulers, and the disagreement only ever surfaces downstream.
|
|
25
|
-
|
|
26
|
-
## What it does
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
pnpm check:frame-axe # every frame, 3 viewports
|
|
30
|
-
pnpm check:frame-axe -- --update # rewrite the baseline
|
|
31
|
-
pnpm check:frame-axe -- --scope=showcase # the 30 whole-page frames only, 30s
|
|
32
|
-
pnpm check:frame-axe -- /isolate/layout-topbar # one route, while fixing
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
| | |
|
|
36
|
-
| --------- | --------------------------------------------------------------------------------- |
|
|
37
|
-
| tool | `@axe-core/playwright` |
|
|
38
|
-
| tags | `wcag2a` · `wcag2aa` · `wcag21aa` · `wcag22aa` — **the consumer's set, verbatim** |
|
|
39
|
-
| routes | every `/isolate/<id>` in `window.__STORY_MANIFEST__` + every `/showcase/<id>` |
|
|
40
|
-
| viewports | 1440×900 · 375×667 · **320×568** |
|
|
41
|
-
| states | as rendered, **plus** one overlay OPEN on the routes that declare `data-axe-open` |
|
|
42
|
-
|
|
43
|
-
320 is not decoration: it is WCAG 2.2 SC 1.4.10's reflow width, it is the width the consumer's
|
|
44
|
-
nightly runs, and it is the width gh#639 failed at while 390 passed.
|
|
45
|
-
|
|
46
|
-
Showcases are included on purpose. They are the only frames here shaped like a real screen — a whole
|
|
47
|
-
page, a landmark tree, a focus order — which is precisely the class the component frames cannot
|
|
48
|
-
reach and the consumer has been carrying alone.
|
|
49
|
-
|
|
50
|
-
## The overlay scope — opening the thing before measuring it
|
|
51
|
-
|
|
52
|
-
A menu, dialog, listbox or popover that is closed at rest **paints nothing**. Every axe rule whose
|
|
53
|
-
condition only exists while one is open was therefore outside this gate's field of view, not passing
|
|
54
|
-
it. The gate shipped in 24.1.0 without this half; it is back (gh#643 item 4), rebuilt from the
|
|
55
|
-
version #492 deleted.
|
|
56
|
-
|
|
57
|
-
A demo opts in **declaratively**, from the demo itself:
|
|
58
|
-
|
|
59
|
-
```tsx
|
|
60
|
-
// the trigger, when it forwards DOM props
|
|
61
|
-
<DialogTrigger asChild>
|
|
62
|
-
<Button data-axe-open size="sm">仕訳新規作成</Button>
|
|
63
|
-
</DialogTrigger>
|
|
64
|
-
|
|
65
|
-
// the region that owns it, when the component renders its own trigger
|
|
66
|
-
<CardContent data-axe-open>
|
|
67
|
-
<FormField id="status" label="状態"><Select … /></FormField>
|
|
68
|
-
</CardContent>
|
|
69
|
-
|
|
70
|
-
// right-click, for the gesture nothing else reaches
|
|
71
|
-
<Button data-axe-open="contextmenu" variant="outline">…</Button>
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
What the gate then does, per route/viewport, **after** the default-state scan (opening an overlay is
|
|
75
|
-
destructive to the state that scan measures):
|
|
76
|
-
|
|
77
|
-
1. Take the **first** `[data-axe-open]` on the page. No declaration ⇒ the route skips this entirely
|
|
78
|
-
and costs nothing.
|
|
79
|
-
2. Press **Escape** up to three times while any overlay is mounted. Several demos deliberately
|
|
80
|
-
render one open at rest (`popover`'s anchored panel, `dropdown-menu`'s `defaultOpen` card), and a
|
|
81
|
-
modal one makes the rest of the page unreachable. Dismissing first also makes the measurement a
|
|
82
|
-
real **closed → open** transition rather than whatever the demo happened to leave mounted.
|
|
83
|
-
3. Resolve the click target: the declaring element itself when it matches
|
|
84
|
-
`button, [role=button], [role=combobox], [role=menuitem], a[href], summary`, otherwise the first
|
|
85
|
-
such control inside it. (`Select` and `DatePicker` own their trigger DOM and forward no `data-*`
|
|
86
|
-
to it — hence the declare-on-the-region form. `DatePicker`'s combobox `<input>` is what opens the
|
|
87
|
-
calendar, and it is what gets pressed.)
|
|
88
|
-
4. Click (or right-click), then wait until **one more** overlay is mounted
|
|
89
|
-
(`[data-radix-popper-content-wrapper], [role=dialog], [role=alertdialog], [role=menu],
|
|
90
|
-
[role=listbox]`) — never a bare timer.
|
|
91
|
-
5. Scan again, and key the rows `@<viewport>+open`:
|
|
92
|
-
|
|
93
|
-
```
|
|
94
|
-
/isolate/data-entry-select-matrix @1440+open aria-required-children
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
**A declaration whose overlay never opens is a gate FAILURE**, recorded as `overlay-did-not-open`
|
|
98
|
-
and red on the spot. A broken declaration otherwise reads exactly like a clean frame, which is the
|
|
99
|
-
one thing this scope exists to prevent.
|
|
100
|
-
|
|
101
|
-
**Routes declaring an open step today — 7 declared, 7 open:** `data-entry-select`,
|
|
102
|
-
`data-entry-select-matrix`, `data-entry-date-picker`, `data-display-popover`,
|
|
103
|
-
`navigation-dropdown-menu`, `feedback-dialog`, `feedback-sheet`. (The old `navigation-context-menu`
|
|
104
|
-
frame is gone — `ContextMenu` was folded into `DropdownMenu trigger={["contextMenu"]}` in v23 — so
|
|
105
|
-
the right-click gesture is declared on that card of `navigation-dropdown-menu` instead.)
|
|
106
|
-
|
|
107
|
-
### What it found, and the proof it has teeth
|
|
108
|
-
|
|
109
|
-
**`aria-required-children`, CRITICAL, on `/isolate/data-entry-select-matrix` at all three
|
|
110
|
-
viewports.** `SelectSeparator` rendered react-aria's `<Separator>`, i.e. `role="separator"`, as a
|
|
111
|
-
direct child of the viewport's `role="listbox"`. ARIA 1.2 lets a `listbox` own `option` and `group`
|
|
112
|
-
and nothing else. Fixed in `src/components/data-entry/select.tsx` — the divider is decoration over a
|
|
113
|
-
structure the two `SelectGroup`s already announce, so it now renders `aria-hidden` with no role.
|
|
114
|
-
`menu` **does** own `separator`, so `DropdownMenuSeparator` is correct as it stands. Regression test:
|
|
115
|
-
`src/components/data-entry/__tests__/select-groups.test.tsx`.
|
|
116
|
-
|
|
117
|
-
The control run is the part worth keeping. On the **same defective build**:
|
|
118
|
-
|
|
119
|
-
| declarations | result |
|
|
120
|
-
| ------------ | --------------------------------------------------------------------------- |
|
|
121
|
-
| removed | ✓ green, `0 route(s) opened a declared overlay` |
|
|
122
|
-
| present | ✗ red, 3 × `aria-required-children` on `@1440+open / @375+open / @320+open` |
|
|
123
|
-
|
|
124
|
-
A `data-axe-open` on a `Button` that opens nothing turns the gate red with three
|
|
125
|
-
`overlay-did-not-open` rows, one per viewport.
|
|
126
|
-
|
|
127
|
-
**The original 2026-09 proof no longer reproduces, and the reason matters more than the proof.** That
|
|
128
|
-
commit disabled `src/components/general/inert-background.ts` and watched `aria-hidden-focus` go red
|
|
129
|
-
on `select`, `dropdown-menu` and `context-menu`. Disabling it today changes nothing measurable:
|
|
130
|
-
these overlays are **react-aria-components**, not Radix: react-aria inerts the background itself —
|
|
131
|
-
`#root` plus three focus sentinels carry `inert` the moment a listbox opens, with no `aria-hidden`
|
|
132
|
-
anywhere on them. Stripping every `inert` attribute immediately before the scan still leaves the
|
|
133
|
-
page clean and `aria-hidden-focus` in axe's `passes` bucket, because that rule needs an
|
|
134
|
-
`aria-hidden` ancestor to fire at all. No `src/` component imports `useInertHiddenBackground` any
|
|
135
|
-
more; the only importer is the Radix parity fixture
|
|
136
|
-
`src/components/data-entry/__tests__/radix-select.fixture.tsx`. So `inert-background.ts` is dead
|
|
137
|
-
for `Select` and `DropdownMenu`, and the overlay scope's value is no longer the rule it was built
|
|
138
|
-
for.
|
|
139
|
-
|
|
140
|
-
Be careful with the stronger version of that claim, because the first draft of this paragraph made
|
|
141
|
-
it and it is false: `data-aria-hidden` is **not** absent from the built preview. The `aria-hidden`
|
|
142
|
-
npm package ships inside the `command` chunk (`cmdk`'s dependency tree), so the marker exists in
|
|
143
|
-
the bundle even though no first-party overlay sets it. What is measured above is the narrow claim —
|
|
144
|
-
`Select` and `DropdownMenu` background-inert via `inert`, not `aria-hidden` — not a repo-wide
|
|
145
|
-
absence. It is still the rule class: `aria-required-children` is the same
|
|
146
|
-
shape, and nothing else here could see it.
|
|
147
|
-
|
|
148
|
-
### What is still outside this scope, stated rather than hidden
|
|
149
|
-
|
|
150
|
-
- Only the **first** declaration per route is exercised. A route with several distinct overlays is
|
|
151
|
-
measured on one of them.
|
|
152
|
-
- Only **one step deep**: submenus, an overlay opened from inside another, and the state after a
|
|
153
|
-
selection are not reached.
|
|
154
|
-
- **Keyboard opening is not exercised** — the gate clicks. A trigger that opens on click but not on
|
|
155
|
-
`Enter`/`Space` passes.
|
|
156
|
-
- The overlay's **focus trap and focus order** are not asserted; axe cannot see a JS focus trap.
|
|
157
|
-
|
|
158
|
-
## What it found on its first run — and what came of it
|
|
159
|
-
|
|
160
|
-
54 rows, **159 violation nodes**, on code that passed every other gate in this repository. Fixing
|
|
161
|
-
them took it to **12 rows / 19 nodes**, and then to **0**:
|
|
162
|
-
|
|
163
|
-
| rule | first run | now | what it was |
|
|
164
|
-
| ----------------------- | --------: | --: | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
165
|
-
| `color-contrast` | 62 | 0 | text under 4.5:1 (SC 1.4.3) |
|
|
166
|
-
| `target-size` | 28 | 0 | under 24×24 (SC 2.5.8) — `Carousel` dots, `SearchInput`'s clear button, `Attachments`' file input |
|
|
167
|
-
| `aria-prohibited-attr` | 21 | 0 | `Badge`'s `aria-label` on a `generic` div — the name was dropped by every screen reader |
|
|
168
|
-
| `button-name` | 18 | 0 | **`Select`'s trigger is `role="combobox"`, which cannot be named by its contents** — every unlabelled Select shipped a nameless combobox |
|
|
169
|
-
| `aria-valid-attr-value` | 18 | 0 | `aria-controls` pointing at ids that do not exist |
|
|
170
|
-
| `aria-conditional-attr` | 12 | 0 | `aria-expanded` on a `<tr>`, which only a `treegrid` row may carry |
|
|
171
|
-
|
|
172
|
-
Four of those were LIBRARY defects, not demo slips — `Badge`, `Select`, `Carousel`, `SearchInput` —
|
|
173
|
-
and the fifth produced a new vocabulary member: `tone="inherit"` on `Text` / `Heading` / `Title` /
|
|
174
|
-
`Activity` / `Separator`, because every other tone is an absolute token and there was no way to put
|
|
175
|
-
text on a coloured surface without fighting it.
|
|
176
|
-
|
|
177
|
-
The `target-size` rows are the sharpest point about two rulers. Our own `target-size-min` was
|
|
178
|
-
running on those same frames and reporting them clean, because it measures a painted box. And the
|
|
179
|
-
fix axe wants is not the fix the standard wants: a centred `::after` genuinely makes the target
|
|
180
|
-
24×24 — `docs/MEASUREMENT-CONTRACT.md` records that under `expanders` — but axe reads
|
|
181
|
-
`getBoundingClientRect()`, which cannot see a pseudo-element. Both fixes were tried; the boxes had
|
|
182
|
-
to grow.
|
|
183
|
-
|
|
184
|
-
## The last twelve rows, and what each one turned out to be
|
|
185
|
-
|
|
186
|
-
The table above is what the sweep found; this is what the remaining 12 rows / 19 nodes turned out
|
|
187
|
-
to be once each was measured rather than reasoned about. The rows are kept, with the verdict this
|
|
188
|
-
file used to carry quoted back, because four of the five were wrong: two had no diagnosis at all
|
|
189
|
-
and two had one the measurement contradicted — and in both of those the guess pointed AWAY from
|
|
190
|
-
this package.
|
|
191
|
-
|
|
192
|
-
| rows | what | the measurement, and where it was fixed |
|
|
193
|
-
| ---: | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
194
|
-
| 3 | `foundation-colors` · `--success-foreground` on `--success`, `--attention-foreground` on `--attention` | Called "a PALETTE decision, an owner-level call". It was not the palette: the FILL was fine and the INK was wrong. Two of the light theme's eight fills carried a near-white ink their own lightness cannot support (2.19:1 / 3.32:1) while the sibling `--warning` had always used the near-black one on the equally pale 山吹, and the DARK theme already flipped both. `src/tokens/foundation.css`: ink only — success 2.19 → **7.08**, attention 3.32 → **4.68**. Guarded by `__tests__/status-fill-contrast.test.ts`. |
|
|
195
|
-
| 3 | `case6-agency-handy` · a SELECTED `ToggleGroupItem` paints `--foreground` over `--primary` | "Cause not yet found." Found, with `CSS.getMatchedStylesForNode`: the demo wrote `text-[var(--font-size-xs)]`, and Tailwind v4 reads a bare `var()` in `text-*` as a COLOUR — it compiled to `color: var(--font-size-xs)` in the UTILITIES layer, an invalid colour that clobbered the component's own `color: hsl(var(--primary-foreground))` in `components` and left the trigger inheriting the page ink. The component rule was right all along. Demo fix (`text-[length:var(…)]`, 10 sites in `docs/`), plus the count pill: the hand-rolled `Text` at `opacity-70` measured 2.15:1 and `ToggleGroupItem`'s own `count` prop inverts to 6.32:1. |
|
|
196
|
-
| 3 | `table-view-tabs` · a `Tab`'s `aria-controls` points at a `tabpanel` that is never rendered | A LIBRARY defect, and the composition is published: `Tabs` / `TabsList` / `TabsTrigger` are three separate exports, nothing in their types asks for a fourth, and the attribute could not be overridden (`withDomProps` puts RAC's props after the caller's). `TabsContent` now registers its value and a trigger claims a panel only when one is declared. No new public prop. `__tests__/tabs-panel-reference-643.test.tsx`. |
|
|
197
|
-
| 2 | `futurelastic-web` @320/@375 · white ghost buttons read as 1.01:1 | "Probably a false positive." It was not. The tenant's `.fl-navbar-inner` was a fixed-height flex row with no wrap, so at 320 its content ran to **x=569.6 inside a 320px nav** — the links painted outside the navbar's own box, over the page behind it. A WCAG 2.2 SC 1.4.10 reflow failure reported by the contrast rule, because that is what an overflowing element looks like from the outside. Demo CSS + `Flex wrap`. |
|
|
198
|
-
| 1 | `table-bulk-actions` @375 · `target-size` | "Not yet diagnosed." The left cluster carried `min-w-0 flex-1` — "squeeze me to nothing" — over children that refuse to shrink, so its box shrank to 113.6px while its content ran to x=462 and painted 一括承認 (264.6→360.2) under 解除 (272.3→341.0), leaving 19.2×30.2 unobscured against SC 2.5.8's 24×24. Demo: `wrap`, and no `min-w-0`. |
|
|
199
|
-
|
|
200
|
-
Two of the five were library defects and three were genuine demo slips — a different split from the
|
|
201
|
-
first sweep, where four of five were the library's. Which is the point of writing the number down
|
|
202
|
-
next to each one: "it is the demo" and "it is the palette" are both cheap to say and neither
|
|
203
|
-
survived a measurement here.
|
|
204
|
-
|
|
205
|
-
## The baseline is a debt ledger, not an allowlist
|
|
206
|
-
|
|
207
|
-
The package did not start compliant, and a gate that fails the whole build on its first day gets
|
|
208
|
-
deleted rather than obeyed. `frame-axe-baseline.json` records what was already failing when the gate
|
|
209
|
-
landed, keyed one row per `(route, viewport, rule)`:
|
|
210
|
-
|
|
211
|
-
```
|
|
212
|
-
"/isolate/layout-topbar @320 target-size": { "count": 2, "help": "…" }
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
The gate fails on a key that is **not** in the baseline, and on a baselined key whose `count`
|
|
216
|
-
**grows**. A key that stops firing is reported so it can be dropped.
|
|
217
|
-
|
|
218
|
-
- **Delete rows as you fix them.** `--update` rewrites the file; the diff is the review.
|
|
219
|
-
- **Never add a row by hand to turn a red build green.** That is the one move this file exists to
|
|
220
|
-
make visible.
|
|
221
|
-
|
|
222
|
-
## What this gate does NOT do — stated, not hidden
|
|
223
|
-
|
|
224
|
-
The gate deleted in #492 did three things this one does not. One is now back; two are still gaps:
|
|
225
|
-
|
|
226
|
-
1. ~~**No overlay scope.**~~ Restored — see [the overlay
|
|
227
|
-
scope](#the-overlay-scope--opening-the-thing-before-measuring-it) above.
|
|
228
|
-
2. **No chrome/component split.** The old gate held the preview toolbar to zero violations and
|
|
229
|
-
allowlisted the component scope separately. `/isolate/**` renders the demo alone, so there is
|
|
230
|
-
little chrome to separate — but `/showcase/**` is scanned whole.
|
|
231
|
-
3. **No per-rule severity.** Every WCAG-tagged rule is treated alike.
|
|
232
|
-
|
|
233
|
-
## Determinism
|
|
234
|
-
|
|
235
|
-
Two consecutive sweeps of identical code first disagreed on five `color-contrast` rows: a fade-in
|
|
236
|
-
caught mid-flight renders text at partial opacity and axe scores whatever it finds. A gate that
|
|
237
|
-
disagrees with itself gets ignored, so each page is pinned before the scan —
|
|
238
|
-
`reducedMotion: "reduce"`, an injected stylesheet zeroing every animation and transition duration,
|
|
239
|
-
and `document.fonts.ready` (web fonts change glyph geometry, which changes which boxes overlap,
|
|
240
|
-
which changes what `color-contrast` resolves a background to). Two sweeps after that: identical.
|
|
241
|
-
|
|
242
|
-
## Cost
|
|
243
|
-
|
|
244
|
-
| | |
|
|
245
|
-
| ------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
246
|
-
| full sweep | **2m14s** locally, with the overlay scope — 215 routes × 3 viewports |
|
|
247
|
-
| sequential | ~55 min — the three viewport passes run concurrently, which is the whole difference |
|
|
248
|
-
| showcase only (`--scope=showcase`) | ~30s |
|
|
249
|
-
| one route (`pnpm check:frame-axe /isolate/…`) | seconds — the loop to use while fixing |
|
|
250
|
-
|
|
251
|
-
The overlay pass is bounded by declaration: only the 7 declaring routes pay it (21 extra scans plus
|
|
252
|
-
their open steps), and no `/showcase/**` route declares one, so `--scope=showcase` is unchanged by it.
|
|
253
|
-
|
|
254
|
-
## Where it runs: your machine
|
|
255
|
-
|
|
256
|
-
**Never in CI/CD** — see the rule at the top. The procedure:
|
|
257
|
-
|
|
258
|
-
```bash
|
|
259
|
-
pnpm build && pnpm preview:build # the STATIC preview — not `pnpm dev` / `pnpm preview`
|
|
260
|
-
pnpm check:frame-axe # full sweep; must end with 0 baselined entries, 0 nodes
|
|
261
|
-
pnpm check:frame-axe /isolate/<frame> # one route, while fixing
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
Run it before a PR that touches markup, ARIA, focus behaviour or colour, and commit what it writes —
|
|
265
|
-
`audit-evidence/frame-axe/results.json` and, only when a full sweep genuinely changed it,
|
|
266
|
-
`frame-axe-baseline.json`.
|
|
267
|
-
|
|
268
|
-
**The static preview, not the dev server.** Against the vite dev server the sweep produces 1–3
|
|
269
|
-
spurious `route-did-not-render` / `axe-did-not-run` rows on different routes each run — 30s
|
|
270
|
-
`page.goto` timeouts while three viewport contexts hammer an on-demand-transforming server. Each is
|
|
271
|
-
clean alone. The static build does not do this.
|
|
272
|
-
|
|
273
|
-
**`--shard=i/n` and `--scope=` are for splitting a LOCAL run**, e.g. across two terminals. Two guards
|
|
274
|
-
hold for both: `--update` refuses under either (a partial run would rewrite the ledger from a fraction
|
|
275
|
-
of the frames and delete the rest), and the "no longer fires" report is suppressed on a partial run
|
|
276
|
-
(every other partition's rows would read as fixed). Regenerate the baseline from a full sweep only.
|
|
277
|
-
|
|
278
|
-
### What leaving CI costs, stated rather than discovered
|
|
279
|
-
|
|
280
|
-
A regression is now caught when someone runs this, not on merge. Nothing in the pipeline will turn
|
|
281
|
-
red on a new `aria-*` defect, a nameless button or a sub-24px target. That is the trade the rule
|
|
282
|
-
makes, and the only thing that closes it is the local run above actually happening before a PR.
|
|
283
|
-
|
|
284
|
-
## Related
|
|
285
|
-
|
|
286
|
-
- [FRAME-COVERAGE-STANDARD.md](./FRAME-COVERAGE-STANDARD.md) — which frames must exist at all.
|
|
287
|
-
- [DEVELOPMENT.md](./DEVELOPMENT.md) §5 — the `/isolate/<id>` · `/frame/<id>` addressing.
|