@mtdt/observeops-ds-spec 0.1.3 → 0.1.5

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 CHANGED
@@ -106,3 +106,6 @@ block is the contract violation; composing DS parts into an undocumented screen
106
106
  - [ ] The page is composed from a recipe + the right layout shell/regions.
107
107
  - [ ] a11y honoured (labels, keyboard, aria).
108
108
  - [ ] Any deviation was **asked**, not guessed.
109
+ - [ ] **Verified the RENDER**, not just the rules — run the conformance checker
110
+ (`conformance/ds-conformance.mjs <page>` in the spec package, or the MCP `validate_render`); fix every
111
+ off-token colour (brand must be navy, not blue/cyan), off-scale spacing, and `mds-*`. Aim for ≥ 90.
@@ -27,15 +27,15 @@
27
27
  "$note": "The structural layer — the 12-col grid (MRow/MCol) + app shell, layout shells, screen regions & panel behaviours (layout/layouts.json; Storybook: Foundations/Layout/*). foundation/*.md = a page-by-page PRODUCT coverage sweep per element (which pages/flows use each variant + findings + best practices)."
28
28
  },
29
29
  "counts": {
30
- "components": 26,
31
- "families": 15,
30
+ "components": 27,
31
+ "families": 16,
32
32
  "coverage": {
33
- "props": 19,
33
+ "props": 20,
34
34
  "apis": 8,
35
- "states": 26,
35
+ "states": 27,
36
36
  "sizes": 8,
37
- "variants": 23,
38
- "a11y": 26
37
+ "variants": 24,
38
+ "a11y": 27
39
39
  }
40
40
  },
41
41
  "families": {
@@ -45,6 +45,9 @@
45
45
  "Date & Time Pickers": [
46
46
  "date-time-pickers"
47
47
  ],
48
+ "Divider": [
49
+ "divider"
50
+ ],
48
51
  "Filters": [
49
52
  "filters"
50
53
  ],
@@ -315,6 +318,45 @@
315
318
  "a11y": true
316
319
  }
317
320
  },
321
+ {
322
+ "id": "divider",
323
+ "display": "Divider",
324
+ "tier": "atom",
325
+ "family": "Divider",
326
+ "category": null,
327
+ "status": "core",
328
+ "summary": "A thin rule that marks a semantic break — horizontal between stacked sections, vertical between inline items.",
329
+ "selectHint": "Separate sections (horizontal) or inline items (vertical). If you only need space, use margin, not a divider.",
330
+ "variants": [
331
+ "horizontal",
332
+ "vertical",
333
+ "dashed",
334
+ "with-text",
335
+ "darkVariant"
336
+ ],
337
+ "registry": "components/registry/divider.json",
338
+ "spec": "components/specs/divider.md",
339
+ "storybook": "Atoms/Divider",
340
+ "related": [
341
+ "table",
342
+ "toolbars",
343
+ "form-item"
344
+ ],
345
+ "knownIssueCount": 1,
346
+ "tokenCount": 5,
347
+ "has": {
348
+ "props": true,
349
+ "states": true,
350
+ "sizes": false,
351
+ "variants": true,
352
+ "decisionFlow": true,
353
+ "do": true,
354
+ "dont": true,
355
+ "tokensUsed": true,
356
+ "apis": false,
357
+ "a11y": true
358
+ }
359
+ },
318
360
  {
319
361
  "id": "drawer",
320
362
  "display": "Drawer",
@@ -347,7 +347,13 @@
347
347
  "changelog": [
348
348
  "2026-06-05: added; variants corrected to distinct set + primary-alt; navy-fallback flagged (F1); light/dark verified.",
349
349
  "2026-06-06: enhanced doc standard — anatomy/behaviors/content/accessibility (F3/F4/F5), related, changelog.",
350
- "2026-06-07: thorough button audit — added icon buttons (shape=circle 218x + squared-button 365x) story + section; findings F6 (inverted shadow) + F7 (circle not circular); noted FlotoLink + segmented-control relatives."
350
+ "2026-06-07: thorough button audit — added icon buttons (shape=circle 218x + squared-button 365x) story + section; findings F6 (inverted shadow) + F7 (circle not circular); noted FlotoLink + segmented-control relatives.",
351
+ "2026-06-30: fixed the `block` (full-width) modifier — the custom-element host defaulted to inline so width:100% had nothing to fill; added :host([block]){display:block;width:100%} (+ the showcase stage now expands for any [block] element). Block buttons now span their container.",
352
+ "2026-07-01: fixed font-weight 500→400 (owner) — the product/Storybook button is Ant's default 400 (@btn-font-weight override is commented out; no LESS sets a weight). Button had never been diff-gated, so the wrong weight was never caught.",
353
+ "2026-07-01: fixed the large size (owner) — it was inheriting the default 0.8rem font. The product large button keeps the DEFAULT height/padding but bumps the font to --font-size-lg (1rem) (@font-size-lg: @text-regular; @btn-font-size-lg: @font-size-lg) — bigger text, same box height. .s-large now sets font-size: var(--font-size-lg, 1rem).",
354
+ "2026-07-01: built specs/button.spec.mjs and diff-gated the button for the first time (13 scenarios, light+dark) — the gate caught the small-button padding (12px→7px, now Ant's 7px) and confirms weight 400 / radius 4px / Poppins / large-1rem. Two intentional divergences declared: ghost (navy vs Ant dark-bg white) and primary-hover (DS token 0.7 vs product render 0.89).",
355
+ "2026-07-01: added the icon+text button example (owner asked) — the product has 83× leading-icon+label buttons (MIcon in the slot) and 538× icon-only (circle/squared). obs-button already supports both via the default slot (.btn is inline-flex gap:6px); showcased both in the Elements gallery. Note: the Storybook button story only shows icon-ONLY.",
356
+ "2026-07-01: replaced the placeholder button-example icons with the REAL product icons (from src/assets/icons/icons.js); also added a dedicated Icons page (542 Font Awesome Light glyphs) with search + copy SVG/PNG + download."
351
357
  ],
352
358
  "storybook": "Atoms/Button",
353
359
  "figma": {
@@ -365,4 +371,4 @@
365
371
  "slots": {
366
372
  "default": "button label / content (text and/or an icon)"
367
373
  }
368
- }
374
+ }
@@ -5,6 +5,18 @@
5
5
  "family": "Popover & Tooltip",
6
6
  "status": "stable",
7
7
  "summary": "The product's chart & widget hover tooltips — a distinct family from MTooltip, owned by the chart layer (Highcharts TooltipBuilder, graph canvases, widget Vue components), not DS components. ~28 reference reproductions cover every mechanism.",
8
+ "props": {
9
+ "kind": {
10
+ "type": "string",
11
+ "default": "bar",
12
+ "description": "which chart/widget or live-graph tooltip to reproduce (28 kinds — bar, donut, heatmap, …, graph-node, graph-edge, …)"
13
+ },
14
+ "block": {
15
+ "type": "boolean",
16
+ "default": false,
17
+ "description": "stretch the card to its container width instead of its intrinsic per-kind width (preview how a tooltip fills a wide surface)"
18
+ }
19
+ },
8
20
  "variants": [
9
21
  {
10
22
  "name": "bar-series",
@@ -405,5 +417,9 @@
405
417
  ],
406
418
  "doc": "Molecules/Data-Viz Tooltips/Accessibility",
407
419
  "$note": "Catalogue-wide gap SF-001 = no visible :focus-visible ring; tracked in findings/."
408
- }
409
- }
420
+ },
421
+ "changelog": [
422
+ "2026-06-29: added to the Elements site — obs-dataviz-tooltip: all 28 chart/widget + live-graph tooltip reference reproductions (kind prop), real tokens (--chart-tooltip-background, --topology-graph-tooltip-bg, --severity-*).",
423
+ "2026-06-30: added a `block` prop (Full width) — the card stretches to its container instead of its intrinsic per-kind width; exposed as a Playground toggle + a Full-width Examples group, and documented kind/block in Details."
424
+ ]
425
+ }
@@ -5,6 +5,38 @@
5
5
  "family": "Date & Time Pickers",
6
6
  "status": "stable",
7
7
  "summary": "The product's date/time selection family. The hero is TimeRangePicker (42×) — the observability time-range control (relative presets + absolute custom range). MDatePicker (10×, wraps a-date-picker) is the form date-time field, in practice ALWAYS used with show-time. MTimePicker wraps a-time-picker (12-hour) but is rarely used standalone. DateTimePopover is a lighter custom-range-only popover.",
8
+ "props": {
9
+ "kind": {
10
+ "type": "string",
11
+ "default": "range",
12
+ "description": "which family member to render — range (the 42× hero TimeRangePicker), range-presets (hide-custom, 24×), field-datetime / field-date / field-time (MDatePicker/MTimePicker fields), slider (TimeRangeSlider scrubber)"
13
+ },
14
+ "disabled": {
15
+ "type": "boolean",
16
+ "default": false,
17
+ "description": "non-interactive (greyed field / inert trigger)"
18
+ },
19
+ "bordered": {
20
+ "type": "boolean",
21
+ "default": false,
22
+ "description": "range trigger gets a --border-color frame (1×)"
23
+ },
24
+ "allowClear": {
25
+ "type": "boolean",
26
+ "default": false,
27
+ "description": "attr allow-clear — a times-circle × on the range pill that resets the selection (7×)"
28
+ },
29
+ "empty": {
30
+ "type": "boolean",
31
+ "default": false,
32
+ "description": "start with no selection — shows the calendar icon + “Select Time” placeholder"
33
+ },
34
+ "placeholder": {
35
+ "type": "string",
36
+ "default": "",
37
+ "description": "field placeholder text (defaults per kind)"
38
+ }
39
+ },
8
40
  "variants": [
9
41
  {
10
42
  "name": "TimeRangePicker",
@@ -292,5 +324,12 @@
292
324
  ],
293
325
  "doc": "Molecules/Date & Time Pickers/Accessibility",
294
326
  "$note": "Catalogue-wide gap SF-001 = no visible :focus-visible ring; tracked in findings/."
295
- }
296
- }
327
+ },
328
+ "changelog": [
329
+ "2026-06-30: added to the Elements site — obs-date-time-picker, the date/time family as one element via a `kind` prop: range (the 42× TimeRangePicker hero — interactive pill → presets → Custom dual-month calendar with From/To time menus), range-presets (hide-custom 24×), field-datetime/field-date/field-time (MDatePicker/MTimePicker fields + disabled), slider (draggable TimeRangeSlider). Reference reproductions with real tokens (--timerange-*, --calendar-selected-day-background-color, --slider-tracker, --dropdown-*); gated by cross-render token check (light+dark) + driven open/custom/disabled states.",
330
+ "2026-06-30: made the MDatePicker/MTimePicker FIELD kinds interactive (owner caught they were static, non-functional) — field-date/field-datetime open a single-month calendar (today ringed, allow-clear ×), field-datetime adds a 12h time field, field-time opens a 12h time menu; reset popups on kind-change. Playground fixes: slider now fills the stage width; tall picker panels no longer clip (stage top-aligns + overflow visible + min-height).",
331
+ "2026-06-30: reworked the MDatePicker/MTimePicker field popovers to match the real Ant render (owner compared to Storybook) — a connected card with the value input on top, the calendar (today navy-filled), a footer (Now · select time/select date · Ok), and a proper 3-COLUMN time spinner (HH · MM · AM/PM, selected row banded + scrolled to top) instead of a flat time dropdown. field-date = Now·Ok, field-time = the spinner alone.",
332
+ "2026-06-30: matched the per-variant footer pattern (owner) — date-only shows a single centered \"Today\" link (not Now·Ok); time-only keeps Now·Ok; date-time keeps Now·select-time/date·Ok with the time spinner opening in the same popover.",
333
+ "2026-06-30: fixed field-calendar day states (owner) — selected (filled navy) and today (navy RING) were rendering identically; now distinct, plus a hover background on days. Applies to field-date and field-datetime (refactored day cells from inline styles to CSS classes so :hover works)."
334
+ ]
335
+ }
@@ -0,0 +1,106 @@
1
+ {
2
+ "name": "divider",
3
+ "component": "MDivider",
4
+ "display": "Divider",
5
+ "tier": "atom",
6
+ "family": "Divider",
7
+ "source": "mkit",
8
+ "status": "core",
9
+ "maturity": "stable",
10
+ "summary": "A thin rule that marks a semantic break between content — horizontal between stacked sections, vertical between inline items.",
11
+ "selectHint": "Use to separate sections (horizontal) or inline items (vertical). If you only need space, use margin instead.",
12
+ "whenToUse": "A real boundary between two groups of content — not merely spacing.",
13
+ "insteadOf": ["a hardcoded 1px border div", "extra margin used as a fake separator"],
14
+ "variants": [
15
+ { "name": "horizontal", "what": "Full-width rule between stacked sections (default).", "usage": "126×" },
16
+ { "name": "vertical", "what": "Inline separator between items in a row (type=\"vertical\").", "usage": "7×" },
17
+ { "name": "dashed", "what": "Dashed prop — but renders SOLID (no-op, F1) due to the DS background override.", "usage": "0× (kit-supported; no visible effect — F1)" },
18
+ { "name": "with-text", "what": "Labelled section rule (slot text + orientation).", "usage": "0× (kit-supported, unused)" },
19
+ { "name": "darkVariant", "what": "Tuned for a dark background.", "usage": "rare" }
20
+ ],
21
+ "sizes": [
22
+ { "name": "default", "value": "1px", "note": "1px hairline; not size-configurable." }
23
+ ],
24
+ "states": [
25
+ { "name": "default", "what": "Static decorative rule; no interactive states." }
26
+ ],
27
+ "props": {
28
+ "type": { "type": "string", "default": "horizontal", "enum": ["horizontal", "vertical"], "note": "Vertical is an inline separator." },
29
+ "dashed": { "type": "boolean", "default": false, "note": "Dashed instead of solid." },
30
+ "orientation": { "type": "string", "default": "", "enum": ["", "start", "end"], "note": "Label position when a with-text divider is used (default center); start→left, end→right." },
31
+ "darkVariant": { "type": "boolean", "default": false, "note": "Tuned for a dark background." }
32
+ },
33
+ "events": [],
34
+ "slots": { "default": "Optional label text — renders a with-text divider." },
35
+ "decisionFlow": [
36
+ "Just want space between elements (no real boundary)? -> use margin/spacing, NOT a divider (don't overuse dividers).",
37
+ "Separating items sitting in a row (inline metadata, toolbar actions, compare columns)? -> type=\"vertical\".",
38
+ "Does the section below need a label (a titled group)? -> a with-text divider (slot text + orientation).",
39
+ "Otherwise separating stacked blocks/sections? -> the default horizontal rule.",
40
+ "Modifiers: darkVariant = tuned for a dark background. (dashed is a no-op today, F1 — it renders solid.)"
41
+ ],
42
+ "usageRules": {
43
+ "horizontal": {
44
+ "useWhen": "two vertically-stacked groups need a clear boundary — form sections, card regions, header above body",
45
+ "dontUse": "you only need spacing (use margin), or the groups are already separate cards",
46
+ "example": "the rule between Connection details and Advanced options in a settings form",
47
+ "asSeenIn": "settings log-parser forms, NCM device-template-form, integration lama-profile-form"
48
+ },
49
+ "vertical": {
50
+ "useWhen": "items sit in a row and need a light separator — inline metadata, compare columns, a small action group",
51
+ "dontUse": "the items are stacked (use horizontal), or a gap reads clearly enough",
52
+ "example": "separating status · version · updated-time on one line",
53
+ "asSeenIn": "NCM backup-compare-form / device-policy-breakdown, alert ncm-compare-diff, flow-analytics-card"
54
+ },
55
+ "dashed": {
56
+ "useWhen": "don't rely on it today — the dashed prop renders SOLID (F1)",
57
+ "dontUse": "any case needing a visible dashed line, until F1 is fixed",
58
+ "example": "no visible effect: the DS .ant-divider background override paints over Ant's dashed border"
59
+ },
60
+ "with-text": {
61
+ "useWhen": "the rule also titles the group below it and a full heading is too heavy",
62
+ "dontUse": "the section already has a heading (the label would duplicate it)",
63
+ "example": "supported; not currently used in the product. orientation=start|end moves the label"
64
+ },
65
+ "darkVariant": {
66
+ "useWhen": "the divider sits on a dark background and the default line is too faint",
67
+ "dontUse": "on the normal page surface (the default already resolves per theme)",
68
+ "example": "a divider inside a dark-surfaced panel"
69
+ }
70
+ },
71
+ "usage": {
72
+ "total": 133,
73
+ "files": 93,
74
+ "byType": { "horizontal": 126, "vertical": 7 },
75
+ "byModule": { "settings": 31, "components (shared)": 14, "alert": 10, "ncm-approval": 6, "ncm": 6, "topology": 5, "apm": 4 },
76
+ "note": "byType is exact from the sweep (type=\"vertical\" appears 7×; the rest default to horizontal). dashed and with-text/orientation have zero product uses."
77
+ },
78
+ "do": [
79
+ "Use one rule per boundary — never stack two dividers.",
80
+ "Try whitespace/margin first; a divider is a semantic break, not a spacer.",
81
+ "Let the line inherit the theme (var(--border-color)); don't hardcode a colour.",
82
+ "Use type=\"vertical\" for inline separators, horizontal for stacked sections."
83
+ ],
84
+ "dont": [
85
+ "Don't use a divider just to add space (use margin).",
86
+ "Don't stack dividers or box every section — it reads noisy.",
87
+ "Don't rely on a divider alone to communicate meaning (pair it with text/state)."
88
+ ],
89
+ "a11y": {
90
+ "summary": "Decorative separator — Ant renders role=\"separator\"; conveys a thematic break without interactive noise.",
91
+ "issues": [],
92
+ "doc": "Atoms/Divider/Accessibility",
93
+ "notes": "A rule is a visual break, not a landmark/heading — give navigable sections a real heading. Line is a low-contrast hairline by design; never rely on it alone to convey meaning."
94
+ },
95
+ "knownIssues": [
96
+ "F1 (low): `dashed` renders SOLID — no visible effect. The DS override `.ant-divider { background: var(--border-color) }` (general.less:213, form.less:448) paints a solid 1px line over Ant's dashed `border-top`, so `:dashed=\"true\"` does nothing. Verified by computed style: dashed element has borderTopStyle=dashed AND background=--border-color on a 1px-high box → the solid fill wins. Fix: drop the background fill so the dashed border shows, or paint a dashed line explicitly. 0× product use."
97
+ ],
98
+ "tokensUsed": ["--border-color", "--page-text-color", "--neutral-lightest", "--action-dropdown-divider", "--nav-divider-bg"],
99
+ "related": ["table", "toolbars", "form-item"],
100
+ "changelog": [
101
+ "2026-07-04 — Added to the DS (first catalogue). Swept 133×/93 files: 126 horizontal + 7 vertical; with-text kit-supported but unused. Base line verified as background: var(--border-color) (light + dark). Decision-grade Usage authored + mirrored here.",
102
+ "2026-07-04 — F1 (owner-caught): `dashed` is a no-op — it renders solid because the DS `.ant-divider { background: var(--border-color) }` override paints over Ant's dashed border. Flagged in the Dashed story + Usage + here; measured by computed style."
103
+ ],
104
+ "storybook": "Atoms/Divider",
105
+ "figma": { "status": "not-started", "component": "Divider" }
106
+ }
@@ -51,7 +51,13 @@
51
51
  "what": "not interactive"
52
52
  }
53
53
  ],
54
- "props": "Filters is MULTI-ARCHETYPE — there is no single component prop list. Per-archetype prop/event contracts are in `apis` (e.g. apis.FilterBar = value/fieldSchema/defaultChips + change) and the `archetypes` block.",
54
+ "props": {
55
+ "kind": {
56
+ "type": "string",
57
+ "default": "bar",
58
+ "description": "which filter archetype to render — bar (FlotoFilterBar ~50×), expression (FiltersContainer 32×), quick (preset menu), row (multi-selects + Reset/Apply), vertical (faceted sidebar). Filters is MULTI-ARCHETYPE: per-archetype prop/event contracts live in the apis block below, not as element props."
59
+ }
60
+ },
55
61
  "renders": "REFERENCE REPRODUCTIONS — the live filters are store-bound (FilterCondition is 500+ lines). The Filter bar reproduction is fully interactive.",
56
62
  "archetypes": {
57
63
  "ExpressionBuilder": {
@@ -151,5 +157,11 @@
151
157
  ],
152
158
  "doc": "Molecules/Filters/Accessibility",
153
159
  "$note": "Catalogue-wide gap SF-001 = no visible :focus-visible ring; tracked in findings/."
154
- }
155
- }
160
+ },
161
+ "changelog": [
162
+ "2026-07-01: added to the Elements site — obs-filters, the filtering family as one element via a `kind` prop: bar (FlotoFilterBar ~50× — interactive field·operator·value chips + Match All/Any + Clear All), expression (FiltersContainer 32× — nested AND/OR query builder popover with Pre/Post tabs, groups, conditions, Reset/Clear/Apply), quick (preset menu), row (multi-selects + Reset/Apply), vertical (faceted sidebar — search + collapsible checkbox+count groups). Reference reproductions with real tokens; gated by cross-render token check (light+dark) + driven chip/expression/vertical interaction.",
163
+ "2026-07-01: made the row variant full-width (owner) — it was shrink-wrapping to a narrow box; now the host is block width:100% (like bar) and .frow fills the container in both the playground and examples.",
164
+ "2026-07-01: fixed buttons to match the product Button (border-radius 6px→4px via --btn-radius, primary weight 600→500) and added a native-control font-family reset — the <select>/<input> were rendering in the UA font (Arial), now Poppins.",
165
+ "2026-07-01: button font-weight 500→400 to match the real product Button (Ant default 400)."
166
+ ]
167
+ }
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "layout-app-shell",
3
+ "component": "Layout (views/layouts/main.vue)",
4
+ "display": "App shell",
5
+ "tier": "foundation",
6
+ "section": "Foundations",
7
+ "family": "Layout",
8
+ "status": "stable",
9
+ "summary": "The authenticated app frame — NavBar (left rail, 50px, --nav-panel-bg) + Header (top, 55px) + the one scrolling content panel + a shell-level overlay layer (toasts, OmniBox, portals). The default shell for every in-app page. Toggle the chrome to see how the other shells (EmptyLayout, LoginLayout) drop regions.",
10
+ "props": {
11
+ "sidebar": {
12
+ "type": "boolean",
13
+ "default": "false",
14
+ "note": "show the left NavBar rail"
15
+ },
16
+ "header": {
17
+ "type": "boolean",
18
+ "default": "false",
19
+ "note": "show the top Header"
20
+ },
21
+ "overlay": {
22
+ "type": "boolean",
23
+ "default": "false",
24
+ "note": "show the shell-level overlay (a toast)"
25
+ },
26
+ "empty": {
27
+ "type": "boolean",
28
+ "default": "false",
29
+ "note": "swap the page body for an empty-state prompt"
30
+ },
31
+ "anatomy": {
32
+ "type": "boolean",
33
+ "default": "false",
34
+ "note": "render the annotated region-callout diagram instead of the interactive shell"
35
+ }
36
+ },
37
+ "regions": [
38
+ "NavBar — left rail, @nav-icon-width 50px, --nav-panel-bg; the module icons (active = --primary pill)",
39
+ "Header — top, @header-height 55px; brand logo · global search · notifications · user menu",
40
+ "Content panel — MLayoutContent in FlotoScrollView; the routed page slot, the only scrolling region",
41
+ "Overlay layer — OmniBox, notifications, PortalTargets; shell-level, above the content"
42
+ ],
43
+ "do": [
44
+ "Use the Layout shell for every authenticated app page (the default — no route override needed).",
45
+ "Keep the content panel the only scrolling region.",
46
+ "Mount global/portal UI (toasts, OmniBox) at the overlay layer, above the content."
47
+ ],
48
+ "dont": [
49
+ "Don't put the breadcrumb/back in the Header — that lives in the page header.",
50
+ "Don't add a second scrolling container inside the content panel."
51
+ ],
52
+ "tokensUsed": [
53
+ "--nav-panel-bg",
54
+ "--border-color",
55
+ "--page-background-color",
56
+ "--primary",
57
+ "--code-tag-background-color",
58
+ "--secondary-green"
59
+ ],
60
+ "related": [
61
+ "layout-screen-regions",
62
+ "layout-grid"
63
+ ],
64
+ "storybook": "Foundations/Layout/App shell",
65
+ "a11y": {
66
+ "summary": "Structural reference, not interactive. In the product the regions map to landmarks — NavBar = <nav>, Header = <header>, content = <main>; the content panel is the only scroll container, so focus order is nav → header → content.",
67
+ "issues": [
68
+ "The overlay layer (toasts/OmniBox) must manage focus + ESC at the product level."
69
+ ]
70
+ },
71
+ "knownIssues": [
72
+ "Documentation diagram, not the live shell — the product Layout (src/views/layouts/main.vue) is the source of truth."
73
+ ],
74
+ "changelog": [
75
+ "2026-06-29: added to the Elements site (Foundations › Layout) — Anatomy diagram + interactive chrome toggles; render-first from the Storybook story.",
76
+ "2026-06-29: playground + examples widths fixed to fill the stage.",
77
+ "2026-06-29: Usage enriched — when-to-use + where-it's-used."
78
+ ],
79
+ "whenToUse": "Every signed-in page renders into this frame — you don't opt in. Switch to another shell only for login, print/export, or system pages.",
80
+ "usedIn": [
81
+ "Every authenticated in-app page — the default for ~all routes.",
82
+ "Drop the chrome via a different shell: login, report export, upgrade/restore."
83
+ ]
84
+ }
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "layout-grid",
3
+ "component": "MRow / MCol",
4
+ "display": "Grid",
5
+ "tier": "foundation",
6
+ "section": "Foundations",
7
+ "family": "Layout",
8
+ "status": "stable",
9
+ "summary": "The product's 12-column layout grid — MRow / MCol (wrappers over Ant a-row/a-col), ~540/~522 files. MCol :size is a span out of 12: 6 = half (the default form field), 12 = full, 3 = quarter, 4 = third, 2 = sixth. :gutter=\"16\" for form rows; :gutter=\"0\" only for structural wrappers; auto-size shrinks a column to its content.",
10
+ "props": {
11
+ "size": {
12
+ "type": "number",
13
+ "default": "6",
14
+ "enum": [
15
+ "12",
16
+ "6",
17
+ "4",
18
+ "3",
19
+ "2"
20
+ ],
21
+ "note": "column span (out of 12); the row fills with 12/size equal columns"
22
+ },
23
+ "gutter": {
24
+ "type": "boolean",
25
+ "default": "false",
26
+ "note": "16px gutter between columns (the form-row default)"
27
+ },
28
+ "auto-size": {
29
+ "type": "boolean",
30
+ "default": "false",
31
+ "note": "show the 'filling field + content-width action buttons' row"
32
+ }
33
+ },
34
+ "do": [
35
+ "Use MRow/MCol for all form field layouts.",
36
+ "Sizes: 6 = half, 12 = full, 3 = quarter, 4 = third.",
37
+ "gutter 16 for form rows; gutter 0 only for structural wrappers.",
38
+ "auto-size for action/compact cells; align inside a cell with flex utilities."
39
+ ],
40
+ "dont": [
41
+ "Don't hand-roll a flex grid for form layouts.",
42
+ "Don't put a gutter on full-height structural wrappers (use gutter 0).",
43
+ "Don't nest deep grids where a single MRow of sized MCols works."
44
+ ],
45
+ "tokensUsed": [
46
+ "@padding-md",
47
+ "--border-color",
48
+ "--code-tag-background-color",
49
+ "--page-background-color",
50
+ "--primary"
51
+ ],
52
+ "related": [
53
+ "layout-app-shell",
54
+ "layout-screen-regions"
55
+ ],
56
+ "storybook": "Foundations/Layout/Grid",
57
+ "a11y": {
58
+ "summary": "Layout primitive — no semantics of its own; MRow/MCol are presentational wrappers. The fields/controls placed inside carry the semantics and tab order.",
59
+ "issues": []
60
+ },
61
+ "knownIssues": [
62
+ "Diagram reproduces the visual grid with CSS; the product uses MRow/MCol (wrappers over Ant a-row/a-col)."
63
+ ],
64
+ "changelog": [
65
+ "2026-06-29: added — the 12-column splits + interactive size/gutter/auto-size; render-first from the story.",
66
+ "2026-06-29: examples width fixed (cells were collapsing to content width).",
67
+ "2026-06-29: Usage enriched — when-to-use + where-it's-used.",
68
+ "2026-07-01: primary button weight 600→500 to match the product Button; native-control font reset.",
69
+ "2026-07-01: button font-weight 500→400 (product Button is 400)."
70
+ ],
71
+ "whenToUse": "The default way to lay out form fields and any content needing predictable column proportions — 6 = half a row, 12 = full, with a 16px gutter.",
72
+ "usedIn": [
73
+ "Every form field layout (MRow ~540 files · MCol ~522 files).",
74
+ "Cards, summary rows, split panels — anywhere needing column proportions.",
75
+ "Default form layout is 6 / 6 (two-up); size 12 for textareas / full-width fields."
76
+ ]
77
+ }
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "layout-page-templates",
3
+ "component": "recipes.json",
4
+ "display": "Page templates",
5
+ "tier": "foundation",
6
+ "section": "Foundations",
7
+ "family": "Layout",
8
+ "status": "stable",
9
+ "summary": "The canonical page types ObserveOps repeats, as annotated wireframes inside the app frame — built from the composition recipes. List view (header + toolbar + table + pager) · Form view (field grid) · Detail view (header + tabs + panels) · Dashboard view (picker + time range + widget grid) · Explorer view (left tree/filter + query + results) · Wizard flow (stepper + step + Back/Next) · Graph / Canvas (tree + interactive node graph).",
10
+ "props": {
11
+ "template": {
12
+ "type": "string",
13
+ "default": "list",
14
+ "enum": [
15
+ "list",
16
+ "form",
17
+ "detail",
18
+ "dashboard",
19
+ "explorer",
20
+ "wizard",
21
+ "graph"
22
+ ],
23
+ "note": "which page template wireframe to show"
24
+ }
25
+ },
26
+ "do": [
27
+ "Assemble pages from these archetypes + the per-region component mapping (recipes.json).",
28
+ "Use the List view for the most common index pages; Form/Detail for records.",
29
+ "Graph/Canvas (topology) is its own archetype — not a Dashboard or Explorer."
30
+ ],
31
+ "dont": [
32
+ "Don't invent a new page shape where one of these seven fits.",
33
+ "Don't put a second scrolling region inside the body."
34
+ ],
35
+ "tokensUsed": [
36
+ "--nav-panel-bg",
37
+ "--border-color",
38
+ "--page-background-color",
39
+ "--primary",
40
+ "--code-tag-background-color",
41
+ "--severity-critical",
42
+ "--severity-clear",
43
+ "--severity-warning"
44
+ ],
45
+ "related": [
46
+ "layout-app-shell",
47
+ "layout-screen-regions",
48
+ "layout-shells"
49
+ ],
50
+ "storybook": "Foundations/Layout/Page templates",
51
+ "a11y": {
52
+ "summary": "Composition references — each template names the component per region; those components carry the semantics, headings and tab order.",
53
+ "issues": []
54
+ },
55
+ "knownIssues": [
56
+ "Wireframes, not live pages — assemble from the per-region components (recipes.json)."
57
+ ],
58
+ "changelog": [
59
+ "2026-06-29: added — the 7 canonical page-template wireframes.",
60
+ "2026-06-29: fixed Detail/Explorer/Graph body panes collapsing to zero height (align-items).",
61
+ "2026-06-29: Usage enriched — when-to-use + where-it's-used."
62
+ ],
63
+ "whenToUse": "Pick the page archetype that matches the task, then assemble it from the per-region components (recipes).",
64
+ "usedIn": [
65
+ "List view — inventory / alert / policy lists.",
66
+ "Form view — monitor / policy / credential forms · Detail view — monitor / alert detail.",
67
+ "Dashboard view — dashboards / NOC · Explorer view — log / metric explorers.",
68
+ "Wizard flow — discovery / report setup / 2FA · Graph / Canvas — topology."
69
+ ]
70
+ }
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "layout-panels",
3
+ "component": "panels",
4
+ "display": "Panel behaviours",
5
+ "tier": "foundation",
6
+ "section": "Foundations",
7
+ "family": "Layout",
8
+ "status": "stable",
9
+ "summary": "How panels & overlays open, move and resize. Drawer (slide-over, FlotoDrawer · 146) · Modal (a-modal · 37) · Collapsible (MCollapse · 19) · Expandable rows (9) · Resizable / split (splitpanes · ~3) · Affix / sticky · Dashboard tiles (vue-grid-layout · 5) · Bulk-action bar (fixed bottom · 2) · Popover (20+) · Full-screen / OmniBox overlay.",
10
+ "props": {
11
+ "behaviour": {
12
+ "type": "string",
13
+ "default": "drawer",
14
+ "enum": [
15
+ "drawer",
16
+ "modal",
17
+ "collapse",
18
+ "expand",
19
+ "split",
20
+ "affix",
21
+ "dash",
22
+ "bulkbar",
23
+ "popover",
24
+ "fullscreen"
25
+ ],
26
+ "note": "which panel/overlay behaviour to show"
27
+ }
28
+ },
29
+ "do": [
30
+ "Drawer is the default record surface (forms + deep drill-downs); ESC to close.",
31
+ "Modal for small confirm/collect; Drawer for panel-sized records.",
32
+ "Bulk-action bar appears on selection; Popover for contextual, light content."
33
+ ],
34
+ "dont": [
35
+ "Don't use resizable splits casually (rare — only settings/topology/apm trace).",
36
+ "Don't confuse table column-resize (a grid feature) with a panel behaviour."
37
+ ],
38
+ "tokensUsed": [
39
+ "--border-color",
40
+ "--page-background-color",
41
+ "--primary",
42
+ "--code-tag-background-color",
43
+ "--overlay-bg",
44
+ "--neutral-shadow-light",
45
+ "--neutral-light"
46
+ ],
47
+ "related": [
48
+ "layout-screen-regions",
49
+ "layout-app-shell"
50
+ ],
51
+ "storybook": "Foundations/Layout/Panel behaviours",
52
+ "a11y": {
53
+ "summary": "Behaviour references. In the product: Drawer/Modal trap focus + close on ESC; Popover is aria-described from its anchor; the Bulk-action bar announces the selection count.",
54
+ "issues": []
55
+ },
56
+ "knownIssues": [
57
+ "Behaviour diagrams, not live overlays — the real components own focus-trap / ESC / aria."
58
+ ],
59
+ "changelog": [
60
+ "2026-06-29: added — the 10 panel/overlay behaviours.",
61
+ "2026-06-29: fixed Expandable-rows expanded header/body collapsing to content width.",
62
+ "2026-06-29: Usage enriched — when-to-use + where-it's-used."
63
+ ],
64
+ "whenToUse": "How a surface shows up — editing a record → Drawer; a quick confirm → Modal; optional detail → Collapsible / Expandable rows; the rest are for specific jobs.",
65
+ "usedIn": [
66
+ "Drawer 146 files · Modal 37 · Collapsible 19 · Popover 20+ · Expandable rows 9.",
67
+ "Dashboard tiles 5 · Bulk-action bar 2 · Resizable splits ~3 (settings / topology / apm trace).",
68
+ "Drawer is the default record surface; Modal for small confirms; Bulk-bar appears on selection."
69
+ ]
70
+ }