@once-ui-system/core 1.8.4 → 2.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ai/catalog.json +166 -78
- package/ai/components/Accordion.json +1 -1
- package/ai/components/BarChart.json +34 -3
- package/ai/components/Book.json +128 -0
- package/ai/components/Button.json +1 -1
- package/ai/components/Card.json +1 -0
- package/ai/components/Carousel.json +1 -1
- package/ai/components/ChartHeader.json +2 -1
- package/ai/components/ChartStatus.json +2 -1
- package/ai/components/Checkbox.json +2 -2
- package/ai/components/CodeBlock.json +23 -2
- package/ai/components/ColorInput.json +1 -1
- package/ai/components/DataTooltip.json +3 -2
- package/ai/components/DatePicker.json +2 -2
- package/ai/components/Dialog.json +1 -1
- package/ai/components/DropdownWrapper.json +6 -4
- package/ai/components/Effect.json +133 -0
- package/ai/components/Fade.json +1 -1
- package/ai/components/Feedback.json +1 -1
- package/ai/components/IconButton.json +1 -1
- package/ai/components/InfoTip.json +125 -0
- package/ai/components/Input.json +5 -4
- package/ai/components/Legend.json +2 -1
- package/ai/components/LineBarChart.json +34 -3
- package/ai/components/LineChart.json +39 -3
- package/ai/components/LinearGauge.json +3 -2
- package/ai/components/LinearGradient.json +2 -1
- package/ai/components/Logo.json +2 -2
- package/ai/components/Media.json +1 -1
- package/ai/components/MediaUpload.json +21 -2
- package/ai/components/Modal.json +1 -1
- package/ai/components/NavGroup.json +130 -0
- package/ai/components/NavIcon.json +1 -1
- package/ai/components/NavItem.json +14 -0
- package/ai/components/Option.json +2 -2
- package/ai/components/Particle.json +1 -1
- package/ai/components/PieChart.json +32 -3
- package/ai/components/ProgressBar.json +1 -1
- package/ai/components/Pulse.json +1 -1
- package/ai/components/RadialGauge.json +4 -3
- package/ai/components/RadialGradient.json +2 -1
- package/ai/components/RadioButton.json +1 -1
- package/ai/components/RevealFx.json +1 -1
- package/ai/components/Scrubber.json +136 -0
- package/ai/components/SegmentedControl.json +3 -3
- package/ai/components/Setting.json +128 -0
- package/ai/components/SettingAxes.json +127 -0
- package/ai/components/SettingGroup.json +129 -0
- package/ai/components/ShineFx.json +1 -1
- package/ai/components/Skeleton.json +2 -3
- package/ai/components/SplitView.json +2 -0
- package/ai/components/StylePanel.json +4 -2
- package/ai/components/Swatch.json +11 -0
- package/ai/components/Swiper.json +1 -1
- package/ai/components/Switch.json +1 -1
- package/ai/components/Tag.json +1 -1
- package/ai/components/Textarea.json +6 -5
- package/ai/components/ThemeSwitcher.json +3 -0
- package/ai/components/Toast.json +1 -1
- package/ai/components/ToggleButton.json +2 -1
- package/ai/eval-tasks.md +8 -0
- package/ai/examples/app-shell.tsx +111 -0
- package/ai/examples/auth.tsx +1 -1
- package/ai/examples/blocks/Dashboard1.tsx +17 -28
- package/ai/examples/blocks/Feed3.tsx +4 -4
- package/ai/examples/blocks/Footer1.tsx +5 -3
- package/ai/examples/blocks/Footer2.tsx +3 -3
- package/ai/examples/blocks/Footer3.tsx +1 -1
- package/ai/examples/blocks/Footer4.tsx +6 -5
- package/ai/examples/blocks/Header1.tsx +7 -6
- package/ai/examples/blocks/Header3.tsx +7 -7
- package/ai/examples/blocks/Header4.tsx +5 -5
- package/ai/examples/blocks/Sidebar4.tsx +1 -1
- package/ai/examples/blocks/Streaming1.tsx +4 -4
- package/ai/examples/blocks/Table1.tsx +6 -6
- package/ai/examples/blocks/Waitlist1.tsx +5 -5
- package/ai/examples/blocks/content/resources.ts +3 -1
- package/ai/examples/dashboard.tsx +8 -9
- package/ai/examples/marketing-hero.tsx +2 -2
- package/ai/examples/pricing.tsx +4 -5
- package/ai/examples/settings.tsx +3 -3
- package/ai/gotchas.json +80 -23
- package/ai/layouts.md +154 -0
- package/ai/manifest.json +3 -2
- package/ai/recipes.md +49 -4
- package/ai/rules.compact.md +18 -3
- package/ai/rules.md +68 -10
- package/ai/spec.json +634 -176
- package/dist/ai/catalog.json +166 -78
- package/dist/ai/components/Accordion.json +1 -1
- package/dist/ai/components/BarChart.json +34 -3
- package/dist/ai/components/Book.json +128 -0
- package/dist/ai/components/Button.json +1 -1
- package/dist/ai/components/Card.json +1 -0
- package/dist/ai/components/Carousel.json +1 -1
- package/dist/ai/components/ChartHeader.json +2 -1
- package/dist/ai/components/ChartStatus.json +2 -1
- package/dist/ai/components/Checkbox.json +2 -2
- package/dist/ai/components/CodeBlock.json +23 -2
- package/dist/ai/components/ColorInput.json +1 -1
- package/dist/ai/components/DataTooltip.json +3 -2
- package/dist/ai/components/DatePicker.json +2 -2
- package/dist/ai/components/Dialog.json +1 -1
- package/dist/ai/components/DropdownWrapper.json +6 -4
- package/dist/ai/components/Effect.json +133 -0
- package/dist/ai/components/Fade.json +1 -1
- package/dist/ai/components/Feedback.json +1 -1
- package/dist/ai/components/IconButton.json +1 -1
- package/dist/ai/components/InfoTip.json +125 -0
- package/dist/ai/components/Input.json +5 -4
- package/dist/ai/components/Legend.json +2 -1
- package/dist/ai/components/LineBarChart.json +34 -3
- package/dist/ai/components/LineChart.json +39 -3
- package/dist/ai/components/LinearGauge.json +3 -2
- package/dist/ai/components/LinearGradient.json +2 -1
- package/dist/ai/components/Logo.json +2 -2
- package/dist/ai/components/Media.json +1 -1
- package/dist/ai/components/MediaUpload.json +21 -2
- package/dist/ai/components/Modal.json +1 -1
- package/dist/ai/components/NavGroup.json +130 -0
- package/dist/ai/components/NavIcon.json +1 -1
- package/dist/ai/components/NavItem.json +14 -0
- package/dist/ai/components/Option.json +2 -2
- package/dist/ai/components/Particle.json +1 -1
- package/dist/ai/components/PieChart.json +32 -3
- package/dist/ai/components/ProgressBar.json +1 -1
- package/dist/ai/components/Pulse.json +1 -1
- package/dist/ai/components/RadialGauge.json +4 -3
- package/dist/ai/components/RadialGradient.json +2 -1
- package/dist/ai/components/RadioButton.json +1 -1
- package/dist/ai/components/RevealFx.json +1 -1
- package/dist/ai/components/Scrubber.json +136 -0
- package/dist/ai/components/SegmentedControl.json +3 -3
- package/dist/ai/components/Setting.json +128 -0
- package/dist/ai/components/SettingAxes.json +127 -0
- package/dist/ai/components/SettingGroup.json +129 -0
- package/dist/ai/components/ShineFx.json +1 -1
- package/dist/ai/components/Skeleton.json +2 -3
- package/dist/ai/components/SplitView.json +2 -0
- package/dist/ai/components/StylePanel.json +4 -2
- package/dist/ai/components/Swatch.json +11 -0
- package/dist/ai/components/Swiper.json +1 -1
- package/dist/ai/components/Switch.json +1 -1
- package/dist/ai/components/Tag.json +1 -1
- package/dist/ai/components/Textarea.json +6 -5
- package/dist/ai/components/ThemeSwitcher.json +3 -0
- package/dist/ai/components/Toast.json +1 -1
- package/dist/ai/components/ToggleButton.json +2 -1
- package/dist/ai/eval-tasks.md +8 -0
- package/dist/ai/gotchas.json +80 -23
- package/dist/ai/layouts.md +154 -0
- package/dist/ai/manifest.json +3 -2
- package/dist/ai/recipes.md +49 -4
- package/dist/ai/rules.compact.md +18 -3
- package/dist/ai/rules.md +68 -10
- package/dist/ai/spec.json +634 -176
- package/dist/components/Accordion.d.ts +2 -1
- package/dist/components/Accordion.d.ts.map +1 -1
- package/dist/components/Accordion.js.map +1 -1
- package/dist/components/Avatar.js +1 -1
- package/dist/components/Avatar.js.map +1 -1
- package/dist/components/Background.d.ts +6 -6
- package/dist/components/Background.d.ts.map +1 -1
- package/dist/components/Book.d.ts +28 -0
- package/dist/components/Book.d.ts.map +1 -0
- package/dist/components/Book.js +24 -0
- package/dist/components/Book.js.map +1 -0
- package/dist/components/Book.module.scss +45 -0
- package/dist/components/Button.d.ts +1 -1
- package/dist/components/Button.d.ts.map +1 -1
- package/dist/components/Button.js +4 -4
- package/dist/components/Button.js.map +1 -1
- package/dist/components/Card.d.ts +8 -0
- package/dist/components/Card.d.ts.map +1 -1
- package/dist/components/Card.js +10 -2
- package/dist/components/Card.js.map +1 -1
- package/dist/components/Card.module.scss +11 -1
- package/dist/components/Carousel.d.ts +7 -1
- package/dist/components/Carousel.d.ts.map +1 -1
- package/dist/components/Carousel.js +7 -7
- package/dist/components/Carousel.js.map +1 -1
- package/dist/components/Carousel.module.scss +1 -8
- package/dist/components/Checkbox.d.ts +3 -3
- package/dist/components/Checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox.js +5 -5
- package/dist/components/Checkbox.js.map +1 -1
- package/dist/components/ClientFlex.d.ts.map +1 -1
- package/dist/components/ClientFlex.js +5 -10
- package/dist/components/ClientFlex.js.map +1 -1
- package/dist/components/ClientGrid.d.ts.map +1 -1
- package/dist/components/ClientGrid.js +2 -7
- package/dist/components/ClientGrid.js.map +1 -1
- package/dist/components/ColorInput.d.ts +1 -1
- package/dist/components/ColorInput.d.ts.map +1 -1
- package/dist/components/ColorInput.js +7 -13
- package/dist/components/ColorInput.js.map +1 -1
- package/dist/components/CompareImage.d.ts.map +1 -1
- package/dist/components/CompareImage.js +2 -2
- package/dist/components/CompareImage.js.map +1 -1
- package/dist/components/DateInput.d.ts.map +1 -1
- package/dist/components/DateInput.js +10 -1
- package/dist/components/DateInput.js.map +1 -1
- package/dist/components/DatePicker.d.ts +2 -2
- package/dist/components/DatePicker.d.ts.map +1 -1
- package/dist/components/DatePicker.js +21 -14
- package/dist/components/DatePicker.js.map +1 -1
- package/dist/components/DateRangeInput.js +3 -3
- package/dist/components/DateRangeInput.js.map +1 -1
- package/dist/components/Dialog.d.ts +1 -1
- package/dist/components/Dialog.d.ts.map +1 -1
- package/dist/components/Dialog.js +14 -14
- package/dist/components/Dialog.js.map +1 -1
- package/dist/components/DropdownWrapper.d.ts +8 -3
- package/dist/components/DropdownWrapper.d.ts.map +1 -1
- package/dist/components/DropdownWrapper.js +17 -6
- package/dist/components/DropdownWrapper.js.map +1 -1
- package/dist/components/Effect.d.ts +41 -0
- package/dist/components/Effect.d.ts.map +1 -0
- package/dist/components/Effect.js +30 -0
- package/dist/components/Effect.js.map +1 -0
- package/dist/components/ElementType.d.ts +2 -1
- package/dist/components/ElementType.d.ts.map +1 -1
- package/dist/components/ElementType.js +4 -2
- package/dist/components/ElementType.js.map +1 -1
- package/dist/components/EmojiPicker.d.ts.map +1 -1
- package/dist/components/EmojiPicker.js +1 -1
- package/dist/components/EmojiPicker.js.map +1 -1
- package/dist/components/Feedback.d.ts +1 -1
- package/dist/components/Feedback.d.ts.map +1 -1
- package/dist/components/Feedback.js +2 -2
- package/dist/components/Feedback.js.map +1 -1
- package/dist/components/Flex.d.ts.map +1 -1
- package/dist/components/Flex.js +46 -5
- package/dist/components/Flex.js.map +1 -1
- package/dist/components/Icon.d.ts.map +1 -1
- package/dist/components/Icon.js.map +1 -1
- package/dist/components/IconButton.d.ts +1 -1
- package/dist/components/IconButton.d.ts.map +1 -1
- package/dist/components/IconButton.js +4 -4
- package/dist/components/IconButton.js.map +1 -1
- package/dist/components/InfoTip.d.ts +17 -0
- package/dist/components/InfoTip.d.ts.map +1 -0
- package/dist/components/InfoTip.js +12 -0
- package/dist/components/InfoTip.js.map +1 -0
- package/dist/components/Input.d.ts +11 -5
- package/dist/components/Input.d.ts.map +1 -1
- package/dist/components/Input.js +32 -16
- package/dist/components/Input.js.map +1 -1
- package/dist/components/Input.module.scss +313 -1
- package/dist/components/InteractiveDetails.d.ts.map +1 -1
- package/dist/components/InteractiveDetails.js +1 -1
- package/dist/components/InteractiveDetails.js.map +1 -1
- package/dist/components/Kbd.d.ts.map +1 -1
- package/dist/components/Kbd.js +4 -1
- package/dist/components/Kbd.js.map +1 -1
- package/dist/components/Logo.d.ts +16 -4
- package/dist/components/Logo.d.ts.map +1 -1
- package/dist/components/Logo.js +32 -14
- package/dist/components/Logo.js.map +1 -1
- package/dist/components/Media.d.ts +9 -2
- package/dist/components/Media.d.ts.map +1 -1
- package/dist/components/Media.js +25 -16
- package/dist/components/Media.js.map +1 -1
- package/dist/components/MediaAudioPlayer.d.ts +29 -0
- package/dist/components/MediaAudioPlayer.d.ts.map +1 -0
- package/dist/components/MediaAudioPlayer.js +115 -0
- package/dist/components/MediaAudioPlayer.js.map +1 -0
- package/dist/components/MediaAudioPlayer.module.scss +38 -0
- package/dist/components/Modal.d.ts +1 -1
- package/dist/components/Modal.d.ts.map +1 -1
- package/dist/components/Modal.js +10 -10
- package/dist/components/Modal.js.map +1 -1
- package/dist/components/NavGroup.d.ts +33 -0
- package/dist/components/NavGroup.d.ts.map +1 -0
- package/dist/components/NavGroup.js +27 -0
- package/dist/components/NavGroup.js.map +1 -0
- package/dist/components/NavIcon.d.ts +1 -1
- package/dist/components/NavIcon.d.ts.map +1 -1
- package/dist/components/NavIcon.js +2 -2
- package/dist/components/NavIcon.js.map +1 -1
- package/dist/components/NavItem.d.ts +24 -0
- package/dist/components/NavItem.d.ts.map +1 -0
- package/dist/components/NavItem.js +18 -0
- package/dist/components/NavItem.js.map +1 -0
- package/dist/components/NumberInput.js +1 -1
- package/dist/components/NumberInput.js.map +1 -1
- package/dist/components/OgCard.js +3 -3
- package/dist/components/OgCard.js.map +1 -1
- package/dist/components/Option.d.ts +3 -3
- package/dist/components/Option.d.ts.map +1 -1
- package/dist/components/Option.js +2 -2
- package/dist/components/Option.js.map +1 -1
- package/dist/components/Particle.d.ts +2 -2
- package/dist/components/Particle.d.ts.map +1 -1
- package/dist/components/PasswordInput.d.ts.map +1 -1
- package/dist/components/PasswordInput.js +2 -2
- package/dist/components/PasswordInput.js.map +1 -1
- package/dist/components/ProgressBar.d.ts +1 -1
- package/dist/components/ProgressBar.d.ts.map +1 -1
- package/dist/components/ProgressBar.js +2 -2
- package/dist/components/ProgressBar.js.map +1 -1
- package/dist/components/Pulse.d.ts +1 -1
- package/dist/components/Pulse.d.ts.map +1 -1
- package/dist/components/Pulse.js +2 -2
- package/dist/components/Pulse.js.map +1 -1
- package/dist/components/RadioButton.d.ts +2 -2
- package/dist/components/RadioButton.d.ts.map +1 -1
- package/dist/components/RadioButton.js +1 -1
- package/dist/components/RadioButton.js.map +1 -1
- package/dist/components/RevealFx.d.ts +2 -1
- package/dist/components/RevealFx.d.ts.map +1 -1
- package/dist/components/RevealFx.js +8 -8
- package/dist/components/RevealFx.js.map +1 -1
- package/dist/components/ScrollContainer.d.ts.map +1 -1
- package/dist/components/ScrollContainer.js +1 -1
- package/dist/components/ScrollContainer.js.map +1 -1
- package/dist/components/Scrubber.d.ts +70 -0
- package/dist/components/Scrubber.d.ts.map +1 -0
- package/dist/components/Scrubber.js +161 -0
- package/dist/components/Scrubber.js.map +1 -0
- package/dist/components/SegmentedControl.d.ts +4 -4
- package/dist/components/SegmentedControl.d.ts.map +1 -1
- package/dist/components/SegmentedControl.js +11 -11
- package/dist/components/SegmentedControl.js.map +1 -1
- package/dist/components/Select.d.ts.map +1 -1
- package/dist/components/Select.js +48 -15
- package/dist/components/Select.js.map +1 -1
- package/dist/components/ServerFlex.d.ts +0 -1
- package/dist/components/ServerFlex.d.ts.map +1 -1
- package/dist/components/ServerFlex.js +99 -52
- package/dist/components/ServerFlex.js.map +1 -1
- package/dist/components/ServerGrid.d.ts +0 -1
- package/dist/components/ServerGrid.d.ts.map +1 -1
- package/dist/components/ServerGrid.js +11 -9
- package/dist/components/ServerGrid.js.map +1 -1
- package/dist/components/Setting.d.ts +50 -0
- package/dist/components/Setting.d.ts.map +1 -0
- package/dist/components/Setting.js +43 -0
- package/dist/components/Setting.js.map +1 -0
- package/dist/components/ShineFx.d.ts +1 -0
- package/dist/components/ShineFx.d.ts.map +1 -1
- package/dist/components/ShineFx.js +2 -2
- package/dist/components/ShineFx.js.map +1 -1
- package/dist/components/Skeleton.d.ts +16 -3
- package/dist/components/Skeleton.d.ts.map +1 -1
- package/dist/components/Skeleton.js +2 -2
- package/dist/components/Skeleton.js.map +1 -1
- package/dist/components/Skeleton.module.scss +14 -51
- package/dist/components/SplitView.d.ts +23 -3
- package/dist/components/SplitView.d.ts.map +1 -1
- package/dist/components/SplitView.js +90 -58
- package/dist/components/SplitView.js.map +1 -1
- package/dist/components/StyleOverlay.d.ts.map +1 -1
- package/dist/components/StyleOverlay.js +1 -1
- package/dist/components/StyleOverlay.js.map +1 -1
- package/dist/components/StylePanel.d.ts +47 -6
- package/dist/components/StylePanel.d.ts.map +1 -1
- package/dist/components/StylePanel.js +16 -189
- package/dist/components/StylePanel.js.map +1 -1
- package/dist/components/StylePanel.module.scss +6 -1
- package/dist/components/StylePanelSections.d.ts +117 -0
- package/dist/components/StylePanelSections.d.ts.map +1 -0
- package/dist/components/StylePanelSections.js +175 -0
- package/dist/components/StylePanelSections.js.map +1 -0
- package/dist/components/Swiper.d.ts +7 -1
- package/dist/components/Swiper.d.ts.map +1 -1
- package/dist/components/Swiper.js +7 -7
- package/dist/components/Swiper.js.map +1 -1
- package/dist/components/Switch.d.ts +2 -2
- package/dist/components/Switch.d.ts.map +1 -1
- package/dist/components/Switch.js +4 -4
- package/dist/components/Switch.js.map +1 -1
- package/dist/components/Table.d.ts.map +1 -1
- package/dist/components/Table.js +2 -2
- package/dist/components/Table.js.map +1 -1
- package/dist/components/Tag.d.ts +1 -1
- package/dist/components/Tag.d.ts.map +1 -1
- package/dist/components/Tag.js +2 -2
- package/dist/components/Tag.js.map +1 -1
- package/dist/components/Textarea.d.ts +15 -5
- package/dist/components/Textarea.d.ts.map +1 -1
- package/dist/components/Textarea.js +31 -17
- package/dist/components/Textarea.js.map +1 -1
- package/dist/components/ThemeSwitcher.d.ts +14 -1
- package/dist/components/ThemeSwitcher.d.ts.map +1 -1
- package/dist/components/ThemeSwitcher.js +19 -9
- package/dist/components/ThemeSwitcher.js.map +1 -1
- package/dist/components/ThemeSwitcher.module.scss +54 -0
- package/dist/components/Toast.d.ts +1 -1
- package/dist/components/Toast.d.ts.map +1 -1
- package/dist/components/Toast.js +2 -2
- package/dist/components/Toast.js.map +1 -1
- package/dist/components/ToggleButton.d.ts +9 -2
- package/dist/components/ToggleButton.d.ts.map +1 -1
- package/dist/components/ToggleButton.js +5 -5
- package/dist/components/ToggleButton.js.map +1 -1
- package/dist/components/User.js +1 -1
- package/dist/components/User.js.map +1 -1
- package/dist/components/index.d.ts +7 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +7 -0
- package/dist/components/index.js.map +1 -1
- package/dist/contexts/AdapterProvider.d.ts +50 -0
- package/dist/contexts/AdapterProvider.d.ts.map +1 -0
- package/dist/contexts/AdapterProvider.js +91 -0
- package/dist/contexts/AdapterProvider.js.map +1 -0
- package/dist/contexts/IconProvider.d.ts +2 -2
- package/dist/contexts/IconProvider.d.ts.map +1 -1
- package/dist/contexts/IconProvider.js +2 -2
- package/dist/contexts/IconProvider.js.map +1 -1
- package/dist/contexts/LayoutProvider.d.ts +0 -2
- package/dist/contexts/LayoutProvider.d.ts.map +1 -1
- package/dist/contexts/LayoutProvider.js +15 -10
- package/dist/contexts/LayoutProvider.js.map +1 -1
- package/dist/contexts/ThemeProvider.d.ts +29 -1
- package/dist/contexts/ThemeProvider.d.ts.map +1 -1
- package/dist/contexts/ThemeProvider.js +42 -15
- package/dist/contexts/ThemeProvider.js.map +1 -1
- package/dist/contexts/index.d.ts +3 -2
- package/dist/contexts/index.d.ts.map +1 -1
- package/dist/contexts/index.js +3 -2
- package/dist/contexts/index.js.map +1 -1
- package/dist/css/styles.css +1 -1
- package/dist/css/tokens.css +1 -1
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +0 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/icons/ATTRIBUTION.md +19 -0
- package/dist/icons/data.d.ts +1919 -0
- package/dist/icons/data.d.ts.map +1 -0
- package/dist/icons/data.js +102 -0
- package/dist/icons/data.js.map +1 -0
- package/dist/icons/renderIcon.d.ts +26 -0
- package/dist/icons/renderIcon.d.ts.map +1 -0
- package/dist/icons/renderIcon.js +22 -0
- package/dist/icons/renderIcon.js.map +1 -0
- package/dist/icons.d.ts +35 -4
- package/dist/icons.d.ts.map +1 -1
- package/dist/icons.js +13 -60
- package/dist/icons.js.map +1 -1
- package/dist/modules/code/CodeBlock.impl.d.ts +2 -1
- package/dist/modules/code/CodeBlock.impl.d.ts.map +1 -1
- package/dist/modules/code/CodeBlock.impl.js +7 -2
- package/dist/modules/code/CodeBlock.impl.js.map +1 -1
- package/dist/modules/data/ChartHeader.d.ts.map +1 -1
- package/dist/modules/data/ChartHeader.js +1 -1
- package/dist/modules/data/ChartHeader.js.map +1 -1
- package/dist/modules/data/DataTooltip.d.ts +1 -1
- package/dist/modules/data/DataTooltip.d.ts.map +1 -1
- package/dist/modules/data/DataTooltip.js +2 -2
- package/dist/modules/data/DataTooltip.js.map +1 -1
- package/dist/modules/data/LinearGauge.d.ts +3 -2
- package/dist/modules/data/LinearGauge.d.ts.map +1 -1
- package/dist/modules/data/LinearGauge.js +1 -1
- package/dist/modules/data/LinearGauge.js.map +1 -1
- package/dist/modules/data/PieChart.impl.d.ts +1 -1
- package/dist/modules/data/PieChart.impl.d.ts.map +1 -1
- package/dist/modules/data/PieChart.impl.js +4 -1
- package/dist/modules/data/PieChart.impl.js.map +1 -1
- package/dist/modules/data/RadialGauge.d.ts +3 -2
- package/dist/modules/data/RadialGauge.d.ts.map +1 -1
- package/dist/modules/data/RadialGauge.js +1 -1
- package/dist/modules/data/RadialGauge.js.map +1 -1
- package/dist/modules/data/interfaces.d.ts +12 -3
- package/dist/modules/data/interfaces.d.ts.map +1 -1
- package/dist/modules/index.d.ts +1 -4
- package/dist/modules/index.d.ts.map +1 -1
- package/dist/modules/index.js +9 -3
- package/dist/modules/index.js.map +1 -1
- package/dist/modules/media/MediaUpload.impl.d.ts +1 -1
- package/dist/modules/media/MediaUpload.impl.d.ts.map +1 -1
- package/dist/modules/media/MediaUpload.impl.js +1 -1
- package/dist/modules/media/MediaUpload.impl.js.map +1 -1
- package/dist/modules/navigation/Kbar.d.ts +5 -4
- package/dist/modules/navigation/Kbar.d.ts.map +1 -1
- package/dist/modules/navigation/Kbar.js +32 -35
- package/dist/modules/navigation/Kbar.js.map +1 -1
- package/dist/modules/navigation/MegaMenu.d.ts +5 -3
- package/dist/modules/navigation/MegaMenu.d.ts.map +1 -1
- package/dist/modules/navigation/MegaMenu.js +24 -12
- package/dist/modules/navigation/MegaMenu.js.map +1 -1
- package/dist/modules/navigation/MobileMegaMenu.d.ts +3 -2
- package/dist/modules/navigation/MobileMegaMenu.d.ts.map +1 -1
- package/dist/modules/navigation/MobileMegaMenu.js +1 -1
- package/dist/modules/navigation/MobileMegaMenu.js.map +1 -1
- package/dist/modules/seo/Meta.d.ts +40 -2
- package/dist/modules/seo/Meta.d.ts.map +1 -1
- package/dist/modules/seo/Meta.js.map +1 -1
- package/dist/modules/seo/Schema.d.ts.map +1 -1
- package/dist/modules/seo/Schema.js +1 -2
- package/dist/modules/seo/Schema.js.map +1 -1
- package/dist/next/index.d.ts +35 -0
- package/dist/next/index.d.ts.map +1 -0
- package/dist/next/index.js +56 -0
- package/dist/next/index.js.map +1 -0
- package/dist/package.json +52 -7
- package/dist/scripts/init-agent.js +0 -0
- package/dist/scripts/validate-ai-code.js +74 -10
- package/dist/server/og-utils.d.ts +9 -3
- package/dist/server/og-utils.d.ts.map +1 -1
- package/dist/server/og-utils.js +15 -9
- package/dist/server/og-utils.js.map +1 -1
- package/dist/styles/breakpoints.scss +16 -5
- package/dist/test/setup.js +21 -0
- package/dist/test/setup.js.map +1 -1
- package/dist/types.d.ts +13 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/colorScheme.d.ts +35 -0
- package/dist/utils/colorScheme.d.ts.map +1 -0
- package/dist/utils/colorScheme.js +140 -0
- package/dist/utils/colorScheme.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/navMatch.d.ts +21 -0
- package/dist/utils/navMatch.d.ts.map +1 -0
- package/dist/utils/navMatch.js +26 -0
- package/dist/utils/navMatch.js.map +1 -0
- package/package.json +228 -171
- package/scripts/init-agent.js +0 -0
- package/scripts/validate-ai-code.js +74 -10
- package/LICENSE.md +0 -21
- package/dist/css/styles.css.map +0 -1
- package/dist/css/tokens.css.map +0 -1
- package/dist/hooks/useResponsiveClasses.d.ts +0 -9
- package/dist/hooks/useResponsiveClasses.d.ts.map +0 -1
- package/dist/hooks/useResponsiveClasses.js +0 -293
- package/dist/hooks/useResponsiveClasses.js.map +0 -1
- package/dist/styles/background.scss +0 -423
- package/dist/styles/border.scss +0 -546
- package/dist/styles/color.scss +0 -183
- package/dist/styles/display.scss +0 -391
- package/dist/styles/flex.scss +0 -518
- package/dist/styles/global.scss +0 -36
- package/dist/styles/grid.scss +0 -293
- package/dist/styles/index.scss +0 -14
- package/dist/styles/position.scss +0 -1549
- package/dist/styles/shadow.scss +0 -19
- package/dist/styles/size.scss +0 -53
- package/dist/styles/spacing.scss +0 -1505
- package/dist/styles/typography.scss +0 -223
- package/dist/styles/utilities.scss +0 -23
- package/dist/tokens/border.scss +0 -95
- package/dist/tokens/data.scss +0 -107
- package/dist/tokens/function.scss +0 -742
- package/dist/tokens/index.scss +0 -8
- package/dist/tokens/layout.scss +0 -275
- package/dist/tokens/scheme.scss +0 -352
- package/dist/tokens/shadow.scss +0 -7
- package/dist/tokens/theme.scss +0 -657
- package/dist/tokens/typography.scss +0 -118
- package/next-env.d.ts +0 -5
- package/scripts/copy-files.js +0 -103
- package/scripts/generate-ai-spec.js +0 -464
- package/scripts/generate-emoji-data.js +0 -128
- package/scss.d.ts +0 -4
- package/tsconfig.vitest.json +0 -20
- package/vitest.config.ts +0 -19
package/ai/gotchas.json
CHANGED
|
@@ -1,86 +1,143 @@
|
|
|
1
1
|
{
|
|
2
2
|
"Background.gradient.width": {
|
|
3
3
|
"rule": "Quarter-percent units: 400 = 100% of container. Soft glows use width 100–200, not 500.",
|
|
4
|
-
"components": [
|
|
4
|
+
"components": [
|
|
5
|
+
"Background"
|
|
6
|
+
]
|
|
5
7
|
},
|
|
6
8
|
"Background.gradient.x": {
|
|
7
9
|
"rule": "x/y are percent positions of the container (50/50 = center).",
|
|
8
|
-
"components": [
|
|
10
|
+
"components": [
|
|
11
|
+
"Background"
|
|
12
|
+
]
|
|
9
13
|
},
|
|
10
14
|
"Background.absolute": {
|
|
11
15
|
"rule": "Every absolute decorative layer needs top=\"0\" left=\"0\" or it offsets by parent padding.",
|
|
12
|
-
"components": [
|
|
16
|
+
"components": [
|
|
17
|
+
"Background",
|
|
18
|
+
"MatrixFx",
|
|
19
|
+
"BlobFx"
|
|
20
|
+
]
|
|
13
21
|
},
|
|
14
22
|
"Card.interactive": {
|
|
15
23
|
"rule": "Card is for interactive surfaces only (href or onClick). Static panels use Column + background=\"surface\" border=\"neutral-alpha-weak\" radius=\"l\".",
|
|
16
|
-
"components": [
|
|
24
|
+
"components": [
|
|
25
|
+
"Card"
|
|
26
|
+
]
|
|
17
27
|
},
|
|
18
28
|
"Fade.edge": {
|
|
19
29
|
"rule": "Fade is an edge overlay strip on scroll containers, not a content wrapper.",
|
|
20
|
-
"components": [
|
|
30
|
+
"components": [
|
|
31
|
+
"Fade"
|
|
32
|
+
]
|
|
21
33
|
},
|
|
22
34
|
"RevealFx.delay": {
|
|
23
|
-
"rule": "delay is in
|
|
24
|
-
"components": [
|
|
35
|
+
"rule": "delay is in milliseconds — stagger with delay={index * 100}, never index * 0.1 (that was 1.8.x; 2.0 reads 0.1 as a tenth of a millisecond, i.e. no stagger).",
|
|
36
|
+
"components": [
|
|
37
|
+
"RevealFx",
|
|
38
|
+
"ShineFx"
|
|
39
|
+
]
|
|
25
40
|
},
|
|
26
41
|
"RevealFx.translateY": {
|
|
27
42
|
"rule": "translateY as a number is in rem. Use translateY={1} or token \"16\" (1rem); 16 means 16rem.",
|
|
28
|
-
"components": [
|
|
43
|
+
"components": [
|
|
44
|
+
"RevealFx"
|
|
45
|
+
]
|
|
29
46
|
},
|
|
30
47
|
"LogoCloud.columns": {
|
|
31
48
|
"rule": "LogoCloud extends Grid — always set columns and responsive overrides or logos stack in one column.",
|
|
32
|
-
"components": [
|
|
49
|
+
"components": [
|
|
50
|
+
"LogoCloud"
|
|
51
|
+
]
|
|
33
52
|
},
|
|
34
53
|
"StatusIndicator.color": {
|
|
35
54
|
"rule": "StatusIndicator uses color=\"green\" | \"red\" | \"orange\" | \"gray\" etc. — not variant or semantic scheme names.",
|
|
36
|
-
"components": [
|
|
55
|
+
"components": [
|
|
56
|
+
"StatusIndicator"
|
|
57
|
+
]
|
|
37
58
|
},
|
|
38
59
|
"Icon.names": {
|
|
39
|
-
"rule": "Icon names must come from
|
|
40
|
-
"components": [
|
|
60
|
+
"rule": "Icon names must come from iconNames in spec.json, which is a real union in 2.0 (an unregistered name is a type error, not a blank space). Do not guess a plausible name, and do not cast one with `as IconName` to silence the check. Brand marks are not in the set — an app registers those itself by augmenting IconLibraryOverrides.",
|
|
61
|
+
"components": [
|
|
62
|
+
"Icon",
|
|
63
|
+
"Button",
|
|
64
|
+
"IconButton"
|
|
65
|
+
]
|
|
41
66
|
},
|
|
42
67
|
"Badge.duplicate": {
|
|
43
68
|
"rule": "Do not pass the same text as both title prop and children — it renders twice.",
|
|
44
|
-
"components": [
|
|
69
|
+
"components": [
|
|
70
|
+
"Badge"
|
|
71
|
+
]
|
|
45
72
|
},
|
|
46
73
|
"Tag.duplicate": {
|
|
47
74
|
"rule": "Do not pass the same text as both label prop and children — it renders twice.",
|
|
48
|
-
"components": [
|
|
75
|
+
"components": [
|
|
76
|
+
"Tag"
|
|
77
|
+
]
|
|
49
78
|
},
|
|
50
79
|
"color.tokens": {
|
|
51
80
|
"rule": "Colors are semantic tokens ({scheme}-{weight}), never hex/rgb. background also accepts surface | overlay | page | transparent.",
|
|
52
|
-
"components": [
|
|
81
|
+
"components": [
|
|
82
|
+
"Column",
|
|
83
|
+
"Row",
|
|
84
|
+
"Text",
|
|
85
|
+
"Button"
|
|
86
|
+
]
|
|
53
87
|
},
|
|
54
88
|
"color.background-weak": {
|
|
55
89
|
"rule": "*-background-weak is nearly the page color — invisible as accent. Use alpha tokens (brand-alpha-medium) for glows.",
|
|
56
|
-
"components": [
|
|
90
|
+
"components": [
|
|
91
|
+
"Background"
|
|
92
|
+
]
|
|
57
93
|
},
|
|
58
94
|
"layout.shorthands": {
|
|
59
95
|
"rule": "Use fill not fillWidth fillHeight; center not horizontal=\"center\" vertical=\"center\"; Row/Column not Flex direction=.",
|
|
60
|
-
"components": [
|
|
96
|
+
"components": [
|
|
97
|
+
"Row",
|
|
98
|
+
"Column",
|
|
99
|
+
"Flex",
|
|
100
|
+
"Grid"
|
|
101
|
+
]
|
|
61
102
|
},
|
|
62
103
|
"layout.defaults": {
|
|
63
104
|
"rule": "Never write props equal to defaults: position=\"relative\", direction on Row/Column, variant=\"primary\" on Button.",
|
|
64
|
-
"components": [
|
|
105
|
+
"components": [
|
|
106
|
+
"Row",
|
|
107
|
+
"Column",
|
|
108
|
+
"Button"
|
|
109
|
+
]
|
|
65
110
|
},
|
|
66
111
|
"section.gaps": {
|
|
67
112
|
"rule": "Gap between page sections: 80–160 (typical 104). Inside sections: 24–40.",
|
|
68
|
-
"components": [
|
|
113
|
+
"components": [
|
|
114
|
+
"Column"
|
|
115
|
+
]
|
|
69
116
|
},
|
|
70
117
|
"heading.scale": {
|
|
71
118
|
"rule": "Hero = display-strong-l/xl; section titles = display-strong-xs/s — never heading-* for section titles.",
|
|
72
|
-
"components": [
|
|
119
|
+
"components": [
|
|
120
|
+
"Heading"
|
|
121
|
+
]
|
|
73
122
|
},
|
|
74
123
|
"animation.budget": {
|
|
75
124
|
"rule": "Entry animation budget: hero + at most 1–2 key moments. Animate coherent blocks all-or-none within a sibling set.",
|
|
76
|
-
"components": [
|
|
125
|
+
"components": [
|
|
126
|
+
"RevealFx",
|
|
127
|
+
"CountFx"
|
|
128
|
+
]
|
|
77
129
|
},
|
|
78
130
|
"CountFx.trigger": {
|
|
79
131
|
"rule": "CountFx has no trigger prop — drive value from useInViewport latch instead.",
|
|
80
|
-
"components": [
|
|
132
|
+
"components": [
|
|
133
|
+
"CountFx"
|
|
134
|
+
]
|
|
81
135
|
},
|
|
82
136
|
"overflow.hero": {
|
|
83
137
|
"rule": "overflow=\"hidden\" on full-bleed sections clips glows into hard bands — only use when parent has radius.",
|
|
84
|
-
"components": [
|
|
138
|
+
"components": [
|
|
139
|
+
"Column",
|
|
140
|
+
"Background"
|
|
141
|
+
]
|
|
85
142
|
}
|
|
86
143
|
}
|
package/ai/layouts.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Once UI — application layouts
|
|
2
|
+
|
|
3
|
+
Recipes for the shells a product sits inside, as opposed to the decoration in
|
|
4
|
+
`recipes.md`. Each is the shape a working product converged on, not a sketch.
|
|
5
|
+
|
|
6
|
+
Use them verbatim, then adjust. The values that look arbitrary usually are not —
|
|
7
|
+
the notes say which ones matter and why.
|
|
8
|
+
|
|
9
|
+
All three compile: they are also `ai/examples/app-shell.tsx`, which `pnpm
|
|
10
|
+
typecheck` covers, so a renamed prop breaks the recipe rather than leaving it
|
|
11
|
+
quietly wrong.
|
|
12
|
+
|
|
13
|
+
## 1. App shell with a sidebar
|
|
14
|
+
|
|
15
|
+
The one agents get wrong most often. A dashboard built without this scrolls the
|
|
16
|
+
whole document, so the header and sidebar slide away and the nav has to be
|
|
17
|
+
scrolled back to.
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
<Column fill horizontal="center" flex={1}>
|
|
21
|
+
<Header /> {/* 56px tall */}
|
|
22
|
+
<Row fill paddingX="8">
|
|
23
|
+
<Sidebar s={{ hide: true }} maxWidth={18} fitHeight position="sticky" top="56" />
|
|
24
|
+
<Row fill horizontal="center" topRadius="l" overflow="hidden">
|
|
25
|
+
<Row
|
|
26
|
+
height="calc(100dvh - var(--static-space-56))"
|
|
27
|
+
overflowY="auto"
|
|
28
|
+
topRadius="l"
|
|
29
|
+
horizontal="center"
|
|
30
|
+
fillWidth
|
|
31
|
+
background="surface">
|
|
32
|
+
<Column maxWidth="xl" gap="m" paddingY="32" fitHeight>
|
|
33
|
+
{children}
|
|
34
|
+
</Column>
|
|
35
|
+
</Row>
|
|
36
|
+
</Row>
|
|
37
|
+
</Row>
|
|
38
|
+
</Column>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
What each part is doing:
|
|
42
|
+
|
|
43
|
+
- **The pane scrolls, not the page.** `height: calc(100dvh - <header>)` plus
|
|
44
|
+
`overflowY="auto"` is what keeps the header and sidebar in place. `dvh`, not
|
|
45
|
+
`vh` — on mobile `vh` ignores the browser chrome and the pane runs off-screen.
|
|
46
|
+
- **`position="sticky" top="56"`** on the sidebar, matching the header height.
|
|
47
|
+
`fitHeight` so it does not stretch and fight the sticky.
|
|
48
|
+
- **`topRadius="l"` + `background="surface"`** is what makes the content read as
|
|
49
|
+
a panel sitting on the page rather than the page itself. The radius is on the
|
|
50
|
+
top only, since the bottom is off-screen.
|
|
51
|
+
- **`s={{ hide: true }}`** rather than a media query. The mobile nav is a
|
|
52
|
+
separate surface, not this one reflowed.
|
|
53
|
+
- **`maxWidth="xl"`** inside the pane. A dashboard is wider than a document;
|
|
54
|
+
`"m"` is for reading.
|
|
55
|
+
|
|
56
|
+
## 2. Data-driven navigation
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { NavGroup, NavItem, selectNavHref } from "@once-ui-system/core";
|
|
60
|
+
|
|
61
|
+
const current = selectNavHref(pathname, nav.flatMap((i) =>
|
|
62
|
+
i.items ? i.items.map((s) => s.href) : [i.href],
|
|
63
|
+
));
|
|
64
|
+
|
|
65
|
+
<Column fill gap="4" paddingX="8">
|
|
66
|
+
{nav.map((item) =>
|
|
67
|
+
item.items ? (
|
|
68
|
+
<NavGroup
|
|
69
|
+
key={item.key}
|
|
70
|
+
label={item.label}
|
|
71
|
+
icon={item.icon}
|
|
72
|
+
defaultOpen={item.items.some((s) => s.href === current)}>
|
|
73
|
+
{item.items.map((sub) => (
|
|
74
|
+
<NavItem
|
|
75
|
+
key={sub.href}
|
|
76
|
+
href={sub.href}
|
|
77
|
+
label={sub.label}
|
|
78
|
+
badge={sub.badge}
|
|
79
|
+
selected={sub.href === current}
|
|
80
|
+
/>
|
|
81
|
+
))}
|
|
82
|
+
</NavGroup>
|
|
83
|
+
) : (
|
|
84
|
+
<NavItem
|
|
85
|
+
key={item.href}
|
|
86
|
+
href={item.href}
|
|
87
|
+
icon={item.icon}
|
|
88
|
+
label={item.label}
|
|
89
|
+
selected={item.href === current}
|
|
90
|
+
/>
|
|
91
|
+
),
|
|
92
|
+
)}
|
|
93
|
+
</Column>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
- **`selectNavHref` over `===` or `startsWith`.** An equality check leaves a
|
|
97
|
+
nested route (`/settings/billing/invoices/42`) with nothing highlighted; a
|
|
98
|
+
prefix check lights the parent up alongside its child. It returns the longest
|
|
99
|
+
href that matches, which is the right one.
|
|
100
|
+
- **Compute `current` once** for the whole tree, not per item — a child needs to
|
|
101
|
+
know about its siblings to know it is the deepest match.
|
|
102
|
+
- **`defaultOpen` from the match**, so the group holding the current page is open
|
|
103
|
+
on arrival.
|
|
104
|
+
- Child items take **no icon**. The rail inside `NavGroup` carries the hierarchy;
|
|
105
|
+
a second column of icons competes with it.
|
|
106
|
+
|
|
107
|
+
## 3. Editor shell
|
|
108
|
+
|
|
109
|
+
Two panes and a timeline — the shape of a video editor, a page builder, a
|
|
110
|
+
diff view.
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
<Column fill>
|
|
114
|
+
<SplitView
|
|
115
|
+
fill
|
|
116
|
+
leftPanel={<Column fill overflowY="auto">{/* layers, blocks, files */}</Column>}
|
|
117
|
+
rightPanel={<Column fill overflowY="auto">{/* canvas, preview */}</Column>}
|
|
118
|
+
defaultSplit={0.28}
|
|
119
|
+
minSplit={0.2}
|
|
120
|
+
maxSplit={0.6}
|
|
121
|
+
collapseBelow="s"
|
|
122
|
+
labels={{ left: "Layers", right: "Canvas" }}
|
|
123
|
+
/>
|
|
124
|
+
<Scrubber
|
|
125
|
+
duration={duration}
|
|
126
|
+
value={time}
|
|
127
|
+
onChange={setTime}
|
|
128
|
+
tracks={tracks}
|
|
129
|
+
onGestureStart={pause}
|
|
130
|
+
/>
|
|
131
|
+
</Column>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
- **`overflowY="auto"` on each panel, not on the SplitView.** The divider needs
|
|
135
|
+
the container to stay put while the panes scroll independently.
|
|
136
|
+
- **`collapseBelow` + `labels`.** Below the breakpoint the split becomes tabs, and
|
|
137
|
+
`labels` is what they say. Without it the tabs are unlabelled.
|
|
138
|
+
- **`onGestureStart` pauses playback.** Scrubbing while playing fights the
|
|
139
|
+
playhead — the drag sets a time, playback immediately moves it.
|
|
140
|
+
- **The timeline is a sibling of the split, not inside it.** It spans both panes,
|
|
141
|
+
and putting it in one makes the divider drag it.
|
|
142
|
+
|
|
143
|
+
## Anti-patterns
|
|
144
|
+
|
|
145
|
+
- A dashboard with no scrolling pane — the whole document scrolls and the nav
|
|
146
|
+
leaves with it.
|
|
147
|
+
- `100vh` in an app shell. Use `100dvh`; `vh` is wrong on mobile the moment the
|
|
148
|
+
browser chrome shows or hides.
|
|
149
|
+
- A sticky sidebar without `fitHeight` — it stretches to the row and the sticky
|
|
150
|
+
never engages.
|
|
151
|
+
- `pathname === href` or `startsWith` for nav selection. Use `selectNavHref`.
|
|
152
|
+
- Icons on both a NavGroup and its children — two columns of icons, no hierarchy.
|
|
153
|
+
- `overflow` on the SplitView instead of on its panels — the divider stops
|
|
154
|
+
tracking the pointer.
|
package/ai/manifest.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "
|
|
3
|
-
"generated": "2026-
|
|
2
|
+
"version": "2.0.0-alpha.0",
|
|
3
|
+
"generated": "2026-09-16",
|
|
4
4
|
"files": {
|
|
5
5
|
"spec": "spec.json",
|
|
6
6
|
"catalog": "catalog.json",
|
|
7
7
|
"rules": "rules.compact.md",
|
|
8
8
|
"rulesFull": "rules.md",
|
|
9
9
|
"recipes": "recipes.md",
|
|
10
|
+
"layouts": "layouts.md",
|
|
10
11
|
"gotchas": "gotchas.json",
|
|
11
12
|
"tasks": "tasks/index.json",
|
|
12
13
|
"examples": "examples/",
|
package/ai/recipes.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
# Once UI — decoration recipes
|
|
1
|
+
# Once UI — decoration and restraint recipes
|
|
2
2
|
|
|
3
|
-
Curated
|
|
4
|
-
|
|
3
|
+
Curated patterns that keep pages premium without going over the top: decorative
|
|
4
|
+
layers that carry a section, and controls that earn their room back. Use them
|
|
5
|
+
verbatim, then adjust values. All units follow rules.md #21–24.
|
|
5
6
|
|
|
6
7
|
## Budget (hard limits)
|
|
7
8
|
|
|
@@ -129,7 +130,7 @@ useEffect(() => {
|
|
|
129
130
|
|
|
130
131
|
<Grid ref={ref} columns="3" gap="16" s={{ columns: 1 }}>
|
|
131
132
|
{items.map((item, index) => (
|
|
132
|
-
<RevealFx key={item.id}
|
|
133
|
+
<RevealFx key={item.id} revealed={seen} translateY="8" delay={index * 100}>
|
|
133
134
|
<Card ... />
|
|
134
135
|
</RevealFx>
|
|
135
136
|
))}
|
|
@@ -138,8 +139,52 @@ useEffect(() => {
|
|
|
138
139
|
|
|
139
140
|
For stats, drive `CountFx` value from the same latch: `<CountFx value={seen ? 2400 : 0} separator="," />`.
|
|
140
141
|
|
|
142
|
+
## 8. Reveal on hover (controls that earn their room back)
|
|
143
|
+
|
|
144
|
+
A control that must be reachable from every page but is used once a session does
|
|
145
|
+
not need permanent width. Show its current state; reveal the options on hover or
|
|
146
|
+
focus.
|
|
147
|
+
|
|
148
|
+
`ThemeSwitcher` ships this as a prop:
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
<ThemeSwitcher collapsed />
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
For any other toggle group, the pattern is the same three rules — and all three
|
|
155
|
+
are load-bearing, because hover-to-reveal is one of the easiest ways to ship an
|
|
156
|
+
inaccessible control:
|
|
157
|
+
|
|
158
|
+
- **Open on `:focus-within` as well as `:hover`,** and keep the hidden options
|
|
159
|
+
focusable. Collapse them with `max-width: 0` and `overflow: hidden`, never
|
|
160
|
+
`display: none` or `visibility: hidden` — those remove the tab stops, and then
|
|
161
|
+
the only way to reach the options is with a mouse.
|
|
162
|
+
- **Stay open under `@media (hover: none)`.** On a touch device the first tap
|
|
163
|
+
lands on the visible control, which means the tap that was meant to open the
|
|
164
|
+
group has already committed to an option.
|
|
165
|
+
- **Animate width only, and drop it under `prefers-reduced-motion`.** The
|
|
166
|
+
control must do exactly the same thing with the transition off.
|
|
167
|
+
|
|
168
|
+
```scss
|
|
169
|
+
.group { overflow: hidden; }
|
|
170
|
+
.group .option { overflow: hidden; max-width: var(--static-space-40); transition: max-width var(--transition-duration-micro-medium) ease; }
|
|
171
|
+
.group .option.inactive { max-width: 0; opacity: 0; }
|
|
172
|
+
.group:hover .option.inactive,
|
|
173
|
+
.group:focus-within .option.inactive { max-width: var(--static-space-40); opacity: 1; }
|
|
174
|
+
|
|
175
|
+
@media (hover: none) { .group .option.inactive { max-width: var(--static-space-40); opacity: 1; } }
|
|
176
|
+
@media (prefers-reduced-motion: reduce) { .group .option { transition: none; } }
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Use it for theme, density, or view-mode switchers in a header or a footer. Do
|
|
180
|
+
not use it for anything a visitor needs to *see* the state of at a glance across
|
|
181
|
+
options, for primary navigation, or for a destructive action — a control that
|
|
182
|
+
hides until pointed at is a control nobody finds.
|
|
183
|
+
|
|
141
184
|
## Anti-patterns
|
|
142
185
|
|
|
186
|
+
- **Hover-only reveals.** A group that opens on `:hover` but not `:focus-within`, or that collapses with `display: none`, is unreachable by keyboard and unusable by touch. See #8.
|
|
187
|
+
|
|
143
188
|
- Glow with `colorStart: "brand-background-weak"` — invisible against the page; use alpha tokens.
|
|
144
189
|
- `width: 500` gradients — that's 125% of the container blown past its edges; stay ≤ 200 for glows.
|
|
145
190
|
- Background layers without `top="0" left="0"` inside padded parents — misaligned.
|
package/ai/rules.compact.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Once UI — compact codegen rules
|
|
2
2
|
|
|
3
|
-
Load with task bundle from `@once-ui-system/core/ai/tasks/{intent}.json`. For production-quality composition, read matching Pro blocks from `examples/blocks/manifest.json`. Fetch component slices on demand.
|
|
3
|
+
Load with task bundle from `@once-ui-system/core/ai/tasks/{intent}.json`. For an app shell, a sidebar nav or an editor, read `ai/layouts.md` first — those are the shapes that are hard to get right from props alone. For production-quality composition, read matching Pro blocks from `examples/blocks/manifest.json`. Fetch component slices on demand.
|
|
4
4
|
|
|
5
5
|
## Layout
|
|
6
6
|
|
|
@@ -47,9 +47,9 @@ Absolute layers always: `position="absolute" top="0" left="0" fill pointerEvents
|
|
|
47
47
|
|
|
48
48
|
## Motion
|
|
49
49
|
|
|
50
|
-
- `RevealFx delay` in **
|
|
50
|
+
- `RevealFx delay` (and `ShineFx speed`) in **milliseconds**: `delay={index * 100}` — `* 0.1` was 1.8.x
|
|
51
51
|
- `RevealFx translateY`: number = rem; prefer `"8"`–`"16"` tokens
|
|
52
|
-
- Viewport-
|
|
52
|
+
- Viewport-reveal with `useInViewport` + latch into `RevealFx revealed`; `CountFx` driven by `value`, no trigger prop
|
|
53
53
|
- Animate all siblings in a set or none — never one lone animated card
|
|
54
54
|
|
|
55
55
|
## Components
|
|
@@ -64,6 +64,21 @@ Absolute layers always: `position="absolute" top="0" left="0" fill pointerEvents
|
|
|
64
64
|
| Icons | `IconName` from spec only |
|
|
65
65
|
| Logos grid | `LogoCloud` with `columns` set |
|
|
66
66
|
|
|
67
|
+
## Imports
|
|
68
|
+
|
|
69
|
+
Most things come from the package root. Three modules do not, because their
|
|
70
|
+
dependencies are optional peers:
|
|
71
|
+
|
|
72
|
+
| Import | From |
|
|
73
|
+
|--------|------|
|
|
74
|
+
| charts, gauges, chart chrome | `@once-ui-system/core/data` (needs `recharts`) |
|
|
75
|
+
| `CodeBlock` | `@once-ui-system/core/code` (needs `prismjs`) |
|
|
76
|
+
| `MediaUpload` | `@once-ui-system/core/media` (needs `compressorjs`) |
|
|
77
|
+
|
|
78
|
+
Naming one of these from the root does not resolve. `IconName` is a real union,
|
|
79
|
+
so an unregistered icon name is a type error, not a blank space — take names
|
|
80
|
+
from `spec.json`.
|
|
81
|
+
|
|
67
82
|
## Defaults — omit these
|
|
68
83
|
|
|
69
84
|
`position="relative"`, `direction` on Row/Column, `variant="primary"` on Button, `size="m"` when default.
|
package/ai/rules.md
CHANGED
|
@@ -47,7 +47,7 @@ If you can't ask (or the user says "you decide"), default to: restrained, center
|
|
|
47
47
|
|
|
48
48
|
## Spacing and sizing
|
|
49
49
|
|
|
50
|
-
4. Use spacing tokens, never raw CSS: `gap`, `padding`, `margin`, `paddingX/Y`, `marginX/Y` accept
|
|
50
|
+
4. Use spacing tokens, never raw CSS: `gap`, `padding`, `margin`, `paddingX/Y`, `marginX/Y` accept the full `SpacingToken` scale (`"0" "1" "2" "4" "8" "12" "16" "20" "24" "32" "40" "48" "56" "64" "80" "104" "128" "160"`, or `"xs" "s" "m" "l" "xl"`). The top of the scale is what rule 17 calls for between sections — it is not an extension, it is part of the same list.
|
|
51
51
|
|
|
52
52
|
```tsx
|
|
53
53
|
// Good
|
|
@@ -109,9 +109,9 @@ If you can't ask (or the user says "you decide"), default to: restrained, center
|
|
|
109
109
|
- `CursorCard`, `HoverCard`, `ContextMenu`, `EmojiPicker`, `CompareImage`, `OgCard`, `Timeline`, `MasonryGrid`, `InfiniteScroll`, `SegmentedControl`, `Kbar` (command palette)
|
|
110
110
|
- Forms: `Input`, `PasswordInput`, `OTPInput`, `NumberInput`, `TagInput`, `Select`, `DatePicker`, `DateRangePicker`, `ColorInput`, `Slider`, `Switch`, `Checkbox`, `Chip`
|
|
111
111
|
|
|
112
|
-
14. Buttons: `variant` = `primary | secondary | tertiary | danger
|
|
112
|
+
14. Buttons: `variant` = `primary | secondary | tertiary | quaternary | subtle | danger | success | warning | ghost | link` (the slice is authoritative; `primary` is the default); pair with `prefixIcon`/`suffixIcon` (icon names, not elements). `IconButton` for icon-only actions with `tooltip`.
|
|
113
113
|
|
|
114
|
-
14b. Icon names must come from
|
|
114
|
+
14b. Icon names must come from `iconNames` in spec.json. In 2.0 `IconName` is a real union, so an unregistered name is a type error rather than a blank space — do not guess a plausible one, and never reach for `as IconName` to silence the check. If no registered icon fits, omit the icon. The registry is 99 icons; brand marks (github, discord, google) are deliberately not among them, so an app registers its own.
|
|
115
115
|
|
|
116
116
|
14c. Components with a text prop render it — never pass the same text as both prop and children, it renders twice:
|
|
117
117
|
|
|
@@ -155,9 +155,47 @@ If you can't ask (or the user says "you decide"), default to: restrained, center
|
|
|
155
155
|
// Good eyebrow
|
|
156
156
|
<Text variant="label-default-s" onBackground="brand-medium">Pricing</Text>
|
|
157
157
|
// Bad eyebrow
|
|
158
|
-
<Tag
|
|
158
|
+
<Tag scheme="neutral" prefixIcon="sparkle">Pricing</Tag>
|
|
159
159
|
```
|
|
160
160
|
|
|
161
|
+
20b. **Proportion is a decision, not a leftover.** Two columns in a row finish at
|
|
162
|
+
roughly the same place, or one of them is wrong. A tall card beside a strip of
|
|
163
|
+
small controls leaves a column of dead space that reads as an unfinished page —
|
|
164
|
+
and the fix is almost never more whitespace tokens.
|
|
165
|
+
|
|
166
|
+
Give the thin side real content instead. Tiles grow to carry their own height,
|
|
167
|
+
with a placeholder, a preview, a swatch, a count — something true about the
|
|
168
|
+
thing they stand for. Then keep them quiet: low-contrast surfaces, small labels,
|
|
169
|
+
no competing headline. A grid of twenty loud tiles takes the section away from
|
|
170
|
+
the card it was meant to support.
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
// Bad: a tall card and 20 chips, most of the row empty
|
|
174
|
+
<Row fillWidth gap="32">
|
|
175
|
+
<Column flex={1} maxWidth={26}><FeatureCard /></Column>
|
|
176
|
+
<Column flex={1}><Row wrap gap="4">{items.map(i => <Button key={i} size="s">{i}</Button>)}</Row></Column>
|
|
177
|
+
</Row>
|
|
178
|
+
|
|
179
|
+
// Good: both sides carry weight, the card still leads
|
|
180
|
+
<Row fillWidth gap="32">
|
|
181
|
+
<Column flex={2}><FeatureCard /></Column>
|
|
182
|
+
<Column flex={3}>
|
|
183
|
+
<Grid columns={5} s={{ columns: 3 }} gap="8" fillWidth>
|
|
184
|
+
{items.map(i => (
|
|
185
|
+
<Column key={i} aspectRatio="1 / 1" padding="12" radius="l"
|
|
186
|
+
background="page" border="neutral-alpha-weak" vertical="between">
|
|
187
|
+
{/* a preview of the thing, not just its name */}
|
|
188
|
+
</Column>
|
|
189
|
+
))}
|
|
190
|
+
</Grid>
|
|
191
|
+
</Column>
|
|
192
|
+
</Row>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Check it by squinting at the two columns' bottom edges. If one ends halfway up
|
|
196
|
+
the other, change the flex ratio, the tile size, or what the tiles contain —
|
|
197
|
+
in that order.
|
|
198
|
+
|
|
161
199
|
## Decorative layers
|
|
162
200
|
|
|
163
201
|
21. Every absolute decorative layer uses the full recipe — `top="0" left="0"` are required or the layer gets offset by parent padding:
|
|
@@ -184,21 +222,21 @@ Siblings holding content get `zIndex={1}`. `overflow="hidden"` goes on the paren
|
|
|
184
222
|
|
|
185
223
|
## Effect units
|
|
186
224
|
|
|
187
|
-
24. `RevealFx`: `delay` is in **
|
|
225
|
+
24. `RevealFx`: `delay` is in **milliseconds** — stagger with `delay={index * 100}`, never `index * 0.1` (that was 1.8.x, and 2.0 reads it as a tenth of a millisecond, i.e. no stagger at all). `ShineFx.speed` is milliseconds for the same reason. `translateY` as a number is in **rem** — use `translateY={1}` or a token like `"16"` (1rem); `16` means 16rem.
|
|
188
226
|
|
|
189
227
|
25. `LogoCloud` extends `Grid` — always set `columns` (and responsive overrides), or logos stack in one column: `columns="4" m={{ columns: 3 }} s={{ columns: 2 }}`.
|
|
190
228
|
|
|
191
|
-
26. Use decoration recipes from `recipes.md` verbatim, then adjust. Budget: at most one ambient background layer per section, ambient motion in at most the hero and final CTA, one accent color family per page.
|
|
229
|
+
26. Use decoration recipes from `recipes.md` verbatim, then adjust. Application shells — a dashboard with a sidebar, a data-driven nav, a two-pane editor — come from `layouts.md` the same way. Budget: at most one ambient background layer per section, ambient motion in at most the hero and final CTA, one accent color family per page.
|
|
192
230
|
|
|
193
231
|
## Motion
|
|
194
232
|
|
|
195
|
-
27. Animations are **eye-leading, not eye-grabbing**: they direct attention to the one thing that should be read next, they don't announce themselves. Small distances (`translateY="8"`–`"16"`, i.e. 0.5–1rem), short staggers (`delay={index *
|
|
233
|
+
27. Animations are **eye-leading, not eye-grabbing**: they direct attention to the one thing that should be read next, they don't announce themselves. Small distances (`translateY="8"`–`"16"`, i.e. 0.5–1rem), short staggers (`delay={index * 100}` max), and only on elements worth leading the eye to — the hero heading, stat numbers, the highlighted card in a set.
|
|
196
234
|
|
|
197
235
|
28. Do **not** wrap every section in `RevealFx` — uniform entrance animation on everything reads dated and makes scrolling feel slow. Entry-animation budget per page: the hero, plus at most one or two key moments (stats, a card set). Everything else just renders.
|
|
198
236
|
|
|
199
|
-
28b. Animate **coherent blocks, all-or-none**. Within a sibling set (cards, list items), either every sibling animates with a stagger or none do — never a single item out of the set (e.g. only the highlighted pricing card). For a hero, reveal it as 1–3 stacked chunks with increasing delay (`0 /
|
|
237
|
+
28b. Animate **coherent blocks, all-or-none**. Within a sibling set (cards, list items), either every sibling animates with a stagger or none do — never a single item out of the set (e.g. only the highlighted pricing card). For a hero, reveal it as 1–3 stacked chunks with increasing delay (`0 / 100 / 200`), not individual text fragments. One entrance moment per viewport: if the hero animates, the cards below it don't.
|
|
200
238
|
|
|
201
|
-
29. Trigger below-the-fold animations with `useInViewport`, latched so they play once. `RevealFx` takes `
|
|
239
|
+
29. Trigger below-the-fold animations with `useInViewport`, latched so they play once. `RevealFx` takes `revealed`; `CountFx` has no trigger prop — drive its `value` instead:
|
|
202
240
|
|
|
203
241
|
```tsx
|
|
204
242
|
const ref = useRef<HTMLDivElement>(null);
|
|
@@ -209,9 +247,29 @@ useEffect(() => {
|
|
|
209
247
|
}, [inViewport]);
|
|
210
248
|
|
|
211
249
|
<Column ref={ref} gap="16">
|
|
212
|
-
<RevealFx
|
|
250
|
+
<RevealFx revealed={seen} translateY="8">...</RevealFx>
|
|
213
251
|
<CountFx value={seen ? 2400 : 0} speed={1500} separator="," variant="display-strong-m" />
|
|
214
252
|
</Column>
|
|
215
253
|
```
|
|
216
254
|
|
|
217
255
|
Without this, mount-timed animations play while still off-screen and the user scrolls into an already-finished state.
|
|
256
|
+
|
|
257
|
+
## Imports
|
|
258
|
+
|
|
259
|
+
30. Most things come from the package root, but three modules do not, because
|
|
260
|
+
their dependencies are optional peers and a root re-export would drag the
|
|
261
|
+
specifier into every consumer's module graph:
|
|
262
|
+
|
|
263
|
+
| Import | From | Peer the app installs |
|
|
264
|
+
|--------|------|-----------------------|
|
|
265
|
+
| charts, gauges, chart chrome | `@once-ui-system/core/data` | `recharts` |
|
|
266
|
+
| `CodeBlock` | `@once-ui-system/core/code` | `prismjs` |
|
|
267
|
+
| `MediaUpload` | `@once-ui-system/core/media` | `compressorjs` |
|
|
268
|
+
|
|
269
|
+
Naming one of these from the root does not resolve. Each component slice in
|
|
270
|
+
`ai/components/` carries the specifier to import it from.
|
|
271
|
+
|
|
272
|
+
31. `IconName` is a real union, not `string`. An unregistered name is a type
|
|
273
|
+
error now, where it used to render a blank space with a console warning — so
|
|
274
|
+
take icon names from `spec.json`'s `iconNames` rather than guessing a plausible
|
|
275
|
+
one. An app registers its own by augmenting `IconLibraryOverrides`.
|