@astryxdesign/cli 0.1.7 → 0.1.8-canary.07362a9
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/CHANGELOG.md +40 -0
- package/README.md +115 -19
- package/{src/api → api/blog}/blog.mjs +42 -6
- package/{src/api → api/blog}/blog.test.mjs +2 -2
- package/api/build/build.mjs +92 -0
- package/api/build/build.test.mjs +92 -0
- package/{src/api → api/component}/component.mjs +49 -26
- package/{src/api → api/discover}/discover.mjs +55 -18
- package/{src/api → api/docs}/docs.mjs +47 -21
- package/{src/api → api/doctor}/doctor.mjs +13 -10
- package/{src/api → api}/error.mjs +2 -2
- package/{src/api → api/hook}/hook.mjs +11 -11
- package/{src/api → api}/index.mjs +16 -9
- package/{src/api → api/integration}/validate-integration.mjs +48 -15
- package/{src/api → api/integration}/validate-integration.test.mjs +1 -1
- package/{src/api → api/layout}/layout.mjs +66 -17
- package/{src/api → api/layout}/layout.test.mjs +1 -1
- package/{src/api → api/search}/search.mjs +71 -12
- package/api/swizzle/swizzle.mjs +283 -0
- package/{src/commands → api/swizzle}/swizzle.test.mjs +26 -1
- package/{src/api → api/template}/template-integration.test.mjs +2 -2
- package/{src/api → api/template}/template-suffix.test.mjs +3 -3
- package/{src/api → api/template}/template.mjs +96 -19
- package/{src/api → api/theme}/theme-add.mjs +35 -7
- package/{src → authoring}/codemod.mjs +6 -6
- package/{src → authoring}/config.test.mjs +1 -1
- package/{src → authoring}/doc.mjs +1 -1
- package/{src → authoring}/doc.test.mjs +1 -1
- package/{src → authoring}/template.mjs +1 -1
- package/bin/astryx.mjs +12 -10
- package/{src → cli}/commands/blog.mjs +48 -7
- package/{src → cli}/commands/build-theme.mjs +133 -115
- package/cli/commands/build.mjs +172 -0
- package/cli/commands/cli-postinstall.test.mjs +42 -0
- package/{src → cli}/commands/component/index.mjs +52 -25
- package/{src → cli}/commands/component-ownership.test.mjs +3 -3
- package/{src → cli}/commands/component-package.test.mjs +1 -1
- package/{src → cli}/commands/component-resolution.test.mjs +2 -2
- package/{src → cli}/commands/discover.mjs +23 -12
- package/{src → cli}/commands/docs.mjs +42 -10
- package/{src → cli}/commands/docs.test.mjs +1 -1
- package/{src → cli}/commands/doctor.mjs +3 -3
- package/{src → cli}/commands/doctor.test.mjs +2 -2
- package/{src → cli}/commands/ensure-core-built.mjs +3 -2
- package/{src → cli}/commands/external-showcase.test.mjs +1 -1
- package/{src → cli}/commands/hook/index.mjs +40 -17
- package/{src → cli}/commands/import-hint-correctness.test.mjs +1 -1
- package/cli/commands/init.mjs +195 -0
- package/{src → cli}/commands/init.next-steps.test.mjs +1 -1
- package/cli/commands/interactive-guard.test.mjs +66 -0
- package/{src → cli}/commands/json-contract.test.mjs +2 -2
- package/{src → cli}/commands/layout.mjs +59 -19
- package/{src → cli}/commands/search.mjs +22 -15
- package/{src → cli}/commands/search.test.mjs +1 -1
- package/cli/commands/setup-nudge.test.mjs +108 -0
- package/cli/commands/swizzle.mjs +103 -0
- package/{src → cli}/commands/template.mjs +84 -53
- package/{src → cli}/commands/template.path-safety.test.mjs +2 -2
- package/{src → cli}/commands/upgrade.integration-policy.test.mjs +1 -1
- package/{src → cli}/commands/upgrade.mjs +291 -77
- package/cli/commands/upgrade.test.mjs +314 -0
- package/{src → cli}/commands/validate-integration.mjs +17 -37
- package/{src → cli}/index.mjs +55 -19
- package/{src/codemods → codemods}/__tests__/registry.test.mjs +1 -0
- package/{src/codemods → codemods}/ensure-jscodeshift.mjs +12 -28
- package/{src/codemods → codemods}/integration-discovery.mjs +6 -3
- package/{src/codemods → codemods}/integration-discovery.test.mjs +1 -1
- package/{src/codemods → codemods}/integration-runner.mjs +8 -3
- package/{src/codemods → codemods}/registry.mjs +4 -1
- package/{src/codemods → codemods}/run-codemod.mjs +18 -11
- package/{src/codemods → codemods}/runner.mjs +24 -14
- package/{src/codemods → codemods}/transforms/v0.0.10/remove-size-props.mjs +9 -4
- package/{src/codemods → codemods}/transforms/v0.0.12/add-is-icon-only.mjs +27 -22
- package/{src/codemods → codemods}/transforms/v0.0.13/icon-name-deprecations.mjs +12 -5
- package/{src/codemods → codemods}/transforms/v0.0.13/rename-attachments-to-drawer.mjs +15 -8
- package/{src/codemods → codemods}/transforms/v0.0.13/toolbar-density-to-size.mjs +10 -4
- package/{src/codemods → codemods}/transforms/v0.0.14/rename-action-props.mjs +11 -5
- package/{src/codemods → codemods}/transforms/v0.0.14/rename-section-wash-to-muted.mjs +11 -6
- package/{src/codemods → codemods}/transforms/v0.0.14/rename-status-variants.mjs +15 -10
- package/{src/codemods → codemods}/transforms/v0.0.15/migrate-item-children-to-endcontent.mjs +13 -8
- package/{src/codemods → codemods}/transforms/v0.0.15/migrate-selector-children-to-render-option.mjs +18 -13
- package/{src/codemods → codemods}/transforms/v0.0.15/migrate-theme-selectors-to-data-attrs.mjs +8 -4
- package/{src/codemods → codemods}/transforms/v0.0.15/rename-date-picker-to-input.mjs +11 -6
- package/{src/codemods → codemods}/transforms/v0.0.15/rename-imperative-ref-to-handleRef.mjs +6 -1
- package/{src/codemods → codemods}/transforms/v0.0.15/rename-isStreaming-to-isStopShown.mjs +6 -1
- package/{src/codemods → codemods}/transforms/v0.0.15/rename-stack-element-to-as.mjs +8 -3
- package/{src/codemods → codemods}/transforms/v0.0.2/migrate-badge-dot-to-statusdot.mjs +17 -10
- package/{src/codemods → codemods}/transforms/v0.0.2/migrate-gap-to-numeric.mjs +7 -1
- package/{src/codemods → codemods}/transforms/v0.0.2/migrate-isFullBleed-to-padding.mjs +9 -4
- package/{src/codemods → codemods}/transforms/v0.0.2/migrate-useXDSIcon-to-getIcon.mjs +12 -7
- package/{src/codemods → codemods}/transforms/v0.0.2/rename-banner-endButton-to-endContent.mjs +7 -2
- package/{src/codemods → codemods}/transforms/v0.0.2/rename-form-tooltip-startIcon.mjs +8 -2
- package/{src/codemods → codemods}/transforms/v0.0.2/rename-isShown-to-isOpen.mjs +7 -2
- package/{src/codemods → codemods}/transforms/v0.0.2/rename-selector-items-to-options.mjs +7 -2
- package/{src/codemods → codemods}/transforms/v0.0.2/rename-sidenav-header-to-heading.mjs +11 -4
- package/{src/codemods → codemods}/transforms/v0.0.2/rename-topnav-title-to-heading.mjs +10 -4
- package/{src/codemods → codemods}/transforms/v0.0.2/unify-uncontrolled-to-defaultX.mjs +7 -2
- package/{src/codemods → codemods}/transforms/v0.0.2/unify-visibility-to-onOpenChange.mjs +10 -5
- package/{src/codemods → codemods}/transforms/v0.0.6/migrate-badge-children-to-label.mjs +7 -2
- package/{src/codemods → codemods}/transforms/v0.0.6/migrate-collapse-to-collapsible.mjs +9 -3
- package/{src/codemods → codemods}/transforms/v0.0.6/migrate-radius-tokens.mjs +11 -5
- package/{src/codemods → codemods}/transforms/v0.0.6/migrate-shadow-tokens.mjs +13 -6
- package/{src/codemods → codemods}/transforms/v0.0.6/migrate-skeleton-radius.mjs +7 -1
- package/{src/codemods → codemods}/transforms/v0.0.6/migrate-token-names.mjs +11 -5
- package/{src/codemods → codemods}/transforms/v0.0.7/rename-banner-variant-to-container.mjs +8 -3
- package/{src/codemods → codemods}/transforms/v0.0.8/migrate-token-renames.mjs +15 -8
- package/{src/codemods → codemods}/transforms/v0.0.8/rename-endslot-to-endcontent.mjs +7 -2
- package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/drop-xds-prefix-imports.test.mjs +42 -7
- package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/migrate-xds-module-specifiers.test.mjs +43 -0
- package/{src/codemods → codemods}/transforms/v0.1.0/drop-xds-prefix-imports.mjs +117 -13
- package/{src/codemods → codemods}/transforms/v0.1.0/migrate-xds-css-surfaces.mjs +21 -17
- package/{src/codemods → codemods}/transforms/v0.1.0/migrate-xds-declare-module.mjs +7 -2
- package/{src/codemods → codemods}/transforms/v0.1.0/migrate-xds-module-specifiers.mjs +86 -15
- package/{src/codemods → codemods}/transforms/v0.1.2/rename-text-color-active-to-accent.mjs +15 -9
- package/{src/codemods → codemods}/transforms/v0.1.3/migrate-layout-components-to-experimental.mjs +17 -12
- package/{src/codemods → codemods}/transforms/v0.1.5/rename-switch-label-spacing-default-to-hug.mjs +15 -9
- package/{src/codemods → codemods}/transforms/v0.1.7/migrate-table-tableprops-to-direct-props.mjs +17 -10
- package/{src/codemods → codemods}/transforms/v0.1.7/rename-table-renderprops-styles-to-xstyle.mjs +18 -13
- package/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +161 -0
- package/codemods/transforms/v0.1.8/index.mjs +19 -0
- package/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +239 -0
- package/docs/cli-integrations.doc.mjs +150 -0
- package/docs/elevation.doc.mjs +79 -1
- package/docs/getting-started.doc.mjs +9 -9
- package/docs/internationalization.doc.mjs +92 -46
- package/docs/migration.doc.mjs +18 -18
- package/docs/principles.doc.dense.mjs +1 -1
- package/docs/principles.doc.mjs +6 -6
- package/docs/principles.doc.zh.mjs +1 -1
- package/docs/styling-libraries.doc.mjs +3 -3
- package/docs/styling.doc.mjs +4 -4
- package/docs/theme.doc.dense.mjs +2 -2
- package/docs/theme.doc.mjs +7 -7
- package/docs/theme.doc.zh.mjs +1 -1
- package/docs/tokens.doc.mjs +1 -1
- package/docs/working-with-ai.doc.mjs +19 -19
- package/{src/commands → lib/agent-docs}/agent-docs.mjs +164 -29
- package/{src/commands → lib/agent-docs}/agent-docs.path-safety.test.mjs +1 -1
- package/{src/commands → lib/agent-docs}/agent-docs.test.mjs +123 -10
- package/{src/lib → lib}/cli-error.mjs +2 -2
- package/{src/lib → lib}/component-discovery.mjs +44 -2
- package/{src/lib → lib}/component-format.mjs +67 -25
- package/{src/lib → lib}/component-loader.mjs +27 -13
- package/{src/lib → lib}/componentDocOverlay.test.mjs +0 -1
- package/{src/lib → lib}/error-codes.test.mjs +1 -1
- package/{src/lib → lib}/hook-discovery.mjs +14 -1
- package/{src/lib → lib}/hook-format.mjs +29 -5
- package/{src/lib → lib}/integration-warnings.mjs +2 -2
- package/{src/lib → lib}/integrations.mjs +20 -0
- package/{src/lib → lib}/integrations.test.mjs +1 -1
- package/{src/lib → lib}/json-contract.test.mjs +1 -1
- package/{src/lib → lib}/json-shim.mjs +11 -6
- package/{src/lib → lib}/json-shim.test.mjs +1 -1
- package/{src/lib → lib}/json.mjs +3 -3
- package/{src/lib → lib}/levenshtein.mjs +6 -0
- package/{src/lib → lib}/manifest.mjs +7 -5
- package/{src/lib → lib}/manifest.test.mjs +2 -2
- package/{src/lib → lib}/module-loader.mjs +1 -0
- package/{src/lib → lib}/package-scanner.mjs +47 -0
- package/{src/lib → lib}/project.mjs +48 -18
- package/{src/lib → lib}/project.test.mjs +1 -1
- package/{src/lib → lib}/resolve-theme.mjs +5 -0
- package/{src/lib → lib}/string-utils.mjs +15 -0
- package/lib/term-log.mjs +57 -0
- package/{src/lib → lib}/xle/browser.mjs +18 -8
- package/{src/lib → lib}/xle/expand.mjs +155 -22
- package/{src/lib → lib}/xle/parse.mjs +119 -13
- package/{src/lib → lib}/xle/print.mjs +54 -14
- package/{src/lib → lib}/xle/registry-core.mjs +28 -3
- package/{src/lib → lib}/xle/registry.mjs +9 -4
- package/{src/lib → lib}/xle/splice.mjs +13 -2
- package/{src/lib → lib}/xle/validate.mjs +95 -14
- package/lib/xle/xle-ast.d.ts +214 -0
- package/package.json +37 -28
- package/scripts/postinstall.mjs +74 -0
- package/templates/blocks/components/Avatar/AvatarFallbackChain.tsx +4 -4
- package/templates/blocks/components/Avatar/AvatarGroup.tsx +2 -2
- package/templates/blocks/components/Avatar/AvatarInitialsFallback.tsx +1 -1
- package/templates/blocks/components/Avatar/AvatarShowcase.tsx +5 -5
- package/templates/blocks/components/Avatar/AvatarUserCard.tsx +1 -1
- package/templates/blocks/components/Avatar/AvatarWithImage.tsx +4 -4
- package/templates/blocks/components/Avatar/AvatarWithStatus.tsx +3 -3
- package/templates/blocks/components/AvatarGroup/AvatarGroupShowcase.tsx +2 -2
- package/templates/blocks/components/AvatarGroupOverflow/AvatarGroupOverflowCustomText.tsx +1 -1
- package/templates/blocks/components/AvatarGroupOverflow/AvatarGroupOverflowDefault.tsx +1 -1
- package/templates/blocks/components/AvatarGroupOverflow/AvatarGroupOverflowShowcase.tsx +2 -2
- package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotShowcase.tsx +3 -3
- package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotVariants.tsx +3 -3
- package/templates/blocks/components/Banner/BannerFloating.doc.mjs +14 -0
- package/templates/blocks/components/Banner/BannerFloating.tsx +16 -0
- package/templates/blocks/components/Button/ButtonFloating.doc.mjs +14 -0
- package/templates/blocks/components/Button/ButtonFloating.tsx +37 -0
- package/templates/blocks/components/ButtonGroup/ButtonGroupFloating.doc.mjs +14 -0
- package/templates/blocks/components/ButtonGroup/ButtonGroupFloating.tsx +23 -0
- package/templates/blocks/components/Card/CardElevations.doc.mjs +14 -0
- package/templates/blocks/components/Card/CardElevations.tsx +32 -0
- package/templates/blocks/components/Card/ClickableCardElevated.doc.mjs +14 -0
- package/templates/blocks/components/Card/ClickableCardElevated.tsx +21 -0
- package/templates/blocks/components/Card/SelectableCardElevated.doc.mjs +14 -0
- package/templates/blocks/components/Card/SelectableCardElevated.tsx +37 -0
- package/templates/blocks/components/Carousel/CarouselSnap.tsx +1 -1
- package/templates/blocks/components/ChatComposer/ChatComposerFlat.doc.mjs +14 -0
- package/templates/blocks/components/ChatComposer/ChatComposerFlat.tsx +75 -0
- package/templates/blocks/components/ChatMessage/ChatMessageAvatarName.tsx +2 -2
- package/templates/blocks/components/ChatMessage/ChatMessageMultiBubble.tsx +1 -1
- package/templates/blocks/components/ChatMessageBubble/ChatMessageBubbleGrouping.tsx +1 -1
- package/templates/blocks/components/ChatMessageBubble/ChatMessageBubbleMetadata.tsx +1 -1
- package/templates/blocks/components/ChatMessageList/ChatMessageListDensity.tsx +5 -9
- package/templates/blocks/components/ChatMessageList/ChatMessageListFullFeatured.tsx +1 -1
- package/templates/blocks/components/CodeBlock/CodeBlockTerminal.tsx +1 -1
- package/templates/blocks/components/HoverCard/HoverCardShowcase.tsx +1 -1
- package/templates/blocks/components/IconButton/IconButtonFloating.doc.mjs +14 -0
- package/templates/blocks/components/IconButton/IconButtonFloating.tsx +37 -0
- package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.doc.mjs +19 -0
- package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +46 -0
- package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider02Overrides.doc.mjs +14 -0
- package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider02Overrides.tsx +33 -0
- package/templates/blocks/components/Item/ItemWithMedia.tsx +2 -2
- package/templates/blocks/components/ListItem/ListItemWithMedia.tsx +2 -2
- package/templates/blocks/components/OverflowList/OverflowListCappedToolbar.doc.mjs +14 -0
- package/templates/blocks/components/OverflowList/OverflowListCappedToolbar.tsx +39 -0
- package/templates/blocks/components/OverflowList/OverflowListMultiRowTags.doc.mjs +14 -0
- package/templates/blocks/components/OverflowList/OverflowListMultiRowTags.tsx +44 -0
- package/templates/blocks/components/Pagination/PaginationDotsCarousel.tsx +2 -6
- package/templates/blocks/components/Stack/StackFillItem.tsx +2 -6
- package/templates/blocks/components/TabList/TabListTabsWithActions.doc.mjs +1 -1
- package/templates/blocks/components/TabList/TabListTabsWithActions.tsx +2 -7
- package/templates/blocks/components/Table/TableRowStatusTable.doc.mjs +14 -0
- package/templates/blocks/components/Table/TableRowStatusTable.tsx +59 -0
- package/templates/blocks/components/Thumbnail/ThumbnailDisabled.tsx +6 -1
- package/templates/blocks/components/Thumbnail/ThumbnailGallery.tsx +1 -0
- package/templates/blocks/components/Thumbnail/ThumbnailRemovable.tsx +1 -0
- package/templates/blocks/components/TypeaheadItem/TypeaheadItemShowcase.tsx +1 -1
- package/templates/pages/ai-chat/page.tsx +4 -4
- package/templates/pages/dashboard-portfolio/page.tsx +3 -11
- package/templates/pages/detail-page/page.tsx +5 -12
- package/templates/pages/documentation-design/page.tsx +1 -1
- package/templates/pages/messaging-shell/page.tsx +6 -8
- package/templates/pages/table-grouped/page.tsx +9 -14
- package/templates/pages/table-page/page.tsx +7 -9
- package/templates/pages/table-page-heatmap-status/page.tsx +5 -13
- package/{src/types → types}/api.contract.assert.ts +17 -8
- package/{src/types → types}/api.d.ts +110 -9
- package/{src/types → types}/base.d.ts +40 -4
- package/types/build.d.ts +53 -0
- package/types/codemod.d.ts +166 -0
- package/{src/types → types}/component.d.ts +1 -1
- package/{src/types → types}/discover.d.ts +1 -1
- package/{src/types → types}/docs.d.ts +1 -4
- package/{src/types → types}/hook.d.ts +1 -1
- package/{src/types → types}/index.d.ts +1 -0
- package/types/jscodeshift.d.ts +19 -0
- package/types/layout.d.ts +74 -0
- package/{src/types → types}/swizzle.d.ts +4 -0
- package/{src/types → types}/template-api.d.ts +4 -1
- package/types/theme.d.ts +53 -0
- package/types/upgrade.d.ts +108 -0
- package/utils/package-manager.mjs +178 -0
- package/utils/package-manager.test.mjs +220 -0
- package/{src/utils → utils}/path-safety.mjs +0 -18
- package/{src/utils → utils}/paths.mjs +4 -1
- package/{src/utils → utils}/update-check.mjs +5 -4
- package/{src/utils → utils}/update-check.test.mjs +3 -3
- package/docs/integration-authoring.md +0 -105
- package/src/commands/build.mjs +0 -196
- package/src/commands/init.mjs +0 -288
- package/src/commands/interactive-guard.test.mjs +0 -69
- package/src/commands/swizzle.mjs +0 -440
- package/src/commands/upgrade.test.mjs +0 -160
- package/src/types/codemod.d.ts +0 -81
- package/src/types/theme.d.ts +0 -23
- package/src/types/upgrade.d.ts +0 -64
- package/src/utils/interactive.mjs +0 -76
- package/src/utils/interactive.test.mjs +0 -70
- package/src/utils/package-manager.mjs +0 -74
- package/src/utils/package-manager.test.mjs +0 -113
- /package/{src/api → api/docs}/docOverlays.test.mjs +0 -0
- /package/{src/api → api/integration}/integration-block-exports.test.mjs +0 -0
- /package/{src/api → api/template}/template.test.mjs +0 -0
- /package/{src → authoring}/codemod.test.mjs +0 -0
- /package/{src → authoring}/config.mjs +0 -0
- /package/{src → authoring}/integration.mjs +0 -0
- /package/{src → authoring}/template.test.mjs +0 -0
- /package/{src → cli}/cli-exit-codes.test.mjs +0 -0
- /package/{src → cli}/commands/build-theme.color-scheme.test.mjs +0 -0
- /package/{src → cli}/commands/build-theme.import-path.test.mjs +0 -0
- /package/{src → cli}/commands/build-theme.path-safety.test.mjs +0 -0
- /package/{src → cli}/commands/build-theme.prose.test.mjs +0 -0
- /package/{src → cli}/commands/build-theme.variants.test.mjs +0 -0
- /package/{src → cli}/commands/build-theme.watch.test.mjs +0 -0
- /package/{src → cli}/commands/component.test.mjs +0 -0
- /package/{src → cli}/commands/detail-levels.test.mjs +0 -0
- /package/{src → cli}/commands/swizzle.path-safety.test.mjs +0 -0
- /package/{src → cli}/commands/swizzle.routing.test.mjs +0 -0
- /package/{src → cli}/commands/template.test.mjs +0 -0
- /package/{src → cli}/commands/upgrade.config-ordering.test.mjs +0 -0
- /package/{src → cli}/commands/validate-integration.test.mjs +0 -0
- /package/{src → cli}/update-hint-commands.test.mjs +0 -0
- /package/{src/codemods → codemods}/__tests__/rename-imperative-ref-to-handleRef.test.mjs +0 -0
- /package/{src/codemods → codemods}/__tests__/rename-isStreaming-to-isStopShown.test.mjs +0 -0
- /package/{src/codemods → codemods}/__tests__/rename-section-wash-to-muted.test.mjs +0 -0
- /package/{src/codemods → codemods}/__tests__/runner.test.mjs +0 -0
- /package/{src/codemods → codemods}/__tests__/toolbar-density-to-size.test.mjs +0 -0
- /package/{src/codemods → codemods}/__tests__/validation.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.10/__tests__/remove-size-props.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.10/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.12/__tests__/add-is-icon-only.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.12/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.13/__tests__/icon-name-deprecations.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.13/__tests__/rename-attachments-to-drawer.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.13/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.14/__tests__/rename-action-props.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.14/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/migrate-item-children-to-endcontent.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/migrate-selector-children-to-render-option.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/migrate-theme-selectors-to-data-attrs.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/rename-date-picker-to-input.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/rename-stack-element-to-as.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.15/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-badge-dot-to-statusdot.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-gap-to-numeric.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-isFullBleed-to-padding.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-useXDSIcon-to-getIcon.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-banner-endButton-to-endContent.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-form-tooltip-startIcon.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-isShown-to-isOpen.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-selector-items-to-options.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-sidenav-header-to-heading.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-topnav-title-to-heading.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/unify-uncontrolled-to-defaultX.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/unify-visibility-to-onOpenChange.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.2/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-collapse-to-collapsible.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-radius-tokens.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-shadow-tokens.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-skeleton-radius.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-token-names.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.6/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.7/__tests__/rename-banner-variant-to-container.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.7/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.8/__tests__/migrate-token-renames.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.8/__tests__/rename-endslot-to-endcontent.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.0.8/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/migrate-xds-css-surfaces.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/migrate-xds-declare-module.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/v0.1.0-ordering.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.0/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.2/__tests__/rename-text-color-active-to-accent.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.2/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.3/__tests__/migrate-layout-components-to-experimental.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.3/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.5/__tests__/rename-switch-label-spacing-default-to-hug.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.5/index.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.7/__tests__/migrate-table-tableprops-to-direct-props.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.7/__tests__/rename-table-renderprops-styles-to-xstyle.test.mjs +0 -0
- /package/{src/codemods → codemods}/transforms/v0.1.7/index.mjs +0 -0
- /package/{src/lib → lib}/cli-error.test.mjs +0 -0
- /package/{src/lib → lib}/component-discovery.importpath.test.mjs +0 -0
- /package/{src/lib → lib}/component-format.test.mjs +0 -0
- /package/{src/lib → lib}/component-loader.test.mjs +0 -0
- /package/{src/lib → lib}/config-cache.mjs +0 -0
- /package/{src/lib → lib}/config-cache.test.mjs +0 -0
- /package/{src/lib → lib}/config-schema.mjs +0 -0
- /package/{src/lib → lib}/error-codes.mjs +0 -0
- /package/{src/lib → lib}/integration-warnings.test.mjs +0 -0
- /package/{src/lib → lib}/module-loader.test.mjs +0 -0
- /package/{src/lib → lib}/node-version.mjs +0 -0
- /package/{src/lib → lib}/node-version.test.mjs +0 -0
- /package/{src/lib → lib}/parse.mjs +0 -0
- /package/{src/lib → lib}/site.mjs +0 -0
- /package/{src/lib → lib}/xle/browser.d.ts +0 -0
- /package/{src/lib → lib}/xle/xle.test.mjs +0 -0
- /package/{src/schemas → schemas}/doc-schema.mjs +0 -0
- /package/{src/schemas → schemas}/template-schema.mjs +0 -0
- /package/{src/types → types}/config.d.ts +0 -0
- /package/{src/types → types}/doc.d.ts +0 -0
- /package/{src/types → types}/doctor.d.ts +0 -0
- /package/{src/types → types}/error-codes.d.ts +0 -0
- /package/{src/types → types}/integration.d.ts +0 -0
- /package/{src/types → types}/manifest.d.ts +0 -0
- /package/{src/types → types}/search.d.ts +0 -0
- /package/{src/types → types}/template.d.ts +0 -0
- /package/{src/types → types}/validate-integration.d.ts +0 -0
- /package/{src/utils → utils}/github.mjs +0 -0
- /package/{src/utils → utils}/path-safety.test.mjs +0 -0
- /package/{src/utils → utils}/paths.test.mjs +0 -0
- /package/{src/utils → utils}/semver.mjs +0 -0
- /package/{src/utils → utils}/semver.test.mjs +0 -0
package/docs/elevation.doc.mjs
CHANGED
|
@@ -36,10 +36,85 @@ export const docs = {
|
|
|
36
36
|
},
|
|
37
37
|
],
|
|
38
38
|
},
|
|
39
|
+
{
|
|
40
|
+
title: 'Choosing a level',
|
|
41
|
+
category: 'foundations',
|
|
42
|
+
content: [
|
|
43
|
+
{
|
|
44
|
+
type: 'prose',
|
|
45
|
+
text: 'Pick the level by how far the surface sits from the page, not by how much shadow you want. Elevation encodes stacking order: a higher level means the surface is layered over more of the UI. Use exactly one level per surface, and only raise a surface above `none` when it actually sits above other content.',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
type: 'table',
|
|
49
|
+
headers: ['Level', 'When to use', 'Examples'],
|
|
50
|
+
rows: [
|
|
51
|
+
[
|
|
52
|
+
'none',
|
|
53
|
+
'The component is flat and embedded in the surface — it is part of the page, not layered above it. This is the default for every surface except ChatComposer.',
|
|
54
|
+
'A Card in a grid, an inline Banner, a standard Button',
|
|
55
|
+
],
|
|
56
|
+
[
|
|
57
|
+
'low',
|
|
58
|
+
'The component is in the normal page flow but should read as distinct from the background. Use for emphasis or to separate the component from the surface behind it — the component still sits on the page, it is not floating over other content.',
|
|
59
|
+
'A raised Card that needs emphasis, a ChatComposer',
|
|
60
|
+
],
|
|
61
|
+
[
|
|
62
|
+
'med',
|
|
63
|
+
'The component sits over other content on the same page — it floats above nearby elements but not the whole screen.',
|
|
64
|
+
'A Popover, a floating Banner, a floating action Button',
|
|
65
|
+
],
|
|
66
|
+
[
|
|
67
|
+
'high',
|
|
68
|
+
'The component is placed over the entire UI — it is the topmost layer and typically has a backdrop or takes focus from everything else.',
|
|
69
|
+
'A modal Dialog, a full-screen overlay surface',
|
|
70
|
+
],
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
type: 'prose',
|
|
75
|
+
text: 'If two surfaces overlap, the one on top takes the higher level. If a surface does not overlap anything, it is `none` or `low` — never `med` or `high`.',
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
title: 'The elevation prop',
|
|
81
|
+
category: 'foundations',
|
|
82
|
+
content: [
|
|
83
|
+
{
|
|
84
|
+
type: 'prose',
|
|
85
|
+
text: 'Configurable surfaces expose a single `elevation` prop instead of asking consumers to hand-write a box-shadow. It takes the graded enum `none | low | med | high`, narrowed per component to the steps that surface needs: Card, ClickableCard, SelectableCard, Button, IconButton, ButtonGroup, and Banner expose the full scale, while ChatComposer exposes only `none | low`. `none` is a flat literal (`box-shadow: none`); the other levels map to the `--shadow-*` tokens above, so a surface stays theme-agnostic.',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
type: 'prose',
|
|
89
|
+
text: 'Prop defaults preserve current appearance: every surface defaults to `none` except ChatComposer, which defaults to `low` to keep its raised look. Set `elevation="none"` to flatten it — the flat composer draws a border with the same rest / hover / focus treatment as a text input.',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
type: 'code',
|
|
93
|
+
lang: 'tsx',
|
|
94
|
+
label: 'Raising a surface with the elevation prop',
|
|
95
|
+
code: `// Flat by default — raise only when the surface needs to float.
|
|
96
|
+
<Card elevation="low">Raised card</Card>
|
|
97
|
+
|
|
98
|
+
// A floating action button.
|
|
99
|
+
<IconButton icon={<Icon icon="add" />} label="New" variant="primary" elevation="med" />
|
|
100
|
+
|
|
101
|
+
// Flatten the composer (defaults to 'low').
|
|
102
|
+
<ChatComposer elevation="none" onSubmit={handleSubmit} />`,
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
type: 'prose',
|
|
106
|
+
text: 'Always float — no prop: intrinsic overlays (Dialog, Popover, Tooltip, Toast, HoverCard, DropdownMenu, and the components that compose them) bake their elevation in and never expose the prop. Flow content (inputs, Text, layout) is never elevated; input fields use inset rings, which are a separate concept from elevation.',
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
},
|
|
39
110
|
{
|
|
40
111
|
title: 'Usage',
|
|
41
112
|
category: 'foundations',
|
|
42
113
|
content: [
|
|
114
|
+
{
|
|
115
|
+
type: 'prose',
|
|
116
|
+
text: 'When building a custom surface, read elevation from the token scale rather than a hand-rolled shadow — the same tokens the elevation prop resolves to.',
|
|
117
|
+
},
|
|
43
118
|
{
|
|
44
119
|
type: 'code',
|
|
45
120
|
lang: 'tsx',
|
|
@@ -68,7 +143,8 @@ const styles = stylex.create({
|
|
|
68
143
|
type: 'list',
|
|
69
144
|
style: 'do',
|
|
70
145
|
items: [
|
|
71
|
-
'
|
|
146
|
+
'Reach for the `elevation` prop on a configurable surface before writing any custom shadow.',
|
|
147
|
+
'Choose the level by how far the surface sits from the page: `none` when flat/embedded, `low` when in-flow but distinct, `med` when over page content, `high` when over the whole UI. See "Choosing a level".',
|
|
72
148
|
'Use inset shadows for input focus/selection states; they compose better than outlines.',
|
|
73
149
|
],
|
|
74
150
|
},
|
|
@@ -76,6 +152,8 @@ const styles = stylex.create({
|
|
|
76
152
|
type: 'list',
|
|
77
153
|
style: 'dont',
|
|
78
154
|
items: [
|
|
155
|
+
'Hand-write a `box-shadow` in app code — set the `elevation` prop or read `shadowVars` instead.',
|
|
156
|
+
'Raise a surface that does not sit above other content — a non-overlapping surface is `none` or `low`, never `med` or `high`.',
|
|
79
157
|
'Stack multiple elevation levels on the same element.',
|
|
80
158
|
'Use elevation shadows for decorative borders. Use --color-border tokens instead.',
|
|
81
159
|
],
|
|
@@ -21,7 +21,7 @@ export const docs = {
|
|
|
21
21
|
type: 'code',
|
|
22
22
|
lang: 'text',
|
|
23
23
|
label: 'Paste this into your AI',
|
|
24
|
-
code: 'Install @astryxdesign/core, @astryxdesign/theme-neutral, and @astryxdesign/cli in this project
|
|
24
|
+
code: 'Install @astryxdesign/core, @astryxdesign/theme-neutral, and @astryxdesign/cli in this project, then run `npx @astryxdesign/cli init` to set up agent docs. Read the generated files to learn the conventions.',
|
|
25
25
|
},
|
|
26
26
|
],
|
|
27
27
|
},
|
|
@@ -40,7 +40,7 @@ export const docs = {
|
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
type: 'prose',
|
|
43
|
-
text:
|
|
43
|
+
text: "Then run `astryx init` to install the AI agent cheat sheet (AGENTS.md/CLAUDE.md). It's non-interactive — no prompts — so it's safe for AI agents, CI, and scripts. Add `--all` for pointers to the theme and page-building workflows.",
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
type: 'code',
|
|
@@ -67,11 +67,11 @@ export const docs = {
|
|
|
67
67
|
},
|
|
68
68
|
{
|
|
69
69
|
type: 'prose',
|
|
70
|
-
text: 'Available themes: @astryxdesign/theme-neutral (muted minimal, a good starting point), @astryxdesign/theme-butter, @astryxdesign/theme-chocolate, @astryxdesign/theme-gothic (dark-only), @astryxdesign/theme-matcha, @astryxdesign/theme-stone, and @astryxdesign/theme-y2k. See `
|
|
70
|
+
text: 'Available themes: @astryxdesign/theme-neutral (muted minimal, a good starting point), @astryxdesign/theme-butter, @astryxdesign/theme-chocolate, @astryxdesign/theme-gothic (dark-only), @astryxdesign/theme-matcha, @astryxdesign/theme-stone, and @astryxdesign/theme-y2k. See `astryx docs theme` for the full theming guide.',
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
type: 'prose',
|
|
74
|
-
text: 'These stylesheets are cascade-layered: the reset loads in @layer reset and component styles in @layer astryx-base. If your project has existing global CSS, a legacy reset, or Tailwind, declare the layer order explicitly and assign every stylesheet to a layer deliberately: unlayered styles and later layers both override astryx-base regardless of specificity. See the Cascade Layer Safety section in `
|
|
74
|
+
text: 'These stylesheets are cascade-layered: the reset loads in @layer reset and component styles in @layer astryx-base. If your project has existing global CSS, a legacy reset, or Tailwind, declare the layer order explicitly and assign every stylesheet to a layer deliberately: unlayered styles and later layers both override astryx-base regardless of specificity. See the Cascade Layer Safety section in `astryx docs migration` before building screens.',
|
|
75
75
|
},
|
|
76
76
|
],
|
|
77
77
|
},
|
|
@@ -172,11 +172,11 @@ pnpm dev`,
|
|
|
172
172
|
type: 'code',
|
|
173
173
|
lang: 'bash',
|
|
174
174
|
label: 'Terminal',
|
|
175
|
-
code: `
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
175
|
+
code: `astryx component # list all components
|
|
176
|
+
astryx component Button # props, usage, theming for Button
|
|
177
|
+
astryx docs # list all doc topics
|
|
178
|
+
astryx template --list # available page templates
|
|
179
|
+
astryx docs tokens # spacing, color, radius reference`,
|
|
180
180
|
},
|
|
181
181
|
],
|
|
182
182
|
},
|
|
@@ -7,7 +7,7 @@ export const docs = {
|
|
|
7
7
|
title: 'Internationalization',
|
|
8
8
|
category: 'guide',
|
|
9
9
|
description:
|
|
10
|
-
'
|
|
10
|
+
'Set the active locale for astryx components, load locale catalogs, coexist with your own i18n library, swap languages at runtime, and test translations with the pseudo locale.',
|
|
11
11
|
|
|
12
12
|
sections: [
|
|
13
13
|
{
|
|
@@ -16,13 +16,13 @@ export const docs = {
|
|
|
16
16
|
content: [
|
|
17
17
|
{
|
|
18
18
|
type: 'prose',
|
|
19
|
-
text: 'Internationalization ships with `@astryxdesign/core`. There is nothing to install. Wrap your app in `<InternationalizationProvider>` and set
|
|
19
|
+
text: 'Internationalization ships with `@astryxdesign/core`. There is nothing to install. Wrap your app in `<InternationalizationProvider>` and set the active `locale`; astryx components pick up localized strings from that provider.',
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
type: 'code',
|
|
23
23
|
lang: 'tsx',
|
|
24
24
|
label: 'Wrap your app',
|
|
25
|
-
code: `import {InternationalizationProvider} from '@astryxdesign/core';
|
|
25
|
+
code: `import {InternationalizationProvider} from '@astryxdesign/core/i18n';
|
|
26
26
|
|
|
27
27
|
function App() {
|
|
28
28
|
return (
|
|
@@ -32,53 +32,56 @@ function App() {
|
|
|
32
32
|
);
|
|
33
33
|
}`,
|
|
34
34
|
},
|
|
35
|
+
{
|
|
36
|
+
type: 'prose',
|
|
37
|
+
text: 'The provider always has the built-in English catalog. Pass additional catalogs through `messages` when you enable another locale.',
|
|
38
|
+
},
|
|
35
39
|
{
|
|
36
40
|
type: 'code',
|
|
37
41
|
lang: 'tsx',
|
|
38
|
-
label: '
|
|
39
|
-
code: `import {
|
|
42
|
+
label: 'Load an astryx locale catalog',
|
|
43
|
+
code: `import {InternationalizationProvider} from '@astryxdesign/core/i18n';
|
|
44
|
+
import fr from '@astryxdesign/core/locales/fr.json';
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}`,
|
|
46
|
+
<InternationalizationProvider locale="fr" messages={{fr}}>
|
|
47
|
+
<App />
|
|
48
|
+
</InternationalizationProvider>;`,
|
|
45
49
|
},
|
|
46
50
|
{
|
|
47
51
|
type: 'prose',
|
|
48
|
-
text: '
|
|
52
|
+
text: 'Astryx ships English today, with first-party translations for other locales on the roadmap. Until a locale is available from `@astryxdesign/core/locales/*`, apps can pass a local catalog with the same shape. See `@astryxdesign/core/locales/en.json` for the current key inventory. Missing keys fall back through the locale chain to English (for example, `pt-BR` walks to `pt`, then to shipped `en`).',
|
|
49
53
|
},
|
|
50
54
|
{
|
|
51
55
|
type: 'prose',
|
|
52
|
-
text:
|
|
56
|
+
text: 'Locale catalogs only affect astryx strings. Your app can continue using its own i18n system for product copy.',
|
|
53
57
|
},
|
|
54
58
|
],
|
|
55
59
|
},
|
|
56
60
|
{
|
|
57
|
-
title: '
|
|
61
|
+
title: 'Runtime language swap',
|
|
58
62
|
category: 'guide',
|
|
59
63
|
content: [
|
|
60
64
|
{
|
|
61
65
|
type: 'prose',
|
|
62
|
-
text: '
|
|
66
|
+
text: 'Re-render `<InternationalizationProvider>` with a new `locale` prop and every astryx string updates live. No reload, no separate API call.',
|
|
63
67
|
},
|
|
64
68
|
{
|
|
65
69
|
type: 'code',
|
|
66
70
|
lang: 'tsx',
|
|
67
|
-
label: '
|
|
68
|
-
code: `
|
|
69
|
-
import fr from './locales/astryx/fr.json';
|
|
71
|
+
label: 'Toggle between locales',
|
|
72
|
+
code: `const [locale, setLocale] = useState<'en' | 'fr'>('en');
|
|
70
73
|
|
|
71
|
-
<InternationalizationProvider locale=
|
|
74
|
+
<InternationalizationProvider locale={locale} messages={{fr}}>
|
|
75
|
+
<Button
|
|
76
|
+
label={locale === 'en' ? 'Français' : 'English'}
|
|
77
|
+
onClick={() => setLocale(l => (l === 'en' ? 'fr' : 'en'))}
|
|
78
|
+
/>
|
|
72
79
|
<App />
|
|
73
80
|
</InternationalizationProvider>;`,
|
|
74
81
|
},
|
|
75
82
|
{
|
|
76
83
|
type: 'prose',
|
|
77
|
-
text: "
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
type: 'prose',
|
|
81
|
-
text: 'A community-maintained set of astryx translations is on the roadmap but not shipped yet. For now, consumer apps that ship in multiple languages own their astryx catalogs alongside their app catalogs. Contributions to a first-party set are welcome; track discussion at https://github.com/facebook/astryx/issues/3641.',
|
|
84
|
+
text: "Persisting the user's choice (localStorage, cookie, URL segment, account setting) is up to the consumer. Astryx reads whatever `locale` you pass in.",
|
|
82
85
|
},
|
|
83
86
|
],
|
|
84
87
|
},
|
|
@@ -119,7 +122,7 @@ import fr from './locales/astryx/fr.json';
|
|
|
119
122
|
type: 'code',
|
|
120
123
|
lang: 'tsx',
|
|
121
124
|
label: 'Astryx + react-intl side by side',
|
|
122
|
-
code: `import {InternationalizationProvider} from '@astryxdesign/core';
|
|
125
|
+
code: `import {InternationalizationProvider} from '@astryxdesign/core/i18n';
|
|
123
126
|
import {Selector} from '@astryxdesign/core/Selector';
|
|
124
127
|
import {Button} from '@astryxdesign/core/Button';
|
|
125
128
|
import {FormattedMessage, IntlProvider, useIntl} from 'react-intl';
|
|
@@ -169,35 +172,56 @@ export default function App() {
|
|
|
169
172
|
},
|
|
170
173
|
{
|
|
171
174
|
type: 'prose',
|
|
172
|
-
text: "Single-catalog usage (where an external i18n runtime like react-intl or i18next resolves both your app strings AND astryx's strings through one provider) is on the roadmap via a `Translator` adapter. Track https://github.com/facebook/astryx/issues/4029. For now, run the two providers side by side as shown above.",
|
|
175
|
+
text: "Single-catalog usage (where an external i18n runtime like react-intl or i18next resolves both your app strings AND astryx's strings through one provider) is on the roadmap via a `Translator` adapter. Track [facebook/astryx#4029](https://github.com/facebook/astryx/issues/4029). For now, run the two providers side by side as shown above.",
|
|
173
176
|
},
|
|
174
177
|
],
|
|
175
178
|
},
|
|
176
179
|
{
|
|
177
|
-
title: '
|
|
180
|
+
title: 'Using astryx as your i18n library',
|
|
178
181
|
category: 'guide',
|
|
179
182
|
content: [
|
|
180
183
|
{
|
|
181
184
|
type: 'prose',
|
|
182
|
-
text:
|
|
185
|
+
text: "For production apps with substantial localization needs, we recommend a dedicated i18n library such as react-intl, i18next, next-intl, or LinguiJS. If your app is small or you do not want another runtime, you can resolve your own strings through astryx too. Keep app keys in a separate namespace from `@astryx.*`, and include your own `en` catalog because astryx's built-in English fallback only contains astryx component strings.",
|
|
183
186
|
},
|
|
184
187
|
{
|
|
185
188
|
type: 'code',
|
|
186
189
|
lang: 'tsx',
|
|
187
|
-
label: '
|
|
188
|
-
code: `
|
|
190
|
+
label: 'Translate app strings with astryx',
|
|
191
|
+
code: `import {Button} from '@astryxdesign/core/Button';
|
|
192
|
+
import {
|
|
193
|
+
InternationalizationProvider,
|
|
194
|
+
useTranslator,
|
|
195
|
+
type Catalog,
|
|
196
|
+
type MessagesByLocale,
|
|
197
|
+
} from '@astryxdesign/core/i18n';
|
|
189
198
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
199
|
+
const en: Catalog = {
|
|
200
|
+
'@myapp.actions.save': {defaultMessage: 'Save'},
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const fr: Catalog = {
|
|
204
|
+
'@myapp.actions.save': {defaultMessage: 'Enregistrer'},
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const messages: MessagesByLocale = {en, fr};
|
|
208
|
+
|
|
209
|
+
function SaveButton() {
|
|
210
|
+
const t = useTranslator();
|
|
211
|
+
return <Button label={t('@myapp.actions.save')} />;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export default function App() {
|
|
215
|
+
return (
|
|
216
|
+
<InternationalizationProvider locale="fr" messages={messages}>
|
|
217
|
+
<SaveButton />
|
|
218
|
+
</InternationalizationProvider>
|
|
219
|
+
);
|
|
220
|
+
}`,
|
|
197
221
|
},
|
|
198
222
|
{
|
|
199
223
|
type: 'prose',
|
|
200
|
-
text:
|
|
224
|
+
text: '`Catalog` types a single locale file; `MessagesByLocale` types the map passed to `messages`. A catalog entry uses the same `{defaultMessage, description?}` shape as `@astryxdesign/core/locales/en.json`.',
|
|
201
225
|
},
|
|
202
226
|
],
|
|
203
227
|
},
|
|
@@ -207,36 +231,58 @@ export default function App() {
|
|
|
207
231
|
content: [
|
|
208
232
|
{
|
|
209
233
|
type: 'prose',
|
|
210
|
-
text: 'Astryx generates a `pseudo` locale that wraps every string in `⟦…⟧` and replaces letters with accented look-alikes.
|
|
234
|
+
text: 'Astryx generates a `pseudo` locale that wraps every string in `⟦…⟧` and replaces letters with accented look-alikes. Switch to it in development to catch hardcoded astryx strings and layout issues caused by longer text.',
|
|
211
235
|
},
|
|
212
236
|
{
|
|
213
237
|
type: 'code',
|
|
214
238
|
lang: 'tsx',
|
|
215
239
|
label: 'Turn on pseudo-localization',
|
|
216
|
-
code: `import
|
|
240
|
+
code: `import {InternationalizationProvider} from '@astryxdesign/core/i18n';
|
|
241
|
+
import pseudo from '@astryxdesign/core/locales/pseudo.json';
|
|
217
242
|
|
|
218
243
|
<InternationalizationProvider locale="pseudo" messages={{pseudo}}>
|
|
219
244
|
<App />
|
|
220
245
|
</InternationalizationProvider>;`,
|
|
221
246
|
},
|
|
222
|
-
{
|
|
223
|
-
type: 'prose',
|
|
224
|
-
text: 'Any bare English text you still see on screen is a hardcoded string that needs to be routed through `useTranslator`.',
|
|
225
|
-
},
|
|
226
|
-
{
|
|
227
|
-
type: 'prose',
|
|
228
|
-
text: "Pseudoloc also has a subtle caveat worth knowing: the pseudo catalog is complete (astryx generates it from every shipped key), so a component using an astryx-shipped key will always render its pseudo version. Your handwritten translation catalogs, on the other hand, only cover the keys you translated; anything missing falls back to English. That means \"looks perfect in pseudo\" is not the same guarantee as \"looks perfect in French.\" Check each real locale by hand for coverage gaps.",
|
|
229
|
-
},
|
|
230
247
|
],
|
|
231
248
|
},
|
|
232
249
|
{
|
|
233
250
|
title: 'For contributors',
|
|
234
251
|
category: 'guide',
|
|
235
252
|
content: [
|
|
253
|
+
{
|
|
254
|
+
type: 'heading',
|
|
255
|
+
level: 3,
|
|
256
|
+
text: 'Developers',
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
type: 'prose',
|
|
260
|
+
text: 'Astryx component authors read strings with `useTranslator()` rather than hardcoding user-facing text.',
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
type: 'code',
|
|
264
|
+
lang: 'tsx',
|
|
265
|
+
label: 'Read an astryx string',
|
|
266
|
+
code: `import {useTranslator} from '@astryxdesign/core/i18n';
|
|
267
|
+
|
|
268
|
+
function SaveButton() {
|
|
269
|
+
const t = useTranslator();
|
|
270
|
+
return <button>{t('@astryx.actions.save')}</button>;
|
|
271
|
+
}`,
|
|
272
|
+
},
|
|
236
273
|
{
|
|
237
274
|
type: 'prose',
|
|
238
275
|
text: "Astryx's own strings live in `packages/core/locales/en.json`. New user-facing strings must go through `useTranslator`; this is enforced by the `@astryx/no-hardcoded-i18n-string` ESLint rule. See the AI contribution guide for the alias-and-resolve pattern used when adding new keys.",
|
|
239
276
|
},
|
|
277
|
+
{
|
|
278
|
+
type: 'heading',
|
|
279
|
+
level: 3,
|
|
280
|
+
text: 'Translators',
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
type: 'prose',
|
|
284
|
+
text: 'Crowdin is the preferred way to contribute — [join a language](https://crowdin.com/project/astryx), translate strings in the web UI, and your work syncs back to the repo without opening a PR. Direct PRs against `packages/core/locales/*.json` also work if you prefer that flow.',
|
|
285
|
+
},
|
|
240
286
|
],
|
|
241
287
|
},
|
|
242
288
|
],
|
package/docs/migration.doc.mjs
CHANGED
|
@@ -54,18 +54,18 @@ export const docs = {
|
|
|
54
54
|
type: 'code',
|
|
55
55
|
lang: 'bash',
|
|
56
56
|
label: 'Migration-oriented CLI pass',
|
|
57
|
-
code: `
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
57
|
+
code: `astryx docs migration
|
|
58
|
+
astryx docs theme
|
|
59
|
+
astryx docs styling
|
|
60
|
+
astryx template --list --type block
|
|
61
|
+
astryx template AppShellTopNavWithSideNav --skeleton
|
|
62
|
+
astryx template PopoverSettingsPanel --skeleton
|
|
63
|
+
astryx component AppShell
|
|
64
|
+
astryx component SideNav
|
|
65
|
+
astryx component TopNav
|
|
66
|
+
astryx component CommandPalette
|
|
67
|
+
astryx component Button
|
|
68
|
+
astryx component TextInput`,
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
type: 'prose',
|
|
@@ -75,8 +75,8 @@ npx astryx component TextInput`,
|
|
|
75
75
|
type: 'code',
|
|
76
76
|
lang: 'bash',
|
|
77
77
|
label: 'Dense and JSON modes',
|
|
78
|
-
code: `
|
|
79
|
-
|
|
78
|
+
code: `astryx docs migration --dense
|
|
79
|
+
astryx component Button --json`,
|
|
80
80
|
},
|
|
81
81
|
],
|
|
82
82
|
},
|
|
@@ -371,10 +371,10 @@ if (getComputedStyle(button).paddingInline === '0px') {
|
|
|
371
371
|
code: `We are migrating this existing Tailwind/shadcn app to Astryx incrementally.
|
|
372
372
|
|
|
373
373
|
First run:
|
|
374
|
-
-
|
|
375
|
-
-
|
|
376
|
-
-
|
|
377
|
-
-
|
|
374
|
+
- astryx docs migration --dense
|
|
375
|
+
- astryx docs theme --dense
|
|
376
|
+
- astryx docs styling --dense
|
|
377
|
+
- astryx template AppShellTopNavWithSideNav --skeleton
|
|
378
378
|
|
|
379
379
|
Then migrate one route or shell surface at a time. Keep business logic and routing intact. Replace shadcn/Radix/Tailwind primitives with Astryx components, remove hardcoded colors, verify light and dark mode, and take screenshots before moving to the next surface.`,
|
|
380
380
|
},
|
|
@@ -9,6 +9,6 @@ export const docsDense = {
|
|
|
9
9
|
{ section: 'Rules', title: 'Rules', content: [{ type: 'list', items: ['use components', 'frame-first layout: shell + region budgets before content (astryx docs layout)', 'dense data = rows (Table, List/Item) not Cards; Card = widgets/galleries/settings groups', 'StyleX or Tailwind for styling', 'semantic tokens only', 'CSS vars for colors', 'controlled form inputs', 'useLinkComponent() for navigation'] }] },
|
|
10
10
|
{ section: 'Styling Approach', title: 'Styling', content: [{ type: 'prose', text: 'xstyle prop for component overrides. StyleX or Tailwind for layout. See astryx docs styling.' }] },
|
|
11
11
|
{ section: 'Anti-Patterns', title: 'Anti-Patterns', content: [{ type: 'list', items: ['no inline styles on raw elements', 'no hardcoded colors — use tokens or Tailwind semantic classes', 'no hardcoded spacing', 'no hardcoded <a> — use useLinkComponent()', 'no Card-wrapped list items — frame first, rows for dense data (astryx docs layout)', 'no decorative Badge — StatusDot/Token for status', 'read docs before inventing props'] }] },
|
|
12
|
-
{ section: 'Design Tokens', title: 'Tokens', content: [{ type: 'prose', text: 'run
|
|
12
|
+
{ section: 'Design Tokens', title: 'Tokens', content: [{ type: 'prose', text: 'run astryx docs tokens for full reference' }] },
|
|
13
13
|
],
|
|
14
14
|
};
|
package/docs/principles.doc.mjs
CHANGED
|
@@ -39,10 +39,10 @@ export const docs = {
|
|
|
39
39
|
style: 'ordered',
|
|
40
40
|
items: [
|
|
41
41
|
'Use components for everything they cover',
|
|
42
|
-
'Layout is frame-first: pick the shell and budget regions before writing content (see \`
|
|
42
|
+
'Layout is frame-first: pick the shell and budget regions before writing content (see \`astryx docs layout\`)',
|
|
43
43
|
'Dense data renders as rows (Table, List/Item), edge-to-edge with dividers; Card is for widgets, galleries, and settings groups',
|
|
44
|
-
'StyleX or Tailwind for custom styling; both are first-class (see \`
|
|
45
|
-
'Semantic tokens, not hardcoded values (see \`
|
|
44
|
+
'StyleX or Tailwind for custom styling; both are first-class (see \`astryx docs styling\`)',
|
|
45
|
+
'Semantic tokens, not hardcoded values (see \`astryx docs tokens\`)',
|
|
46
46
|
'CSS custom properties for colors, not hex values',
|
|
47
47
|
'Form inputs are controlled (value + onChange)',
|
|
48
48
|
'Use useLinkComponent() for navigation so consumers can plug in their framework router via LinkProvider',
|
|
@@ -60,7 +60,7 @@ export const docs = {
|
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
type: 'prose',
|
|
63
|
-
text: 'See \`
|
|
63
|
+
text: 'See \`astryx docs styling\` for the complete guide with examples.',
|
|
64
64
|
},
|
|
65
65
|
],
|
|
66
66
|
},
|
|
@@ -76,7 +76,7 @@ export const docs = {
|
|
|
76
76
|
'Hardcoded colors (#fff). Use var(--color-*) or Tailwind semantic classes (text-primary, bg-surface)',
|
|
77
77
|
'Hardcoded spacing (16px). Use spacing tokens or Tailwind spacing utilities',
|
|
78
78
|
'Hardcoded <a> elements. Use useLinkComponent() so consumers can swap in their framework router via LinkProvider',
|
|
79
|
-
'Wrapping every list item or page section in a Card. Decide the frame first; dense data renders as rows (see \`
|
|
79
|
+
'Wrapping every list item or page section in a Card. Decide the frame first; dense data renders as rows (see \`astryx docs layout\`)',
|
|
80
80
|
'Badge as decoration. Reserve Badge for counts and enumerated states; use StatusDot or Token for status',
|
|
81
81
|
'Inventing props. Read component docs first',
|
|
82
82
|
],
|
|
@@ -89,7 +89,7 @@ export const docs = {
|
|
|
89
89
|
content: [
|
|
90
90
|
{
|
|
91
91
|
type: 'prose',
|
|
92
|
-
text: 'The design system provides semantic design tokens for spacing, color, radius, shadow, typography, and size. Tokens adapt to the active theme and color mode. Run \`
|
|
92
|
+
text: 'The design system provides semantic design tokens for spacing, color, radius, shadow, typography, and size. Tokens adapt to the active theme and color mode. Run \`astryx docs tokens\` for the full reference with all values.',
|
|
93
93
|
},
|
|
94
94
|
],
|
|
95
95
|
},
|
|
@@ -9,6 +9,6 @@ export const docsZh = {
|
|
|
9
9
|
{ section: 'Rules', title: '规则', content: [{ type: 'list', items: ['所有支持的场景都使用 XDS 组件', '布局采用框架优先:先选定外壳并规划区域尺寸,再编写内容(见 astryx docs layout)', '密集数据使用行(Table、List/Item)通栏渲染;Card 用于小部件、画廊和设置分组', '使用 StyleX 或 Tailwind 进行样式设置', '使用语义化令牌,不使用硬编码值', '使用 CSS 变量设置颜色,不使用十六进制值', '表单输入为受控组件(value + onChange)', '使用 useLinkComponent() 进行导航'] }] },
|
|
10
10
|
{ section: 'Styling Approach', title: '样式方法', content: [{ type: 'prose', text: '组件覆盖使用 xstyle 属性。布局使用 StyleX 或 Tailwind。详见 astryx docs styling。' }] },
|
|
11
11
|
{ section: 'Anti-Patterns', title: '反模式', content: [{ type: 'list', items: ['不要在原始元素上使用内联样式', '不要硬编码颜色 — 使用令牌或 Tailwind 语义类', '不要硬编码间距', '不要硬编码 <a> 元素 — 使用 useLinkComponent()', '不要把每个列表项都包在 Card 里 — 先定框架,密集数据用行渲染(见 astryx docs layout)', '不要把 Badge 当装饰 — 状态请使用 StatusDot 或 Token', '不要自创属性。先阅读组件文档'] }] },
|
|
12
|
-
{ section: 'Design Tokens', title: '设计令牌', content: [{ type: 'prose', text: '运行
|
|
12
|
+
{ section: 'Design Tokens', title: '设计令牌', content: [{ type: 'prose', text: '运行 astryx docs tokens 查看完整参考' }] },
|
|
13
13
|
],
|
|
14
14
|
};
|
|
@@ -24,7 +24,7 @@ export const docs = {
|
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
type: 'prose',
|
|
27
|
-
text: 'For available token names and values, run `
|
|
27
|
+
text: 'For available token names and values, run `astryx docs tokens`. Focused references are also available with `astryx docs color`, `astryx docs spacing`, `astryx docs shape`, `astryx docs typography`, `astryx docs elevation`, and `astryx docs motion`.',
|
|
28
28
|
},
|
|
29
29
|
],
|
|
30
30
|
},
|
|
@@ -452,10 +452,10 @@ function RevenueChart({data}: {data: Array<{x: string; y: number}>}) {
|
|
|
452
452
|
type: 'list',
|
|
453
453
|
style: 'ordered',
|
|
454
454
|
items: [
|
|
455
|
-
'Import the reset/base CSS and a theme CSS file early enough for first paint. For production SSR, prefer built themes from `
|
|
455
|
+
'Import the reset/base CSS and a theme CSS file early enough for first paint. For production SSR, prefer built themes from `astryx theme build` or published `/built` theme imports plus `theme.css`.',
|
|
456
456
|
'Choose one owner for color mode. Theme uses `data-theme="light|dark"` and `color-scheme` to resolve `light-dark()` tokens.',
|
|
457
457
|
'Map the external library\'s semantic layer to system variables by intent, not by exact naming. For example, MUI `background.paper` maps to `--color-background-surface`.',
|
|
458
|
-
'Use `
|
|
458
|
+
'Use `astryx docs tokens` and focused token docs when building mappings. Keep mappings small at first: text, surface/body/card/popover, border, accent, status, spacing, radius, typography, shadow.',
|
|
459
459
|
'Use token resolver APIs only for non-CSS APIs that need resolved values.',
|
|
460
460
|
],
|
|
461
461
|
},
|
package/docs/styling.doc.mjs
CHANGED
|
@@ -30,7 +30,7 @@ export const docs = {
|
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
type: 'prose',
|
|
33
|
-
text: 'All approaches resolve to the same design tokens, so theming and dark mode work regardless of which you choose. For external styling libraries, run `
|
|
33
|
+
text: 'All approaches resolve to the same design tokens, so theming and dark mode work regardless of which you choose. For external styling libraries, run `astryx docs styling-libraries`; it covers Tailwind, StyleX, Panda, Chakra, MUI, CSS-in-JS, CSS Modules, Sass, and `useTheme()` for non-CSS processing.',
|
|
34
34
|
},
|
|
35
35
|
],
|
|
36
36
|
},
|
|
@@ -118,7 +118,7 @@ const overrides = stylex.create({
|
|
|
118
118
|
},
|
|
119
119
|
{
|
|
120
120
|
type: 'prose',
|
|
121
|
-
text: 'The bridge is pure CSS with zero JS. Theme changes (dark mode, custom themes) apply automatically because the utilities reference the same CSS custom properties that components use. This is the paved Tailwind path; for other styling libraries that follow the same aliasing pattern, run `
|
|
121
|
+
text: 'The bridge is pure CSS with zero JS. Theme changes (dark mode, custom themes) apply automatically because the utilities reference the same CSS custom properties that components use. This is the paved Tailwind path; for other styling libraries that follow the same aliasing pattern, run `astryx docs styling-libraries`.',
|
|
122
122
|
},
|
|
123
123
|
],
|
|
124
124
|
},
|
|
@@ -263,7 +263,7 @@ const overrides = stylex.create({
|
|
|
263
263
|
},
|
|
264
264
|
{
|
|
265
265
|
type: 'prose',
|
|
266
|
-
text: 'For systematic theming, use defineTheme component overrides instead of raw CSS selectors. defineTheme keeps the higher-level `prop:value` API (`variant:primary`, `size:sm`) and handles selector generation for you. Run `
|
|
266
|
+
text: 'For systematic theming, use defineTheme component overrides instead of raw CSS selectors. defineTheme keeps the higher-level `prop:value` API (`variant:primary`, `size:sm`) and handles selector generation for you. Run `astryx docs theme` for the full theming guide.',
|
|
267
267
|
},
|
|
268
268
|
],
|
|
269
269
|
},
|
|
@@ -334,7 +334,7 @@ const styles = stylex.create({
|
|
|
334
334
|
},
|
|
335
335
|
{
|
|
336
336
|
type: 'prose',
|
|
337
|
-
text: 'See `
|
|
337
|
+
text: 'See `astryx docs tokens` for the full token reference (all spacing, color, radius, shadow, and typography tokens with values). See `astryx docs theme` for how to override tokens via defineTheme.',
|
|
338
338
|
},
|
|
339
339
|
],
|
|
340
340
|
},
|
package/docs/theme.doc.dense.mjs
CHANGED
|
@@ -10,9 +10,9 @@ export const docsDense = {
|
|
|
10
10
|
{ section: 'Theme Props', title: 'Props', content: [null] },
|
|
11
11
|
{ section: 'Creating a Custom Theme', title: 'Custom Theme', content: [{ type: 'prose', text: 'CLI wizard or manual defineTheme. only override tokens that differ.' }, null] },
|
|
12
12
|
{ section: 'defineTheme', title: 'defineTheme', content: [{ type: 'prose', text: 'scale configs (color, typography, radius, motion) + explicit token overrides + component overrides. color derives full palette from accent hex via HCT.' }, null, null] },
|
|
13
|
-
{ section: 'Component Style Overrides', title: 'Component Overrides', content: [{ type: 'prose', text: 'components field uses semantic component keys + style keys (base, variant:value, stateName), not raw selectors. for external CSS, prefer data-* selectors from `astryx docs styling`. write standard CSS (borderRadius, padding) — pipeline expands to internal vars. public vars (--button-press-scale etc) set directly. private vars (--_*) cannot be set — use CSS properties. run `
|
|
13
|
+
{ section: 'Component Style Overrides', title: 'Component Overrides', content: [{ type: 'prose', text: 'components field uses semantic component keys + style keys (base, variant:value, stateName), not raw selectors. for external CSS, prefer data-* selectors from `astryx docs styling`. write standard CSS (borderRadius, padding) — pipeline expands to internal vars. public vars (--button-press-scale etc) set directly. private vars (--_*) cannot be set — use CSS properties. run `astryx component <Name>` for details.' }, null, null, null, null] },
|
|
14
14
|
{ section: 'Custom Variants', title: 'Custom Variants', content: [{ type: 'prose', text: 'any unknown prop:value in components becomes a new variant. astryx theme build generates TS augmentations. works on any extensible prop axis (variant, status, etc).' }, null, null, null, null] },
|
|
15
|
-
{ section: 'Building Themes for Production', title: 'Build for Production', content: [{ type: 'prose', text: '
|
|
15
|
+
{ section: 'Building Themes for Production', title: 'Build for Production', content: [{ type: 'prose', text: 'astryx theme build compiles defineTheme to static CSS. outputs .css + .js (__built:true) + .d.ts.' }, null, null, null, null] },
|
|
16
16
|
{ section: 'Runtime vs Built Themes', title: 'Runtime vs Built', content: [{ type: 'prose', text: 'runtime: useInsertionEffect injects styles client-side. built: static CSS on first paint. USE /built + theme.css FOR SSR.' }, null, null, null] },
|
|
17
17
|
{ section: 'Light/Dark Mode', title: 'Light/Dark', content: [{ type: 'prose', text: 'light-dark() in token values via [light, dark] tuples. mode=system follows OS.' }, null, null] },
|
|
18
18
|
{ section: 'Nesting Themes', title: 'Nesting', content: [{ type: 'prose', text: 'wrap sections in separate <Theme> providers' }, null] },
|