@once-ui-system/core 2.0.0-alpha.0 → 2.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/LICENSE.md +21 -0
- package/ai/catalog.json +2 -2
- package/ai/eval-tasks.md +2 -1
- package/ai/examples/auth.tsx +1 -2
- package/ai/examples/blocks/Dashboard1.tsx +8 -8
- package/ai/examples/blocks/Feed3.tsx +4 -4
- package/ai/examples/blocks/Header2.tsx +1 -1
- package/ai/examples/blocks/Header4.tsx +1 -2
- package/ai/examples/blocks/Productivity1.tsx +1 -1
- package/ai/examples/blocks/Roadmap1.tsx +3 -3
- package/ai/examples/blocks/Sidebar1.tsx +1 -1
- package/ai/examples/blocks/Sidebar2.tsx +1 -1
- package/ai/examples/blocks/Table1.tsx +3 -3
- package/ai/examples/dashboard.tsx +5 -5
- package/ai/examples/marketing-hero.tsx +2 -2
- package/ai/examples/pricing.tsx +3 -3
- package/ai/examples/settings.tsx +4 -4
- package/ai/gotchas.json +19 -2
- package/ai/manifest.json +2 -2
- package/ai/recipes.md +1 -1
- package/ai/rules.compact.md +8 -2
- package/ai/rules.md +17 -5
- package/ai/spec.json +2 -2
- package/ai/tasks/settings.json +1 -1
- package/dist/AGENTS.md +1 -1
- package/dist/ai/catalog.json +2 -2
- package/dist/ai/eval-tasks.md +2 -1
- package/dist/ai/gotchas.json +19 -2
- package/dist/ai/manifest.json +2 -2
- package/dist/ai/recipes.md +1 -1
- package/dist/ai/rules.compact.md +8 -2
- package/dist/ai/rules.md +17 -5
- package/dist/ai/spec.json +2 -2
- package/dist/ai/tasks/settings.json +1 -1
- package/dist/components/Avatar.d.ts.map +1 -1
- package/dist/components/Avatar.js +1 -1
- package/dist/components/Avatar.js.map +1 -1
- package/dist/components/Carousel.js +1 -1
- package/dist/components/Carousel.js.map +1 -1
- package/dist/components/CountFx.d.ts.map +1 -1
- package/dist/components/CountFx.js +19 -7
- package/dist/components/CountFx.js.map +1 -1
- package/dist/components/DatePicker.js +2 -2
- package/dist/components/DatePicker.js.map +1 -1
- package/dist/components/EmojiPicker.js +1 -1
- package/dist/components/EmojiPicker.js.map +1 -1
- package/dist/components/OgCard.d.ts.map +1 -1
- package/dist/components/OgCard.js +7 -4
- package/dist/components/OgCard.js.map +1 -1
- package/dist/components/Select.js +1 -1
- package/dist/components/Select.js.map +1 -1
- package/dist/components/Table.js +2 -2
- package/dist/components/Table.js.map +1 -1
- package/dist/components/User.js +1 -1
- package/dist/components/User.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/scripts/validate-ai-code.js +239 -21
- package/package.json +1 -1
- package/scripts/validate-ai-code.js +239 -21
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
|
|
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
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
|
package/ai/examples/auth.tsx
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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} />
|
|
@@ -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
|
-
|
|
43
|
-
horizontal="center"
|
|
42
|
+
center
|
|
44
43
|
textVariant="body-default-xs"
|
|
45
44
|
solid="brand-strong"
|
|
46
45
|
onSolid="brand-strong"
|
|
@@ -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
|
|
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
|
|
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
|
|
114
|
+
border
|
|
115
115
|
fillWidth
|
|
116
116
|
radius="s"
|
|
117
117
|
key={taskIndex}
|
|
@@ -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
|
|
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
|
|
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
|
|
128
|
-
<Row fillWidth gap="16" paddingX="24" paddingY="12" borderBottom
|
|
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
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
120
|
+
border
|
|
121
121
|
radius="l"
|
|
122
122
|
padding="24"
|
|
123
123
|
gap="16"
|
package/ai/examples/pricing.tsx
CHANGED
|
@@ -95,7 +95,7 @@ export function PricingExample() {
|
|
|
95
95
|
</Column>
|
|
96
96
|
|
|
97
97
|
<Column fillWidth horizontal="center">
|
|
98
|
-
<Column
|
|
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
|
|
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
|
|
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">
|
package/ai/examples/settings.tsx
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
]
|
|
@@ -101,13 +101,30 @@
|
|
|
101
101
|
]
|
|
102
102
|
},
|
|
103
103
|
"layout.defaults": {
|
|
104
|
-
"rule": "Never write props equal to defaults: position=\"relative\", direction on Row/Column, variant=\"primary\" on Button.",
|
|
104
|
+
"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
105
|
"components": [
|
|
106
106
|
"Row",
|
|
107
107
|
"Column",
|
|
108
|
+
"Grid",
|
|
108
109
|
"Button"
|
|
109
110
|
]
|
|
110
111
|
},
|
|
112
|
+
"border.default": {
|
|
113
|
+
"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\".",
|
|
114
|
+
"components": [
|
|
115
|
+
"Row",
|
|
116
|
+
"Column",
|
|
117
|
+
"Card"
|
|
118
|
+
]
|
|
119
|
+
},
|
|
120
|
+
"zIndex.scope": {
|
|
121
|
+
"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.",
|
|
122
|
+
"components": [
|
|
123
|
+
"Row",
|
|
124
|
+
"Column",
|
|
125
|
+
"Background"
|
|
126
|
+
]
|
|
127
|
+
},
|
|
111
128
|
"section.gaps": {
|
|
112
129
|
"rule": "Gap between page sections: 80–160 (typical 104). Inside sections: 24–40.",
|
|
113
130
|
"components": [
|
package/ai/manifest.json
CHANGED
package/ai/recipes.md
CHANGED
|
@@ -87,7 +87,7 @@ For the emphasized item in a set (e.g. "most popular" pricing tier). Border + to
|
|
|
87
87
|
Self-contained drifting brand/accent blobs (already blurred and pointer-transparent). Use behind a final CTA or feature visual — counts as continuous motion:
|
|
88
88
|
|
|
89
89
|
```tsx
|
|
90
|
-
<Card fillWidth radius="l" border
|
|
90
|
+
<Card fillWidth radius="l" border overflow="hidden" padding="48">
|
|
91
91
|
<BlobFx position="absolute" top="0" left="0" fill opacity={60} seed={2} />
|
|
92
92
|
<Column zIndex={1} center gap="24">
|
|
93
93
|
{/* CTA content */}
|
package/ai/rules.compact.md
CHANGED
|
@@ -11,6 +11,9 @@ Load with task bundle from `@once-ui-system/core/ai/tasks/{intent}.json`. For an
|
|
|
11
11
|
| `fill` | `fillWidth fillHeight` |
|
|
12
12
|
| `fit` | `fitWidth fitHeight` |
|
|
13
13
|
| `center` | `horizontal="center" vertical="center"` |
|
|
14
|
+
| `maxWidth="l"` | `fillWidth maxWidth="l"` |
|
|
15
|
+
| `fillWidth` | `fillWidth minWidth={0}` |
|
|
16
|
+
| `border` | `border="neutral-alpha-weak"` |
|
|
14
17
|
|
|
15
18
|
- `Flex` only when direction changes at breakpoints: `<Row s={{ direction: "column" }}>`
|
|
16
19
|
- Page skeleton: `Column as="main" fillWidth horizontal="center"` → content `Column maxWidth="l"` → sections
|
|
@@ -22,9 +25,10 @@ Load with task bundle from `@once-ui-system/core/ai/tasks/{intent}.json`. For an
|
|
|
22
25
|
Static panel recipe (pricing tiers, stats, settings sections):
|
|
23
26
|
|
|
24
27
|
```tsx
|
|
25
|
-
<Column background="surface" border
|
|
28
|
+
<Column background="surface" border radius="l" padding="24" gap="16">
|
|
26
29
|
```
|
|
27
30
|
|
|
31
|
+
- Bare `border` (and `borderTop`, `borderBottom`, …) = the default border. Name a colour only to deviate: `border="brand-alpha-medium"`.
|
|
28
32
|
- `Card` = interactive only (`href` or `onClick`). Static panels = Column + surface recipe.
|
|
29
33
|
- Colors: `{scheme}-{weight}` or `{scheme}-alpha-{weight}`. Never hex/rgb.
|
|
30
34
|
- `background` also: `surface | overlay | page | transparent`
|
|
@@ -40,6 +44,8 @@ Static panel recipe (pricing tiers, stats, settings sections):
|
|
|
40
44
|
|
|
41
45
|
Absolute layers always: `position="absolute" top="0" left="0" fill pointerEvents="none"`, content `zIndex={1}`.
|
|
42
46
|
|
|
47
|
+
- `zIndex` only inside that layer group (or on a sticky header over its pane). Never on a lone element, never a page-wide ladder.
|
|
48
|
+
|
|
43
49
|
- Gradient `width`: quarter-percent (400 = 100%). Glows: 100–200.
|
|
44
50
|
- Glow colors: `brand-alpha-medium`, not `brand-background-weak`
|
|
45
51
|
- Ambient layers on full-bleed section wrapper, outside `maxWidth` column
|
|
@@ -81,7 +87,7 @@ from `spec.json`.
|
|
|
81
87
|
|
|
82
88
|
## Defaults — omit these
|
|
83
89
|
|
|
84
|
-
`position="relative"`, `direction` on Row/Column, `variant="primary"` on Button, `size="m"` when default.
|
|
90
|
+
`position="relative"`, `direction` on Row/Column, `variant="primary"` on Button, `size="m"` when default, `fillWidth` beside `maxWidth`, `minWidth={0}` beside `fillWidth`, a border colour that restates the default.
|
|
85
91
|
|
|
86
92
|
## Before building
|
|
87
93
|
|
package/ai/rules.md
CHANGED
|
@@ -40,10 +40,22 @@ If you can't ask (or the user says "you decide"), default to: restrained, center
|
|
|
40
40
|
<Row fillWidth fillHeight horizontal="center" vertical="center">...</Row>
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
3. Never write a prop that equals its default. The spec marks defaults with `= value`. Common offenders:
|
|
43
|
+
3. Never write a prop that equals its default, or one that another prop on the same element already implies. The spec marks defaults with `= value`. Common offenders:
|
|
44
44
|
- `position="relative"` (default on all layout components)
|
|
45
45
|
- `direction="row"` on `Row`, `direction="column"` on `Column`
|
|
46
46
|
- `variant="primary"`, `size="m"` on `Button`
|
|
47
|
+
- `fillWidth` beside `maxWidth` — `maxWidth` already fills the width up to the cap
|
|
48
|
+
- `minWidth={0}` beside `fillWidth` — `fillWidth` already sets `min-width: 0`
|
|
49
|
+
- a colour on `border` (or `borderTop`, `borderBottom`, `borderX`, …) that only restates the default — bare `border` draws the default border; name a colour only to deviate from it
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
// Good
|
|
53
|
+
<Column maxWidth="l" border radius="l">
|
|
54
|
+
// Bad
|
|
55
|
+
<Column fillWidth maxWidth="l" minWidth={0} position="relative" border="neutral-alpha-weak" radius="l">
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
3b. `zIndex` belongs to a stacking group, not to a page. Use it only inside an isolated group that needs an order — a decorative absolute layer and the content sibling above it (rule 21), a sticky header over the pane it covers — and keep the values small within that group. A `zIndex` on a lone element, or a page-wide ladder of `zIndex={3}`, `{5}`, `{9}`, means the hierarchy is being managed by hand; restructure the tree instead.
|
|
47
59
|
|
|
48
60
|
## Spacing and sizing
|
|
49
61
|
|
|
@@ -66,10 +78,10 @@ If you can't ask (or the user says "you decide"), default to: restrained, center
|
|
|
66
78
|
- `background` also accepts `surface | overlay | page | transparent`
|
|
67
79
|
- `onBackground` colors text/icons on a background
|
|
68
80
|
|
|
69
|
-
8. Standard surface recipe: `background="surface"` (or `"overlay"` over imagery) + `border="neutral-alpha-
|
|
81
|
+
8. Standard surface recipe: `background="surface"` (or `"overlay"` over imagery) + `border` + `radius="l"`. Bare `border` is the default border; name a colour (`border="neutral-alpha-medium"`, `border="brand-alpha-medium"`) only when the surface should differ from it.
|
|
70
82
|
|
|
71
83
|
```tsx
|
|
72
|
-
<Column background="surface" border
|
|
84
|
+
<Column background="surface" border radius="l" padding="24" gap="16">
|
|
73
85
|
```
|
|
74
86
|
|
|
75
87
|
## Text
|
|
@@ -183,7 +195,7 @@ the card it was meant to support.
|
|
|
183
195
|
<Grid columns={5} s={{ columns: 3 }} gap="8" fillWidth>
|
|
184
196
|
{items.map(i => (
|
|
185
197
|
<Column key={i} aspectRatio="1 / 1" padding="12" radius="l"
|
|
186
|
-
background="page" border
|
|
198
|
+
background="page" border vertical="between">
|
|
187
199
|
{/* a preview of the thing, not just its name */}
|
|
188
200
|
</Column>
|
|
189
201
|
))}
|
|
@@ -204,7 +216,7 @@ in that order.
|
|
|
204
216
|
<Background position="absolute" top="0" left="0" fill pointerEvents="none" ... />
|
|
205
217
|
```
|
|
206
218
|
|
|
207
|
-
Siblings holding content get `zIndex={1}`. `overflow="hidden"` goes on the parent **only when it has a radius** (cards, panels) — clipping a full-bleed section turns the glow into a hard-edged band.
|
|
219
|
+
Siblings holding content get `zIndex={1}`. That layer and its content sibling are the whole stacking group — nothing else in the section needs a `zIndex` (rule 3b). `overflow="hidden"` goes on the parent **only when it has a radius** (cards, panels) — clipping a full-bleed section turns the glow into a hard-edged band.
|
|
208
220
|
|
|
209
221
|
21b. Ambient section layers (hero glows) live on the **full-width section wrapper**, outside the `maxWidth` content column, with generous room (`paddingY="80"`+). Inside a narrow container the gradient gets clipped at the container edge and reads as a misplaced card:
|
|
210
222
|
|
package/ai/spec.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@once-ui-system/core",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
4
|
-
"generated": "2026-09-
|
|
3
|
+
"version": "2.0.0-alpha.1",
|
|
4
|
+
"generated": "2026-09-17",
|
|
5
5
|
"format": "props are 'type', 'type = default', or '!type' (required). Components with 'mixins' also accept all props of those mixins. 'extends' means all props of that component are accepted. In 'types', an array lists a union's allowed values, an object gives a shape's fields in the same notation as props, and a string is the type as written — usually pointing at a component whose props are already listed.",
|
|
6
6
|
"tokens": {
|
|
7
7
|
"StaticSpacingToken": "\"0\" | \"1\" | \"2\" | \"4\" | \"8\" | \"12\" | \"16\" | \"20\" | \"24\" | \"32\" | \"40\" | \"48\" | \"56\" | \"64\" | \"72\" | \"80\" | \"104\" | \"128\" | \"160\"",
|
package/ai/tasks/settings.json
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"layout.defaults"
|
|
29
29
|
],
|
|
30
30
|
"quality": {
|
|
31
|
-
"surfaceRecipe": "background=\"surface\" border
|
|
31
|
+
"surfaceRecipe": "background=\"surface\" border radius=\"l\" padding=\"24\"",
|
|
32
32
|
"dangerZone": "border=\"danger-alpha-medium\" on danger actions only"
|
|
33
33
|
}
|
|
34
34
|
}
|
package/dist/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
|
|
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/dist/ai/catalog.json
CHANGED
package/dist/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
|