@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,230 @@
|
|
|
1
|
+
# Button (`MButton`) โ Spec, Findings & Solutions
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Tier** | Atom |
|
|
6
|
+
| **Maturity** | ๐ข Stable (core, most-used component) |
|
|
7
|
+
| **Source** | `@motadata/ui` kit โ `ui/components/Button/Button.vue` (wraps Ant `a-button`) |
|
|
8
|
+
| **Storybook** | `Atoms/Button` |
|
|
9
|
+
| **Registry** | [`../registry/button.json`](../registry/button.json) |
|
|
10
|
+
| **Figma** | TODO (library not built yet) |
|
|
11
|
+
|
|
12
|
+
> Documented to the [enhanced standard](../documentation-standard.md): Overview ยท Anatomy ยท
|
|
13
|
+
> Options ยท Behaviors ยท Content ยท Accessibility ยท API ยท Tokens ยท Findings ยท Do/Don't ยท
|
|
14
|
+
> Related ยท Changelog.
|
|
15
|
+
|
|
16
|
+
## Usage (product analytics)
|
|
17
|
+
|
|
18
|
+
- **`<MButton>` used 1,373ร across 424 files โ the most-used component in the product.**
|
|
19
|
+
- **By variant** (exact): default 301, neutral-lightest 320, transparent 255, primary 91,
|
|
20
|
+
neutral 77, primary-alt 36, error 31, neutral-lighter 17, info 7, success 5, danger 3;
|
|
21
|
+
unused: dashed/ghost/warning/neutral-light/topology-overlay.
|
|
22
|
+
- **By size** (approx; shared prop): `small` 76, `large` 9 โ the rest default.
|
|
23
|
+
- **Modifiers** (approx; shared): `outline`/ghost ~11 explicit, `rounded="false"` 273, `loading` 518, `block` 0.
|
|
24
|
+
- **Icon buttons:** `shape="circle"` **218ร** ยท `class="squared-button"` (35ร35) **365ร** โ the
|
|
25
|
+
squared form is more common than the circular one.
|
|
26
|
+
|
|
27
|
+
## Overview
|
|
28
|
+
|
|
29
|
+
The primary action control. Wraps Ant `a-button` and adds the project's variant system,
|
|
30
|
+
rounding, and shadow. `variant` routes two ways (`Button.vue`): values in
|
|
31
|
+
`{primary, dashed, danger, ghost, default}` โ Ant `type`; everything else โ a
|
|
32
|
+
`.button-<variant>` class (+ `type="primary"`). Renders a native `<button type="button">`.
|
|
33
|
+
|
|
34
|
+
## Anatomy
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
38
|
+
โ [leading icon] Label [trailing] โ โ container (.ant-btn, variant class, radius)
|
|
39
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
40
|
+
โฒ loading spinner replaces/precedes label when :loading
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- **Container** โ `.ant-btn` + variant class; height from `size`; radius from `rounded`.
|
|
44
|
+
- **Label** โ default slot (text).
|
|
45
|
+
- **Icon(s)** โ optional `<MIcon>` in the slot (leading/trailing).
|
|
46
|
+
- **Loading spinner** โ shown when `:loading`.
|
|
47
|
+
|
|
48
|
+
## Options
|
|
49
|
+
|
|
50
|
+
### Variants โ render distinctly โ
|
|
51
|
+
|
|
52
|
+
| Variant | Applied as | Background | Usage |
|
|
53
|
+
| --- | --- | --- | --- |
|
|
54
|
+
| `primary` | Ant type | `#07101f` navy | 91 |
|
|
55
|
+
| `primary-alt` | class | `#1d2a3e` slate | 36 |
|
|
56
|
+
| `default` | Ant type | `#fff` / border `#e3e8f2` | 301 |
|
|
57
|
+
| `danger` | Ant type | light `#f5f5f5` (see F2) | 3 |
|
|
58
|
+
| `success` | class | `#14b053` green | 5 |
|
|
59
|
+
| `error` | class | `#ec5b5b` red | 31 |
|
|
60
|
+
| `neutral-lighter` | class | `#e3e8f2` | 17 |
|
|
61
|
+
| `neutral-lightest` | class | `#ecf1f9` | 320 |
|
|
62
|
+
| `transparent` | class | transparent | 255 |
|
|
63
|
+
| `dashed` / `ghost` | Ant type | white+dashed / transparent+border | 0 |
|
|
64
|
+
|
|
65
|
+
### Variants โ render as navy โ ๏ธ (see F1)
|
|
66
|
+
|
|
67
|
+
`neutral` (77ร), `info` (7ร), `neutral-light`, `warning` โ not allow-listed โ navy.
|
|
68
|
+
|
|
69
|
+
### Sizes
|
|
70
|
+
|
|
71
|
+
`small` (~24px) ยท `default` (~34px) ยท `large` (~34px โ **same as default, see F5**).
|
|
72
|
+
|
|
73
|
+
### Icon buttons (two forms โ both heavily used)
|
|
74
|
+
|
|
75
|
+
The product has **two** icon-only button forms, both previously undocumented:
|
|
76
|
+
|
|
77
|
+
| Form | How | Usage | Notes |
|
|
78
|
+
| --- | --- | --- | --- |
|
|
79
|
+
| **`shape="circle"`** | Ant circular icon button | **218ร** | Renders `border-radius: 4px` (not a true circle) because MButton's default `rounded` class overrides Ant's 50% โ see F7. |
|
|
80
|
+
| **`class="squared-button"`** | `buttons.less` 35ร35 square | **365ร** | Fixed `35px ร 35px`, 8px padding; the most-used icon-button treatment. |
|
|
81
|
+
|
|
82
|
+
Both wrap an `<MIcon>` with no text and take any `variant`. โ ๏ธ **They require an
|
|
83
|
+
`aria-label`** (no automatic name). Other contextual icon-button classes exist
|
|
84
|
+
(`.model-header-button` 3ร, `.button-topology-overlay` 5ร) โ app-specific, not core.
|
|
85
|
+
|
|
86
|
+
### States & modifiers
|
|
87
|
+
|
|
88
|
+
`loading` ยท `disabled` ยท `outline` (ghost) ยท `block` (full width) ยท `rounded` (default
|
|
89
|
+
true) ยท `shadow` (default true โ **inverted, see F6**) ยท `shape` (`circle`).
|
|
90
|
+
|
|
91
|
+
## Behaviors
|
|
92
|
+
|
|
93
|
+
- **Loading:** `:loading` shows a spinner and blocks clicks โ use it to prevent
|
|
94
|
+
double-submits during async actions.
|
|
95
|
+
- **Block:** `:block` makes the button span its container's width.
|
|
96
|
+
- **Label overflow:** buttons hug their label; no built-in truncation โ keep labels short.
|
|
97
|
+
- **Rounded:** `rounded` (default) gives a pill radius; `:rounded="false"` squares it (4px).
|
|
98
|
+
|
|
99
|
+
## Content & writing
|
|
100
|
+
|
|
101
|
+
- **Action-first, concise labels:** "Save", "Create policy", "Delete" โ verb + object.
|
|
102
|
+
- Avoid vague labels ("OK", "Submit") where a specific verb is clearer.
|
|
103
|
+
- One word or short phrase; no sentences. *(Confirm casing convention against product โ
|
|
104
|
+
appears sentence/Title case; standardize in a later content-guidelines pass.)*
|
|
105
|
+
|
|
106
|
+
## Accessibility
|
|
107
|
+
|
|
108
|
+
- **Semantics:** renders a native `<button type="button">` โ correct role, Enter/Space
|
|
109
|
+
activate. โ
|
|
110
|
+
- **Icon-only buttons:** must have an accessible name โ provide visually-hidden text or an
|
|
111
|
+
`aria-label` (no automatic label). โ ๏ธ
|
|
112
|
+
- **Target size:** default/large โ 34px tall, `small` โ 24px. Meets a ~28px pointer
|
|
113
|
+
target but is **below the 44โ48px touch-target** guideline (Uber Base uses 48px tap) โ
|
|
114
|
+
caution using `small` on touch surfaces. (See F4.)
|
|
115
|
+
- **Focus indicator:** **appears to be removed** (`outline: none`, no focus shadow) โ a
|
|
116
|
+
WCAG 2.4.7 risk. (See F3.)
|
|
117
|
+
- **Contrast:** primary navy `#07101f` + white text = high contrast โ
; verify the lighter
|
|
118
|
+
variants (`neutral-lightest`, `transparent`) text contrast in both themes.
|
|
119
|
+
|
|
120
|
+
## Props / API
|
|
121
|
+
|
|
122
|
+
`variant` ยท `size` ยท `loading` (bool/obj) ยท `disabled` ยท `outline` ยท `block` ยท
|
|
123
|
+
`rounded` (default true) ยท `shadow` (default true) ยท `shape`. Emits `click`.
|
|
124
|
+
Full machine spec: [`../registry/button.json`](../registry/button.json).
|
|
125
|
+
|
|
126
|
+
## Design tokens used
|
|
127
|
+
|
|
128
|
+
`--primary-button-bg` ยท `--primary-button-text` ยท `--btn-height` ยท `--btn-radius` ยท
|
|
129
|
+
`--severity-*` (success/error) ยท `--neutral-*` (neutral variants) ยท `--primary` (focus,
|
|
130
|
+
proposed).
|
|
131
|
+
|
|
132
|
+
## Findings & Inconsistencies
|
|
133
|
+
|
|
134
|
+
### F1 โ `variant` allow-list forces info/neutral/warning to navy ยท High ยท Proposed
|
|
135
|
+
|
|
136
|
+
`info`/`neutral`(77ร)/`neutral-light`/`warning` render navy because
|
|
137
|
+
`src/design/buttons.less` only allow-lists certain variants to escape navy via a
|
|
138
|
+
high-specificity `:not(...)`. **Solution options A/B/C below.**
|
|
139
|
+
|
|
140
|
+
### F2 โ `danger` renders light, not solid red ยท Low ยท Open
|
|
141
|
+
|
|
142
|
+
Ant 1.4 `type="danger"` styling; the codebase uses `error` (31ร) for destructive actions.
|
|
143
|
+
**Solution:** standardize on `error`; optionally map `danger` โ `error`.
|
|
144
|
+
|
|
145
|
+
### F3 โ No visible focus indicator ยท High ยท Open *(a11y)* โ see SF-001
|
|
146
|
+
|
|
147
|
+
Focused buttons show `outline: none` and no focus shadow โ keyboard users can't see focus
|
|
148
|
+
(WCAG 2.4.7). **This is system-wide** โ tracked as
|
|
149
|
+
[SF-001](../../findings/SF-001-focus-visible.md) (fix once globally with a `:focus-visible`
|
|
150
|
+
ring, don't patch per component).
|
|
151
|
+
|
|
152
|
+
### F4 โ Small/large target sizes ยท Medium ยท Open *(new, a11y)*
|
|
153
|
+
|
|
154
|
+
`small` โ 24px is below the 44โ48px touch target; risky on touch. **Solution:** reserve
|
|
155
|
+
`small` for dense desktop UIs; ensure โฅ44px hit area on touch (padding) or avoid `small`.
|
|
156
|
+
|
|
157
|
+
### F5 โ `large` renders the same height as `default` ยท Low ยท Open *(new)*
|
|
158
|
+
|
|
159
|
+
Measured `large` โ 34px = `default`. **Solution:** confirm intent; if `large` should be
|
|
160
|
+
bigger, add a size token; else drop `large` from the documented sizes (used only 9ร).
|
|
161
|
+
|
|
162
|
+
### F6 โ `shadow` prop is inverted/confusing ยท Low ยท Open *(new)*
|
|
163
|
+
|
|
164
|
+
`shadow` defaults to **true**, but `:shadow="true"` applies the `.button-shadow` class which
|
|
165
|
+
sets `box-shadow: none !important`. So the prop named "shadow" **removes** the shadow, and
|
|
166
|
+
variant hover styles re-add their own shadow. **Solution:** rename to `noShadow`/`flat`, or
|
|
167
|
+
invert the logic so `shadow` means what it says (document loudly meanwhile).
|
|
168
|
+
|
|
169
|
+
### F7 โ `shape="circle"` isn't circular ยท Medium ยท Open *(new)*
|
|
170
|
+
|
|
171
|
+
Because `rounded` defaults to **true** (`.rounded { border-radius: 4px }`) and wins over Ant's
|
|
172
|
+
`.ant-btn-circle` (50%), `shape="circle"` buttons render as **4px-rounded squares**, not
|
|
173
|
+
circles (measured `border-radius: 4px`). **This is the real product behaviour, not a Storybook
|
|
174
|
+
artifact**, and it's not an edge case: of **198** `shape="circle"` buttons, only **24** pass
|
|
175
|
+
`:rounded="false"` (true circle) โ **~174 render as rounded squares**. The prop name is
|
|
176
|
+
misleading for ~88% of its uses. **Solution:** if a true circle is intended, pass
|
|
177
|
+
`:rounded="false"` with `shape="circle"`, or have the `circle` shape override the radius (so
|
|
178
|
+
"circle" means circle).
|
|
179
|
+
|
|
180
|
+
## Recommended solution โ F1 (the main one)
|
|
181
|
+
|
|
182
|
+
- **A (recommended):** add the variants to the allow-list + token-backed styles:
|
|
183
|
+
|
|
184
|
+
```less
|
|
185
|
+
.ant-btn.ant-btn-primary:not(
|
|
186
|
+
โฆexistingโฆ, .button-neutral, .button-info
|
|
187
|
+
) { background: var(--primary-button-bg); }
|
|
188
|
+
.ant-btn.button-neutral { background: var(--neutral-button-bg); color: var(--neutral-button-text); }
|
|
189
|
+
.ant-btn.button-info { background: var(--secondary-blue, var(--primary-alt)); color: #fff; }
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
- **B:** deprecate info/neutral/neutral-light/warning; migrate ~84 usages.
|
|
193
|
+
- **C:** won't-fix; rename in docs (unlikely โ "neutral" reading navy is confusing).
|
|
194
|
+
|
|
195
|
+
## Do / Don't
|
|
196
|
+
|
|
197
|
+
### Do
|
|
198
|
+
|
|
199
|
+
- Use `variant="primary"` for the single main action; `primary-alt` for secondary emphasis.
|
|
200
|
+
- Use `error` (not `danger`) for destructive actions, with a confirm.
|
|
201
|
+
- Use `neutral-lighter` / `neutral-lightest` / `transparent` for subtle actions.
|
|
202
|
+
- Give icon-only buttons an `aria-label`; show `:loading` during async work.
|
|
203
|
+
|
|
204
|
+
### Don't
|
|
205
|
+
|
|
206
|
+
- Don't use `neutral`/`info` expecting gray/blue โ they render navy today (F1).
|
|
207
|
+
- Don't put two `primary` buttons in one action group.
|
|
208
|
+
- Don't rely on `small` for touch targets (F4); don't hardcode colors.
|
|
209
|
+
|
|
210
|
+
## Related components
|
|
211
|
+
|
|
212
|
+
`MConfirmBtn` (confirm-on-click) ยท `MDropdown` (menu trigger) ยท `FlotoGridActions` (row
|
|
213
|
+
actions). **Icon buttons** (`shape="circle"` / `.squared-button`) now documented above.
|
|
214
|
+
Button-*like* relatives (own families): **`FlotoLink`** (link-styled button, 67ร) and the
|
|
215
|
+
**segmented control** (`MRadioGroup` `as-button`, 255ร โ part of the Radio family). See the
|
|
216
|
+
[Family Map](../family-map.md).
|
|
217
|
+
|
|
218
|
+
## Changelog
|
|
219
|
+
|
|
220
|
+
- **2026-06-05** โ Added to Storybook. Variants corrected to the distinctly-rendering set;
|
|
221
|
+
`primary-alt` added; `info`/`neutral`/etc. moved to a flagged "navy fallback" story (F1).
|
|
222
|
+
- **2026-06-05** โ Light/dark verified (primary flips white-on-navy in dark).
|
|
223
|
+
- **2026-06-06** โ Upgraded to the enhanced doc standard; added Anatomy, Behaviors,
|
|
224
|
+
Content, Accessibility (F3 focus ring, F4 target size, F5 large-size), Related, Changelog.
|
|
225
|
+
- **2026-06-07** โ Thorough button audit (whole product). Added the two **icon-button** forms
|
|
226
|
+
(`shape="circle"` 218ร + `.squared-button` 365ร) โ story + Options section + usage. New
|
|
227
|
+
findings **F6** (inverted `shadow` prop) and **F7** (`shape="circle"` not circular). Noted
|
|
228
|
+
button-like relatives `FlotoLink` (67ร) and the segmented control (`MRadioGroup as-button`,
|
|
229
|
+
255ร); both filed in the Family Map.
|
|
230
|
+
</content>
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Checkbox (`MCheckbox`) โ Spec, Findings & Solutions
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Tier** | Atom |
|
|
6
|
+
| **Maturity** | ๐ข Stable (core) โ but has an open **accessibility** finding (F3) |
|
|
7
|
+
| **Source** | **Floto override** โ `src/components/_base-checkbox.vue` (kit's `MCheckbox` is **excluded** in `main.js`) |
|
|
8
|
+
| **Storybook** | `Atoms/Checkbox` |
|
|
9
|
+
| **Registry** | [`../registry/checkbox.json`](../registry/checkbox.json) |
|
|
10
|
+
| **Figma** | TODO |
|
|
11
|
+
|
|
12
|
+
> Documented to the [enhanced standard](../documentation-standard.md).
|
|
13
|
+
|
|
14
|
+
## Usage (product analytics)
|
|
15
|
+
|
|
16
|
+
- **`<MCheckbox>` used 76ร across 59 files.**
|
|
17
|
+
- **`<MCheckboxGroup>` 0ร** (kit group unused; multi-select built ad-hoc).
|
|
18
|
+
- **`indeterminate` used ~5 sites** โ select-all permission groups, hierarchy/tree
|
|
19
|
+
pickers, NOC dashboard picker.
|
|
20
|
+
|
|
21
|
+
## Overview
|
|
22
|
+
|
|
23
|
+
A single boolean toggle, usually with a label. The product ships the Floto override
|
|
24
|
+
`_base-checkbox.vue` โ a **`<template functional>`**, **fully-controlled** component (no
|
|
25
|
+
internal state) that renders the Ant checkbox markup and emits `change(checked)`. Bind
|
|
26
|
+
with `v-model` (or `:checked` + `@change`).
|
|
27
|
+
|
|
28
|
+
## Anatomy
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
โโ label (.ant-checkbox-wrapper) โโโโโโโโโโโโโโโโ
|
|
32
|
+
โ โโโโ โ
|
|
33
|
+
โ โโ โ Label text (default slot) โ
|
|
34
|
+
โ โโโโ โ
|
|
35
|
+
โ โฒ box (.ant-checkbox-inner, 19px) + check (::after, navy) โ
|
|
36
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
- **Wrapper** โ `<label class="ant-checkbox-wrapper">` (clicking it toggles).
|
|
40
|
+
- **Box** โ `.ant-checkbox-inner`, 19ร19px, radius 3px.
|
|
41
|
+
- **Checkmark** โ `::after`, navy (`--primary`).
|
|
42
|
+
- **Hidden input** โ `<input type="checkbox">` (the real control for AT).
|
|
43
|
+
- **Label** โ default slot (optional).
|
|
44
|
+
|
|
45
|
+
## Options / States
|
|
46
|
+
|
|
47
|
+
`unchecked` ยท `checked` ยท `indeterminate` (dash; partial-group) ยท `disabled`
|
|
48
|
+
(+ disabled-checked). All **controlled** โ pass the state in.
|
|
49
|
+
|
|
50
|
+
**Context re-check (2026-06-07):** swept all checkbox styling (`checkbox.less`, kit override,
|
|
51
|
+
`table.less`, `app.less`, `general.less`) for hidden/context variants like Radio's segmented
|
|
52
|
+
set. Result: **none** โ the table rules (`td.checkbox` 60px column, wrapper `float`) and
|
|
53
|
+
`.checkbox-label` are pure **layout**, not new looks. The only extra is an **unused
|
|
54
|
+
`.checkbox-info`** variant (info-blue checked) in the kit override โ **0ร usage**, and not part
|
|
55
|
+
of the Floto override's API (parallel to `radio-info`). So the checkbox surface is complete.
|
|
56
|
+
|
|
57
|
+
## Behaviors
|
|
58
|
+
|
|
59
|
+
- **Controlled only:** no internal state / no `defaultChecked`. The parent owns `checked`
|
|
60
|
+
via `v-model`; without it the box won't change on click.
|
|
61
|
+
- **Indeterminate** is a parent-over-group signal (shown as a dash), not a stored value.
|
|
62
|
+
|
|
63
|
+
## Content & writing
|
|
64
|
+
|
|
65
|
+
- Label states the positive choice ("Send me updates", "Enable notifications").
|
|
66
|
+
- Keep labels short; avoid negatives ("Don'tโฆ") which confuse the checked meaning.
|
|
67
|
+
|
|
68
|
+
## Accessibility
|
|
69
|
+
|
|
70
|
+
- **Label association:** the `<input>` is nested in the `<label>` (implicit association) โ
|
|
71
|
+
clicking the label toggles. โ
Provide a label (or an `aria-label` for a bare box).
|
|
72
|
+
- **Keyboard:** native input โ Space toggles, Tab focuses. โ
|
|
73
|
+
- **๐ด Screen-reader state is wrong (F3):** the override never binds `:checked` to the
|
|
74
|
+
`<input>`, so the input reports `checked = false` even when visually checked. AT
|
|
75
|
+
announces the wrong state.
|
|
76
|
+
- **Indeterminate not exposed (F4):** the dash is CSS-only; the input has no
|
|
77
|
+
`indeterminate` property / `aria-checked="mixed"`, so AT can't announce "mixed".
|
|
78
|
+
- **Target size:** 19px box is below the ~24px+ min; the wrapper label extends the hit
|
|
79
|
+
area, but a bare box (no label) is a small touch target (F5).
|
|
80
|
+
|
|
81
|
+
## Props / API (the override โ not the kit's)
|
|
82
|
+
|
|
83
|
+
| Prop | Type | Notes |
|
|
84
|
+
| --- | --- | --- |
|
|
85
|
+
| `checked` | Boolean | **v-model** (`model: checked/change`) |
|
|
86
|
+
| `disabled` | Boolean | |
|
|
87
|
+
| `indeterminate` | Boolean | parent-over-group |
|
|
88
|
+
| `value` | Boolean/String | grouping id |
|
|
89
|
+
|
|
90
|
+
Event `change(checked)`; slot = label. **Not present:** `variant`, `defaultChecked`,
|
|
91
|
+
`autoFocus`. Machine spec: [`../registry/checkbox.json`](../registry/checkbox.json).
|
|
92
|
+
|
|
93
|
+
## Design tokens used
|
|
94
|
+
|
|
95
|
+
`--checkbox-bg` (checked fill: `#fff` light / `#2b394f` dark) ยท
|
|
96
|
+
`--checkbox-checked-border-color` ยท `--primary` (checkmark) ยท `--neutral-lighter` (border).
|
|
97
|
+
|
|
98
|
+
## Findings & Inconsistencies
|
|
99
|
+
|
|
100
|
+
### F1 โ Product `MCheckbox` is a functional override; kit's is excluded ยท Medium ยท Documented
|
|
101
|
+
|
|
102
|
+
Two `MCheckbox` implementations; the kit's (with `variant`/`defaultChecked`) is excluded
|
|
103
|
+
in `main.js` and effectively dead. Document the **override's** API. Storybook preview
|
|
104
|
+
replicates the exclusion+override (fixed).
|
|
105
|
+
|
|
106
|
+
### F2 โ Checked state relies on the checkmark, not a colored fill ยท Low ยท Open
|
|
107
|
+
|
|
108
|
+
Checked fill is `--checkbox-bg` (white in light), not a brand fill โ subtler than typical.
|
|
109
|
+
Confirm intent; if stronger affordance wanted, fill with `--primary` + white tick.
|
|
110
|
+
|
|
111
|
+
### F3 โ `<input>.checked` not bound โ screen readers announce wrong state ยท High ยท Open *(a11y)*
|
|
112
|
+
|
|
113
|
+
The functional template sets `:disabled` but **not `:checked`** on the input; the visual
|
|
114
|
+
checked is class-driven. So AT reads the input as unchecked even when checked.
|
|
115
|
+
|
|
116
|
+
**Solution:** bind the input's checked state in `_base-checkbox.vue`:
|
|
117
|
+
|
|
118
|
+
```vue
|
|
119
|
+
<input type="checkbox" :checked="props.checked" :disabled="props.disabled" @change="โฆ" />
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
(and set the `indeterminate` DOM property โ see F4).
|
|
123
|
+
|
|
124
|
+
### F4 โ Indeterminate not exposed to AT ยท Medium ยท Open *(a11y)*
|
|
125
|
+
|
|
126
|
+
`indeterminate` only adds a CSS class; the input lacks the `indeterminate` property /
|
|
127
|
+
`aria-checked="mixed"`. **Solution:** set `inputEl.indeterminate = props.indeterminate`
|
|
128
|
+
(DOM property via a small directive/ref, since it's not a reflected attribute).
|
|
129
|
+
|
|
130
|
+
### F5 โ 19px box is a small touch target ยท Low ยท Open
|
|
131
|
+
|
|
132
|
+
Fine with a label (extended hit area); risky as a bare box on touch. **Solution:** ensure
|
|
133
|
+
โฅ24px hit area (padding) for label-less checkboxes.
|
|
134
|
+
|
|
135
|
+
## Do / Don't
|
|
136
|
+
|
|
137
|
+
### Do
|
|
138
|
+
|
|
139
|
+
- Provide a label via the default slot; bind with `v-model`.
|
|
140
|
+
- Use `indeterminate` for a parent over a mixed group.
|
|
141
|
+
|
|
142
|
+
### Don't
|
|
143
|
+
|
|
144
|
+
- Don't use `variant`/`defaultChecked` (the override has neither).
|
|
145
|
+
- Don't use a checkbox for mutually-exclusive choices (`MRadio`) or instant settings (`MSwitch`).
|
|
146
|
+
|
|
147
|
+
## Related components
|
|
148
|
+
|
|
149
|
+
`MRadio` (mutually-exclusive) ยท `MSwitch` (instant on/off) ยท `MCheckboxGroup` (kit, unused)
|
|
150
|
+
ยท select-all/tree-picker patterns that use `indeterminate`.
|
|
151
|
+
|
|
152
|
+
## Changelog
|
|
153
|
+
|
|
154
|
+
- **2026-06-05** โ Added to Storybook to the real (Floto override) API; preview fixed to
|
|
155
|
+
exclude the kit's MCheckbox and register the override (F1). Light/dark verified.
|
|
156
|
+
- **2026-06-06** โ Documented `indeterminate` product usage. Upgraded to enhanced standard;
|
|
157
|
+
added Anatomy, Behaviors, Content, Accessibility โ surfacing **F3** (SR state not bound,
|
|
158
|
+
High) and **F4** (indeterminate not exposed) with fixes; Related; Changelog.
|
|
159
|
+
- **2026-06-07** โ Context-variant re-check (post-Radio): swept all checkbox LESS for hidden
|
|
160
|
+
variants โ none (table/label rules are layout only); noted the unused `.checkbox-info`
|
|
161
|
+
variant (0ร). Surface confirmed complete.
|
|
162
|
+
</content>
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Data-Viz Tooltips โ Spec, Findings & Solutions
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Tier** | Molecule (reference patterns) |
|
|
6
|
+
| **Maturity** | ๐ข Stable |
|
|
7
|
+
| **Source** | `src/components/chart/options/tooltip-builder.js` (`TooltipBuilder`) + `.hc-tooltip-bg` / `.highcharts-tooltip-container-class` (Highcharts) ยท `heatmap-tooltip.vue` + sparkline (Vue widgets) ยท graph canvases (vis-network / d3, `--topology-graph-tooltip-bg`) ยท d3 flame graph. |
|
|
8
|
+
| **Storybook** | Molecules/Data-Viz Tooltips |
|
|
9
|
+
| **Registry** | [`registry/data-viz-tooltips.json`](../registry/data-viz-tooltips.json) |
|
|
10
|
+
| **Family** | Tooltip family (see also [`tooltip.md`](./tooltip.md)) |
|
|
11
|
+
|
|
12
|
+
## Why this is a family
|
|
13
|
+
|
|
14
|
+
The product's **chart & widget hover tooltips** are a **distinct family from `MTooltip`** โ they are
|
|
15
|
+
**not** DS Vue components. They are owned by the **chart layer**: most are rendered by Highcharts via
|
|
16
|
+
the shared **`TooltipBuilder`**, the graph tooltips by canvas libraries (vis-network / d3), and a few by
|
|
17
|
+
widget Vue components (heatmap, sparkline). We catalogue them as **reference reproductions** (built from
|
|
18
|
+
real tokens โ `--chart-tooltip-background`, `--severity-*`, `--topology-graph-tooltip-bg`) so a designer
|
|
19
|
+
or AI can map **place โ tooltip** without us re-implementing chart internals.
|
|
20
|
+
|
|
21
|
+
## Render mechanisms (the 4 surfaces)
|
|
22
|
+
|
|
23
|
+
| Mechanism | Surface token / class | Tooltips |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| **Highcharts `TooltipBuilder`** | `--chart-tooltip-background` + `blur(15px)` (`hc-tooltip-bg`) | series/bar, donut/pie, bubble, map/geo, radar, timeline/x-range, gauge, sankey, treemap, scatter, anomaly/forecast band, RUM waterfall, geo marker, log-pattern, sparkline |
|
|
26
|
+
| **Vue widget component** | component-scoped | heatmap (`heatmap-tooltip.vue`), alert/availability segment, availability bar |
|
|
27
|
+
| **Graph canvas** (vis-network / d3) | `--topology-graph-tooltip-bg` (fixed-dark both themes) | live-graph node/edge, APM service-map node, SDN tunnel edge, Cisco ACI endpoint/link, network interface edge, netroute node/edge |
|
|
28
|
+
| **d3 flame graph** | `hc-tooltip-bg` surface | flame-graph span (APM / RUM traces) |
|
|
29
|
+
|
|
30
|
+
## Which tooltip โ where (lookup)
|
|
31
|
+
|
|
32
|
+
| Tooltip | Where used | Renderer |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| Bar / series | severity/metric stacked columns & line charts | Highcharts `TooltipBuilder` |
|
|
35
|
+
| Donut / pie | status/distribution donuts | Highcharts |
|
|
36
|
+
| Bubble (packed-bubble) | grouped-count bubble widgets | Highcharts |
|
|
37
|
+
| Map / geo | geo-distribution maps | Highcharts |
|
|
38
|
+
| Radar | multi-axis comparison | Highcharts |
|
|
39
|
+
| Timeline / x-range | SLO / availability timelines | Highcharts |
|
|
40
|
+
| Gauge / circular-progress | KPI gauges | Highcharts |
|
|
41
|
+
| Sankey / flow | flow / traffic sankey | Highcharts |
|
|
42
|
+
| Treemap | capacity / hierarchy treemaps | Highcharts |
|
|
43
|
+
| Scatter (x / y) | correlation scatter | Highcharts |
|
|
44
|
+
| Anomaly / forecast band | anomaly & forecast charts (actual vs expected range) | Highcharts |
|
|
45
|
+
| RUM resource waterfall | RUM page resource timing | Highcharts |
|
|
46
|
+
| Geo map marker (RUM apdex) | RUM geo apdex map | Highcharts |
|
|
47
|
+
| Log pattern distribution | log pattern value distribution | Highcharts |
|
|
48
|
+
| Sparkline | inline mini-trends (grid cells, KPIs) | Highcharts (mini) |
|
|
49
|
+
| Heatmap | heatmap widgets | `heatmap-tooltip.vue` |
|
|
50
|
+
| Alert / availability segment | segmented availability cells | Vue (segmented-cell) |
|
|
51
|
+
| Availability bar segment | Up/Down % bars | Vue |
|
|
52
|
+
| Live graph โ node | topology / netroute maps | graph canvas |
|
|
53
|
+
| Live graph โ edge | link / interface edges | graph canvas |
|
|
54
|
+
| APM service-map node | APM service map | graph canvas |
|
|
55
|
+
| SDN tunnel edge | SD-WAN tunnels | graph canvas |
|
|
56
|
+
| Cisco ACI endpoint | ACI endpoint edges | graph canvas |
|
|
57
|
+
| Cisco ACI fabric link | ACI fabric links | graph canvas |
|
|
58
|
+
| Network interface edge | interface topology | graph canvas |
|
|
59
|
+
| Netroute hop node | netroute path hops | graph canvas |
|
|
60
|
+
| Netroute edge (transit) | netroute transit edges | graph canvas |
|
|
61
|
+
| Flame graph span | APM / RUM trace flame graphs | d3 flame graph |
|
|
62
|
+
|
|
63
|
+
## Accessibility
|
|
64
|
+
|
|
65
|
+
- These are **hover-only, canvas/SVG-rendered** surfaces โ they are **not keyboard-reachable** and not
|
|
66
|
+
exposed to assistive tech (a known limitation of the chart libraries). Where the underlying data
|
|
67
|
+
matters for a11y, it must also be available in an adjacent **table / legend** (verify per widget).
|
|
68
|
+
|
|
69
|
+
## Design tokens used
|
|
70
|
+
|
|
71
|
+
`--chart-tooltip-background` ยท `--topology-graph-tooltip-bg` ยท `--tooltip-text-color` ยท
|
|
72
|
+
`--severity-{down,unreachable,critical,major,warning,up,โฆ}` ยท `--page-text-color` ยท `--border-color`.
|
|
73
|
+
|
|
74
|
+
## Findings & Inconsistencies
|
|
75
|
+
|
|
76
|
+
| # | Severity | Status | Finding |
|
|
77
|
+
| --- | --- | --- | --- |
|
|
78
|
+
| F1 | Low | Noted | Owned by the chart layer (Highcharts/vis-network/d3), **not** DS components โ catalogued as **reference reproductions** (real tokens), not live renders. |
|
|
79
|
+
| F2 | Low (a11y) | Open | Hover-only, canvas-rendered โ not keyboard-reachable / not in the a11y tree; ensure the data also exists in a table/legend. |
|
|
80
|
+
|
|
81
|
+
## Related components
|
|
82
|
+
|
|
83
|
+
**Tooltip** (`MTooltip` โ the UI/text tooltip family) ยท **Table** (sparkline cells) ยท the chart/widget
|
|
84
|
+
layer (`src/components/chart`, `src/components/widgets`).
|
|
85
|
+
|
|
86
|
+
## Changelog
|
|
87
|
+
|
|
88
|
+
- **2026-06-16** โ Added the **registry + spec** (this page) and a **which-tooltipโwhere** lookup table,
|
|
89
|
+
so the family matches the "four pages move together" rule (it was previously a **story only**). No
|
|
90
|
+
story changes โ the ~28 reference reproductions already cover every mechanism (Highcharts series,
|
|
91
|
+
donut, bubble, map, radar, timeline, gauge, sankey, treemap, scatter, anomaly band, waterfall, geo
|
|
92
|
+
marker, log-pattern, sparkline; heatmap & segment Vue widgets; 9 graph-canvas node/edge tooltips; the
|
|
93
|
+
d3 flame graph). Findings F1 (reproduction), F2 (a11y).
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Date & Time Pickers โ Spec, Findings & Solutions
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Tier** | Molecule |
|
|
6
|
+
| **Maturity** | ๐ข Stable |
|
|
7
|
+
| **Source** | `src/components/widgets/time-range-picker.vue` (`TimeRangePicker`) ยท `ui/components/Datepicker/Datepicker.vue` (`MDatePicker`) ยท `ui/components/Datepicker/Timepicker.vue` (`MTimePicker`) ยท `src/components/common/date-time-popover.vue` (`DateTimePopover`). |
|
|
8
|
+
| **Storybook** | Molecules/Date & Time Pickers |
|
|
9
|
+
| **Registry** | [`registry/date-time-pickers.json`](../registry/date-time-pickers.json) |
|
|
10
|
+
| **Family** | [Date & Time Pickers](../family-map.md) |
|
|
11
|
+
|
|
12
|
+
## Usage analytics
|
|
13
|
+
|
|
14
|
+
- **`TimeRangePicker`** โ **42ร / 35 files**. The dominant control; the observability time-range
|
|
15
|
+
selector. Real variants: **`hide-custom-time-range`** (24ร, presets-only), `allow-clear` (7ร),
|
|
16
|
+
`max-selectable-range-days` (2ร), plus `bordered`, `pill-style`, `hide-selected-time`, `only-label`.
|
|
17
|
+
- **`MDatePicker`** โ **10ร / 8 files**. **All 10 usages pass `:show-time`** โ it is the **date-time**
|
|
18
|
+
field, not date-only. Often with `:min-date` (7ร), `:allow-clear` (9ร), `:disabled` (5ร).
|
|
19
|
+
- **`TimeRangeSlider`** โ **2ร** (dashboard view + alert correlation drawer); a timeline scrubber
|
|
20
|
+
variant of the time-range control (square handles, navy track, time-mark ticks).
|
|
21
|
+
- **Standalone time pickers โ `0ร`.** Both the kit **`MTimePicker`** and the custom **`TimePicker`**
|
|
22
|
+
(`time-picker.vue`, a `FlotoDropdownPicker` of time options) are **0ร as standalone tags**. Time is
|
|
23
|
+
entered via MDatePicker `show-time` or inside the TimeRangePicker custom view (which uses the custom
|
|
24
|
+
dropdown-based `TimePicker`, not an Ant spinner).
|
|
25
|
+
- **`DateTimePopover`** โ **1ร** (SLO correction profile); a custom-range-only popover.
|
|
26
|
+
- **Checked & scoped out:** **Scheduler / Recurrence** (`schedule-input/`, 17 files โ Once/Daily/
|
|
27
|
+
Weekly/Monthly builder) is a **separate family** (future entry), not a picker; `date-remark-pairs`
|
|
28
|
+
(holiday list) is a composite; kit `DateRangePicker`/`NotifyTimePicker` are 0ร; **no** week / month /
|
|
29
|
+
quarter / calendar pickers exist. `only-label` and `daily-rolling` props are **declared but 0ร**.
|
|
30
|
+
|
|
31
|
+
## Overview
|
|
32
|
+
|
|
33
|
+
The family covers three jobs: **pick a time window** (relative or absolute) for charts/dashboards/
|
|
34
|
+
logs โ **`TimeRangePicker`**; **pick a date(+time) value** in a form โ **`MDatePicker`** (always with
|
|
35
|
+
`show-time`); **pick a time of day** โ **`MTimePicker`**. `TimeRangePicker` is the hero and is unique
|
|
36
|
+
to this product; the others wrap Ant `a-date-picker` / `a-time-picker`.
|
|
37
|
+
|
|
38
|
+
## Anatomy
|
|
39
|
+
|
|
40
|
+
### TimeRangePicker โ anatomy
|
|
41
|
+
|
|
42
|
+
- **Trigger (closed):** a `--timerange-background-color` **shortcut pill** (`24h`, `1h`, or a computed
|
|
43
|
+
duration like `6d 23h`) + a separator + the **range label** (`Last 24 Hours`). Empty โ a
|
|
44
|
+
**calendar-alt** icon + "Select Time". `:bordered` adds a frame; `:allow-clear` a **times-circle** ร.
|
|
45
|
+
- **Panel โ presets:** the 15 relative options (Last 5/15/30 Mins ยท Last 1/6/12/24/48 Hours ยท Today ยท
|
|
46
|
+
Last Day ยท Last/This Week ยท Last/This Month), each with its shortcut pill; active row uses
|
|
47
|
+
`--dropdown-hover-background`. **Custom** sits at the bottom (hidden by `hide-custom-time-range`).
|
|
48
|
+
- **Panel โ custom:** an `a-range-picker` calendar (start/end) with two `MTimePicker` (From/To,
|
|
49
|
+
seconds) and **Apply / Cancel** buttons; validates end > start.
|
|
50
|
+
|
|
51
|
+
### MDatePicker / MTimePicker
|
|
52
|
+
|
|
53
|
+
- `MDatePicker` = `a-date-picker` + a **calendar** suffix icon, `show-time` (12-hour `hh:mm A`),
|
|
54
|
+
`dateRender` slot for custom cells, `disabled-date` / `min-date` constraints.
|
|
55
|
+
- `MTimePicker` = `a-time-picker`, **12-hour**, **clock** suffix icon, `allow-clear` default true.
|
|
56
|
+
|
|
57
|
+
## Options (props)
|
|
58
|
+
|
|
59
|
+
### TimeRangePicker
|
|
60
|
+
|
|
61
|
+
| Prop | Default | Notes |
|
|
62
|
+
| --- | --- | --- |
|
|
63
|
+
| `value` | โ | v-model; `{ selectedKey, startDate, endDate, startTime, endTime, dailyRollingData }` |
|
|
64
|
+
| `hideCustomTimeRange` | `false` | **24ร** โ drop "Custom" (presets-only) |
|
|
65
|
+
| `maxSelectableRangeDays` | `93` | disables dates beyond the span (365 for report export) |
|
|
66
|
+
| `allowClear` | `false` | times-circle ร โ emits `change=undefined` |
|
|
67
|
+
| `bordered` / `pillStyle` / `hideSelectedTime` / `onlyLabel` | โ | trigger display variants |
|
|
68
|
+
| `excludedOptions` | โ | array of preset keys to drop |
|
|
69
|
+
| `disabled` / `overlayClassName` / `getPopupContainer` | โ | standard |
|
|
70
|
+
|
|
71
|
+
### MDatePicker
|
|
72
|
+
|
|
73
|
+
| Prop | Default | Notes |
|
|
74
|
+
| --- | --- | --- |
|
|
75
|
+
| `value` | โ | moment/string/number; v-model |
|
|
76
|
+
| `showTime` | `{ use12Hours:true, format:'hh:mm A' }` | **always passed in real use** |
|
|
77
|
+
| `allowClear` | โ | 9ร |
|
|
78
|
+
| `minDate` | โ | 7ร; earliest selectable |
|
|
79
|
+
| `disabledDate` | โ | function to grey out days |
|
|
80
|
+
| `format` / `placeholder` | โ | display format / `Select...` |
|
|
81
|
+
|
|
82
|
+
### MTimePicker
|
|
83
|
+
|
|
84
|
+
| Prop | Default | Notes |
|
|
85
|
+
| --- | --- | --- |
|
|
86
|
+
| `value` | โ | moment/string/number |
|
|
87
|
+
| `format` | `hh:mm A` | 12-hour |
|
|
88
|
+
| `use12Hours` | `true` | |
|
|
89
|
+
| `allowClear` | `true` | |
|
|
90
|
+
|
|
91
|
+
## Behaviors
|
|
92
|
+
|
|
93
|
+
- **TimeRangePicker emit:** relative โ `{ selectedKey:'-24h', startDate, endDate, startTime, endTime }`;
|
|
94
|
+
custom โ `{ selectedKey:'custom', โฆ }`; cleared โ `undefined`. Custom blocks Apply if end โค start.
|
|
95
|
+
- **Start-time rounding:** relative ranges round the start to the nearest 5-minute boundary.
|
|
96
|
+
- **MTimePicker emit:** `change(formattedString, moment)`.
|
|
97
|
+
|
|
98
|
+
## Accessibility
|
|
99
|
+
|
|
100
|
+
- **Provided by Ant:** `a-date-picker` / `a-time-picker` give a focusable text input + a
|
|
101
|
+
keyboard-navigable calendar/time panel; Escape closes.
|
|
102
|
+
- **Verify:** focus-visible ring (**SF-001**) on the inputs and on the TimeRangePicker **preset rows**
|
|
103
|
+
(clickable `<a>`/divs โ ensure they're keyboard-reachable and labelled).
|
|
104
|
+
|
|
105
|
+
## Design tokens used
|
|
106
|
+
|
|
107
|
+
`--timerange-background-color` ยท `--timerange-text-color` (pill) ยท `--dropdown-background` ยท
|
|
108
|
+
`--dropdown-hover-background` ยท `--left-menu-text-color-hover` (active preset) ยท `--border-color` ยท
|
|
109
|
+
`--primary` ยท `--calendar-selected-day-background-color` ยท `--tag-bg` (calendar range) ยท
|
|
110
|
+
`--secondary-red` (error) ยท `--neutral-light` / `--neutral-lightest` / `--page-text-color`.
|
|
111
|
+
|
|
112
|
+
## Findings & Inconsistencies
|
|
113
|
+
|
|
114
|
+
| # | Severity | Status | Finding |
|
|
115
|
+
| --- | --- | --- | --- |
|
|
116
|
+
| F1 | Low | Noted | `TimeRangePicker` depends on the user-preference store + `datetime` filter + moment โ **reference reproduction** in Storybook (live render not feasible, like the Kendo grid). |
|
|
117
|
+
| F2 | Low (a11y) | Open | Catalog-wide focus-ring removal (**SF-001**) may affect picker inputs / preset rows. |
|
|
118
|
+
| N1 | Info | โ | Passing an **empty string** to MTimePicker/MDatePicker `value` renders **"Invalid date"** (it parses `''` via moment) โ pass `null`/`undefined` or a moment. |
|
|
119
|
+
|
|
120
|
+
## Recommended solutions
|
|
121
|
+
|
|
122
|
+
- **F1:** keep the reproduction; if a headless TimeRangePicker is ever extracted (Vue 3), it could
|
|
123
|
+
render live with an injected format/timezone instead of the store.
|
|
124
|
+
- **F2:** adopt the shared `:focus-visible` ring (SF-001).
|
|
125
|
+
- **N1:** initialize empty values to `null`, never `''`.
|
|
126
|
+
|
|
127
|
+
## Do / Don't
|
|
128
|
+
|
|
129
|
+
- **Do** use TimeRangePicker for chart/dashboard/log windows; `hide-custom-time-range` for
|
|
130
|
+
presets-only; `MDatePicker` **with** `show-time` for date-time form fields; constrain with
|
|
131
|
+
`max-selectable-range-days` / `min-date`.
|
|
132
|
+
- **Don't** hand-roll a relative-range dropdown; don't use a bare date picker for chart windows;
|
|
133
|
+
don't pass `''` as a value (Invalid date); don't assume inline/card calendar variants (popup only).
|
|
134
|
+
|
|
135
|
+
## Related components
|
|
136
|
+
|
|
137
|
+
`FlotoDropdownPicker` (select) ยท `FlotoFormItem` (wraps date/time fields in forms) ยท `MPopover`
|
|
138
|
+
(DateTimePopover is built on it).
|
|
139
|
+
|
|
140
|
+
## Changelog
|
|
141
|
+
|
|
142
|
+
- **2026-06-15 (sweep recheck โ added the missed variant + corrections)** โ Owner: the UI doesn't
|
|
143
|
+
match the product and a variant was missed. Full census of every `<MDatePicker>` / `<MTimePicker>` /
|
|
144
|
+
`<TimeRangePicker>` tag found: **(1)** added the **`TimeRangeSlider`** โ a draggable **timeline
|
|
145
|
+
scrubber** (dashboard + alert correlation drawer, 2ร) โ as its own story; **(2)** corrected the
|
|
146
|
+
time-picker story: **no standalone time picker is used** (kit `MTimePicker` *and* custom `TimePicker`
|
|
147
|
+
are 0ร; time comes via `show-time` or the range custom view, which uses a **dropdown-based**
|
|
148
|
+
`TimePicker`, not an Ant spinner); **(3)** `excluded-options` is a real variant (**7ร**) and
|
|
149
|
+
`hide-icon` (3ร), while `only-label`/`daily-rolling` are **0ร** (overstated before); **(4)**
|
|
150
|
+
`MDatePicker` has **no** size/format/mode in use; **(5)** flagged **Scheduler/Recurrence**
|
|
151
|
+
(`schedule-input/`, 17 files) as a **separate family**. โ ๏ธ The TimeRangePicker stories are
|
|
152
|
+
reproductions โ pixel-matching the product needs a reference screenshot (requested).
|
|
153
|
+
- **2026-06-15** โ Added (decision-grade) โ the **Date & Time Pickers family** in one entry.
|
|
154
|
+
Established **`TimeRangePicker` (42ร)** as the hero (the others are 10ร/rare), the **presets list**
|
|
155
|
+
(15 options + Custom), the **emit shape**, and the **`hide-custom-time-range`** presets-only variant
|
|
156
|
+
(24ร). Documented that **`MDatePicker` is always a date-*time* field** (all 10 usages pass
|
|
157
|
+
`show-time`). Stories: real `MDatePicker`/`MTimePicker`; **reference reproductions** of the
|
|
158
|
+
TimeRangePicker trigger, presets panel, and custom range (it depends on the store/moment). Verified
|
|
159
|
+
by render+screenshot (every shot opened): MDatePicker calendar themed correctly; caught + fixed
|
|
160
|
+
MTimePicker showing **"Invalid date"** from an empty-string value (โ `null`) and an `<a>` underline
|
|
161
|
+
on preset rows. Findings F1 (reproduction), F2 (SF-001), N1 (empty-string โ Invalid date).
|