@mtdt/observeops-ds-spec 0.1.0
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 +102 -0
- package/README.md +73 -0
- package/components/index.json +1270 -0
- package/components/recipes/README.md +41 -0
- package/components/recipes/recipes.json +922 -0
- package/components/registry/README.md +44 -0
- package/components/registry/_schema.json +47 -0
- package/components/registry/button.json +368 -0
- package/components/registry/checkbox.json +177 -0
- package/components/registry/data-viz-tooltips.json +409 -0
- package/components/registry/date-time-pickers.json +296 -0
- package/components/registry/drawer.json +222 -0
- package/components/registry/dropdown-picker.json +388 -0
- package/components/registry/filters.json +155 -0
- package/components/registry/form-item.json +281 -0
- package/components/registry/input.json +277 -0
- package/components/registry/link.json +186 -0
- package/components/registry/loose-tags.json +196 -0
- package/components/registry/menu.json +145 -0
- package/components/registry/modal.json +265 -0
- package/components/registry/navigation.json +425 -0
- package/components/registry/popover.json +216 -0
- package/components/registry/radio.json +238 -0
- package/components/registry/scheduler.json +188 -0
- package/components/registry/select.json +247 -0
- package/components/registry/severity.json +179 -0
- package/components/registry/switch.json +177 -0
- package/components/registry/table.json +275 -0
- package/components/registry/tabs.json +264 -0
- package/components/registry/tag.json +345 -0
- package/components/registry/tags-list.json +115 -0
- package/components/registry/toolbars.json +240 -0
- package/components/registry/tooltip.json +175 -0
- package/components/specs/README.md +72 -0
- package/components/specs/button.md +230 -0
- package/components/specs/checkbox.md +162 -0
- package/components/specs/data-viz-tooltips.md +93 -0
- package/components/specs/date-time-pickers.md +161 -0
- package/components/specs/drawer.md +162 -0
- package/components/specs/dropdown-picker.md +161 -0
- package/components/specs/filters.md +118 -0
- package/components/specs/form-item.md +130 -0
- package/components/specs/input.md +130 -0
- package/components/specs/link.md +131 -0
- package/components/specs/loose-tags.md +139 -0
- package/components/specs/menu.md +88 -0
- package/components/specs/modal.md +176 -0
- package/components/specs/navigation.md +181 -0
- package/components/specs/popover.md +118 -0
- package/components/specs/radio.md +144 -0
- package/components/specs/scheduler.md +133 -0
- package/components/specs/select.md +118 -0
- package/components/specs/switch.md +124 -0
- package/components/specs/table.md +115 -0
- package/components/specs/tabs.md +136 -0
- package/components/specs/tag.md +196 -0
- package/components/specs/tags-list.md +105 -0
- package/components/specs/toolbars.md +108 -0
- package/components/specs/tooltip.md +112 -0
- package/foundation/README.md +39 -0
- package/foundation/layout-shells.md +67 -0
- package/foundation/page-templates.md +69 -0
- package/foundation/panel-behaviours.md +61 -0
- package/foundation/screen-regions.md +62 -0
- package/index.js +75 -0
- package/layout/grid.json +34 -0
- package/layout/layouts.json +310 -0
- package/llms.txt +60 -0
- package/package.json +42 -0
- package/spec.manifest.json +407 -0
- package/tokens/README.md +125 -0
- package/tokens/component.json +34 -0
- package/tokens/kit-accents.json +14 -0
- package/tokens/primitive.json +130 -0
- package/tokens/purpose-map.json +67 -0
- package/tokens/semantic.dark.json +90 -0
- package/tokens/semantic.light.json +90 -0
- package/tokens/structural.json +35 -0
- package/tokens/variables.json +2018 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Navigation β Spec, Findings & Solutions
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Tier** | Molecule |
|
|
6
|
+
| **Maturity** | π’ Stable |
|
|
7
|
+
| **Source** | `layout/navbar.vue` (`FlotoNavBar`) Β· `settings/components/left-menu.vue` Β· `report/components/report-steps.vue` (`ReportSteps`) + `product-setup/components/guide-section-step.vue` + `auth/two-factor-verification.vue` (the steppers β all bespoke, no `MSteps`) Β· `report/components/compliance-breadcrumb.vue` Β· `_base-back-button.vue` (`FlotoBackButton`). |
|
|
8
|
+
| **Storybook** | Molecules/Navigation |
|
|
9
|
+
| **Registry** | [`registry/navigation.json`](../registry/navigation.json) |
|
|
10
|
+
| **Family** | [Navigation](../family-map.md) |
|
|
11
|
+
|
|
12
|
+
## Why this is a family
|
|
13
|
+
|
|
14
|
+
The product's **wayfinding** components β distinct from **Toolbars** (which hold *actions*) and
|
|
15
|
+
**Tabs** (sibling views of one page). Catalogued by archetype.
|
|
16
|
+
|
|
17
|
+
## The archetypes
|
|
18
|
+
|
|
19
|
+
| Archetype | Source | Usage | What it is |
|
|
20
|
+
| --- | --- | --- | --- |
|
|
21
|
+
| **Primary nav** | `FlotoNavBar` | global | left vertical **module** nav (icon + label) |
|
|
22
|
+
| **Side menu** | `settings/left-menu` Β· Log/Topology hierarchy Β· Dashboard Β· Report/saved-views | many | the **left-panel** nav β 4 forms: section Β· tree Β· category-list Β· list/saved-views |
|
|
23
|
+
| **Steps** | `report-steps.vue` Β· `product-setup` guide Β· 2FA | 3 flows | numbered **wizard / stepper** (bespoke, no `MSteps`) |
|
|
24
|
+
| **Breadcrumb** | `compliance-breadcrumb` | β | back + **path trail** |
|
|
25
|
+
| **Back button** | `FlotoBackButton` | 3Γ | a **chevron-left** router link |
|
|
26
|
+
| **Tabs** | `MTab` | 86Γ | *its own family* (Molecules/Tabs) β cross-referenced |
|
|
27
|
+
|
|
28
|
+
### Primary nav
|
|
29
|
+
|
|
30
|
+
- The left vertical **module** sidebar (`MLayoutSider`). **Collapsed 65px** by default (brand mark +
|
|
31
|
+
module icons only); **hover-expands to 170px** (`@mouseover`/`@mouseout` β `pinned`) revealing the
|
|
32
|
+
**ObserveOps** logo + module labels. The **16 modules** come from `visibleMenuItems`
|
|
33
|
+
(role/license-gated): Dashboards, Monitors, Alerts, SLO *(BETA)*, Reports, Topology, NCCM, NetRoute,
|
|
34
|
+
Metric Explorer, Log Explorer, APM Explorer, RUM Explorer, Flow Explorer, Trap Explorer, Audits,
|
|
35
|
+
Settings β each with its registered module icon. **Active** module highlights `--primary` on
|
|
36
|
+
`--code-tag-background-color` with an inset left rule when expanded. `MMenu theme="dark"` +
|
|
37
|
+
`MMenuItem` + `FlotoLink`. **Collapsed β expanded is the primary variant.**
|
|
38
|
+
|
|
39
|
+
### Side menu (the left-panel β 4 forms)
|
|
40
|
+
|
|
41
|
+
The product's **left-hand panel** in list/explorer views. One archetype, **four forms** (all share a
|
|
42
|
+
shell: optional **tabs** + **search** + a scrollable list; selecting an item filters/navigates the main
|
|
43
|
+
view). Surfaced by a per-module sweep β the original entry only covered the first.
|
|
44
|
+
|
|
45
|
+
1. **Section menu** β `settings/components/left-menu.vue` (**20Γ**): a search atop an **`MCollapse`**
|
|
46
|
+
accordion of sections (icon + name + optional beta tag) β sub-items; active item gets a `--primary`
|
|
47
|
+
left rule. The Settings sub-nav.
|
|
48
|
+
2. **Tree** β **Log Explorer** `log/components/hierarchy/*`, **Topology** `topology-hierarchy.vue`, and
|
|
49
|
+
**Inventory** (Monitors) via the shared **`@views/layouts/monitor-hierarchy-layout.vue`** β all on the
|
|
50
|
+
shared **`components/hierarchy/infinite-tree.vue`**: tabs (Type / Group / Saved Query), search, then a
|
|
51
|
+
**virtualised hierarchy** β each node a **chevron + type icon (or severity badge) + name + count
|
|
52
|
+
badge** (`57.25 M`), nested; the Saved-Query tab is a flat `MMenu` list with Create/βdelete.
|
|
53
|
+
3. **Category list** β **Dashboard** `dashboard/components/dashboard-dropdown.vue`: a **segmented**
|
|
54
|
+
Dashboard / NOC View toggle + round **οΌ**, search + layout-toggle, then `MCollapse` **categories with
|
|
55
|
+
count badges** (My Favorite 7, Server 6 β¦) and a **favourite star** per row.
|
|
56
|
+
4. **List / Saved views** β **Report** `report/components/report-sidebar.vue` + the **`ExplorerSavedViewList`**
|
|
57
|
+
reused by **APM / RUM / Metric Explorer** (and the Log Saved-Query tab): tabs + search + a flat
|
|
58
|
+
`MMenu` list with a **Favorites (β
)** row, an **active** highlight, and a per-row **pencil** to inline-rename.
|
|
59
|
+
|
|
60
|
+
> **Not in this family (cross-refs):** the **faceted checkbox** left-panel (`vertical-filter/filters.vue` β
|
|
61
|
+
> APM/RUM/NCM) is a **Filter** β **Molecules/Filters β Vertical filter**; the **Metric Explorer**
|
|
62
|
+
> picker (`metric-picker.vue` β `counter-list.vue`, β-add + drag) is a **picker** β cross-ref
|
|
63
|
+
> **DropdownPicker**. The **Flow** "Result By" sidebar is a *config* panel (sortable list + dropdowns),
|
|
64
|
+
> not nav.
|
|
65
|
+
|
|
66
|
+
### Steps
|
|
67
|
+
|
|
68
|
+
- A **count circle + label** per step: **completed** (β filled), **current** (filled + ring),
|
|
69
|
+
**remaining** (grey); connectors fill `--primary` up to the current step. **All steppers are bespoke**
|
|
70
|
+
(the product has no `MSteps`). Three real usages:
|
|
71
|
+
- **Report builder** (`report-steps.vue`, `ReportSteps`) β horizontal 3-step wizard:
|
|
72
|
+
*Report Properties β Visualizations & Preview β Schedule*. The reproduction models this one.
|
|
73
|
+
- **Product setup / onboarding guide** (`product-setup/guide-sections.vue` + `guide-section-step.vue`)
|
|
74
|
+
β vertical numbered step list (completed shows a green β) for the Log / Metric / Flow setup guides.
|
|
75
|
+
- **Two-factor auth setup** (`auth/two-factor-verification.vue`) β a *Step 1 / 2 / 3* indicator with
|
|
76
|
+
dividers.
|
|
77
|
+
|
|
78
|
+
### Breadcrumb / Back button
|
|
79
|
+
|
|
80
|
+
- **Breadcrumb** β a back chevron + a path (`Reports / Compliance / β¦`), current crumb bold. (Some are
|
|
81
|
+
a back + title/subtitle context header rather than a full trail.)
|
|
82
|
+
- **Back button** (`FlotoBackButton`, 3Γ) β a `chevron-left` `MIcon` in a `FlotoLink`; also the Page
|
|
83
|
+
header's `back-button` slot.
|
|
84
|
+
|
|
85
|
+
## App chrome & specialised navigators (from the full per-module sweep)
|
|
86
|
+
|
|
87
|
+
The 2026-06-16 per-module fan-out surfaced six more wayfinding components beyond the core archetypes:
|
|
88
|
+
|
|
89
|
+
| Member | Source | What it is |
|
|
90
|
+
| --- | --- | --- |
|
|
91
|
+
| **User account menu** | `components/layout/user-dropdown.vue` | header avatar β `MPopover`: profile, theme toggle, logout |
|
|
92
|
+
| **Notification dropdown** | `components/layout/notification-dropdown.vue` | header bell + badge β **Alerts / System** tabs + View all |
|
|
93
|
+
| **Global search / Omnibox** | `components/omnibox/searchbar.vue` | command/search palette (category + CodeMirror query + Execute) |
|
|
94
|
+
| **NOC Player** | `dashboard/components/noc-player.vue` | wallboard **rotator** β βΉ prev/next βΊ, countdown, play/pause |
|
|
95
|
+
| **Timeline scrollbar** | `netroute/components/timeline-scrollbar.vue` | **temporal** navigator (single βΉ βΊ + batch βΉβΉ βΊβΊ through time buckets) |
|
|
96
|
+
| **Graph expansion breadcrumb** | `netroute/components/graph-view.vue` | a **Breadcrumb variant** β closable tags of expanded graph nodes |
|
|
97
|
+
|
|
98
|
+
## Checked & scoped out (sweeps)
|
|
99
|
+
|
|
100
|
+
Swept the product for nav variants beyond the archetypes; these were considered and deliberately placed
|
|
101
|
+
elsewhere or confirmed absent:
|
|
102
|
+
|
|
103
|
+
| Candidate | Usage | Verdict |
|
|
104
|
+
| --- | --- | --- |
|
|
105
|
+
| Topology Full/Tree switch Β· chart-type selector | β | **Radio (segmented)** usage, not a new nav entry β cross-ref Atoms/Radio. |
|
|
106
|
+
| Topology category / APM section / Alert two-level tabs | β | **Tabs** usage (Alert adds a hover sub-menu) β cross-ref Molecules/Tabs. |
|
|
107
|
+
| ViewDetailDrawer (tabs inside a drawer) | β | **Drawer + Tabs** composition β cross-ref Organisms/Drawer. |
|
|
108
|
+
| Faceted checkbox sidebar (`vertical-filter/filters.vue`) | APM/RUM/NCM | A **Filter**, not nav β **Molecules/Filters β Vertical filter**. |
|
|
109
|
+
| Swap/reorder control Β· Role-navigation form Β· flame-graph zoom Β· Layer-3 toggle Β· shortcuts tooltip | β | **Not navigation** (reorder control / settings form / chart-zoom / filter toggle / help legend). |
|
|
110
|
+
| **Pagination** (`FlotoPaginatedCrud` / `k-pager`) | **79Γ** | A **page-nav** archetype, but it belongs to the **Table** family (grid footer) β cross-referenced, not duplicated here. |
|
|
111
|
+
| **Menu toggle** (`menu-toggle-button`) | 7Γ | The Primary nav's own collapse control β folded into Primary nav's **collapsed β expanded** variant, not a separate entry. |
|
|
112
|
+
| `role="navigation"` landmark | 2Γ | An a11y attribute, not a component β tracked in **F2**. |
|
|
113
|
+
| `MMenu` | 13Γ | The shared primitive under Primary nav / Side menu β now catalogued in its own right in the **Menu** family (Molecules/Menu). |
|
|
114
|
+
| `MSubMenu` (flyout submenus) | **0Γ** | Confirmed **absent** β the product has no flyout/mega-menu pattern. |
|
|
115
|
+
| Context / action menu (`FlotoGridActions` Β· `MDropdown`) | grid rows Β· 1Γ | An action surface ("do something"), not wayfinding β now homed in the **Menu** family (Molecules/Menu). |
|
|
116
|
+
|
|
117
|
+
## Which navigation? (decision)
|
|
118
|
+
|
|
119
|
+
1. **Top-level modules?** β **Primary nav**.
|
|
120
|
+
2. **Sections within a module?** β **Side menu**.
|
|
121
|
+
3. **A multi-step flow?** β **Steps**.
|
|
122
|
+
4. **Location + a way up?** β **Breadcrumb**.
|
|
123
|
+
5. **Just back one level?** β **Back button**.
|
|
124
|
+
6. **Sibling views of one page?** β **Tabs** (Molecules/Tabs).
|
|
125
|
+
|
|
126
|
+
## Accessibility
|
|
127
|
+
|
|
128
|
+
- **Verify:** nav **landmarks** (`role="navigation"`), **`aria-current`** on the active item,
|
|
129
|
+
focus-visible ring (**SF-001**), and that the **stepper** conveys step state (not color-only) to
|
|
130
|
+
assistive tech.
|
|
131
|
+
|
|
132
|
+
## Design tokens used
|
|
133
|
+
|
|
134
|
+
`--nav-panel-bg` Β· `--code-tag-background-color` (active) Β· `--left-menu-text-color` Β· `--primary` Β·
|
|
135
|
+
`--primary-alt` Β· `--border-color` Β· `--neutral-lightest` Β· `--neutral-light` Β· `--page-text-color`.
|
|
136
|
+
|
|
137
|
+
## Findings & Inconsistencies
|
|
138
|
+
|
|
139
|
+
| # | Severity | Status | Finding |
|
|
140
|
+
| --- | --- | --- | --- |
|
|
141
|
+
| F1 | Low | Noted | Router/store-bound (`visibleMenuItems`, `FlotoLink`, `MCollapse`) β reproductions. |
|
|
142
|
+
| F2 | Low (a11y) | Open | Verify nav landmarks / `aria-current` / focus ring / stepper semantics. |
|
|
143
|
+
|
|
144
|
+
## Do / Don't
|
|
145
|
+
|
|
146
|
+
- **Do** use Primary nav for modules, Side menu for sections, Steps for ordered flows; put the Back
|
|
147
|
+
button in the Page header slot.
|
|
148
|
+
- **Don't** use Tabs for module/section nav; don't hand-roll a sidebar; don't confuse a breadcrumb
|
|
149
|
+
(location) with a toolbar (actions).
|
|
150
|
+
|
|
151
|
+
## Related components
|
|
152
|
+
|
|
153
|
+
**Tabs** (sibling-view nav) Β· **Toolbars** (Page header hosts the back button + breadcrumb) Β·
|
|
154
|
+
`MMenu` / `MCollapse` (the primitives) Β· `Input` (the side-menu search).
|
|
155
|
+
|
|
156
|
+
## Changelog
|
|
157
|
+
|
|
158
|
+
- **2026-06-16** β Added a **second Steps example** β **Setup guide steps** (vertical
|
|
159
|
+
`product-setup/guide-section-step.vue` pattern: 50Γ50 rounded index box, number β green β when done,
|
|
160
|
+
title + description) alongside the existing horizontal **report-builder** wizard. Verified light +
|
|
161
|
+
dark.
|
|
162
|
+
- **2026-06-16** β Fidelity pass (round 2, against a product screenshot) β corrected the Primary nav
|
|
163
|
+
logo from a square "M" to the real **ObserveOps donut mark** (coral wedge + ring + hollow centre,
|
|
164
|
+
theme-aware ring via `--nav-text-color`); changed the active item from a tinted row + left rule to a
|
|
165
|
+
**filled rounded pill** (`--primary` bg, `--nav-panel-bg` text, inset margins) matching the product;
|
|
166
|
+
made the **BETA** tag a rounded grey pill; added the bottom **MaskGroup** decoration (translucent
|
|
167
|
+
overlapping circles). Also **corrected the Steps source**: the product has **no `MSteps`** β the
|
|
168
|
+
steppers are bespoke (`report-steps.vue`, the `product-setup` guide, and `two-factor-verification`).
|
|
169
|
+
- **2026-06-16** β Recheck β **rebuilt Primary nav for product fidelity** against the real
|
|
170
|
+
`FlotoNavBar`: collapsible `MLayoutSider` (**collapsed 65px β hover-expand 170px**), the **ObserveOps**
|
|
171
|
+
logo, the real **16 modules** with their registered icons, the **SLO BETA** tag, and the `--primary`
|
|
172
|
+
active highlight + inset left rule. Verified collapsed + expanded in **both light and dark** themes
|
|
173
|
+
(screenshots). Recorded the recheck sweep: **Pagination** (79Γ) β cross-referenced to the **Table**
|
|
174
|
+
family; **menu toggle** folded into the collapsedβexpanded variant; `MSubMenu` flyouts confirmed
|
|
175
|
+
**absent** (0Γ).
|
|
176
|
+
- **2026-06-16** β Added β the **Navigation** family (the wayfinding archetypes): **Primary nav**
|
|
177
|
+
(`FlotoNavBar`), **Side menu** (`settings/left-menu`, 20Γ), **Steps** (`MSteps`), **Breadcrumb**,
|
|
178
|
+
**Back button** (`FlotoBackButton`). **Tabs** stay their own family (cross-referenced). Surfaced as a
|
|
179
|
+
separate family during the Toolbars recheck (nav β toolbar). Reproductions (router/store-bound);
|
|
180
|
+
verified Primary nav + Side menu + Steps render, no console errors. Findings F1 (reproduction),
|
|
181
|
+
F2 (a11y landmarks/aria-current).
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Popover (`MPopover`) β Spec, Findings & Solutions
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Tier** | Molecule |
|
|
6
|
+
| **Maturity** | π’ Stable |
|
|
7
|
+
| **Source** | `ui/components/Popover/Popover.vue` (kit; wraps Ant `a-popover`). Positioning primitive: `src/components/_base-popper.vue` (**MPopper**, wraps `v-popover`). |
|
|
8
|
+
| **Storybook** | Molecules/Popover |
|
|
9
|
+
| **Registry** | [`registry/popover.json`](../registry/popover.json) |
|
|
10
|
+
| **Family** | [Popover / Tooltip](../family-map.md) |
|
|
11
|
+
|
|
12
|
+
## Usage analytics
|
|
13
|
+
|
|
14
|
+
- **MPopover 35Γ** Β· **MPopper 2Γ** (direct β but MPopper also powers **FlotoDropdownPicker**'s
|
|
15
|
+
positioning, so its real footprint is much larger).
|
|
16
|
+
- Patterns: **action/kebab menus** (`_base-grid-actions.vue`), **color picker**
|
|
17
|
+
(`color-picker.vue`), **date/time pickers**, rich panels, **"+N overflow" hover reveals**
|
|
18
|
+
(`tags-list.vue`). Overlay classes: `picker-action-dropdown`, `color-picker-popover`,
|
|
19
|
+
`picker-overlay`, `readable-content-overlay`.
|
|
20
|
+
- **Opening behavior:** `trigger` β **click 20Γ**, **hover 13Γ** (passive reveals), explicit
|
|
21
|
+
click 2Γ. Transition: **`transition-name="slide-up"` 16Γ**.
|
|
22
|
+
- **Placement (Ant names):** **`bottomLeft` 11Γ** (most common) Β· `bottomRight` 9Γ Β· `bottom` 7Γ Β·
|
|
23
|
+
`leftTop` 4Γ Β· `top`/`right` 1Γ. Default `bottom`. β οΈ Ant names β **not** the Tooltip's VTippy
|
|
24
|
+
`top-start` names.
|
|
25
|
+
|
|
26
|
+
## Overview
|
|
27
|
+
|
|
28
|
+
A **click-triggered floating panel** anchored to a trigger, holding **interactive** content β
|
|
29
|
+
unlike a Tooltip (hover, non-interactive). `MPopover` wraps Ant `a-popover`; **`MPopper`** is the
|
|
30
|
+
lower-level `v-popover` primitive used as the picker positioning engine. Use a Popover for
|
|
31
|
+
anchored menus/pickers/mini-forms; for a center-interrupting task use **`MModal`**, and for
|
|
32
|
+
select-from-options use **`FlotoDropdownPicker`**.
|
|
33
|
+
|
|
34
|
+
## Anatomy
|
|
35
|
+
|
|
36
|
+
- **Trigger** (`trigger` slot, scope `{ hide, show, toggle }`) β the anchor.
|
|
37
|
+
- **Title** (optional `title` slot) β a header row.
|
|
38
|
+
- **Content** (default slot, scope `{ hide, show, toggle }`) β the interactive panel.
|
|
39
|
+
|
|
40
|
+
## Options (props)
|
|
41
|
+
|
|
42
|
+
| Prop | Default | Notes |
|
|
43
|
+
| --- | --- | --- |
|
|
44
|
+
| `trigger` | `click` | `click` / `hover` / `focus` / `contextmenu` |
|
|
45
|
+
| `placement` | `bottom` | `bottom` / `bottomRight` / `top` / `left` / `right` β¦ |
|
|
46
|
+
| `visible` | β | controlled mode; pair with `@visibleChange` (one-way β F1) |
|
|
47
|
+
| `overlayClassName` | β | e.g. `color-picker-popover`, `picker-action-dropdown` |
|
|
48
|
+
| `overlayStyle` | β | inline overlay style (width/padding/radius) |
|
|
49
|
+
| `destroyTooltipOnHide` | `true` | re-creates content each open |
|
|
50
|
+
| `getPopupContainer` | β | defaults to closest `.__panel` or `document.body` |
|
|
51
|
+
|
|
52
|
+
## Behaviors
|
|
53
|
+
|
|
54
|
+
- Opens on **click** by default; the slot scope `{ hide, show, toggle }` lets content drive
|
|
55
|
+
dismissal (an action item calls `hide()` on select).
|
|
56
|
+
- `destroyTooltipOnHide` re-mounts the content each open (fresh state).
|
|
57
|
+
- **MPopper** adds a ResizeObserver to keep the panel positioned as content resizes; boundary is
|
|
58
|
+
the closest `.__panel` or the viewport.
|
|
59
|
+
|
|
60
|
+
## Content & writing
|
|
61
|
+
|
|
62
|
+
- Title is a short noun; content is the interactive panel. Keep menus to a handful of items β
|
|
63
|
+
beyond ~7, reconsider the pattern.
|
|
64
|
+
|
|
65
|
+
## Accessibility
|
|
66
|
+
|
|
67
|
+
- **Disclosure semantics missing (F2):** the trigger has no `aria-haspopup`/`aria-expanded`,
|
|
68
|
+
focus is **not** moved into the panel on open, and there is **no focus trap** β keyboard/SR
|
|
69
|
+
users aren't told a panel opened or guided into it. Recommended: set `aria-haspopup` +
|
|
70
|
+
`aria-expanded` on the trigger; move focus to the first focusable on open; restore on close.
|
|
71
|
+
- **Focus ring** removed on the overlay (`:focus { outline:none }` in `_base-popper.less`) β
|
|
72
|
+
**F3**, links to [SF-001](../../findings/SF-001-focus-visible.md).
|
|
73
|
+
- Escape/outside-click dismissal comes from `a-popover`; verify Escape returns focus to the trigger.
|
|
74
|
+
|
|
75
|
+
## Props / API
|
|
76
|
+
|
|
77
|
+
See the table above and [`registry/popover.json`](../registry/popover.json).
|
|
78
|
+
|
|
79
|
+
## Design tokens used
|
|
80
|
+
|
|
81
|
+
`--page-background-color` Β· `--border-color` Β· `--page-text-color` (panel surface/border/text).
|
|
82
|
+
|
|
83
|
+
## Findings & Inconsistencies
|
|
84
|
+
|
|
85
|
+
| # | Severity | Status | Finding |
|
|
86
|
+
| --- | --- | --- | --- |
|
|
87
|
+
| F1 | Low | Open | `visible` is one-way β controlled mode needs an explicit `@visibleChange` handler to stay in sync. |
|
|
88
|
+
| F2 | Medium (a11y) | Open | No `aria-haspopup`/`aria-expanded`, no focus move into the panel, no focus trap. |
|
|
89
|
+
| F3 | Medium (a11y) | Open | No focus ring on the overlay β links to **SF-001**. |
|
|
90
|
+
|
|
91
|
+
## Recommended solutions
|
|
92
|
+
|
|
93
|
+
- **F1:** document/standardize the controlled pattern (`:visible` + `@visibleChange`), or expose a
|
|
94
|
+
`v-model:visible`.
|
|
95
|
+
- **F2:** add disclosure ARIA + focus management (move in on open, restore on close, Escape closes).
|
|
96
|
+
- **F3:** adopt the `:focus-visible` ring from SF-001.
|
|
97
|
+
|
|
98
|
+
## Do / Don't
|
|
99
|
+
|
|
100
|
+
- **Do** use for interactive, click-triggered content; give items a `hide()` on select; anchor row
|
|
101
|
+
actions `bottomRight`.
|
|
102
|
+
- **Don't** use for plain hints (use **Tooltip**); don't use for center-interrupting tasks or
|
|
103
|
+
confirmations (use **Modal**); don't hand-roll a select dropdown (use **FlotoDropdownPicker**).
|
|
104
|
+
|
|
105
|
+
## Related components
|
|
106
|
+
|
|
107
|
+
`MTooltip` (hover label) Β· `FlotoDropdownPicker` (select; uses MPopper) Β· `MModal` (dialog).
|
|
108
|
+
|
|
109
|
+
## Changelog
|
|
110
|
+
|
|
111
|
+
- **2026-06-11 (nth-level audit)** β Documented the real opening/placement behavior: `trigger`
|
|
112
|
+
click 20Γ / **hover 13Γ** (+N overflow reveals), `transition-name="slide-up"` 16Γ, placement
|
|
113
|
+
**`bottomLeft` 11Γ** (most common) / `bottomRight` 9Γ / `leftTop` 4Γ; Ant placement names (not
|
|
114
|
+
VTippy). Added **Behavior: hover trigger** + **Placements** stories.
|
|
115
|
+
- **2026-06-11** β Added (decision-grade Usage). Deep-dive of `Popover.vue` (35Γ, kit `a-popover`)
|
|
116
|
+
and `_base-popper.vue` (MPopper, the picker engine). Stories: Basic (title + content) Β· Action /
|
|
117
|
+
kebab menu Β· Rich panel (color picker) Β· Playground β verified click-open with title + items, no
|
|
118
|
+
console errors. Findings F1 (one-way `visible`), F2 (disclosure ARIA + focus), F3 (focus β SF-001).
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Radio (`MRadioGroup`) β Spec, Findings & Solutions
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Tier** | Atom (selection control) |
|
|
6
|
+
| **Maturity** | π’ Stable (core selection control) |
|
|
7
|
+
| **Source** | `@motadata/ui` β `ui/components/Radio/RadioGroup.vue` (+ `Radio.vue`); wraps Ant `a-radio-group` |
|
|
8
|
+
| **Storybook** | `Atoms/Radio` (Examples Β· Usage Β· Accessibility Β· Changelog) |
|
|
9
|
+
| **Registry** | [`../registry/radio.json`](../registry/radio.json) |
|
|
10
|
+
| **Family** | selection controls β sibling of [Checkbox](./checkbox.md) & [Switch](./switch.md); the `as-button` segmented control is the Button family's "segmented" relative |
|
|
11
|
+
| **Figma** | TODO |
|
|
12
|
+
|
|
13
|
+
## Usage (product analytics)
|
|
14
|
+
|
|
15
|
+
- **`<MRadioGroup>` used 225Γ across 136 files.**
|
|
16
|
+
- **Standalone `<MRadio>` is used 0Γ** β radios are always rendered through the **group** with
|
|
17
|
+
an `:options` array.
|
|
18
|
+
- **`as-button` (segmented control) used 255Γ** β the segmented form is at least as common as
|
|
19
|
+
the plain radio list. `buttonStyle` is never overridden (always `solid`).
|
|
20
|
+
|
|
21
|
+
## Overview
|
|
22
|
+
|
|
23
|
+
A **one-of-many** selection control. Use `MRadioGroup` with an `:options` array
|
|
24
|
+
(`{ value, text }`) and v-model the selected `value` (`model: { event: 'change' }`). Set
|
|
25
|
+
`as-button` to render a **segmented control** (joined buttons) instead of a radio list. An
|
|
26
|
+
`option` slot allows custom row rendering.
|
|
27
|
+
|
|
28
|
+
## Anatomy
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
Radio list: β Low β Medium β High β a-radio per option
|
|
32
|
+
Segmented: ββββββββ¬βββββββ¬ββββββ¬ββββββ
|
|
33
|
+
(as-button) β 1h β 24h* β 7d β 30d β β a-radio-button; selected fills navy
|
|
34
|
+
ββββββββ΄βββββββ΄ββββββ΄ββββββ
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Options / API
|
|
38
|
+
|
|
39
|
+
- **`options`** (Array) β `{ value, text | label | title, disabled? }`; the selectable set.
|
|
40
|
+
- **`value`** (v-model) β the selected `value`.
|
|
41
|
+
- **`asButton`** (Boolean) β segmented control vs radio list.
|
|
42
|
+
- **`size`** (`small` Β· `default` Β· `large`) β mainly affects the segmented buttons.
|
|
43
|
+
- **`disabled`** (Boolean) β disable the whole group (per-option via `option.disabled`).
|
|
44
|
+
- **`buttonStyle`** (`solid` Β· `outline`, default `solid`) β never changed in the product.
|
|
45
|
+
- **`name`**, **`defaultValue`**.
|
|
46
|
+
- Slots: default (custom `a-radio`/`a-radio-button` children) Β· `option` (custom row).
|
|
47
|
+
- Emits **`change`**.
|
|
48
|
+
|
|
49
|
+
## Behaviors
|
|
50
|
+
|
|
51
|
+
- **Single selection** β picking one option deselects the others.
|
|
52
|
+
- **Segmented** (`as-button`): the selected button fills the brand color; the rest are
|
|
53
|
+
outlined/joined. **The selected fill is context-dependent (see F4).**
|
|
54
|
+
- **Keyboard:** native radio behavior β Arrow keys move selection within the group, Space
|
|
55
|
+
selects.
|
|
56
|
+
|
|
57
|
+
## Segmented variants (all real in the product)
|
|
58
|
+
|
|
59
|
+
- **Plain segmented** (`as-button`) β kit default; selected = navy `#111c2c` @ 0.8 opacity.
|
|
60
|
+
- **With icons** β an icon per option via the `option` slot (the `without-icon-margin`
|
|
61
|
+
context, **14Γ**) β view/mode toggles.
|
|
62
|
+
- **Severity switch** β `class="radio-toggle-shadow alert-severity-buttons"` (the real
|
|
63
|
+
`severity-switch.vue` combo): borderless segments with thin separators; selected = a tinted
|
|
64
|
+
rounded chip. (`radio-toggle-shadow` 2Γ, `alert-severity-buttons` 2Γ.)
|
|
65
|
+
- **Radio dot color** (list) = cyan `#099dd9` (Ant `@primary-color`) β matches the product.
|
|
66
|
+
- `buttonStyle="outline"` exists but is **unused** (always `solid`).
|
|
67
|
+
|
|
68
|
+
## Design tokens used
|
|
69
|
+
|
|
70
|
+
Selected segment fill = primary/brand (measured `#111c2c` light β `#e3e8f2` dark); inherits
|
|
71
|
+
Ant radio tokens for the dot and borders.
|
|
72
|
+
|
|
73
|
+
## Accessibility
|
|
74
|
+
|
|
75
|
+
- Built on native `<input type="radio">` grouped by `name` β correct role and arrow-key
|
|
76
|
+
navigation. β
|
|
77
|
+
- β οΈ **No visible keyboard focus indicator** ([SF-001](../../findings/SF-001-focus-visible.md)).
|
|
78
|
+
- Ensure the group has a label (a field label or `aria-label`) describing what's being chosen.
|
|
79
|
+
|
|
80
|
+
## Findings & Inconsistencies
|
|
81
|
+
|
|
82
|
+
### F1 β Standalone `MRadio` + `variant`/`type` are effectively dead Β· Low Β· Open
|
|
83
|
+
|
|
84
|
+
`MRadio` is never used directly (0Γ); its `variant="info"` (β `.radio-info`) and
|
|
85
|
+
`type="button"` paths are unexercised. The group is the real API. **Solution:** document the
|
|
86
|
+
group as the entry point; treat `MRadio` as an internal building block.
|
|
87
|
+
|
|
88
|
+
### F2 β `buttonStyle` outline unused Β· Low Β· Open
|
|
89
|
+
|
|
90
|
+
`buttonStyle` defaults to `solid` and is never set to `outline` (0Γ). **Solution:** document
|
|
91
|
+
`solid` as the de-facto style; keep `outline` only if a real need appears.
|
|
92
|
+
|
|
93
|
+
### F3 β No visible focus indicator Β· High Β· Open *(a11y)* β see [SF-001](../../findings/SF-001-focus-visible.md)
|
|
94
|
+
|
|
95
|
+
Same system-wide focus-ring gap as other controls.
|
|
96
|
+
|
|
97
|
+
### F4 β Segmented selected style is context-dependent Β· Medium Β· Open
|
|
98
|
+
|
|
99
|
+
The selected segment renders differently depending on the **ancestor**: standalone it uses the
|
|
100
|
+
kit's `.ant-radio-group-solid` (navy `#111c2c` **@ 0.8 opacity**), but inside form/panel
|
|
101
|
+
contexts `src/design/form.less` overrides it to a **solid `--primary` fill (`!important`),
|
|
102
|
+
11px padding, and icon spacing**. So the *same* `as-button` group looks slightly different
|
|
103
|
+
(opacity + padding) inside a form vs standalone. Storybook (loading the same stylesheets)
|
|
104
|
+
matches the product **for the same markup**; the divergence is purely the missing form
|
|
105
|
+
ancestor. **Solution:** decide on one canonical segmented appearance and move it out of the
|
|
106
|
+
form-scoped selectors into the component (kit) styles so it's consistent everywhere; meanwhile
|
|
107
|
+
the catalog shows the standalone look + documents the in-form override here.
|
|
108
|
+
|
|
109
|
+
## Do / Don't
|
|
110
|
+
|
|
111
|
+
### Do
|
|
112
|
+
|
|
113
|
+
- Use `MRadioGroup` with `:options` for one-of-many; v-model the value.
|
|
114
|
+
- Use `as-button` for a small set of always-visible, mutually-exclusive choices.
|
|
115
|
+
- Disable individual options with `option.disabled`.
|
|
116
|
+
|
|
117
|
+
### Don't
|
|
118
|
+
|
|
119
|
+
- Don't use a radio group for multi-select (use `Checkbox`) or an instant on/off (use `Switch`).
|
|
120
|
+
- Don't use radios for **many** options or when space is tight (use `DropdownPicker`).
|
|
121
|
+
- Don't render standalone `MRadio` β go through the group.
|
|
122
|
+
|
|
123
|
+
## Related
|
|
124
|
+
|
|
125
|
+
`Checkbox` (multi-select) Β· `Switch` (instant on/off) Β· `DropdownPicker` (many options) Β·
|
|
126
|
+
Button's **segmented control** is this component with `as-button`.
|
|
127
|
+
|
|
128
|
+
## Changelog
|
|
129
|
+
|
|
130
|
+
- **2026-06-07** β Added (first authored to the decision-grade Usage standard). Deep-dive of
|
|
131
|
+
`RadioGroup.vue`/`Radio.vue` (225Γ; standalone radio 0Γ; `as-button` 255Γ). Verified radio
|
|
132
|
+
list + segmented in light/dark. Findings F1 (dead standalone/variants), F2 (`outline`
|
|
133
|
+
unused), F3 (focus β SF-001). Closes the Button family's "segmented control" relative.
|
|
134
|
+
- **2026-06-07** β Fidelity deep-dive (owner flagged the segmented didn't match the product).
|
|
135
|
+
Confirmed radio-list dots = cyan `#099dd9` (matches). Found the full segmented variant set
|
|
136
|
+
and added stories: **with icons** (14Γ) and the **severity switch** combo
|
|
137
|
+
(`radio-toggle-shadow` + `alert-severity-buttons`, the real `severity-switch.vue`). New
|
|
138
|
+
finding **F4**: segmented selected style is context-dependent (kit navy @0.8 standalone vs
|
|
139
|
+
solid `--primary` inside forms). Storybook matches the product for identical markup.
|
|
140
|
+
- **2026-06-07** β Fixed the icon-segmented story: the icon was wrapped in a `flex` span, whose
|
|
141
|
+
baseline offset the selected segment by 7px (stair-step). Switched to the product's inline
|
|
142
|
+
icon pattern (`.without-icon-margin`, icon `mr-1`) β segments now align (all `top: 40`).
|
|
143
|
+
Authoring note: don't `flex`-wrap content inside Ant `vertical-align: baseline` radio
|
|
144
|
+
buttons; keep it inline.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Scheduler / Recurrence (`ScheduleInput`) β Spec, Findings & Solutions
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Tier** | Molecule |
|
|
6
|
+
| **Maturity** | π’ Stable |
|
|
7
|
+
| **Source** | `src/components/schedule-input/index.vue` (`ScheduleInput`) + `once-input.vue` Β· `weekly-input.vue` Β· `monthly-input.vue` (sub-forms). |
|
|
8
|
+
| **Storybook** | Molecules/Scheduler |
|
|
9
|
+
| **Registry** | [`registry/scheduler.json`](../registry/scheduler.json) |
|
|
10
|
+
| **Family** | [Scheduler / Recurrence](../family-map.md) |
|
|
11
|
+
|
|
12
|
+
## Usage analytics
|
|
13
|
+
|
|
14
|
+
- **16Γ** across settings & reports: **backups** (`backup-profile-form`,
|
|
15
|
+
`device-inventory-schedule-backup`), **network discovery** (`discovery-schedules`), **compliance
|
|
16
|
+
audits** (`compliance-audit-schedules`), **monitor (re)discovery** (`monitor-schedule-form`,
|
|
17
|
+
`rediscover/custom-schedule-form`, `topology-scanner/schedule-form`), **runbooks**
|
|
18
|
+
(`runbook-schedules`), **reports** (`report-form`), **policies** (`policy-form/basic-info`).
|
|
19
|
+
- Built entirely from already-catalogued primitives β it's a **composition**, not a new control.
|
|
20
|
+
|
|
21
|
+
## Overview
|
|
22
|
+
|
|
23
|
+
A **recurrence builder**: pick *how often* a job runs and *when*. A **"Scheduler Type"** segmented
|
|
24
|
+
control (`MRadioGroup as-button`) β **Once Β· Daily Β· Weekly Β· Monthly** β swaps in a sub-form. This is
|
|
25
|
+
distinct from the **Date & Time Pickers** family (which picks a *value* or a *window*); the Scheduler
|
|
26
|
+
produces a **recurrence rule**.
|
|
27
|
+
|
|
28
|
+
## Anatomy
|
|
29
|
+
|
|
30
|
+
- **Scheduler Type** β segmented `MRadioGroup as-button` (Once/Daily/Weekly/Monthly).
|
|
31
|
+
- **Sub-form** (swaps on type):
|
|
32
|
+
- **Once / Daily** β **Start Date** (`MDatePicker`, date-only, `min-date` = today) + **Hours** (the
|
|
33
|
+
custom dropdown `TimePicker` β a `FlotoDropdownPicker` of times, multi-select).
|
|
34
|
+
- **Weekly** β **Days** (`FlotoDropdownPicker`, MonβSun multi) + Start Date + Hours.
|
|
35
|
+
- **Monthly** β **Months** (JanβDec multi) + **Dates** (1β31 multi) + Start Date + Hours.
|
|
36
|
+
- Each field is a **`FlotoFormItem`** with `rules="required"`.
|
|
37
|
+
|
|
38
|
+
## Options (props)
|
|
39
|
+
|
|
40
|
+
### ScheduleInput
|
|
41
|
+
|
|
42
|
+
| Prop | Default | Notes |
|
|
43
|
+
| --- | --- | --- |
|
|
44
|
+
| `value` | β | v-model; `{ scheduleType, scheduleInfo }` |
|
|
45
|
+
| `excludedScheduleOptions` | `[]` | drop types from the control (e.g. `['Weekly','Monthly']`) (1Γ) |
|
|
46
|
+
| `showOnlyOnce` | `false` | collapse to **Once** only (no recurrence) (1Γ) |
|
|
47
|
+
| `disabled` (passthrough) | β | via `$attrs` β disables the fields (2Γ) |
|
|
48
|
+
| `$attrs` β sub-form | β | `disabled` (2Γ), `time-options` (2Γ), `use-single-selection` (1Γ), `hide-date-time` (1Γ), `multiple` |
|
|
49
|
+
|
|
50
|
+
### Sub-forms (once / weekly / monthly)
|
|
51
|
+
|
|
52
|
+
| Prop | Default | Notes |
|
|
53
|
+
| --- | --- | --- |
|
|
54
|
+
| `value` | β | the `scheduleInfo` object |
|
|
55
|
+
| `hideDateTime` | `false` | hide Start Date + Hours |
|
|
56
|
+
| `timeOptions` | β | override the Hours options |
|
|
57
|
+
| `multiple` | `false` | allow multiple Hours (`use-single-selection` caps to 1) |
|
|
58
|
+
|
|
59
|
+
## Behaviors
|
|
60
|
+
|
|
61
|
+
- **Emit:** `{ scheduleType, scheduleInfo: { startDate:<ms>, times:[β¦], days:[β¦] (weekly),
|
|
62
|
+
months:[β¦] + dates:[β¦] (monthly) } }`. Changing the **type resets** `scheduleInfo` to
|
|
63
|
+
`{ startDate: now }`. Start Date defaults to **today** if unset.
|
|
64
|
+
- **`Daily` reuses the `Once` sub-form** (Start Date + Hours) β the difference is the `scheduleType`
|
|
65
|
+
value, not the fields.
|
|
66
|
+
|
|
67
|
+
## Content & writing
|
|
68
|
+
|
|
69
|
+
- Field labels are fixed (Scheduler Type, Start Date, Hours, Days, Months, Dates) β keep them.
|
|
70
|
+
|
|
71
|
+
## Accessibility
|
|
72
|
+
|
|
73
|
+
- **Provided by** the composed primitives: `MRadioGroup` (radio semantics + arrow-key type selection),
|
|
74
|
+
`MDatePicker` / `FlotoDropdownPicker` (their own a11y), `FlotoFormItem` (labels + required state).
|
|
75
|
+
- **Verify:** focus-visible ring (**SF-001**) on the segmented buttons and the selects.
|
|
76
|
+
|
|
77
|
+
## Design tokens used
|
|
78
|
+
|
|
79
|
+
Inherits from its primitives β segmented control `--primary` (selected), `--neutral-lightest`
|
|
80
|
+
(unselected); fields use `--border-color`, `--page-text-color`, `--neutral-light`. No new tokens.
|
|
81
|
+
|
|
82
|
+
## Findings & Inconsistencies
|
|
83
|
+
|
|
84
|
+
| # | Severity | Status | Finding |
|
|
85
|
+
| --- | --- | --- | --- |
|
|
86
|
+
| F1 | Low | Open | All three sub-forms declare `name: 'OnceForm'` (copy-paste leftover) β should be `WeeklyForm` / `MonthlyForm`. Harmless but confusing. |
|
|
87
|
+
| F2 | Low | Noted | `ScheduleInput` pulls the local DB (**lokijs β Node `fs`**) transitively, so it can't render live in Storybook β **reference reproduction** built from the real primitives. |
|
|
88
|
+
|
|
89
|
+
## Recommended solutions
|
|
90
|
+
|
|
91
|
+
- **F1:** rename each sub-form's `name` to match its file (`WeeklyForm`, `MonthlyForm`).
|
|
92
|
+
- **F2:** if a headless schedule builder is extracted (Vue 3), drop the DB import so it can render
|
|
93
|
+
standalone.
|
|
94
|
+
|
|
95
|
+
## Do / Don't
|
|
96
|
+
|
|
97
|
+
- **Do** use for recurring jobs; drop unsupported recurrences with `excluded-schedule-options`; use
|
|
98
|
+
`show-only-once` for a single run.
|
|
99
|
+
- **Don't** use it for a plain date/time value (β `MDatePicker`) or a chart time window
|
|
100
|
+
(β `TimeRangePicker`); don't hand-roll the Once/Daily/Weekly/Monthly switcher.
|
|
101
|
+
|
|
102
|
+
## Related components
|
|
103
|
+
|
|
104
|
+
`MRadioGroup` (segmented type control) Β· **Date & Time Pickers** (`MDatePicker` / the custom
|
|
105
|
+
`TimePicker` it embeds) Β· `FlotoDropdownPicker` (Days/Months/Dates) Β· `FlotoFormItem`.
|
|
106
|
+
|
|
107
|
+
## Checked & scoped out (sweep recheck)
|
|
108
|
+
|
|
109
|
+
A census of every `<ScheduleInput>` (16Γ) confirmed the **types are Once/Daily/Weekly/Monthly only**
|
|
110
|
+
and accounted for every prop. Deliberately *separate* (not ScheduleInput variants):
|
|
111
|
+
|
|
112
|
+
- **`MetricPollTime` / `metric-collection-time/*`** β metric **polling-frequency** config (a distinct
|
|
113
|
+
monitoring sub-system) β candidate for a future *Monitoring-config* entry, not job recurrence.
|
|
114
|
+
- **`MonitoringHourPicker`** β a monitoring-hours selector.
|
|
115
|
+
- **`monitor-schedules.vue`** (`MonitorSchedule`) β a CRUD **list** of schedules (on/off windows) that
|
|
116
|
+
edits via `monitor-schedule-form` β which *uses* `ScheduleInput`; a consumer, not a new component.
|
|
117
|
+
- **`'Hourly'`** β a **granularity** option in policy anomaly/forecast conditions (aggregation period),
|
|
118
|
+
**not** a recurrence type.
|
|
119
|
+
|
|
120
|
+
## Changelog
|
|
121
|
+
|
|
122
|
+
- **2026-06-16 (sweep recheck)** β Full census of `<ScheduleInput>` (16Γ): types are **Once/Daily/
|
|
123
|
+
Weekly/Monthly only** (the `'Hourly'` elsewhere is a policy-condition *granularity* dropdown, not a
|
|
124
|
+
recurrence type). Added the missed **`:disabled`** passthrough (2Γ). Confirmed `MetricPollTime` /
|
|
125
|
+
`MonitoringHourPicker` / `monitor-schedules` (CRUD list) are **separate**, not variants β documented
|
|
126
|
+
in **Checked & scoped out**. No new types/variants missed.
|
|
127
|
+
- **2026-06-16** β Added (decision-grade) β the **Scheduler / Recurrence** family (`ScheduleInput`,
|
|
128
|
+
16Γ). Documented the **Once/Daily/Weekly/Monthly** segmented switcher and each sub-form's fields,
|
|
129
|
+
the **emit shape**, and the `excluded-schedule-options` / `show-only-once` props. Stories built as a
|
|
130
|
+
**reference reproduction** from the real primitives (`MRadioGroup as-button` + `MDatePicker` +
|
|
131
|
+
`FlotoDropdownPicker`) because the live `ScheduleInput` pulls the local DB (lokijs). Verified the
|
|
132
|
+
type-switch swaps the sub-form (Monthly β Months + Dates) and the `scheduleInfo` shape, no console
|
|
133
|
+
errors. Findings F1 (sub-forms all named `OnceForm`), F2 (lokijs β reproduction).
|