@adia-ai/web-components 0.0.24 → 0.0.26

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.
@@ -0,0 +1,84 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://adiaui.dev/a2ui/v0_9/components/Aside.json",
4
+ "title": "Aside",
5
+ "description": "Side region — styled by closest container parent (AppShell / Drawer / Card).\nHolds nav rails, secondary actions, or supplementary content. CSS-only slot\nstub: no own behavior; the container parent reads `[collapsible]` and\n`[width]` to wire collapse + width. For interactive resize / collapse\nbehavior, compose with `<pane-ui>` inside: aside = semantic role,\npane = resizable / collapsible primitive.\n",
6
+ "type": "object",
7
+ "allOf": [
8
+ {
9
+ "$ref": "common_types.json#/$defs/ComponentCommon"
10
+ },
11
+ {
12
+ "$ref": "common_types.json#/$defs/CatalogComponentCommon"
13
+ }
14
+ ],
15
+ "properties": {
16
+ "collapsible": {
17
+ "description": "Marks the aside as collapsible. The container parent (AppShell, Drawer)\nreads this and wires the toggle affordance + ARIA + state. The aside\nitself ships no collapse logic.\n",
18
+ "type": "boolean",
19
+ "default": false
20
+ },
21
+ "component": {
22
+ "const": "Aside"
23
+ },
24
+ "width": {
25
+ "description": "Token-bound width hint. The container parent reads this to set the\naside column width — `rail` (compact icon-only nav), `panel` (full\nnav text), `wide` (workspace pane). Empty string defers to parent default.\n",
26
+ "type": "string",
27
+ "enum": [
28
+ "",
29
+ "rail",
30
+ "panel",
31
+ "wide"
32
+ ],
33
+ "default": ""
34
+ }
35
+ },
36
+ "required": [
37
+ "component"
38
+ ],
39
+ "unevaluatedProperties": false,
40
+ "x-adiaui": {
41
+ "anti_patterns": [],
42
+ "category": "container",
43
+ "events": {},
44
+ "examples": [
45
+ {
46
+ "description": "Card laid out as a header / aside / section, with the aside holding a nav list.",
47
+ "a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Card\",\n \"children\": [\"hdr\", \"side\", \"main\"]\n },\n {\n \"id\": \"hdr\",\n \"component\": \"Header\",\n \"children\": [\"title\"]\n },\n {\n \"id\": \"title\",\n \"component\": \"Text\",\n \"slot\": \"heading\",\n \"textContent\": \"Settings\"\n },\n {\n \"id\": \"side\",\n \"component\": \"Aside\",\n \"width\": \"rail\",\n \"children\": [\"nav\"]\n },\n {\n \"id\": \"nav\",\n \"component\": \"List\",\n \"children\": []\n },\n {\n \"id\": \"main\",\n \"component\": \"Section\",\n \"children\": []\n }\n]",
48
+ "name": "card-with-side-nav"
49
+ }
50
+ ],
51
+ "keywords": [
52
+ "aside",
53
+ "sidebar",
54
+ "rail",
55
+ "panel",
56
+ "side-region",
57
+ "nav-rail"
58
+ ],
59
+ "name": "AdiaAside",
60
+ "related": [
61
+ "app-shell",
62
+ "drawer",
63
+ "pane",
64
+ "section",
65
+ "header"
66
+ ],
67
+ "slots": {
68
+ "default": {
69
+ "description": "Default slot — primary child content (typically `<list-ui>`, `<tree-ui>`, or app-nav primitives)."
70
+ }
71
+ },
72
+ "states": [
73
+ {
74
+ "description": "Default, ready for interaction.",
75
+ "name": "idle"
76
+ }
77
+ ],
78
+ "synonyms": {},
79
+ "tag": "aside-ui",
80
+ "tokens": {},
81
+ "traits": [],
82
+ "version": 1
83
+ }
84
+ }
@@ -0,0 +1,100 @@
1
+ # Edit this file; run `npm run build:components` to regenerate a2ui.json.
2
+ $schema: ../../../../scripts/schemas/component.yaml.schema.json
3
+ name: AdiaAside
4
+ tag: aside-ui
5
+ component: Aside
6
+ category: container
7
+ version: 1
8
+ description: |
9
+ Side region — styled by closest container parent (AppShell / Drawer / Card).
10
+ Holds nav rails, secondary actions, or supplementary content. CSS-only slot
11
+ stub: no own behavior; the container parent reads `[collapsible]` and
12
+ `[width]` to wire collapse + width. For interactive resize / collapse
13
+ behavior, compose with `<pane-ui>` inside: aside = semantic role,
14
+ pane = resizable / collapsible primitive.
15
+ props:
16
+ collapsible:
17
+ description: |
18
+ Marks the aside as collapsible. The container parent (AppShell, Drawer)
19
+ reads this and wires the toggle affordance + ARIA + state. The aside
20
+ itself ships no collapse logic.
21
+ type: boolean
22
+ default: false
23
+ reflect: true
24
+ width:
25
+ description: |
26
+ Token-bound width hint. The container parent reads this to set the
27
+ aside column width — `rail` (compact icon-only nav), `panel` (full
28
+ nav text), `wide` (workspace pane). Empty string defers to parent default.
29
+ type: string
30
+ default: ""
31
+ enum:
32
+ - ""
33
+ - rail
34
+ - panel
35
+ - wide
36
+ reflect: true
37
+ events: {}
38
+ slots:
39
+ default:
40
+ description: "Default slot — primary child content (typically `<list-ui>`, `<tree-ui>`, or app-nav primitives)."
41
+ states:
42
+ - name: idle
43
+ description: Default, ready for interaction.
44
+ traits: []
45
+ tokens: {}
46
+ a2ui:
47
+ rules: []
48
+ anti_patterns: []
49
+ examples:
50
+ - name: card-with-side-nav
51
+ description: Card laid out as a header / aside / section, with the aside holding a nav list.
52
+ a2ui: >-
53
+ [
54
+ {
55
+ "id": "root",
56
+ "component": "Card",
57
+ "children": ["hdr", "side", "main"]
58
+ },
59
+ {
60
+ "id": "hdr",
61
+ "component": "Header",
62
+ "children": ["title"]
63
+ },
64
+ {
65
+ "id": "title",
66
+ "component": "Text",
67
+ "slot": "heading",
68
+ "textContent": "Settings"
69
+ },
70
+ {
71
+ "id": "side",
72
+ "component": "Aside",
73
+ "width": "rail",
74
+ "children": ["nav"]
75
+ },
76
+ {
77
+ "id": "nav",
78
+ "component": "List",
79
+ "children": []
80
+ },
81
+ {
82
+ "id": "main",
83
+ "component": "Section",
84
+ "children": []
85
+ }
86
+ ]
87
+ keywords:
88
+ - aside
89
+ - sidebar
90
+ - rail
91
+ - panel
92
+ - side-region
93
+ - nav-rail
94
+ synonyms: {}
95
+ related:
96
+ - app-shell
97
+ - drawer
98
+ - pane
99
+ - section
100
+ - header
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://adiaui.dev/a2ui/v0_9/components/Footer.json",
4
4
  "title": "Footer",
5
- "description": "Card footer. Contains actions, pagination, or summary. Typically holds Buttons.",
5
+ "description": "Footer — styled by closest container parent (Card / Drawer / Modal / Page / AppShell). Contains actions, pagination, or summary. Typically holds Buttons.",
6
6
  "type": "object",
7
7
  "allOf": [
8
8
  {
@@ -6,7 +6,7 @@ tag: footer-ui
6
6
  component: Footer
7
7
  category: container
8
8
  version: 1
9
- description: Card footer. Contains actions, pagination, or summary. Typically holds Buttons.
9
+ description: Footer — styled by closest container parent (Card / Drawer / Modal / Page / AppShell). Contains actions, pagination, or summary. Typically holds Buttons.
10
10
  props:
11
11
  justify:
12
12
  description: Horizontal alignment of children
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://adiaui.dev/a2ui/v0_9/components/Header.json",
4
4
  "title": "Header",
5
- "description": "Card header. Contains heading text and optional action slot.",
5
+ "description": "Header — styled by closest container parent (Card / Drawer / Modal / Page / AppShell). Contains heading text and optional action slot.",
6
6
  "type": "object",
7
7
  "allOf": [
8
8
  {
@@ -17,7 +17,7 @@
17
17
  "const": "Header"
18
18
  },
19
19
  "padding": {
20
- "description": "Bare attribute — enables default header padding. Card's own `padding` prop sets scale.",
20
+ "description": "Bare attribute — enables default header padding. The container parent's own `padding` prop sets the scale.",
21
21
  "type": "boolean",
22
22
  "default": false
23
23
  }
@@ -6,10 +6,10 @@ tag: header-ui
6
6
  component: Header
7
7
  category: container
8
8
  version: 1
9
- description: Card header. Contains heading text and optional action slot.
9
+ description: Header — styled by closest container parent (Card / Drawer / Modal / Page / AppShell). Contains heading text and optional action slot.
10
10
  props:
11
11
  padding:
12
- description: Bare attribute — enables default header padding. Card's own `padding` prop sets scale.
12
+ description: Bare attribute — enables default header padding. The container parent's own `padding` prop sets the scale.
13
13
  type: boolean
14
14
  default: false
15
15
  reflect: true
@@ -24,6 +24,7 @@ export { AdiaSegmented } from './segmented/segmented.js';
24
24
  export { AdiaRange } from './range/range.js';
25
25
  export { AdiaTree, AdiaTreeItem } from './tree/tree.js';
26
26
  export { AdiaPane } from './pane/pane.js';
27
+ export { AdiaPage } from './page/page.js';
27
28
  export { AdiaChatInput } from './chat/chat-input.js';
28
29
  export { AdiaChat } from './chat/chat.js';
29
30
  export { AdiaDrawer } from './drawer/drawer.js';
@@ -0,0 +1,107 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://adiaui.dev/a2ui/v0_9/components/Page.json",
4
+ "title": "Page",
5
+ "description": "Page container. Holds page-level chrome — header / content / footer —\nand manages max-width clamps, padding scale, optional scroll-container,\nand an optional sticky-header sentinel. Compose with the slot\nprimitives (`<header-ui>`, `<section-ui>`, `<footer-ui>`); the page's\n@scope rules style them. Drop in directly, or nest inside an\n`<app-shell-ui>`'s main column.\n",
6
+ "type": "object",
7
+ "allOf": [
8
+ {
9
+ "$ref": "common_types.json#/$defs/ComponentCommon"
10
+ },
11
+ {
12
+ "$ref": "common_types.json#/$defs/CatalogComponentCommon"
13
+ }
14
+ ],
15
+ "properties": {
16
+ "component": {
17
+ "const": "Page"
18
+ },
19
+ "maxWidth": {
20
+ "description": "Token-bound max-width clamp. `prose` (65ch) for reading pages,\n`narrow` (80ch) for tight forms, `wide` (1080px) for data-rich\npages, `full` for unconstrained. Empty defers to parent / 100%.\nCentered horizontally via `margin-inline: auto`.\n",
21
+ "type": "string",
22
+ "enum": [
23
+ "",
24
+ "prose",
25
+ "narrow",
26
+ "wide",
27
+ "full"
28
+ ],
29
+ "default": ""
30
+ },
31
+ "padding": {
32
+ "description": "Page-padding scale from the spacing system. Accepts `0`–`8`\n(mapped to `--a-space-N`). Empty (no value) applies the\n`--page-padding-default` token; `0` removes padding.\n",
33
+ "type": "string",
34
+ "default": ""
35
+ },
36
+ "scroll": {
37
+ "description": "Sets the page as a scroll container. `overflow-y: auto`, full\nheight, contained overscroll. Use when the page IS the scroll\nsurface (standalone pages); leave off when nested inside a parent\nthat already manages scroll (e.g. inside an `<app-shell-ui>`'s\nmain `<section>`).\n",
38
+ "type": "boolean",
39
+ "default": false
40
+ },
41
+ "stickyHeader": {
42
+ "description": "Installs an IntersectionObserver sentinel before the first\n`<header>` / `<header-ui>` child. When the sentinel scrolls out\nof view the page gains `[data-header-stuck]`, which the CSS\nuses to add a border + shadow to the header. No-op when no\nheader is present.\n",
43
+ "type": "boolean",
44
+ "default": false
45
+ }
46
+ },
47
+ "required": [
48
+ "component"
49
+ ],
50
+ "unevaluatedProperties": false,
51
+ "x-adiaui": {
52
+ "anti_patterns": [],
53
+ "category": "container",
54
+ "events": {},
55
+ "examples": [
56
+ {
57
+ "description": "Reading page with sticky header, 65ch column, padding scale 6.",
58
+ "a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Page\",\n \"stickyHeader\": true,\n \"maxWidth\": \"prose\",\n \"padding\": \"6\",\n \"children\": [\"hdr\", \"body\"]\n },\n {\n \"id\": \"hdr\",\n \"component\": \"Header\",\n \"children\": [\"title\"]\n },\n {\n \"id\": \"title\",\n \"component\": \"Text\",\n \"variant\": \"display\",\n \"textContent\": \"Reading Page\"\n },\n {\n \"id\": \"body\",\n \"component\": \"Section\",\n \"children\": []\n }\n]",
59
+ "name": "prose-page"
60
+ },
61
+ {
62
+ "description": "Wide-clamp dashboard page acting as a scroll container.",
63
+ "a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"Page\",\n \"scroll\": true,\n \"maxWidth\": \"wide\",\n \"padding\": \"4\",\n \"children\": [\"hdr\", \"body\"]\n },\n {\n \"id\": \"hdr\",\n \"component\": \"Header\",\n \"children\": []\n },\n {\n \"id\": \"body\",\n \"component\": \"Section\",\n \"children\": []\n }\n]",
64
+ "name": "dashboard-page"
65
+ }
66
+ ],
67
+ "keywords": [
68
+ "page",
69
+ "layout",
70
+ "container",
71
+ "scroll",
72
+ "sticky-header",
73
+ "max-width",
74
+ "padding",
75
+ "prose-page",
76
+ "dashboard-page"
77
+ ],
78
+ "name": "AdiaPage",
79
+ "related": [
80
+ "app-shell",
81
+ "card",
82
+ "section",
83
+ "header",
84
+ "footer"
85
+ ],
86
+ "slots": {
87
+ "default": {
88
+ "description": "Composes from the slot primitives — `<header-ui>` (page header),\n`<section-ui>` (main content), optional `<footer-ui>`. Native\n`<header>` / `<section>` / `<footer>` also work; the @scope rules\ntarget both via `:where(header, header-ui)`.\n"
89
+ }
90
+ },
91
+ "states": [
92
+ {
93
+ "description": "Default, ready for interaction.",
94
+ "name": "idle"
95
+ },
96
+ {
97
+ "description": "Header has scrolled past the sentinel; visual cue applied.",
98
+ "name": "header-stuck"
99
+ }
100
+ ],
101
+ "synonyms": {},
102
+ "tag": "page-ui",
103
+ "tokens": {},
104
+ "traits": [],
105
+ "version": 1
106
+ }
107
+ }
@@ -0,0 +1,68 @@
1
+ @scope (page-ui) {
2
+ :where(:scope) {
3
+ /* ── Max-width clamps ── */
4
+ --page-max-width-prose: 65ch;
5
+ --page-max-width-narrow: 80ch;
6
+ --page-max-width-wide: 1080px;
7
+ --page-max-width-full: 100%;
8
+
9
+ /* ── Padding default (when [padding] is set without a value) ── */
10
+ --page-padding-default: var(--a-space-6);
11
+
12
+ /* ── Surfaces ── */
13
+ --page-bg: var(--a-canvas-0);
14
+ --page-fg: var(--a-fg);
15
+
16
+ /* ── Sticky-header chrome (when [data-header-stuck]) ── */
17
+ --page-sticky-bg: var(--a-canvas-0);
18
+ --page-sticky-border: 1px solid var(--a-border-subtle);
19
+ --page-sticky-shadow: var(--a-shadow-sm);
20
+ }
21
+
22
+ :scope {
23
+ box-sizing: border-box;
24
+ display: block;
25
+ width: 100%;
26
+ background: var(--page-bg);
27
+ color: var(--page-fg);
28
+ }
29
+
30
+ /* ── max-width clamps ── */
31
+ :scope[max-width="prose"] { max-width: var(--page-max-width-prose); margin-inline: auto; }
32
+ :scope[max-width="narrow"] { max-width: var(--page-max-width-narrow); margin-inline: auto; }
33
+ :scope[max-width="wide"] { max-width: var(--page-max-width-wide); margin-inline: auto; }
34
+ :scope[max-width="full"] { max-width: var(--page-max-width-full); }
35
+
36
+ /* ── Padding scale (mirrors --a-space-N) ── */
37
+ :scope[padding=""] { padding: var(--page-padding-default); }
38
+ :scope[padding="0"] { padding: 0; }
39
+ :scope[padding="1"] { padding: var(--a-space-1); }
40
+ :scope[padding="2"] { padding: var(--a-space-2); }
41
+ :scope[padding="3"] { padding: var(--a-space-3); }
42
+ :scope[padding="4"] { padding: var(--a-space-4); }
43
+ :scope[padding="5"] { padding: var(--a-space-5); }
44
+ :scope[padding="6"] { padding: var(--a-space-6); }
45
+ :scope[padding="7"] { padding: var(--a-space-7); }
46
+ :scope[padding="8"] { padding: var(--a-space-8); }
47
+
48
+ /* ── Scroll container ── */
49
+ :scope[scroll] {
50
+ overflow-y: auto;
51
+ height: 100%;
52
+ overscroll-behavior: contain;
53
+ }
54
+
55
+ /* ── Sticky-header support ── */
56
+ :scope[sticky-header] > :where(header, header-ui) {
57
+ position: sticky;
58
+ top: 0;
59
+ z-index: 1;
60
+ background: var(--page-sticky-bg);
61
+ transition: border-color 150ms ease, box-shadow 150ms ease;
62
+ }
63
+
64
+ :scope[data-header-stuck] > :where(header, header-ui) {
65
+ border-block-end: var(--page-sticky-border);
66
+ box-shadow: var(--page-sticky-shadow);
67
+ }
68
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * <page-ui> — Page container.
3
+ *
4
+ * Holds page-level chrome — header / content / footer — and manages
5
+ * max-width clamps, padding scale, optional scroll-container, and an
6
+ * optional sticky-header sentinel. Compose with the slot primitives
7
+ * (`<header-ui>`, `<section-ui>`, `<footer-ui>`); the page's @scope
8
+ * rules style them.
9
+ *
10
+ * Authoring:
11
+ * <page-ui sticky-header max-width="prose" padding="6">
12
+ * <header-ui>...</header-ui> <!-- page title + actions -->
13
+ * <section-ui>...</section-ui> <!-- main content -->
14
+ * <footer-ui>...</footer-ui> <!-- optional -->
15
+ * </page-ui>
16
+ *
17
+ * Attributes:
18
+ * scroll — boolean. Page is the scroll container (overflow-y: auto).
19
+ * max-width — '' | 'prose' (65ch) | 'narrow' (80ch) | 'wide' (1080px) | 'full' (100%).
20
+ * padding — '' | '0'..'8' (mapped to --a-space-N).
21
+ * sticky-header — boolean. Installs IntersectionObserver sentinel before the
22
+ * first <header> / <header-ui> child; sets [data-header-stuck]
23
+ * on the page when the sentinel scrolls out of view.
24
+ *
25
+ * ADR: .brain/adrs/0009-promote-app-shell-and-page-to-components.md.
26
+ */
27
+
28
+ import { AdiaElement } from '../../core/element.js';
29
+
30
+ class AdiaPage extends AdiaElement {
31
+ static properties = {
32
+ scroll: { type: Boolean, default: false, reflect: true },
33
+ maxWidth: { type: String, default: '', attribute: 'max-width', reflect: true },
34
+ padding: { type: String, default: '', reflect: true },
35
+ stickyHeader: { type: Boolean, default: false, attribute: 'sticky-header', reflect: true },
36
+ };
37
+
38
+ static template = () => null;
39
+
40
+ #sentinel = null;
41
+ #observer = null;
42
+
43
+ connected() {
44
+ if (this.stickyHeader) this.#installSticky();
45
+ }
46
+
47
+ disconnected() {
48
+ this.#teardownSticky();
49
+ }
50
+
51
+ render() {
52
+ // Sticky-header attribute changes between renders → install / tear down.
53
+ if (this.stickyHeader && !this.#sentinel) this.#installSticky();
54
+ if (!this.stickyHeader && this.#sentinel) this.#teardownSticky();
55
+ }
56
+
57
+ #installSticky() {
58
+ const header = this.querySelector(':scope > :is(header, header-ui)');
59
+ if (!header) return;
60
+
61
+ if (!this.#sentinel) {
62
+ this.#sentinel = document.createElement('div');
63
+ this.#sentinel.setAttribute('data-page-sentinel', '');
64
+ this.#sentinel.style.cssText = 'height: 0; width: 0; pointer-events: none;';
65
+ header.insertAdjacentElement('beforebegin', this.#sentinel);
66
+ }
67
+
68
+ if (!this.#observer) {
69
+ this.#observer = new IntersectionObserver((entries) => {
70
+ this.toggleAttribute('data-header-stuck', !entries[0].isIntersecting);
71
+ }, { threshold: 0 });
72
+ }
73
+
74
+ this.#observer.observe(this.#sentinel);
75
+ }
76
+
77
+ #teardownSticky() {
78
+ this.#observer?.disconnect();
79
+ this.#observer = null;
80
+ this.#sentinel?.remove();
81
+ this.#sentinel = null;
82
+ this.removeAttribute('data-header-stuck');
83
+ }
84
+ }
85
+
86
+ customElements.define('page-ui', AdiaPage);
87
+
88
+ export { AdiaPage };
@@ -0,0 +1,148 @@
1
+ # Edit this file; run `npm run build:components` to regenerate a2ui.json.
2
+ $schema: ../../../../scripts/schemas/component.yaml.schema.json
3
+ name: AdiaPage
4
+ tag: page-ui
5
+ component: Page
6
+ category: container
7
+ version: 1
8
+ description: |
9
+ Page container. Holds page-level chrome — header / content / footer —
10
+ and manages max-width clamps, padding scale, optional scroll-container,
11
+ and an optional sticky-header sentinel. Compose with the slot
12
+ primitives (`<header-ui>`, `<section-ui>`, `<footer-ui>`); the page's
13
+ @scope rules style them. Drop in directly, or nest inside an
14
+ `<app-shell-ui>`'s main column.
15
+ props:
16
+ scroll:
17
+ description: |
18
+ Sets the page as a scroll container. `overflow-y: auto`, full
19
+ height, contained overscroll. Use when the page IS the scroll
20
+ surface (standalone pages); leave off when nested inside a parent
21
+ that already manages scroll (e.g. inside an `<app-shell-ui>`'s
22
+ main `<section>`).
23
+ type: boolean
24
+ default: false
25
+ reflect: true
26
+ maxWidth:
27
+ description: |
28
+ Token-bound max-width clamp. `prose` (65ch) for reading pages,
29
+ `narrow` (80ch) for tight forms, `wide` (1080px) for data-rich
30
+ pages, `full` for unconstrained. Empty defers to parent / 100%.
31
+ Centered horizontally via `margin-inline: auto`.
32
+ type: string
33
+ default: ""
34
+ enum:
35
+ - ""
36
+ - prose
37
+ - narrow
38
+ - wide
39
+ - full
40
+ attribute: max-width
41
+ reflect: true
42
+ padding:
43
+ description: |
44
+ Page-padding scale from the spacing system. Accepts `0`–`8`
45
+ (mapped to `--a-space-N`). Empty (no value) applies the
46
+ `--page-padding-default` token; `0` removes padding.
47
+ type: string
48
+ default: ""
49
+ reflect: true
50
+ stickyHeader:
51
+ description: |
52
+ Installs an IntersectionObserver sentinel before the first
53
+ `<header>` / `<header-ui>` child. When the sentinel scrolls out
54
+ of view the page gains `[data-header-stuck]`, which the CSS
55
+ uses to add a border + shadow to the header. No-op when no
56
+ header is present.
57
+ type: boolean
58
+ default: false
59
+ attribute: sticky-header
60
+ reflect: true
61
+ events: {}
62
+ slots:
63
+ default:
64
+ description: |
65
+ Composes from the slot primitives — `<header-ui>` (page header),
66
+ `<section-ui>` (main content), optional `<footer-ui>`. Native
67
+ `<header>` / `<section>` / `<footer>` also work; the @scope rules
68
+ target both via `:where(header, header-ui)`.
69
+ states:
70
+ - name: idle
71
+ description: Default, ready for interaction.
72
+ - name: header-stuck
73
+ description: Header has scrolled past the sentinel; visual cue applied.
74
+ traits: []
75
+ tokens: {}
76
+ a2ui:
77
+ rules: []
78
+ anti_patterns: []
79
+ examples:
80
+ - name: prose-page
81
+ description: Reading page with sticky header, 65ch column, padding scale 6.
82
+ a2ui: >-
83
+ [
84
+ {
85
+ "id": "root",
86
+ "component": "Page",
87
+ "stickyHeader": true,
88
+ "maxWidth": "prose",
89
+ "padding": "6",
90
+ "children": ["hdr", "body"]
91
+ },
92
+ {
93
+ "id": "hdr",
94
+ "component": "Header",
95
+ "children": ["title"]
96
+ },
97
+ {
98
+ "id": "title",
99
+ "component": "Text",
100
+ "variant": "display",
101
+ "textContent": "Reading Page"
102
+ },
103
+ {
104
+ "id": "body",
105
+ "component": "Section",
106
+ "children": []
107
+ }
108
+ ]
109
+ - name: dashboard-page
110
+ description: Wide-clamp dashboard page acting as a scroll container.
111
+ a2ui: >-
112
+ [
113
+ {
114
+ "id": "root",
115
+ "component": "Page",
116
+ "scroll": true,
117
+ "maxWidth": "wide",
118
+ "padding": "4",
119
+ "children": ["hdr", "body"]
120
+ },
121
+ {
122
+ "id": "hdr",
123
+ "component": "Header",
124
+ "children": []
125
+ },
126
+ {
127
+ "id": "body",
128
+ "component": "Section",
129
+ "children": []
130
+ }
131
+ ]
132
+ keywords:
133
+ - page
134
+ - layout
135
+ - container
136
+ - scroll
137
+ - sticky-header
138
+ - max-width
139
+ - padding
140
+ - prose-page
141
+ - dashboard-page
142
+ synonyms: {}
143
+ related:
144
+ - app-shell
145
+ - card
146
+ - section
147
+ - header
148
+ - footer
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://adiaui.dev/a2ui/v0_9/components/Section.json",
4
4
  "title": "Section",
5
- "description": "Content section inside a Card. Groups related content between Header and Footer.",
5
+ "description": "Content section styled by closest container parent (Card / Drawer / Modal / Page / AppShell). Groups related content between Header and Footer. `[scroll]` only kicks in inside Card / Drawer / Modal — Page and AppShell own their own scroll containers.",
6
6
  "type": "object",
7
7
  "allOf": [
8
8
  {
@@ -6,7 +6,7 @@ tag: section-ui
6
6
  component: Section
7
7
  category: container
8
8
  version: 1
9
- description: Content section inside a Card. Groups related content between Header and Footer.
9
+ description: Content section styled by closest container parent (Card / Drawer / Modal / Page / AppShell). Groups related content between Header and Footer. `[scroll]` only kicks in inside Card / Drawer / Modal — Page and AppShell own their own scroll containers.
10
10
  props:
11
11
  scroll:
12
12
  description: Enable overflow scrolling
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adia-ai/web-components",
3
- "version": "0.0.24",
3
+ "version": "0.0.26",
4
4
  "description": "AdiaUI web components — vanilla custom elements. A2UI runtime (renderer, registry, streams, wiring) lives in @adia-ai/a2ui-utils.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -26,6 +26,7 @@
26
26
  @import "../components/range/range.css";
27
27
  @import "../components/tree/tree.css";
28
28
  @import "../components/pane/pane.css";
29
+ @import "../components/page/page.css";
29
30
  @import "../components/chat/chat-input.css";
30
31
  @import "../components/chat/chat.css";
31
32
  @import "../components/drawer/drawer.css";