Skip to content

Commit b496498

Browse files
xuyushun441-sysos-zhuangclaude
authored
feat(spec): add responsiveStyles to UI page-component envelope (ADR-0065) (#2214)
ResponsiveStylesSchema/StyleMapSchema model per-breakpoint CSS-property maps (large/medium/small/xsmall) for the SDUI scoped-styling primitive; PageComponentSchema gains an optional responsiveStyles field — the preferred build-independent, collision-free styling channel for metadata-authored pages (distinct from the layout-oriented responsive config). 6612 spec tests green; api-surface refreshed. Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 8125c3d commit b496498

4 files changed

Lines changed: 60 additions & 1 deletion

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
"@objectstack/spec": minor
3+
---
4+
5+
feat(spec): add `responsiveStyles` to the UI page-component envelope (ADR-0065)
6+
7+
`ResponsiveStylesSchema` / `StyleMapSchema` model the SDUI scoped-styling
8+
primitive — per-breakpoint CSS-property maps (`large`/`medium`/`small`/`xsmall`)
9+
compiled to id-scoped CSS at render. `PageComponentSchema` gains an optional
10+
`responsiveStyles` field: the preferred, build-independent, collision-free
11+
styling channel for metadata-authored pages (distinct from the layout-oriented
12+
`responsive` config). Prefer design-token values.

packages/spec/api-surface.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3252,6 +3252,8 @@
32523252
"ReportType (const)",
32533253
"ResponsiveConfig (type)",
32543254
"ResponsiveConfigSchema (const)",
3255+
"ResponsiveStyles (type)",
3256+
"ResponsiveStylesSchema (const)",
32553257
"RowColorConfig (type)",
32563258
"RowColorConfigSchema (const)",
32573259
"RowHeight (type)",
@@ -3264,6 +3266,8 @@
32643266
"SharingConfigSchema (const)",
32653267
"Spacing (type)",
32663268
"SpacingSchema (const)",
3269+
"StyleMap (type)",
3270+
"StyleMapSchema (const)",
32673271
"SwipeDirection (type)",
32683272
"SwipeDirectionSchema (const)",
32693273
"SwipeGestureConfig (type)",

packages/spec/src/ui/page.zod.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { ExpressionInputSchema } from '../shared/expression.zod';
66
import { SortItemSchema } from '../shared/enums.zod';
77
import { FilterConditionSchema } from '../data/filter.zod';
88
import { I18nLabelSchema, AriaPropsSchema } from './i18n.zod';
9-
import { ResponsiveConfigSchema } from './responsive.zod';
9+
import { ResponsiveConfigSchema, ResponsiveStylesSchema } from './responsive.zod';
1010
import {
1111
UserActionsConfigSchema,
1212
AppearanceConfigSchema,
@@ -88,6 +88,15 @@ export const PageComponentSchema = lazySchema(() => z.object({
8888
style: z.record(z.string(), z.string()).optional().describe('Inline styles or utility classes'),
8989
className: z.string().optional().describe('CSS class names'),
9090

91+
/**
92+
* SDUI scoped responsive styles (ADR-0065). Per-breakpoint CSS-property maps
93+
* compiled to id-scoped CSS at render. The preferred styling channel for
94+
* metadata-authored pages — build-independent and collision-free, unlike raw
95+
* `className`. Prefer design-token values (`var(--space-6)`, `var(--surface)`).
96+
*/
97+
responsiveStyles: ResponsiveStylesSchema.optional()
98+
.describe('Per-breakpoint scoped style maps (ADR-0065)'),
99+
91100
/** Visibility Rule */
92101
visibility: ExpressionInputSchema.optional().describe('Visibility predicate (CEL).'),
93102

packages/spec/src/ui/responsive.zod.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,40 @@ export const ResponsiveConfigSchema = lazySchema(() => z.object({
7474

7575
export type ResponsiveConfig = z.infer<typeof ResponsiveConfigSchema>;
7676

77+
/**
78+
* Style Map Schema (ADR-0065)
79+
*
80+
* A CSS property → value map (camelCase keys, e.g. `flexDirection`). Values are
81+
* arbitrary CSS strings/numbers but authors should prefer design tokens
82+
* (`var(--space-6)`, `var(--surface)`) for consistency and AI-safety.
83+
*/
84+
export const StyleMapSchema = lazySchema(() =>
85+
z.record(z.string(), z.union([z.string(), z.number()]))
86+
.describe('CSS property → value map (camelCase keys; design tokens encouraged)'));
87+
88+
export type StyleMap = z.infer<typeof StyleMapSchema>;
89+
90+
/**
91+
* Responsive Styles Schema (ADR-0065)
92+
*
93+
* Per-breakpoint CSS-property maps for the SDUI scoped-styling model. Compiled
94+
* to **id-scoped CSS at render** (objectui `SchemaRenderer`) — build-independent,
95+
* collision-free, responsive-correct. Desktop-first: `large` is the
96+
* unconditional base; `medium`/`small`/`xsmall` are `max-width` overrides.
97+
*
98+
* Distinct from {@link ResponsiveConfigSchema}, which configures *layout* (grid
99+
* columns / visibility / order) on the Tailwind `xs..2xl` axis. This styles a
100+
* node's own box; that arranges a node within a grid.
101+
*/
102+
export const ResponsiveStylesSchema = lazySchema(() => z.object({
103+
large: StyleMapSchema.optional().describe('Unconditional base (desktop-first)'),
104+
medium: StyleMapSchema.optional().describe('Applied at ≤ medium breakpoint'),
105+
small: StyleMapSchema.optional().describe('Applied at ≤ small breakpoint'),
106+
xsmall: StyleMapSchema.optional().describe('Applied at ≤ xsmall breakpoint'),
107+
}).describe('Per-breakpoint scoped style maps (ADR-0065)'));
108+
109+
export type ResponsiveStyles = z.infer<typeof ResponsiveStylesSchema>;
110+
77111
/**
78112
* Performance Configuration Schema
79113
*

0 commit comments

Comments
 (0)