diff --git a/.changeset/23610-skills-pages-contract.md b/.changeset/23610-skills-pages-contract.md new file mode 100644 index 00000000000..f850074b321 --- /dev/null +++ b/.changeset/23610-skills-pages-contract.md @@ -0,0 +1,9 @@ +--- +'@objectstack/skills': patch +--- + +docs(skills): the `objectstack-ui` pages rule says what a page type, template and region name run (#23610) + +Clause-②: no + +`skills/objectstack-ui/rules/pages.md` taught `home` as the app's landing page, `utility` as a floating utility panel, templates `two-column` / `single-column` and regions `left_sidebar` / `right_sidebar`, and `kind: 'jsx'` as a live alias of `html` — none of which the console draws or the spec accepts. The rule now states the declared contract: `home` is the widest region page and not a landing (an app opens on its first navigation item; `isDefault` on it is refused), `utility` is a narrow inline region page with no floating or docked shell slot, `template` is one of `default`, `header-sidebar-main`, `three-column` or `dashboard` with the regions each one places (`sidebar` left, `aside` right; `full-width` retired), a region the template does not place or a second region for a filled slot is refused at its `name`, and `kind: 'jsx'` is refused with the prescription `html`. Skill text only; nothing an author writes changes. diff --git a/skills/objectstack-ui/rules/pages.md b/skills/objectstack-ui/rules/pages.md index 85f70ec5309..2daa91a907d 100644 --- a/skills/objectstack-ui/rules/pages.md +++ b/skills/objectstack-ui/rules/pages.md @@ -15,30 +15,28 @@ Register under `defineStack({ pages: [...] })`. ### Page Types -`PageTypeSchema` has exactly **five** values — only types with a dedicated -renderer are authorizable (ADR-0049 enforce-or-remove): +`PageTypeSchema` has exactly **five** values (ADR-0049 enforce-or-remove): | `type` | Purpose | |:----------|:--------| | `record` | Component-based record layout with regions (overrides the default record detail) | -| `home` | App home / landing page | -| `app` | App-level page with navigation context | -| `utility` | Floating utility panel (e.g. notes, phone dialer) | +| `home` | Widest region page; not a landing (`isDefault` refused): an app opens on its first navigation item | +| `app` | Region page at app width | +| `utility` | Narrow inline region page for a tool (notes, a dialer); no floating or docked shell slot exists | | `list` | Record list/grid interface page — configured via `interfaceConfig` | -Disambiguation: there is **no** `record_detail`, `app_launcher`, or -`utility_bar` type — a record layout is `type: 'record'`, an app-level page is -`type: 'app'`, a utility panel is `type: 'utility'`. Likewise -grid/kanban/calendar/gallery/timeline are NOT page types — they are -*visualizations* of a `list` page -(`interfaceConfig.appearance.allowedVisualizations`). +There is **no** `record_detail`, `app_launcher` or `utility_bar` type, and +grid/kanban/calendar/gallery/timeline are *visualizations* of a `list` page +(`interfaceConfig.appearance.allowedVisualizations`), not page types. ### Templates & Regions -`template` controls the column layout (e.g. `'three-column'`, -`'two-column'`, `'single-column'`). Each template exposes named -**regions** (`header`, `left_sidebar`, `main`, `right_sidebar`, `footer`) -which contain components. +`template` is `default` (regions `header`, `sidebar`, `main`, `aside`, `footer`), +`header-sidebar-main` (`header`, `sidebar`, `main`), `three-column` (the same +five) or `dashboard` (`header`, `footer`; other regions are grid cells); +`full-width` is retired (a second name for `default`). On a `kind: 'full'` page a region +the template does not place, or a second one for a filled slot, is refused at +its `name` — the left column is `sidebar`, the right `aside`. ### Component Catalogue (selection) @@ -69,7 +67,7 @@ An invoice, a delivery order, a letter or a report is an ordinary page with a the document. Only a `kind: 'full'` page of `type: 'record'`, `'home'` or `'app'` with its blocks in `regions` may declare it: the parse refuses `print` on a `list` page (its switch is `interfaceConfig.allowPrinting`), a `utility` -panel, a `slotted` / `html` / `react` page and a `full` page with no regions. +page, a `slotted` / `html` / `react` page and a `full` page with no regions. `print` keys, each mapped to print CSS: `paperSize` (`'A4'` default, `'A5'`, `'Letter'`, `'Legal'`) and `orientation` (`'portrait'` default, `'landscape'`); @@ -134,8 +132,8 @@ by what the page needs: | `react` | **real React** (hooks, `.map`, `onClick`, expressions) | yes (main React tree) | complex interactive business UIs — master/detail, wizards, state-driven filters | `source` is the source-of-truth in both source tiers; `regions` is ignored. A -`kind:'html'`/`'react'` page with no `source` fails the build (ADR-0078). The legacy -value `kind:'jsx'` is a deprecated alias for `kind:'html'`. +`kind:'html'`/`'react'` page with no `source` fails the build (ADR-0078). +`kind:'jsx'` is retired: the parse refuses it and names `kind:'html'`. #### `kind:'html'` — constrained JSX, parsed (safe by construction) @@ -284,9 +282,6 @@ Rules: } ``` -The spec field is `PageComponentSchema.responsiveStyles` (`ResponsiveStylesSchema` — -see `node_modules/@objectstack/spec/src/ui/responsive.zod.ts`). - **In the source tiers (`kind:'html'` / `kind:'react'`) the same rule holds — no Tailwind `className` — but the primitive differs:**