@once-ui-system/core 2.0.0-alpha.0 → 2.0.0-alpha.2

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.
Files changed (162) hide show
  1. package/AGENTS.md +1 -1
  2. package/LICENSE.md +21 -0
  3. package/ai/catalog.json +11 -4
  4. package/ai/components/Effect.json +1 -1
  5. package/ai/components/Feedback.json +1 -0
  6. package/ai/components/Form.json +15 -0
  7. package/ai/components/Input.json +3 -2
  8. package/ai/components/{Particle.json → ParticleFx.json} +1 -1
  9. package/ai/components/ScrollContainer.json +9 -1
  10. package/ai/components/Textarea.json +3 -2
  11. package/ai/components/ThemeSwitcher.json +2 -1
  12. package/ai/eval-tasks.md +2 -1
  13. package/ai/examples/auth.tsx +1 -2
  14. package/ai/examples/blocks/Dashboard1.tsx +8 -8
  15. package/ai/examples/blocks/Feed3.tsx +4 -4
  16. package/ai/examples/blocks/Footer4.tsx +2 -2
  17. package/ai/examples/blocks/Header2.tsx +1 -1
  18. package/ai/examples/blocks/Header4.tsx +1 -2
  19. package/ai/examples/blocks/Productivity1.tsx +1 -1
  20. package/ai/examples/blocks/Roadmap1.tsx +3 -3
  21. package/ai/examples/blocks/Sidebar1.tsx +1 -1
  22. package/ai/examples/blocks/Sidebar2.tsx +1 -1
  23. package/ai/examples/blocks/Table1.tsx +3 -3
  24. package/ai/examples/blocks/manifest.json +2 -2
  25. package/ai/examples/dashboard.tsx +5 -5
  26. package/ai/examples/marketing-hero.tsx +2 -2
  27. package/ai/examples/pricing.tsx +3 -3
  28. package/ai/examples/settings.tsx +4 -4
  29. package/ai/gotchas.json +26 -2
  30. package/ai/manifest.json +2 -2
  31. package/ai/recipes.md +1 -1
  32. package/ai/rules.compact.md +8 -2
  33. package/ai/rules.md +18 -6
  34. package/ai/spec.json +35 -10
  35. package/ai/tasks/settings.json +1 -1
  36. package/dist/AGENTS.md +1 -1
  37. package/dist/ai/catalog.json +11 -4
  38. package/dist/ai/components/Effect.json +1 -1
  39. package/dist/ai/components/Feedback.json +1 -0
  40. package/dist/ai/components/Form.json +15 -0
  41. package/dist/ai/components/Input.json +3 -2
  42. package/dist/ai/components/{Particle.json → ParticleFx.json} +1 -1
  43. package/dist/ai/components/ScrollContainer.json +9 -1
  44. package/dist/ai/components/Textarea.json +3 -2
  45. package/dist/ai/components/ThemeSwitcher.json +2 -1
  46. package/dist/ai/eval-tasks.md +2 -1
  47. package/dist/ai/examples/blocks/manifest.json +2 -2
  48. package/dist/ai/gotchas.json +26 -2
  49. package/dist/ai/manifest.json +2 -2
  50. package/dist/ai/recipes.md +1 -1
  51. package/dist/ai/rules.compact.md +8 -2
  52. package/dist/ai/rules.md +18 -6
  53. package/dist/ai/spec.json +35 -10
  54. package/dist/ai/tasks/settings.json +1 -1
  55. package/dist/components/Animation.d.ts +1 -2
  56. package/dist/components/Animation.d.ts.map +1 -1
  57. package/dist/components/Animation.js +1 -1
  58. package/dist/components/Animation.js.map +1 -1
  59. package/dist/components/ArrowNavigationContext.d.ts.map +1 -1
  60. package/dist/components/ArrowNavigationContext.js +12 -3
  61. package/dist/components/ArrowNavigationContext.js.map +1 -1
  62. package/dist/components/Avatar.d.ts.map +1 -1
  63. package/dist/components/Avatar.js +1 -1
  64. package/dist/components/Avatar.js.map +1 -1
  65. package/dist/components/Carousel.js +1 -1
  66. package/dist/components/Carousel.js.map +1 -1
  67. package/dist/components/ContextMenu.d.ts +1 -1
  68. package/dist/components/ContextMenu.d.ts.map +1 -1
  69. package/dist/components/CountFx.d.ts.map +1 -1
  70. package/dist/components/CountFx.js +19 -7
  71. package/dist/components/CountFx.js.map +1 -1
  72. package/dist/components/CursorCard.d.ts +1 -1
  73. package/dist/components/CursorCard.d.ts.map +1 -1
  74. package/dist/components/DatePicker.d.ts.map +1 -1
  75. package/dist/components/DatePicker.js +9 -2
  76. package/dist/components/DatePicker.js.map +1 -1
  77. package/dist/components/DropdownWrapper.d.ts +1 -1
  78. package/dist/components/DropdownWrapper.d.ts.map +1 -1
  79. package/dist/components/DropdownWrapper.js +178 -35
  80. package/dist/components/DropdownWrapper.js.map +1 -1
  81. package/dist/components/DropdownWrapper.module.scss +3 -1
  82. package/dist/components/Effect.d.ts +2 -2
  83. package/dist/components/Effect.d.ts.map +1 -1
  84. package/dist/components/Effect.js +2 -2
  85. package/dist/components/Effect.js.map +1 -1
  86. package/dist/components/EmojiPicker.js +1 -1
  87. package/dist/components/EmojiPicker.js.map +1 -1
  88. package/dist/components/Feedback.d.ts +4 -0
  89. package/dist/components/Feedback.d.ts.map +1 -1
  90. package/dist/components/Feedback.js +2 -2
  91. package/dist/components/Feedback.js.map +1 -1
  92. package/dist/components/FocusTrap.d.ts +3 -3
  93. package/dist/components/FocusTrap.d.ts.map +1 -1
  94. package/dist/components/FocusTrap.js +10 -0
  95. package/dist/components/FocusTrap.js.map +1 -1
  96. package/dist/components/Form.d.ts +48 -0
  97. package/dist/components/Form.d.ts.map +1 -0
  98. package/dist/components/Form.js +191 -0
  99. package/dist/components/Form.js.map +1 -0
  100. package/dist/components/Form.module.scss +160 -0
  101. package/dist/components/FormContext.d.ts +20 -0
  102. package/dist/components/FormContext.d.ts.map +1 -0
  103. package/dist/components/FormContext.js +12 -0
  104. package/dist/components/FormContext.js.map +1 -0
  105. package/dist/components/Input.d.ts +3 -0
  106. package/dist/components/Input.d.ts.map +1 -1
  107. package/dist/components/Input.js +13 -2
  108. package/dist/components/Input.js.map +1 -1
  109. package/dist/components/Input.module.scss +27 -6
  110. package/dist/components/OgCard.d.ts.map +1 -1
  111. package/dist/components/OgCard.js +7 -4
  112. package/dist/components/OgCard.js.map +1 -1
  113. package/dist/components/{Particle.d.ts → ParticleFx.d.ts} +9 -4
  114. package/dist/components/ParticleFx.d.ts.map +1 -0
  115. package/dist/components/{Particle.js → ParticleFx.js} +9 -4
  116. package/dist/components/ParticleFx.js.map +1 -0
  117. package/dist/components/ScrollContainer.d.ts +69 -2
  118. package/dist/components/ScrollContainer.d.ts.map +1 -1
  119. package/dist/components/ScrollContainer.js +377 -46
  120. package/dist/components/ScrollContainer.js.map +1 -1
  121. package/dist/components/ScrollContainer.module.scss +131 -0
  122. package/dist/components/Select.d.ts +1 -1
  123. package/dist/components/Select.d.ts.map +1 -1
  124. package/dist/components/Select.js +1 -1
  125. package/dist/components/Select.js.map +1 -1
  126. package/dist/components/Setting.d.ts.map +1 -1
  127. package/dist/components/Setting.js +6 -1
  128. package/dist/components/Setting.js.map +1 -1
  129. package/dist/components/Table.js +2 -2
  130. package/dist/components/Table.js.map +1 -1
  131. package/dist/components/Textarea.d.ts +3 -0
  132. package/dist/components/Textarea.d.ts.map +1 -1
  133. package/dist/components/Textarea.js +22 -6
  134. package/dist/components/Textarea.js.map +1 -1
  135. package/dist/components/ThemeSwitcher.d.ts +16 -0
  136. package/dist/components/ThemeSwitcher.d.ts.map +1 -1
  137. package/dist/components/ThemeSwitcher.js +48 -9
  138. package/dist/components/ThemeSwitcher.js.map +1 -1
  139. package/dist/components/ThemeSwitcher.module.scss +112 -0
  140. package/dist/components/User.js +1 -1
  141. package/dist/components/User.js.map +1 -1
  142. package/dist/components/UserMenu.d.ts +1 -1
  143. package/dist/components/UserMenu.d.ts.map +1 -1
  144. package/dist/components/index.d.ts +2 -1
  145. package/dist/components/index.d.ts.map +1 -1
  146. package/dist/components/index.js +2 -1
  147. package/dist/components/index.js.map +1 -1
  148. package/dist/data/emoji-data.json +10 -0
  149. package/dist/hooks/useArrowNavigation.d.ts.map +1 -1
  150. package/dist/hooks/useArrowNavigation.js +52 -7
  151. package/dist/hooks/useArrowNavigation.js.map +1 -1
  152. package/dist/modules/navigation/MegaMenu.d.ts.map +1 -1
  153. package/dist/modules/navigation/MegaMenu.js +76 -10
  154. package/dist/modules/navigation/MegaMenu.js.map +1 -1
  155. package/dist/package.json +1 -1
  156. package/dist/scripts/validate-ai-code.js +239 -21
  157. package/dist/types.d.ts +14 -0
  158. package/dist/types.d.ts.map +1 -1
  159. package/package.json +1 -1
  160. package/scripts/validate-ai-code.js +239 -21
  161. package/dist/components/Particle.d.ts.map +0 -1
  162. package/dist/components/Particle.js.map +0 -1
package/AGENTS.md CHANGED
@@ -47,7 +47,7 @@ If you cannot read `node_modules`, use the docs host (may not match your install
47
47
 
48
48
  - Use `Column` / `Row`, not `Flex` unless direction changes at breakpoints
49
49
  - Use `fill`, not `fillWidth fillHeight`; use `center`, not `horizontal="center" vertical="center"`
50
- - Static panels: `Column background="surface" border="neutral-alpha-weak" radius="l" padding="24"`
50
+ - Static panels: `Column background="surface" border radius="l" padding="24"`
51
51
  - `Card` is interactive only (`href` or `onClick`)
52
52
 
53
53
  Full rules: `@once-ui-system/core/ai/rules.compact.md`
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2026 Dopler
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/ai/catalog.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "2.0.0-alpha.0",
3
- "generated": "2026-09-16",
2
+ "version": "2.0.0-alpha.2",
3
+ "generated": "2026-09-23",
4
4
  "components": {
5
5
  "Accordion": {
6
6
  "group": "components",
@@ -430,6 +430,13 @@
430
430
  "components"
431
431
  ]
432
432
  },
433
+ "Form": {
434
+ "group": "components",
435
+ "purpose": "Form component",
436
+ "tags": [
437
+ "components"
438
+ ]
439
+ },
433
440
  "GlitchFx": {
434
441
  "group": "components",
435
442
  "extends": [
@@ -683,12 +690,12 @@
683
690
  "components"
684
691
  ]
685
692
  },
686
- "Particle": {
693
+ "ParticleFx": {
687
694
  "group": "components",
688
695
  "extends": [
689
696
  "Flex"
690
697
  ],
691
- "purpose": "Particle component",
698
+ "purpose": "ParticleFx component",
692
699
  "tags": [
693
700
  "components"
694
701
  ]
@@ -20,7 +20,7 @@
20
20
  "blob": "Omit<React.ComponentProps<typeof BlobFx>, \"children\">",
21
21
  "matrix": "Omit<React.ComponentProps<typeof MatrixFx>, \"children\">",
22
22
  "weather": "Omit<React.ComponentProps<typeof WeatherFx>, \"children\">",
23
- "particle": "Omit<React.ComponentProps<typeof Particle>, \"children\">",
23
+ "particle": "Omit<React.ComponentProps<typeof ParticleFx>, \"children\">",
24
24
  "celebration": "Omit<React.ComponentProps<typeof CelebrationFx>, \"children\">",
25
25
  "children": "React.ReactNode"
26
26
  },
@@ -15,6 +15,7 @@
15
15
  "props": {
16
16
  "variant": "\"info\" | \"danger\" | \"warning\" | \"success\" = info",
17
17
  "showIcon": "boolean = true",
18
+ "icon": "IconName",
18
19
  "title": "string",
19
20
  "description": "string",
20
21
  "showCloseButton": "boolean = false",
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "Form",
3
+ "group": "components",
4
+ "props": {
5
+ "density": "\"stacked\" | \"tight\" | \"spacious\" = tight",
6
+ "columns": "FormColumns",
7
+ "size": "TShirtSizes",
8
+ "as": "\"div\" | \"form\" = div",
9
+ "onSubmit": "React.FormEventHandler<HTMLFormElement>",
10
+ "className": "string",
11
+ "style": "React.CSSProperties",
12
+ "children": "React.ReactNode"
13
+ },
14
+ "mixinsRef": []
15
+ }
@@ -5,7 +5,7 @@
5
5
  "id": "!string",
6
6
  "label": "string",
7
7
  "placeholder": "string",
8
- "size": "TShirtSizes = m",
8
+ "size": "TShirtSizes",
9
9
  "error": "boolean = false",
10
10
  "errorMessage": "ReactNode",
11
11
  "description": "ReactNode",
@@ -19,7 +19,8 @@
19
19
  "characterCount": "boolean",
20
20
  "cursor": "undefined | \"interactive\"",
21
21
  "validate": "(value: ReactNode) => ReactNode | null",
22
- "loading": "boolean = false"
22
+ "loading": "boolean = false",
23
+ "span": "number"
23
24
  },
24
25
  "mixinsRef": []
25
26
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "Particle",
2
+ "name": "ParticleFx",
3
3
  "group": "components",
4
4
  "extends": [
5
5
  "Flex"
@@ -15,7 +15,15 @@
15
15
  ],
16
16
  "props": {
17
17
  "items": "!React.ReactNode[]",
18
- "controlPlacement": "\"top-start\" | \"top-center\" | \"top-end\" | \"top-between\" | \"bottom-start\" | \"bottom-center\" | \"bottom-end\" | \"bottom-between\" = top-start"
18
+ "controlPlacement": "ScrollContainerControlPlacement = top-start",
19
+ "infinite": "boolean = false",
20
+ "markers": "boolean | \"top\" | \"bottom\" = false",
21
+ "draggable": "boolean = true",
22
+ "step": "number = 1",
23
+ "clip": "boolean = false",
24
+ "proximity": "boolean | number = false",
25
+ "active": "number",
26
+ "onActiveChange": "(index: number) => void"
19
27
  },
20
28
  "mixinsRef": [
21
29
  "CommonProps",
@@ -6,7 +6,7 @@
6
6
  "label": "string",
7
7
  "placeholder": "string",
8
8
  "lines": "number | \"auto\" = auto",
9
- "size": "TShirtSizes = m",
9
+ "size": "TShirtSizes",
10
10
  "error": "boolean = false",
11
11
  "errorMessage": "ReactNode",
12
12
  "description": "ReactNode",
@@ -19,7 +19,8 @@
19
19
  "characterCount": "boolean",
20
20
  "resize": "\"horizontal\" | \"vertical\" | \"both\" | \"none\" = vertical",
21
21
  "validate": "(value: ReactNode) => ReactNode | null",
22
- "disabled": "boolean = false"
22
+ "disabled": "boolean = false",
23
+ "span": "number"
23
24
  },
24
25
  "mixinsRef": []
25
26
  }
@@ -14,7 +14,8 @@
14
14
  "StyleProps"
15
15
  ],
16
16
  "props": {
17
- "collapsed": "boolean"
17
+ "collapsed": "boolean",
18
+ "direction": "\"row\" | \"column\" = row"
18
19
  },
19
20
  "mixinsRef": [
20
21
  "CommonProps",
package/ai/eval-tasks.md CHANGED
@@ -25,7 +25,8 @@ is found in the wild.
25
25
  Mechanical (count occurrences):
26
26
 
27
27
  - [ ] Compiles / no invented props or components
28
- - [ ] Redundant-default props (`position="relative"`, `variant="primary"` on Button, ...) — target: 0
28
+ - [ ] Redundant-default props (`position="relative"`, `variant="primary"` on Button, `fillWidth` beside `maxWidth`, `minWidth={0}` beside `fillWidth`, `border="neutral-alpha-weak"` for the default border, ...) — target: 0
29
+ - [ ] `zIndex` outside an isolated stacking group (nothing absolute/fixed/sticky nearby) — target: 0
29
30
  - [ ] Shorthand violations (`fillWidth fillHeight` instead of `fill`, `horizontal+vertical center` instead of `center`, `Flex direction=` instead of `Row`/`Column`) — target: 0
30
31
  - [ ] `style={{}}` uses where a token prop exists — target: 0
31
32
  - [ ] Raw HTML elements where a component exists (`img`, `a`, `button`) — target: 0
@@ -22,11 +22,10 @@ export function AuthExample() {
22
22
  return (
23
23
  <Column as="main" fillWidth center padding="24" minHeight="100vh">
24
24
  <Grid
25
- fillWidth
26
25
  maxWidth="l"
27
26
  columns="2"
28
27
  radius="xl"
29
- border="neutral-alpha-weak"
28
+ border
30
29
  overflow="hidden"
31
30
  background="surface"
32
31
  s={{ columns: 1 }}
@@ -37,7 +37,7 @@ const StatCard: React.FC<StatCardProps> = ({ title, value, change, positive = tr
37
37
  }, [positive]);
38
38
 
39
39
  return (
40
- <Card minWidth={12} href={href} paddingX="20" paddingTop="20" paddingBottom="80" radius="l" fillWidth direction="column" border="neutral-alpha-weak" background="transparent">
40
+ <Card minWidth={12} href={href} paddingX="20" paddingTop="20" paddingBottom="80" radius="l" fillWidth direction="column" border background="transparent">
41
41
  <LineChart
42
42
  pointerEvents="none"
43
43
  position="absolute"
@@ -82,7 +82,7 @@ interface ActivityItemProps {
82
82
  }
83
83
 
84
84
  const ActivityItem: React.FC<ActivityItemProps> = ({ avatar, action, time, href, icon }) => (
85
- <Row fillWidth borderBottom="neutral-alpha-weak">
85
+ <Row fillWidth borderBottom>
86
86
  <Card direction="column" fitHeight href={href} background="transparent" border="transparent" fillWidth>
87
87
  <Row fillWidth horizontal="between" paddingX="24" height="64" vertical="center">
88
88
  <Column fillWidth gap="8">
@@ -110,7 +110,7 @@ interface StatusItemProps {
110
110
  }
111
111
 
112
112
  const StatusItem: React.FC<StatusItemProps> = ({ name, status, icon, href = "#" }) => (
113
- <Row fillWidth borderBottom="neutral-alpha-weak">
113
+ <Row fillWidth borderBottom>
114
114
  <Card direction="column" background="transparent" href={href} border="transparent" fillWidth>
115
115
  <Row fillWidth horizontal="between" height="64" vertical="center" paddingX="24">
116
116
  <Row vertical="center" gap="12">
@@ -240,7 +240,7 @@ export const Dashboard1: React.FC = () => {
240
240
 
241
241
  <LineChart
242
242
  minHeight={20}
243
- border="neutral-alpha-weak"
243
+ border
244
244
  axis="x"
245
245
  grid="y"
246
246
  title="Revenue growth"
@@ -277,7 +277,7 @@ export const Dashboard1: React.FC = () => {
277
277
  />
278
278
 
279
279
  <Grid columns="2" m={{columns: 1}} gap="m" fillWidth>
280
- <Column fillWidth border="neutral-alpha-weak" radius="l" overflow="hidden" height={20}>
280
+ <Column fillWidth border radius="l" overflow="hidden" height={20}>
281
281
  <Row vertical="center" horizontal="between" fillWidth paddingLeft="24" paddingRight="12" paddingY="12" gap="m" wrap>
282
282
  <Heading wrap="nowrap" variant="heading-strong-s">
283
283
  Project status
@@ -295,7 +295,7 @@ export const Dashboard1: React.FC = () => {
295
295
  </Row>
296
296
  </Row>
297
297
 
298
- <Column fillWidth border="neutral-alpha-weak" topRadius="l" overflowY="auto">
298
+ <Column fillWidth border topRadius="l" overflowY="auto">
299
299
  {[
300
300
  { name: "Mobile App Development", status: "At Risk", icon: "code" as IconName },
301
301
  { name: "Marketing Campaign", status: "On Track", icon: "sparkle" as IconName },
@@ -314,7 +314,7 @@ export const Dashboard1: React.FC = () => {
314
314
  </Column>
315
315
  </Column>
316
316
 
317
- <Column border="neutral-alpha-weak" radius="l" fillWidth overflow="hidden" height={20}>
317
+ <Column border radius="l" fillWidth overflow="hidden" height={20}>
318
318
  <Row fillWidth vertical="center" horizontal="between" paddingLeft="24" paddingRight="12" paddingY="12" gap="16" wrap>
319
319
  <Heading wrap="nowrap" variant="heading-strong-s">
320
320
  Recent activity
@@ -323,7 +323,7 @@ export const Dashboard1: React.FC = () => {
323
323
  View all
324
324
  </Button>
325
325
  </Row>
326
- <Column fillWidth border="neutral-alpha-weak" topRadius="l" overflowY="auto">
326
+ <Column fillWidth border topRadius="l" overflowY="auto">
327
327
  {[
328
328
  {
329
329
  avatar: "/images/creators/lorant.jpg",
@@ -34,7 +34,7 @@ export const Feed3: React.FC<React.ComponentProps<typeof Column>> = ({ ...flex }
34
34
 
35
35
  return (
36
36
  <Column fill {...flex}>
37
- <Row fillWidth paddingX="24" paddingY="8" background="surface" borderBottom="neutral-alpha-weak" vertical="center" gap="12">
37
+ <Row fillWidth paddingX="24" paddingY="8" background="surface" borderBottom vertical="center" gap="12">
38
38
  <Text variant="label-default-s">👋 | intro</Text>
39
39
  <Row minWidth="4" minHeight="4" background="neutral-strong" radius="full"/>
40
40
  <Text variant="body-default-xs" onBackground="neutral-weak">Let us know a bit about you!</Text>
@@ -65,7 +65,7 @@ export const Feed3: React.FC<React.ComponentProps<typeof Column>> = ({ ...flex }
65
65
  key={aIdx}
66
66
  maxWidth={20}
67
67
  src={att.media}
68
- border="neutral-alpha-weak"
68
+ border
69
69
  radius="l"
70
70
  sizes="320px"
71
71
  />
@@ -75,9 +75,9 @@ export const Feed3: React.FC<React.ComponentProps<typeof Column>> = ({ ...flex }
75
75
  ) : (
76
76
  messages.attachments[0]?.media && (
77
77
  messages.attachments[0].media.includes("youtube.com") || messages.attachments[0].media.includes("youtu.be") ? (
78
- <Media maxWidth={32} border="neutral-alpha-weak" aspectRatio="16/9" marginTop="16" src={messages.attachments[0].media} radius="l" sizes="320px"/>
78
+ <Media maxWidth={32} border aspectRatio="16/9" marginTop="16" src={messages.attachments[0].media} radius="l" sizes="320px"/>
79
79
  ) : (messages.attachments[0].media.match(/\.(png|jpg|jpeg|gif|webp)$/i)) ? (
80
- <Media maxWidth={32} border="neutral-alpha-weak" marginTop="16" src={messages.attachments[0].media} radius="l" sizes="320px"/>
80
+ <Media maxWidth={32} border marginTop="16" src={messages.attachments[0].media} radius="l" sizes="320px"/>
81
81
  ) : (
82
82
  <Row maxWidth={24} marginTop="16">
83
83
  <OgCard url={messages.attachments[0].media} description={false} />
@@ -1,4 +1,4 @@
1
- import { Avatar, Background, Button, Column, IconButton, Logo, Mask, Particle, Row, SmartLink, Tag, Text, TypeFx } from "@once-ui-system/core";
1
+ import { Avatar, Background, Button, Column, IconButton, Logo, Mask, ParticleFx, Row, SmartLink, Tag, Text, TypeFx } from "@once-ui-system/core";
2
2
  import type { IconName } from "@once-ui-system/core";
3
3
 
4
4
  const social: { icon: IconName; label: string; href: string }[] = [
@@ -147,7 +147,7 @@ export const Footer4 = (flex: React.ComponentProps<typeof Column>) => {
147
147
  y={50}
148
148
  radius={25}
149
149
  >
150
- <Particle style={{transform: "scale(1.1)"}} opacity={70} position="absolute" top="0" left="0" fill interactive speed={1.5} density={100} size="2" intensity={20} mode="attract"/>
150
+ <ParticleFx style={{transform: "scale(1.1)"}} opacity={70} position="absolute" top="0" left="0" fill interactive speed={1.5} density={100} size="2" intensity={20} mode="attract"/>
151
151
  </Mask>
152
152
  </Row>
153
153
  <Column horizontal="center" gap="20">
@@ -29,7 +29,7 @@ export const Header2: React.FC<HeaderProps> = ({ authenticated, avatar, ...flex
29
29
  />
30
30
  <Row
31
31
  as="header"
32
- border="neutral-alpha-weak"
32
+ border
33
33
  maxWidth="m"
34
34
  paddingX="m"
35
35
  radius="l"
@@ -39,8 +39,7 @@ export const Header4: React.FC<HeaderProps> = ({ cartCount = 0, ...flex }) => {
39
39
  <Row
40
40
  data-scaling="90"
41
41
  position="absolute"
42
- vertical="center"
43
- horizontal="center"
42
+ center
44
43
  textVariant="body-default-xs"
45
44
  solid="brand-strong"
46
45
  onSolid="brand-strong"
@@ -237,7 +237,7 @@ export const Productivity1 = () => {
237
237
  <Column
238
238
  key={index}
239
239
  minWidth={20}
240
- border="neutral-alpha-weak"
240
+ border
241
241
  fillWidth
242
242
  paddingX="4"
243
243
  radius="m-4"
@@ -79,7 +79,7 @@ export function Roadmap1() {
79
79
 
80
80
  <Row gap="4" fillWidth overflowX="auto" paddingBottom="16">
81
81
  {product.columns.map((column, columnIndex) => (
82
- <Column key={columnIndex} padding="4" gap="4" radius="s-4" border="neutral-alpha-weak" background="overlay" fillWidth minWidth={20}>
82
+ <Column key={columnIndex} padding="4" gap="4" radius="s-4" border background="overlay" fillWidth minWidth={20}>
83
83
  <Row fillWidth vertical="center" gap="8" paddingY="8" paddingX="16">
84
84
  <Text variant="label-default-m">
85
85
  {column.title}
@@ -99,7 +99,7 @@ export function Roadmap1() {
99
99
  return typedTask.href ? (
100
100
  <Card
101
101
  onBackground="neutral-strong"
102
- border="neutral-alpha-weak"
102
+ border
103
103
  fillWidth
104
104
  radius="s"
105
105
  key={taskIndex}
@@ -111,7 +111,7 @@ export function Roadmap1() {
111
111
  ) : (
112
112
  <Column
113
113
  onBackground="neutral-strong"
114
- border="neutral-alpha-weak"
114
+ border
115
115
  fillWidth
116
116
  radius="s"
117
117
  key={taskIndex}
@@ -16,7 +16,7 @@ export const Sidebar1: React.FC<React.ComponentProps<typeof Column>> = ({ ...fle
16
16
  fillHeight
17
17
  maxWidth={18}
18
18
  background="surface"
19
- borderRight="neutral-alpha-weak"
19
+ borderRight
20
20
  padding="8"
21
21
  gap="4"
22
22
  {...flex}
@@ -4,7 +4,7 @@ import { Column, Text, ToggleButton } from "@once-ui-system/core";
4
4
 
5
5
  /** Productivity sidebar — minimal stub for Productivity1 reference */
6
6
  export const Sidebar2: React.FC<React.ComponentProps<typeof Column>> = ({ ...flex }) => (
7
- <Column fillHeight maxWidth={18} background="surface" borderRight="neutral-alpha-weak" padding="8" gap="4" {...flex}>
7
+ <Column fillHeight maxWidth={18} background="surface" borderRight padding="8" gap="4" {...flex}>
8
8
  <Text variant="label-default-s" onBackground="neutral-weak" padding="12">
9
9
  Workspace
10
10
  </Text>
@@ -94,7 +94,7 @@ export const Table1: React.FC<Table1Props> = ({
94
94
  };
95
95
 
96
96
  return (
97
- <Column fillWidth radius="l" border="neutral-alpha-weak" {...flex}>
97
+ <Column fillWidth radius="l" border {...flex}>
98
98
  <Row fillWidth horizontal="between" paddingY="12" paddingRight="12" paddingLeft="24" gap="16" vertical="center" s={{direction: "column",}}>
99
99
  <Row fillWidth gap="12" vertical="center" horizontal="between">
100
100
  {selectable && someCurrentSelected ? (
@@ -124,8 +124,8 @@ export const Table1: React.FC<Table1Props> = ({
124
124
  )}
125
125
  </Row>
126
126
  <Column fillWidth overflowX="auto">
127
- <Column fillWidth radius="l" border="neutral-alpha-weak" overflow="hidden">
128
- <Row fillWidth gap="16" paddingX="24" paddingY="12" borderBottom="neutral-alpha-weak">
127
+ <Column fillWidth radius="l" border overflow="hidden">
128
+ <Row fillWidth gap="16" paddingX="24" paddingY="12" borderBottom>
129
129
  {selectable && (
130
130
  <Row textVariant="label-default-s" vertical="center" gap="16">
131
131
  <Checkbox
@@ -69,9 +69,9 @@
69
69
  {
70
70
  "id": "Footer4",
71
71
  "file": "Footer4.tsx",
72
- "title": "Premium footer with TypeFx + Particle",
72
+ "title": "Premium footer with TypeFx + ParticleFx",
73
73
  "tags": ["footer", "marketing", "effect"],
74
- "components": ["Background", "Particle", "TypeFx", "Mask", "Avatar", "Tag"],
74
+ "components": ["Background", "ParticleFx", "TypeFx", "Mask", "Avatar", "Tag"],
75
75
  "patterns": ["animated wordmark", "particle decoration", "masked gradient"],
76
76
  "tasks": ["marketing-hero"],
77
77
  "standalone": true
@@ -55,7 +55,7 @@ export function DashboardExample() {
55
55
 
56
56
  return (
57
57
  <Column as="main" fillWidth horizontal="center" paddingY="48" paddingX="24" gap="40">
58
- <Column fillWidth maxWidth="l" gap="40">
58
+ <Column maxWidth="l" gap="40">
59
59
  <Row fillWidth horizontal="between" vertical="end" gap="24" s={{ direction: "column", horizontal: "start" }}>
60
60
  <Column gap="8">
61
61
  <Text variant="label-default-s" onBackground="brand-medium">
@@ -79,7 +79,7 @@ export function DashboardExample() {
79
79
  <Grid ref={statsRef} columns="4" gap="16" m={{ columns: 2 }} s={{ columns: 1 }}>
80
80
  {stats.map((stat, index) => (
81
81
  <RevealFx key={stat.label} fill revealed={seen} translateY="8" delay={index * 100}>
82
- <Column background="surface" border="neutral-alpha-weak" radius="l" padding="24" gap="16">
82
+ <Column background="surface" border radius="l" padding="24" gap="16">
83
83
  <Row fillWidth horizontal="between" vertical="center">
84
84
  <Text variant="label-default-s" onBackground="neutral-weak">
85
85
  {stat.label}
@@ -109,7 +109,7 @@ export function DashboardExample() {
109
109
  </Grid>
110
110
 
111
111
  <Grid columns="2" gap="24" s={{ columns: 1 }}>
112
- <Column background="surface" border="neutral-alpha-weak" radius="l" padding="24" gap="16" minHeight={32}>
112
+ <Column background="surface" border radius="l" padding="24" gap="16" minHeight={32}>
113
113
  <Heading as="h2" variant="heading-strong-s">
114
114
  Revenue trend
115
115
  </Heading>
@@ -120,7 +120,7 @@ export function DashboardExample() {
120
120
  </Text>
121
121
  </Column>
122
122
  </Column>
123
- <Column background="surface" border="neutral-alpha-weak" radius="l" padding="24" gap="16" minHeight={32}>
123
+ <Column background="surface" border radius="l" padding="24" gap="16" minHeight={32}>
124
124
  <Heading as="h2" variant="heading-strong-s">
125
125
  Signups by channel
126
126
  </Heading>
@@ -133,7 +133,7 @@ export function DashboardExample() {
133
133
  </Column>
134
134
  </Grid>
135
135
 
136
- <Column background="surface" border="neutral-alpha-weak" radius="l" padding="24" gap="24">
136
+ <Column background="surface" border radius="l" padding="24" gap="24">
137
137
  <Row fillWidth horizontal="between" vertical="center">
138
138
  <Heading as="h2" variant="heading-strong-s">
139
139
  Recent activity
@@ -103,7 +103,7 @@ export function MarketingHeroExample() {
103
103
 
104
104
  {/* Feature grid — left-aligned section header, not repeated centered blocks */}
105
105
  <Column fillWidth horizontal="center">
106
- <Column fillWidth maxWidth="l" gap="40">
106
+ <Column maxWidth="l" gap="40">
107
107
  <Column gap="12" maxWidth={32}>
108
108
  <Text variant="label-default-s" onBackground="brand-medium">
109
109
  Components
@@ -117,7 +117,7 @@ export function MarketingHeroExample() {
117
117
  <Column
118
118
  key={feature.title}
119
119
  background="surface"
120
- border="neutral-alpha-weak"
120
+ border
121
121
  radius="l"
122
122
  padding="24"
123
123
  gap="16"
@@ -95,7 +95,7 @@ export function PricingExample() {
95
95
  </Column>
96
96
 
97
97
  <Column fillWidth horizontal="center">
98
- <Column fillWidth maxWidth="l" gap="40">
98
+ <Column maxWidth="l" gap="40">
99
99
  <Row fillWidth horizontal="between" vertical="end" gap="24" s={{ direction: "column", horizontal: "start" }}>
100
100
  <Heading as="h2" variant="display-strong-xs">
101
101
  Three plans, one decision
@@ -181,7 +181,7 @@ export function PricingExample() {
181
181
  </Column>
182
182
 
183
183
  <Column fillWidth horizontal="center" background="neutral-alpha-weak" paddingY="80" paddingX="24">
184
- <Column fillWidth maxWidth="l" gap="40">
184
+ <Column maxWidth="l" gap="40">
185
185
  <Heading as="h2" variant="display-strong-xs">
186
186
  Every feature, side by side
187
187
  </Heading>
@@ -203,7 +203,7 @@ export function PricingExample() {
203
203
  </Column>
204
204
 
205
205
  <Column fillWidth horizontal="center">
206
- <Column fillWidth maxWidth="l" radius="xl" border="neutral-alpha-weak" overflow="hidden" padding="64" center>
206
+ <Column maxWidth="l" radius="xl" border overflow="hidden" padding="64" center>
207
207
  <BlobFx position="absolute" top="0" left="0" fill opacity={60} seed={2} />
208
208
  <Column zIndex={1} center gap="24" maxWidth={40}>
209
209
  <Heading as="h2" variant="display-strong-s" align="center">
@@ -29,7 +29,7 @@ const sections = [
29
29
  export function SettingsExample() {
30
30
  return (
31
31
  <Column as="main" fillWidth horizontal="center" paddingY="48" paddingX="24">
32
- <Column fillWidth maxWidth="l" gap="40">
32
+ <Column maxWidth="l" gap="40">
33
33
  <Column gap="12">
34
34
  <Text variant="label-default-s" onBackground="brand-medium">
35
35
  Settings
@@ -46,7 +46,7 @@ export function SettingsExample() {
46
46
  gap="4"
47
47
  padding="16"
48
48
  background="surface"
49
- border="neutral-alpha-weak"
49
+ border
50
50
  radius="l"
51
51
  s={{ hide: true }}
52
52
  >
@@ -66,7 +66,7 @@ export function SettingsExample() {
66
66
  }
67
67
  rightPanel={
68
68
  <Column flex={1} gap="24">
69
- <Column background="surface" border="neutral-alpha-weak" radius="l" padding="24" gap="24">
69
+ <Column background="surface" border radius="l" padding="24" gap="24">
70
70
  <Heading as="h2" variant="heading-strong-m">
71
71
  Profile
72
72
  </Heading>
@@ -97,7 +97,7 @@ export function SettingsExample() {
97
97
  </Row>
98
98
  </Column>
99
99
 
100
- <Column background="surface" border="neutral-alpha-weak" radius="l" padding="24" gap="24">
100
+ <Column background="surface" border radius="l" padding="24" gap="24">
101
101
  <Heading as="h2" variant="heading-strong-m">
102
102
  Notifications
103
103
  </Heading>
package/ai/gotchas.json CHANGED
@@ -20,7 +20,7 @@
20
20
  ]
21
21
  },
22
22
  "Card.interactive": {
23
- "rule": "Card is for interactive surfaces only (href or onClick). Static panels use Column + background=\"surface\" border=\"neutral-alpha-weak\" radius=\"l\".",
23
+ "rule": "Card is for interactive surfaces only (href or onClick). Static panels use Column + background=\"surface\" border radius=\"l\".",
24
24
  "components": [
25
25
  "Card"
26
26
  ]
@@ -76,6 +76,13 @@
76
76
  "Tag"
77
77
  ]
78
78
  },
79
+ "Timeline.notScrubber": {
80
+ "rule": "Timeline lays a sequence of steps down the page. For a video or audio editor's timeline — a playhead over stacked tracks of movable, trimmable blocks — use Scrubber. Do not build one out of Flex and absolute positioning.",
81
+ "components": [
82
+ "Timeline",
83
+ "Scrubber"
84
+ ]
85
+ },
79
86
  "color.tokens": {
80
87
  "rule": "Colors are semantic tokens ({scheme}-{weight}), never hex/rgb. background also accepts surface | overlay | page | transparent.",
81
88
  "components": [
@@ -101,13 +108,30 @@
101
108
  ]
102
109
  },
103
110
  "layout.defaults": {
104
- "rule": "Never write props equal to defaults: position=\"relative\", direction on Row/Column, variant=\"primary\" on Button.",
111
+ "rule": "Never write props equal to defaults or implied by another prop on the element: position=\"relative\", direction on Row/Column, variant=\"primary\" on Button, fillWidth beside maxWidth (maxWidth already fills the width), minWidth={0} beside fillWidth (fillWidth already sets min-width: 0).",
105
112
  "components": [
106
113
  "Row",
107
114
  "Column",
115
+ "Grid",
108
116
  "Button"
109
117
  ]
110
118
  },
119
+ "border.default": {
120
+ "rule": "Bare border (and borderTop, borderBottom, borderX, …) draws the default border. Do not write border=\"neutral-alpha-weak\" to get it; name a colour only to deviate, e.g. border=\"brand-alpha-medium\".",
121
+ "components": [
122
+ "Row",
123
+ "Column",
124
+ "Card"
125
+ ]
126
+ },
127
+ "zIndex.scope": {
128
+ "rule": "zIndex is for an isolated stacking group: an absolute decorative layer and its content sibling (zIndex={1}), or a sticky header over its pane. Never on a lone element, never a page-wide ladder of 3 / 5 / 9 — restructure the tree instead.",
129
+ "components": [
130
+ "Row",
131
+ "Column",
132
+ "Background"
133
+ ]
134
+ },
111
135
  "section.gaps": {
112
136
  "rule": "Gap between page sections: 80–160 (typical 104). Inside sections: 24–40.",
113
137
  "components": [
package/ai/manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "2.0.0-alpha.0",
3
- "generated": "2026-09-16",
2
+ "version": "2.0.0-alpha.2",
3
+ "generated": "2026-09-23",
4
4
  "files": {
5
5
  "spec": "spec.json",
6
6
  "catalog": "catalog.json",