@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,238 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "radio",
|
|
3
|
+
"component": "MRadioGroup",
|
|
4
|
+
"display": "Radio",
|
|
5
|
+
"tier": "atom",
|
|
6
|
+
"source": "mkit",
|
|
7
|
+
"sourceFile": "ui/components/Radio/RadioGroup.vue",
|
|
8
|
+
"status": "core",
|
|
9
|
+
"maturity": "stable",
|
|
10
|
+
"summary": "One-of-many selection control. Use MRadioGroup with :options + v-model; as-button renders a segmented control. Standalone MRadio is unused.",
|
|
11
|
+
"variants": [
|
|
12
|
+
{
|
|
13
|
+
"name": "list",
|
|
14
|
+
"what": "vertical/inline radio list",
|
|
15
|
+
"usage": "225×"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "segmented",
|
|
19
|
+
"what": "joined buttons (as-button)",
|
|
20
|
+
"usage": "255×"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "segmented-with-icons",
|
|
24
|
+
"what": "segmented + icon per option",
|
|
25
|
+
"usage": "14×"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "severity-switch",
|
|
29
|
+
"what": "borderless segmented w/ separators",
|
|
30
|
+
"usage": "2×"
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"sizes": [
|
|
34
|
+
{
|
|
35
|
+
"name": "small",
|
|
36
|
+
"value": "dense",
|
|
37
|
+
"note": "segmented only"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "default",
|
|
41
|
+
"value": "normal",
|
|
42
|
+
"note": ""
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "large",
|
|
46
|
+
"value": "expanded",
|
|
47
|
+
"note": ""
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"states": [
|
|
51
|
+
{
|
|
52
|
+
"name": "unchecked",
|
|
53
|
+
"what": "empty dot"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "checked",
|
|
57
|
+
"what": "cyan dot (list) / navy fill (segmented)"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "focus",
|
|
61
|
+
"what": "no visible ring (SF-001)"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "disabled",
|
|
65
|
+
"what": "muted"
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
"family": "Selection Controls",
|
|
69
|
+
"model": {
|
|
70
|
+
"prop": "value",
|
|
71
|
+
"event": "change"
|
|
72
|
+
},
|
|
73
|
+
"optionShape": {
|
|
74
|
+
"value": "value",
|
|
75
|
+
"label": "text || label || title",
|
|
76
|
+
"disabled": "option.disabled"
|
|
77
|
+
},
|
|
78
|
+
"props": {
|
|
79
|
+
"options": {
|
|
80
|
+
"type": "array",
|
|
81
|
+
"note": "{ value, text|label|title, disabled? }"
|
|
82
|
+
},
|
|
83
|
+
"value": {
|
|
84
|
+
"type": "any",
|
|
85
|
+
"note": "v-model — the selected value"
|
|
86
|
+
},
|
|
87
|
+
"asButton": {
|
|
88
|
+
"type": "boolean",
|
|
89
|
+
"default": false,
|
|
90
|
+
"note": "segmented control vs radio list; 255x"
|
|
91
|
+
},
|
|
92
|
+
"size": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"default": "default",
|
|
95
|
+
"enum": [
|
|
96
|
+
"small",
|
|
97
|
+
"default",
|
|
98
|
+
"large"
|
|
99
|
+
],
|
|
100
|
+
"note": "mainly affects segmented buttons"
|
|
101
|
+
},
|
|
102
|
+
"disabled": {
|
|
103
|
+
"type": "boolean",
|
|
104
|
+
"default": false,
|
|
105
|
+
"note": "whole group; per-option via option.disabled"
|
|
106
|
+
},
|
|
107
|
+
"buttonStyle": {
|
|
108
|
+
"type": "string",
|
|
109
|
+
"default": "solid",
|
|
110
|
+
"enum": [
|
|
111
|
+
"solid",
|
|
112
|
+
"outline"
|
|
113
|
+
],
|
|
114
|
+
"note": "never set to outline in product (F2)"
|
|
115
|
+
},
|
|
116
|
+
"name": {
|
|
117
|
+
"type": "string"
|
|
118
|
+
},
|
|
119
|
+
"defaultValue": {
|
|
120
|
+
"type": "any"
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
"events": [
|
|
124
|
+
"change"
|
|
125
|
+
],
|
|
126
|
+
"slots": [
|
|
127
|
+
"default (custom a-radio/a-radio-button)",
|
|
128
|
+
"option (custom row)"
|
|
129
|
+
],
|
|
130
|
+
"anatomy": [
|
|
131
|
+
"radio list (a-radio per option)",
|
|
132
|
+
"OR segmented buttons (a-radio-button, selected fills brand)"
|
|
133
|
+
],
|
|
134
|
+
"tokensUsed": [
|
|
135
|
+
"--primary",
|
|
136
|
+
"--border-color",
|
|
137
|
+
"@primary-color"
|
|
138
|
+
],
|
|
139
|
+
"accessibility": {
|
|
140
|
+
"semantics": "native input type=radio grouped by name; Arrow keys move selection, Space selects",
|
|
141
|
+
"focus": "no visible ring (SF-001)",
|
|
142
|
+
"label": "give the group a field label or aria-label"
|
|
143
|
+
},
|
|
144
|
+
"decisionFlow": [
|
|
145
|
+
"Multi-select (pick any number)? -> Checkbox.",
|
|
146
|
+
"Instant on/off? -> Switch.",
|
|
147
|
+
"Many options or space-tight? -> DropdownPicker.",
|
|
148
|
+
"Pick exactly one from a few visible options? -> Radio.",
|
|
149
|
+
"[Radio style] >6 options? -> DropdownPicker instead.",
|
|
150
|
+
"[Radio style] Longer labels / vertical form field? -> radio list (default).",
|
|
151
|
+
"[Radio style] Alert severity filter (Critical/Major/Warning)? -> Severity switch (radio-toggle-shadow + alert-severity-buttons, as-button).",
|
|
152
|
+
"[Radio style] Each option clearer with an icon (view/mode toggle)? -> Segmented with icons (as-button + icon in option slot).",
|
|
153
|
+
"[Radio style] Otherwise small compact set (2-5)? -> plain segmented (as-button)."
|
|
154
|
+
],
|
|
155
|
+
"usageRules": {
|
|
156
|
+
"radio-list(default)": {
|
|
157
|
+
"useWhen": "pick one of a few options with a vertical/inline list; longer labels OK",
|
|
158
|
+
"example": "severity Low/Medium/High on a form"
|
|
159
|
+
},
|
|
160
|
+
"segmented(as-button)": {
|
|
161
|
+
"useWhen": "a small set (2-5) of always-visible, mutually-exclusive choices; compact",
|
|
162
|
+
"example": "time range 1h/24h/7d/30d, view-mode toggle"
|
|
163
|
+
},
|
|
164
|
+
"segmented+icons": {
|
|
165
|
+
"useWhen": "segmented where each option reads better with an icon (icon via option slot; without-icon-margin context, 14x)",
|
|
166
|
+
"example": "grid/list/map view toggle"
|
|
167
|
+
},
|
|
168
|
+
"severity-switch": {
|
|
169
|
+
"useWhen": "borderless segmented with separators (real combo: radio-toggle-shadow + alert-severity-buttons, as-button)",
|
|
170
|
+
"example": "severity-switch.vue (Critical/Major/Warning)"
|
|
171
|
+
},
|
|
172
|
+
"disabled": {
|
|
173
|
+
"useWhen": "whole group not changeable; or option.disabled for one option"
|
|
174
|
+
},
|
|
175
|
+
"size=small": {
|
|
176
|
+
"useWhen": "dense toolbars (segmented)"
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
"do": [
|
|
180
|
+
"Use MRadioGroup with :options for one-of-many; v-model the value.",
|
|
181
|
+
"Use as-button for a small set of always-visible exclusive choices.",
|
|
182
|
+
"Disable individual options with option.disabled."
|
|
183
|
+
],
|
|
184
|
+
"dont": [
|
|
185
|
+
"Don't use radio for multi-select (Checkbox) or instant on/off (Switch).",
|
|
186
|
+
"Don't use radio for many options / tight space (DropdownPicker).",
|
|
187
|
+
"Don't render standalone MRadio — go through the group."
|
|
188
|
+
],
|
|
189
|
+
"whenToUse": "Choosing exactly one option from a small, visible set.",
|
|
190
|
+
"insteadOf": [
|
|
191
|
+
"raw a-radio-group",
|
|
192
|
+
"standalone MRadio"
|
|
193
|
+
],
|
|
194
|
+
"usage": {
|
|
195
|
+
"total": 225,
|
|
196
|
+
"files": 136,
|
|
197
|
+
"standaloneMRadio": 0,
|
|
198
|
+
"asButton": 255,
|
|
199
|
+
"buttonStyleOutline": 0
|
|
200
|
+
},
|
|
201
|
+
"knownIssues": [
|
|
202
|
+
"F1 (low): standalone MRadio + its variant=info/type=button are unused (0x); the group is the real API.",
|
|
203
|
+
"F2 (low): buttonStyle outline never used (always solid).",
|
|
204
|
+
"F3 (high, a11y): no visible focus indicator (SF-001).",
|
|
205
|
+
"F4 (medium): segmented selected style is context-dependent — standalone = kit .ant-radio-group-solid (navy #111c2c @0.8 opacity); inside form/panel contexts form.less overrides to solid --primary !important + 11px padding + icon spacing. Same markup renders the same in Storybook as the product; divergence is the missing form ancestor. Move the canonical segmented style into the component to make it consistent."
|
|
206
|
+
],
|
|
207
|
+
"segmentedVariants": {
|
|
208
|
+
"plain": "as-button; selected navy #111c2c @0.8 (kit default)",
|
|
209
|
+
"with-icons": "icon per option via option slot (without-icon-margin, 14x)",
|
|
210
|
+
"severity-switch": "radio-toggle-shadow + alert-severity-buttons + as-button (severity-switch.vue): borderless, separators, tinted rounded selected chip",
|
|
211
|
+
"radio-list-dot": "cyan #099dd9 (Ant @primary-color) — matches product",
|
|
212
|
+
"outline": "buttonStyle=outline exists but unused"
|
|
213
|
+
},
|
|
214
|
+
"related": [
|
|
215
|
+
"MCheckbox",
|
|
216
|
+
"MSwitch",
|
|
217
|
+
"FlotoDropdownPicker",
|
|
218
|
+
"MButton (segmented = this with as-button)"
|
|
219
|
+
],
|
|
220
|
+
"changelog": [
|
|
221
|
+
"2026-06-07: added (decision-grade from the start). 225x; standalone MRadio 0x; as-button 255x. Verified list + segmented light/dark. F1-F3. Closes Button's segmented-control relative."
|
|
222
|
+
],
|
|
223
|
+
"storybook": "Atoms/Radio",
|
|
224
|
+
"figma": {
|
|
225
|
+
"status": "todo",
|
|
226
|
+
"component": "Radio"
|
|
227
|
+
},
|
|
228
|
+
"kitAccent": "the selected list-dot is painted with Ant's @primary-color = cyan #099dd9 (both themes) — NOT --primary (navy). Not in variables.json; see tokens/kit-accents.json.",
|
|
229
|
+
"$tokensNote": "Selected fill = --primary (#111c2c light / #e3e8f2 dark); the radio dot/check uses the kit Ant accent @primary-color (#099dd9, kit-accents.json), which is not in variables.json.",
|
|
230
|
+
"a11y": {
|
|
231
|
+
"summary": "Tab to the group, Arrow keys move selection; each option role=radio with label, shared name groups them. Selected segment = --primary fill.",
|
|
232
|
+
"issues": [
|
|
233
|
+
"No visible focus ring (SF-001)."
|
|
234
|
+
],
|
|
235
|
+
"doc": "Atoms/Radio/Accessibility",
|
|
236
|
+
"$note": "Catalogue-wide gap SF-001 = no visible :focus-visible ring; tracked in findings/."
|
|
237
|
+
}
|
|
238
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "scheduler",
|
|
3
|
+
"display": "Scheduler (Recurrence)",
|
|
4
|
+
"tier": "molecule",
|
|
5
|
+
"family": "Scheduler",
|
|
6
|
+
"source": "src/components/schedule-input/index.vue (ScheduleInput) + once-input.vue / weekly-input.vue / monthly-input.vue (the sub-forms).",
|
|
7
|
+
"status": "stable",
|
|
8
|
+
"summary": "A composite recurrence builder. A 'Scheduler Type' segmented control (MRadioGroup as-button: Once · Daily · Weekly · Monthly) swaps in a sub-form. Once/Daily = Start Date + Hours; Weekly adds Days (Mon-Sun); Monthly adds Months + Dates (1-31). Hours = the custom dropdown TimePicker (multi-select times); Days/Months/Dates = FlotoDropdownPicker multi-selects; Start Date = MDatePicker (date-only, min-date today). Used for backups, network discovery, compliance audits, monitor (re)discovery, reports, runbooks.",
|
|
9
|
+
"variants": [
|
|
10
|
+
{
|
|
11
|
+
"name": "Once",
|
|
12
|
+
"what": "single run",
|
|
13
|
+
"usage": ""
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"name": "Daily",
|
|
17
|
+
"what": "every day",
|
|
18
|
+
"usage": ""
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "Weekly",
|
|
22
|
+
"what": "Days + Start + Hours",
|
|
23
|
+
"usage": ""
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"name": "Monthly",
|
|
27
|
+
"what": "Months + Dates + Start + Hours",
|
|
28
|
+
"usage": ""
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"sizes": [],
|
|
32
|
+
"states": [
|
|
33
|
+
{
|
|
34
|
+
"name": "default",
|
|
35
|
+
"what": "segmented type control"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "disabled",
|
|
39
|
+
"what": "fields not interactive"
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"usage": {
|
|
43
|
+
"total": 16,
|
|
44
|
+
"consumers": [
|
|
45
|
+
"backup-profile-form",
|
|
46
|
+
"device-inventory-schedule-backup",
|
|
47
|
+
"discovery-schedules",
|
|
48
|
+
"compliance-audit-schedules",
|
|
49
|
+
"monitor-schedule-form",
|
|
50
|
+
"rediscover custom-schedule-form",
|
|
51
|
+
"topology-scanner schedule-form",
|
|
52
|
+
"runbook-schedules",
|
|
53
|
+
"report-form",
|
|
54
|
+
"policy-form basic-info"
|
|
55
|
+
],
|
|
56
|
+
"renders": "REFERENCE REPRODUCTION in Storybook — importing the real ScheduleInput pulls the local DB (lokijs -> Node fs), so it can't render live (like TimeRangePicker / the Kendo grid). Reproduced from the REAL primitives (MRadioGroup as-button + MDatePicker + FlotoDropdownPicker)."
|
|
57
|
+
},
|
|
58
|
+
"scheduleTypes": {
|
|
59
|
+
"Once": "single run — Start Date + Hours",
|
|
60
|
+
"Daily": "every day — Start Date + Hours (same sub-form as Once)",
|
|
61
|
+
"Weekly": "Days (Mon-Sun multi) + Start Date + Hours",
|
|
62
|
+
"Monthly": "Months (Jan-Dec multi) + Dates (1-31 multi) + Start Date + Hours"
|
|
63
|
+
},
|
|
64
|
+
"props": {
|
|
65
|
+
"ScheduleInput": {
|
|
66
|
+
"value": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"note": "v-model (model event=change): { scheduleType, scheduleInfo }"
|
|
69
|
+
},
|
|
70
|
+
"excludedScheduleOptions": {
|
|
71
|
+
"type": "array",
|
|
72
|
+
"default": [],
|
|
73
|
+
"note": "drop schedule types from the segmented control, e.g. ['Weekly','Monthly'] (1x)"
|
|
74
|
+
},
|
|
75
|
+
"showOnlyOnce": {
|
|
76
|
+
"type": "boolean",
|
|
77
|
+
"default": false,
|
|
78
|
+
"note": "collapse to the Once type only (no recurrence) (1x)"
|
|
79
|
+
},
|
|
80
|
+
"disabled": {
|
|
81
|
+
"type": "boolean",
|
|
82
|
+
"note": "passthrough ($attrs) — disables the fields (2x)"
|
|
83
|
+
},
|
|
84
|
+
"$attrs": "passed to the sub-form: disabled (2x), time-options (2x), use-single-selection (1x), hide-date-time (1x), multiple"
|
|
85
|
+
},
|
|
86
|
+
"subForms": {
|
|
87
|
+
"value": "object (scheduleInfo)",
|
|
88
|
+
"hideDateTime": "bool — hide Start Date + Hours",
|
|
89
|
+
"timeOptions": "array — override the Hours options (external-options on the TimePicker)",
|
|
90
|
+
"multiple": "bool — allow multiple Hours (use-single-selection caps to 1)"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"emit": "change -> { scheduleType:'Once'|'Daily'|'Weekly'|'Monthly', scheduleInfo: { startDate:<ms>, times:[…], days:[…](weekly), months:[…]+dates:[…](monthly) } }. On type change, scheduleInfo resets to { startDate: now }.",
|
|
94
|
+
"builtFrom": [
|
|
95
|
+
"MRadioGroup (as-button / segmented) — the type control",
|
|
96
|
+
"MDatePicker (show-time:false, min-date today) — Start Date",
|
|
97
|
+
"custom TimePicker (time-picker.vue, a FlotoDropdownPicker of times, multiple) — Hours",
|
|
98
|
+
"FlotoDropdownPicker (multiple, searchable) — Days / Months / Dates",
|
|
99
|
+
"FlotoFormItem (rules='required') — each field"
|
|
100
|
+
],
|
|
101
|
+
"decisionFlow": [
|
|
102
|
+
"Need a RECURRING schedule (run X every day/week/month)? -> ScheduleInput.",
|
|
103
|
+
"Only certain recurrences valid? -> :excluded-schedule-options=['Weekly','Monthly'].",
|
|
104
|
+
"A single, one-off run (no recurrence)? -> :show-only-once.",
|
|
105
|
+
"Just a date or date+time value (not a recurrence)? -> MDatePicker (Date & Time Pickers family), not this.",
|
|
106
|
+
"A chart/dashboard TIME WINDOW? -> TimeRangePicker, not this."
|
|
107
|
+
],
|
|
108
|
+
"usageRules": {
|
|
109
|
+
"recurring": {
|
|
110
|
+
"useWhen": "a job runs on a recurrence",
|
|
111
|
+
"how": "<ScheduleInput v-model>",
|
|
112
|
+
"example": "nightly backup, weekly compliance audit, monthly report"
|
|
113
|
+
},
|
|
114
|
+
"restrictTypes": {
|
|
115
|
+
"useWhen": "only some recurrences make sense",
|
|
116
|
+
"how": ":excluded-schedule-options",
|
|
117
|
+
"example": "a feature that only supports Daily/Weekly"
|
|
118
|
+
},
|
|
119
|
+
"oneOff": {
|
|
120
|
+
"useWhen": "a single scheduled run",
|
|
121
|
+
"how": ":show-only-once",
|
|
122
|
+
"example": "a one-time discovery run"
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"do": [
|
|
126
|
+
"Use for recurring jobs (backups, discovery, audits, reports).",
|
|
127
|
+
"Drop unsupported recurrences with :excluded-schedule-options.",
|
|
128
|
+
"Use :show-only-once for a single non-recurring run.",
|
|
129
|
+
"Keep it inside a form (FlotoFormItem fields are required)."
|
|
130
|
+
],
|
|
131
|
+
"dont": [
|
|
132
|
+
"Don't use it for a plain date/time value — that's MDatePicker.",
|
|
133
|
+
"Don't use it for a chart time window — that's TimeRangePicker.",
|
|
134
|
+
"Don't hand-roll a Once/Daily/Weekly/Monthly switcher — reuse ScheduleInput."
|
|
135
|
+
],
|
|
136
|
+
"knownIssues": {
|
|
137
|
+
"F1": {
|
|
138
|
+
"severity": "Low",
|
|
139
|
+
"issue": "The three sub-forms (once/weekly/monthly-input.vue) all carry name:'OnceForm' — a copy-paste leftover; harmless but should be unique."
|
|
140
|
+
},
|
|
141
|
+
"F2": {
|
|
142
|
+
"severity": "Low",
|
|
143
|
+
"issue": "ScheduleInput pulls the local DB (lokijs) transitively, so it can't render in Storybook — reproduced from primitives."
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
"accessibility": {
|
|
147
|
+
"providedBy": "MRadioGroup (radio semantics / arrow-key selection for the type), MDatePicker / FlotoDropdownPicker (their own a11y), FlotoFormItem (labels + required/validation).",
|
|
148
|
+
"verify": "Each field has a visible label (it does, via FlotoFormItem); focus-visible ring (SF-001) on the segmented buttons + selects."
|
|
149
|
+
},
|
|
150
|
+
"scopedOut": {
|
|
151
|
+
"MetricPollTime / metric-collection-time": "metric POLLING-FREQUENCY config (a separate monitoring sub-system) — not a job recurrence; candidate for a future Monitoring-config entry.",
|
|
152
|
+
"MonitoringHourPicker (_base-monitoring-hour-picker.vue)": "a monitoring-hours selector — separate.",
|
|
153
|
+
"monitor-schedules.vue (MonitorSchedule)": "a CRUD LIST view of schedules (on/off windows); edits via monitor-schedule-form which uses ScheduleInput — a consumer, not a new component.",
|
|
154
|
+
"'Hourly' type": "a granularity dropdown in policy anomaly/forecast conditions (aggregation period), NOT a ScheduleInput recurrence type. ScheduleInput types are Once/Daily/Weekly/Monthly only.",
|
|
155
|
+
"NotifyTimePicker / date-remark-pairs": "notification-timing / holiday-list composites — out of scope."
|
|
156
|
+
},
|
|
157
|
+
"storybook": "Molecules/Scheduler",
|
|
158
|
+
"related": [
|
|
159
|
+
"radio",
|
|
160
|
+
"date-time-pickers",
|
|
161
|
+
"dropdown-picker",
|
|
162
|
+
"form-item"
|
|
163
|
+
],
|
|
164
|
+
"figma": {
|
|
165
|
+
"status": "todo"
|
|
166
|
+
},
|
|
167
|
+
"tokensUsed": [
|
|
168
|
+
"--primary",
|
|
169
|
+
"--neutral-lightest",
|
|
170
|
+
"--border-color",
|
|
171
|
+
"--page-text-color",
|
|
172
|
+
"--neutral-light"
|
|
173
|
+
],
|
|
174
|
+
"events": {
|
|
175
|
+
"ScheduleInput.change": "(value) — emits the full schedule object `{ scheduleType, scheduleInfo }`; this is the v-model event."
|
|
176
|
+
},
|
|
177
|
+
"slots": "none — a segmented schedule-type control (Once / Daily / Weekly / Monthly) + the matching sub-form; no slots.",
|
|
178
|
+
"a11y": {
|
|
179
|
+
"summary": "Type = MRadioGroup (radio semantics); date = MDatePicker (input + calendar, Esc); dropdowns = FlotoDropdownPicker (searchable/keyboard); every field wrapped in FlotoFormItem (label + required).",
|
|
180
|
+
"issues": [
|
|
181
|
+
"SF-001 focus-visible on the segmented control.",
|
|
182
|
+
"Announce the required state.",
|
|
183
|
+
"Type change swaps fields — verify focus lands sensibly."
|
|
184
|
+
],
|
|
185
|
+
"doc": "Molecules/Scheduler/Accessibility",
|
|
186
|
+
"$note": "Catalogue-wide gap SF-001 = no visible :focus-visible ring; tracked in findings/."
|
|
187
|
+
}
|
|
188
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "select",
|
|
3
|
+
"component": "MSelect",
|
|
4
|
+
"display": "Select",
|
|
5
|
+
"tier": "atom",
|
|
6
|
+
"category": "form-control",
|
|
7
|
+
"source": "mkit",
|
|
8
|
+
"sourceFile": "ui/components/Select/Select.vue",
|
|
9
|
+
"status": "low-use",
|
|
10
|
+
"maturity": "low-use",
|
|
11
|
+
"summary": "Kit's raw Ant a-select wrapper. LOW-USE (2x, both mode=tags) — the product's select is FlotoDropdownPicker (510x). Modes default/multiple/tags; v-model value/change.",
|
|
12
|
+
"variants": [
|
|
13
|
+
{
|
|
14
|
+
"name": "single",
|
|
15
|
+
"what": "single select (default, rare)",
|
|
16
|
+
"usage": ""
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "multiple",
|
|
20
|
+
"what": "multi-select chips",
|
|
21
|
+
"usage": ""
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "tags",
|
|
25
|
+
"what": "free-type (mode=tags)",
|
|
26
|
+
"usage": "2×"
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"sizes": [
|
|
30
|
+
{
|
|
31
|
+
"name": "small",
|
|
32
|
+
"value": "compact",
|
|
33
|
+
"note": ""
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "default",
|
|
37
|
+
"value": "normal",
|
|
38
|
+
"note": ""
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "large",
|
|
42
|
+
"value": "expanded",
|
|
43
|
+
"note": ""
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"states": [
|
|
47
|
+
{
|
|
48
|
+
"name": "default",
|
|
49
|
+
"what": "resting"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"name": "focus",
|
|
53
|
+
"what": "no ring (SF-001)"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "open",
|
|
57
|
+
"what": "dropdown visible"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "disabled",
|
|
61
|
+
"what": "greyed"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "loading",
|
|
65
|
+
"what": "chevron → spinner"
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
"family": "Form Controls",
|
|
69
|
+
"model": {
|
|
70
|
+
"prop": "value",
|
|
71
|
+
"event": "change"
|
|
72
|
+
},
|
|
73
|
+
"optionShape": {
|
|
74
|
+
"value": "value || key || id",
|
|
75
|
+
"label": "text || label || title || name",
|
|
76
|
+
"disabled": "option.disabled"
|
|
77
|
+
},
|
|
78
|
+
"props": {
|
|
79
|
+
"mode": {
|
|
80
|
+
"type": "string",
|
|
81
|
+
"default": "default",
|
|
82
|
+
"enum": [
|
|
83
|
+
"default",
|
|
84
|
+
"multiple",
|
|
85
|
+
"tags",
|
|
86
|
+
"combobox"
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
"options": {
|
|
90
|
+
"type": "array",
|
|
91
|
+
"note": "{ value, text } objects; or slot a-select-option"
|
|
92
|
+
},
|
|
93
|
+
"showSearch": {
|
|
94
|
+
"type": "boolean",
|
|
95
|
+
"default": false
|
|
96
|
+
},
|
|
97
|
+
"allowClear": {
|
|
98
|
+
"type": "boolean",
|
|
99
|
+
"default": true
|
|
100
|
+
},
|
|
101
|
+
"size": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"default": "default",
|
|
104
|
+
"enum": [
|
|
105
|
+
"small",
|
|
106
|
+
"default",
|
|
107
|
+
"large"
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
"loading": {
|
|
111
|
+
"type": "boolean",
|
|
112
|
+
"note": "chevron -> spinner"
|
|
113
|
+
},
|
|
114
|
+
"disabled": {
|
|
115
|
+
"type": "boolean",
|
|
116
|
+
"default": false
|
|
117
|
+
},
|
|
118
|
+
"maxTagCount": {
|
|
119
|
+
"type": "number"
|
|
120
|
+
},
|
|
121
|
+
"labelInValue": {
|
|
122
|
+
"type": "boolean"
|
|
123
|
+
},
|
|
124
|
+
"filterOption": {
|
|
125
|
+
"type": [
|
|
126
|
+
"boolean",
|
|
127
|
+
"function"
|
|
128
|
+
],
|
|
129
|
+
"note": "default case-insensitive on label"
|
|
130
|
+
},
|
|
131
|
+
"tokenSeparators": {
|
|
132
|
+
"type": "array"
|
|
133
|
+
},
|
|
134
|
+
"placeholder": {
|
|
135
|
+
"type": "string",
|
|
136
|
+
"default": "Select..."
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"events": [
|
|
140
|
+
"change",
|
|
141
|
+
"search",
|
|
142
|
+
"select",
|
|
143
|
+
"deselect",
|
|
144
|
+
"blur",
|
|
145
|
+
"focus",
|
|
146
|
+
"inputKeydown",
|
|
147
|
+
"popupScroll",
|
|
148
|
+
"dropdownVisibleChange"
|
|
149
|
+
],
|
|
150
|
+
"slots": [
|
|
151
|
+
"default/option",
|
|
152
|
+
"suffixIcon",
|
|
153
|
+
"clearIcon",
|
|
154
|
+
"removeIcon",
|
|
155
|
+
"menuItemSelectedIcon",
|
|
156
|
+
"notFoundContent (MNoData)",
|
|
157
|
+
"dropdownRender"
|
|
158
|
+
],
|
|
159
|
+
"anatomy": [
|
|
160
|
+
"trigger (value/placeholder + chevron)",
|
|
161
|
+
"selected chips (multiple/tags)",
|
|
162
|
+
"dropdown options list",
|
|
163
|
+
"no-data (MNoData)"
|
|
164
|
+
],
|
|
165
|
+
"tokensUsed": [
|
|
166
|
+
"--page-background-color",
|
|
167
|
+
"--border-color",
|
|
168
|
+
"--page-text-color",
|
|
169
|
+
"@input-height-base"
|
|
170
|
+
],
|
|
171
|
+
"accessibility": {
|
|
172
|
+
"semantics": "real Ant combobox — role/aria-expanded/aria-activedescendant, listbox/options, keyboard open + type-ahead",
|
|
173
|
+
"note": "MORE accessible than FlotoDropdownPicker (SF-003); a reference for fixing SF-003",
|
|
174
|
+
"focus": "no visible ring (SF-001)"
|
|
175
|
+
},
|
|
176
|
+
"decisionFlow": [
|
|
177
|
+
"Need the product's standard select (single/multi/search/virtualized/custom trigger)? -> FlotoDropdownPicker (the norm, 510x).",
|
|
178
|
+
"Free-form tag input? -> LooseTags.",
|
|
179
|
+
"Tree / hierarchy select? -> MTreeSelect.",
|
|
180
|
+
"Specifically need the raw Ant a-select primitive? -> MSelect (rare, 2x)."
|
|
181
|
+
],
|
|
182
|
+
"usageRules": {
|
|
183
|
+
"default(single)": {
|
|
184
|
+
"useWhen": "raw single Ant select (rare) — prefer FlotoDropdownPicker",
|
|
185
|
+
"example": "low-level use only"
|
|
186
|
+
},
|
|
187
|
+
"multiple": {
|
|
188
|
+
"useWhen": "raw multi Ant select (rare) — prefer FlotoDropdownPicker multiple",
|
|
189
|
+
"example": "chips in field"
|
|
190
|
+
},
|
|
191
|
+
"tags": {
|
|
192
|
+
"useWhen": "free-type tags — but prefer LooseTags",
|
|
193
|
+
"example": "the 2 real usages (LooseTags / object-tag-picker)"
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
"do": [
|
|
197
|
+
"For a real select use FlotoDropdownPicker; for a tag input use LooseTags.",
|
|
198
|
+
"Use MSelect only as the low-level Ant primitive when raw a-select is specifically needed.",
|
|
199
|
+
"Wrap in FlotoFormItem for label + validation."
|
|
200
|
+
],
|
|
201
|
+
"dont": [
|
|
202
|
+
"Don't introduce new MSelect usages as 'the select' (that's FlotoDropdownPicker).",
|
|
203
|
+
"Don't use mode=tags here — use LooseTags."
|
|
204
|
+
],
|
|
205
|
+
"whenToUse": "Rarely — FlotoDropdownPicker is the product select. MSelect is the low-level Ant primitive.",
|
|
206
|
+
"insteadOf": [
|
|
207
|
+
"raw a-select"
|
|
208
|
+
],
|
|
209
|
+
"usage": {
|
|
210
|
+
"total": 2,
|
|
211
|
+
"files": 2,
|
|
212
|
+
"note": "both mode=tags (LooseTags, object-tag-picker); FlotoDropdownPicker is 510x",
|
|
213
|
+
"MTreeSelect": 0
|
|
214
|
+
},
|
|
215
|
+
"knownIssues": [
|
|
216
|
+
"F1 (medium): superseded by FlotoDropdownPicker (2x vs 510x) — effectively legacy/low-level. Use DropdownPicker for selects, LooseTags for tag inputs.",
|
|
217
|
+
"F2 (medium, a11y, ironic): MSelect IS an accessible combobox (Ant) while the widely-used FlotoDropdownPicker is NOT (SF-003). Mirror Ant's ARIA when fixing SF-003.",
|
|
218
|
+
"F3 (high, a11y): no visible focus ring (SF-001).",
|
|
219
|
+
"F4 (low): clear x is invisible — Select.vue hardcodes clearIcon as <MIcon name=times-circle type=fas> (FA solid) but only fal (light) icons are registered (639 fal, 0 fas). type=fas used 3x (Select, TreeSelect, navbar). Chip remove x works (fal times). Fix: drop type=fas (use fal) or register fas set.",
|
|
220
|
+
"F5 (low): clear x overlaps the dropdown chevron — the custom suffixIcon chevron (MIcon) is wider than Ant's clear mask box, so the chevron's left edge pokes out beside the x (chevron left 123, clear left 129). Fix: hide .ant-select-arrow while clearing, or widen the mask. NET (F4+F5): MSelect clear-all is broken; catalog stories omit allow-clear and show chip-remove; use FlotoDropdownPicker for a clearable select."
|
|
221
|
+
],
|
|
222
|
+
"related": [
|
|
223
|
+
"FlotoDropdownPicker",
|
|
224
|
+
"LooseTags",
|
|
225
|
+
"MTreeSelect",
|
|
226
|
+
"MSelectOption",
|
|
227
|
+
"FlotoFormItem"
|
|
228
|
+
],
|
|
229
|
+
"changelog": [
|
|
230
|
+
"2026-06-07: added (badged low-use, decision-grade). Ant a-select wrapper — modes default/multiple/tags, show-search, allow-clear (default true), sizes, loading, slots (notFoundContent->MNoData); v-model value/change. Verified single/multiple/tags. F1 (superseded 2x vs 510x), F2 (accessible vs SF-003), F3 (focus)."
|
|
231
|
+
],
|
|
232
|
+
"storybook": "Atoms/Select",
|
|
233
|
+
"figma": {
|
|
234
|
+
"status": "n/a",
|
|
235
|
+
"component": "Select (low-use — build DropdownPicker instead)"
|
|
236
|
+
},
|
|
237
|
+
"$tokensNote": "Dropdown/selected highlight uses the kit Ant accent @primary-color (#099dd9, kit-accents.json); other Ant Select internals follow the kit, not variables.json.",
|
|
238
|
+
"a11y": {
|
|
239
|
+
"summary": "role=combobox + aria-expanded + aria-activedescendant; listbox of options. Enter/Space/↓ open, type-ahead, Esc close. Label via FlotoFormItem/aria-label.",
|
|
240
|
+
"issues": [
|
|
241
|
+
"No visible focus ring (SF-001).",
|
|
242
|
+
"Ensure empty (MNoData) result is announced."
|
|
243
|
+
],
|
|
244
|
+
"doc": "Atoms/Select/Accessibility",
|
|
245
|
+
"$note": "Catalogue-wide gap SF-001 = no visible :focus-visible ring; tracked in findings/."
|
|
246
|
+
}
|
|
247
|
+
}
|