Skip to content

Commit 748f588

Browse files
committed
Support length variable
1 parent 4685b68 commit 748f588

File tree

8 files changed

+340
-14
lines changed

8 files changed

+340
-14
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"changes":{"bindings/devup-ui-wasm/package.json":"Patch"},"note":"Support variable","date":"2026-04-01T07:11:17.490320600Z"}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ storybook-static
2020
.sisyphus
2121
test-results
2222
playwright-report
23+
.omc

AGENTS.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ devup-ui/
3636
| Add CSS property | `libs/css/src/constant.rs` | Property mappings |
3737
| Add pseudo selector | `packages/react/src/types/props/selector/` | TypeScript types |
3838
| Modify extraction | `libs/extractor/src/lib.rs` | Core logic + tests |
39-
| Theme system | `libs/sheet/src/theme.rs` | Color/typography |
39+
| Theme system | `libs/sheet/src/theme.rs` | Color/typography/length/shadow |
4040
| Plugin behavior | `packages/*-plugin/src/plugin.ts` | All follow same pattern |
4141
| Component API | `packages/react/src/components/` | Box, Flex, Text... |
4242
| WASM exports | `bindings/devup-ui-wasm/src/lib.rs` | JS-exposed functions |
@@ -49,7 +49,7 @@ devup-ui/
4949
|--------|------|-------|------|
5050
| extractor | `lib.rs` | 9,094 | Main extraction + tests |
5151
| sheet | `lib.rs` | 1,821 | CSS output generation |
52-
| theme | `theme.rs` | 1,526 | Color/typography system |
52+
| theme | `theme.rs` | 1,526 | Color/typography/length/shadow system |
5353
| css_utils | `css_utils.rs` | 1,239 | Template literal parsing |
5454
| visit | `visit.rs` | 669 | AST visitor pattern |
5555

@@ -105,11 +105,19 @@ All React components throw `Error('Cannot run on the runtime')` - they're compil
105105
{
106106
"theme": {
107107
"colors": { "default": {...}, "dark": {...} },
108-
"typography": { "heading": {...} }
108+
"typography": { "heading": {...} },
109+
"length": { "default": { "containerX": ["1px", null, "2px"] } },
110+
"shadow": { "default": { "card": ["0 1px 2px #0003", null, null, "0 4px 8px #0003"] } }
109111
}
110112
}
111113
```
112114

115+
### Length & Shadow Tokens
116+
- Defined responsively like typography (arrays with `null` for skipped breakpoints)
117+
- Used with `$` prefix: `<Box w="$containerX" />`, `<Box boxShadow="$card" />`
118+
- `"$token"` and `{"$token"}` both expand to multiple breakpoint classes
119+
- `{["$token"]}` inside a responsive array stays single class (array defines breakpoints)
120+
113121
### Plugin Pattern
114122
All plugins wrap bundler config:
115123
```ts

SKILL.md

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ description: |
66
TRIGGER WHEN:
77
- Writing/modifying Devup UI components (Box, Flex, Grid, Text, Button, etc.)
88
- Using styling APIs: css(), globalCss(), keyframes()
9-
- Configuring devup.json theme (colors, typography, extends)
9+
- Configuring devup.json theme (colors, typography, length, shadow, extends)
1010
- Setting up build plugins (Vite, Next.js, Webpack, Rsbuild, Bun)
1111
- Debugging "Cannot run on the runtime" errors
1212
- Working with responsive arrays, pseudo-selectors (_hover, _dark, etc.)
1313
- Using polymorphic `as` prop or `selectors` prop
1414
- Working with @devup-ui/components (Button, Input, Select, Toggle, etc.)
15+
- Using responsive length tokens ($containerX, $gutter) or shadow tokens ($card, $sm)
1516
---
1617

1718
# Devup UI
@@ -338,15 +339,42 @@ const spin = keyframes({ from: { transform: "rotate(0)" }, to: { transform: "rot
338339
null,
339340
{ "fontSize": "16px", "lineHeight": 1.6 }
340341
]
342+
},
343+
"length": {
344+
"default": {
345+
"containerX": ["16px", null, "32px"],
346+
"gutter": ["8px", null, "16px"]
347+
}
348+
},
349+
"shadow": {
350+
"default": {
351+
"card": ["0 1px 2px #0003", null, null, "0 4px 8px #0003"],
352+
"sm": "0 1px 2px rgba(0,0,0,0.05)"
353+
}
341354
}
342355
}
343356
}
344357
```
345358

346359
- **Colors**: Use with `$` prefix in JSX props: `<Box color="$primary" />`
347360
- **Typography**: Use with `$` prefix: `<Text typography="$heading" />`
361+
- **Length**: Responsive length tokens: `<Box px="$containerX" />`, `<Flex gap="$gutter" />`
362+
- **Shadow**: Responsive shadow tokens: `<Box boxShadow="$card" />`
348363
- **extends**: Inherit from base config files (deep merge, last wins)
349-
- **Responsive typography**: Use arrays with `null` for unchanged breakpoints
364+
- **Responsive typography/length/shadow**: Use arrays with `null` for unchanged breakpoints
365+
366+
### Length & Shadow Token Behavior
367+
368+
Length and shadow tokens support responsive arrays like typography. The key distinction is how `$token` behaves depending on syntax:
369+
370+
| Syntax | Behavior | Classes |
371+
|--------|----------|---------|
372+
| `px="$containerX"` | Expands to all defined breakpoints | Multiple |
373+
| `px={"$containerX"}` | Expands to all defined breakpoints | Multiple |
374+
| `px={["$containerX"]}` | Single value at index 0 only | 1 |
375+
| `px={["8px", null, "$containerX"]}` | `8px` at index 0, token at index 2 | 2 |
376+
377+
Both `"$token"` and `{"$token"}` expand the responsive token. Only `{["$token"]}` inside a responsive array keeps it as a single class — because the array itself defines the breakpoint levels.
350378

351379
Theme types are auto-generated via module augmentation of `DevupTheme` and `DevupThemeTypography`.
352380

@@ -415,20 +443,22 @@ DevupUI({
415443
})
416444
```
417445

418-
## $color Token Scope
446+
## $token Scope
419447

420-
`$color` tokens only work in **JSX props**. Use `var(--color)` in external objects.
448+
`$token` values (colors, length, shadow) only work in **JSX props**. Use `var(--token)` in external objects.
421449

422450
```tsx
423-
// CORRECT - $color in JSX prop
451+
// CORRECT - $token in JSX prop
424452
<Box bg="$primary" />
453+
<Box px="$containerX" />
454+
<Box boxShadow="$card" />
425455
<Box bg={{ active: '$primary', inactive: '$gray' }[status]} />
426456

427-
// WRONG - $color in external object (won't be transformed)
457+
// WRONG - $token in external object (won't be transformed)
428458
const colors = { active: '$primary' }
429459
<Box bg={colors.active} /> // broken!
430460

431-
// CORRECT - var(--color) in external object
461+
// CORRECT - var(--token) in external object
432462
const colors = { active: 'var(--primary)' }
433463
<Box bg={colors.active} />
434464
```

apps/landing/src/app/(detail)/docs/LeftMenu.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ export function LeftMenu() {
122122
to: '/docs/devup/typography',
123123
children: 'Typography',
124124
},
125+
{
126+
to: '/docs/devup/length',
127+
children: 'Length',
128+
},
129+
{
130+
to: '/docs/devup/shadow',
131+
children: 'Shadow',
132+
},
125133
{
126134
to: '/docs/devup/breakpoints',
127135
children: 'Breakpoints',

apps/landing/src/app/(detail)/docs/devup/devup-json/page.mdx

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export const metadata = {
77

88
# devup.json
99

10-
The `devup.json` file is the configuration file for your Devup UI theme. Create it at the root of your project to define colors, typography, and other design tokens.
10+
The `devup.json` file is the configuration file for your Devup UI theme. Create it at the root of your project to define colors, typography, length, shadow, and other design tokens.
1111

1212
## Basic Structure
1313

@@ -18,7 +18,13 @@ The `devup.json` file is the configuration file for your Devup UI theme. Create
1818
"default": {},
1919
"dark": {}
2020
},
21-
"typography": {}
21+
"typography": {},
22+
"length": {
23+
"default": {}
24+
},
25+
"shadow": {
26+
"default": {}
27+
}
2228
}
2329
}
2430
```
@@ -155,6 +161,53 @@ Typography properties:
155161

156162
See [Typography](/docs/devup/typography) for more details.
157163

164+
## Length Configuration
165+
166+
Define responsive length tokens for spacing, sizing, and other CSS length properties:
167+
168+
```json
169+
{
170+
"theme": {
171+
"length": {
172+
"default": {
173+
"containerX": ["16px", null, "32px", null, "64px"],
174+
"gutter": ["8px", null, "16px"]
175+
}
176+
}
177+
}
178+
}
179+
```
180+
181+
Length tokens use responsive arrays just like typography. Use `null` to skip breakpoints and inherit from the previous value.
182+
183+
See [Length](/docs/devup/length) for more details.
184+
185+
## Shadow Configuration
186+
187+
Define responsive shadow tokens for box-shadow values:
188+
189+
```json
190+
{
191+
"theme": {
192+
"shadow": {
193+
"default": {
194+
"card": [
195+
"0 1px 2px rgba(0,0,0,0.1)",
196+
null,
197+
null,
198+
"0 4px 8px rgba(0,0,0,0.1)"
199+
],
200+
"sm": "0 1px 2px rgba(0,0,0,0.05)"
201+
}
202+
}
203+
}
204+
}
205+
```
206+
207+
Shadow tokens also support responsive arrays. Non-array values define a single shadow for all breakpoints.
208+
209+
See [Shadow](/docs/devup/shadow) for more details.
210+
158211
## Usage in Components
159212

160213
### Colors
@@ -170,6 +223,18 @@ const headingExample = <Text typography="$h1">Heading</Text>
170223
const bodyExample = <Text typography="$body">Body text</Text>
171224
```
172225

226+
### Length
227+
228+
```tsx
229+
<Box gap="$gutter" px="$containerX" />
230+
```
231+
232+
### Shadow
233+
234+
```tsx
235+
<Box boxShadow="$card" />
236+
```
237+
173238
## File Location
174239

175240
The `devup.json` file should be placed at the root of your project:
@@ -215,7 +280,7 @@ module.exports = withDevupUI({
215280

216281
When your project builds, Devup UI automatically generates TypeScript types from your `devup.json`. This enables:
217282

218-
- Autocomplete for color and typography tokens
283+
- Autocomplete for color, typography, length, and shadow tokens
219284
- Type errors for invalid tokens
220285
- Consistent usage across your codebase
221286

@@ -227,6 +292,6 @@ Changes to `devup.json` trigger hot reload during development. You can:
227292

228293
1. Add new color tokens
229294
2. Modify existing values
230-
3. Add typography styles
295+
3. Add typography, length, or shadow styles
231296

232297
And see changes immediately without restarting the dev server.
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
export const metadata = {
2+
title: 'Length',
3+
alternates: {
4+
canonical: '/docs/devup/length',
5+
},
6+
}
7+
8+
# Length
9+
10+
Devup UI supports responsive length tokens for spacing, sizing, border-radius, and other CSS length properties. Like typography, length tokens can be defined as responsive arrays in `devup.json`.
11+
12+
## Defining Length Tokens
13+
14+
Define length tokens in your `devup.json`:
15+
16+
```json
17+
{
18+
"theme": {
19+
"length": {
20+
"default": {
21+
"containerX": ["16px", null, "32px", null, "64px"],
22+
"gutter": ["8px", null, "16px"],
23+
"borderRadiusMd": ["8px", null, "16px"]
24+
}
25+
}
26+
}
27+
}
28+
```
29+
30+
Each array index corresponds to a breakpoint. Use `null` to skip a breakpoint and inherit from the previous value.
31+
32+
## Usage
33+
34+
Use length tokens with the `$` prefix on any length-accepting prop:
35+
36+
```tsx
37+
<>
38+
<Box px="$containerX" />
39+
<Box gap="$gutter" />
40+
<Box borderRadius="$borderRadiusMd" />
41+
<Box px="$containerX" />
42+
</>
43+
```
44+
45+
Both `"$token"` and `{"$token"}` expand the responsive token into multiple breakpoint-level classes.
46+
47+
## Responsive Array Behavior
48+
49+
When a `$token` appears inside a responsive array, it does **not** expand — the array itself defines the breakpoints:
50+
51+
```tsx
52+
{
53+
/* "$containerX" stays as a single value at breakpoint index 2 */
54+
}
55+
;<Box px={['8px', null, '$containerX']} />
56+
```
57+
58+
This is the key distinction:
59+
60+
| Syntax | Behavior | Classes |
61+
| ----------------------------------- | ---------------------------------- | -------- |
62+
| `px="$containerX"` | Expands to all defined breakpoints | Multiple |
63+
| `px={"$containerX"}` | Expands to all defined breakpoints | Multiple |
64+
| `px={["$containerX"]}` | Single value at index 0 | 1 |
65+
| `px={["8px", null, "$containerX"]}` | `8px` at index 0, token at index 2 | 2 |
66+
67+
## Theme Variants
68+
69+
Length tokens support theme variants, similar to colors:
70+
71+
```json
72+
{
73+
"theme": {
74+
"length": {
75+
"default": {
76+
"containerX": ["16px", null, "32px"]
77+
},
78+
"compact": {
79+
"containerX": ["8px", null, "16px"]
80+
}
81+
}
82+
}
83+
}
84+
```
85+
86+
## Non-Responsive Tokens
87+
88+
For a single value across all breakpoints, use a simple string:
89+
90+
```json
91+
{
92+
"theme": {
93+
"length": {
94+
"default": {
95+
"borderRadiusSm": "4px",
96+
"borderRadiusMd": "8px",
97+
"borderRadiusLg": "16px"
98+
}
99+
}
100+
}
101+
}
102+
```
103+
104+
## Type Safety
105+
106+
Length tokens are fully type-safe. TypeScript will autocomplete available tokens when you type `$`:
107+
108+
```tsx
109+
// Autocomplete shows: $containerX, $gutter, $borderRadiusMd, etc.
110+
<Box px="$" />
111+
```

0 commit comments

Comments
 (0)