fluentui-design 0.1.2 → 0.3.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/CHANGELOG.md +49 -0
- package/README.md +0 -2
- package/package.json +1 -1
- package/skills/fluentui-design/references/index.md +9 -9
- package/skills/fluentui-design/references/patterns/PAT-002-list-page.md +24 -13
- package/skills/fluentui-design/references/patterns/PAT-004-form-page.md +21 -11
- package/skills/fluentui-design/references/rules/index.md +12 -0
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,55 @@ Each release records three things: the skill version, the baseline
|
|
|
8
8
|
`@fluentui/react-components` package version, and the pinned `fluentui-mcp` facts commit. See
|
|
9
9
|
[MAINTENANCE.md](MAINTENANCE.md) for the re-pin procedure.
|
|
10
10
|
|
|
11
|
+
## [0.3.0] - 2026-09-22
|
|
12
|
+
|
|
13
|
+
### Baseline
|
|
14
|
+
|
|
15
|
+
| Item | Value |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `@fluentui/react-components` | 9.74.7 |
|
|
18
|
+
| `fluentui-mcp` facts commit | d595d79 |
|
|
19
|
+
|
|
20
|
+
### Fixes
|
|
21
|
+
|
|
22
|
+
- forms: align the numeric rule severity and provenance
|
|
23
|
+
|
|
24
|
+
### Documentation
|
|
25
|
+
|
|
26
|
+
- plan: correct the form-inputs coverage progress count
|
|
27
|
+
- plan: add the form-inputs coverage requirements and plan
|
|
28
|
+
- roadmap: complete the datagrid coverage feature
|
|
29
|
+
|
|
30
|
+
### Features
|
|
31
|
+
|
|
32
|
+
- forms: enrich the form pattern and regenerate the skill
|
|
33
|
+
- forms: add control-choice and input rules
|
|
34
|
+
- forms: analyze the form input sources
|
|
35
|
+
|
|
36
|
+
## [0.2.0] - 2026-09-21
|
|
37
|
+
|
|
38
|
+
### Baseline
|
|
39
|
+
|
|
40
|
+
| Item | Value |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| `@fluentui/react-components` | 9.74.7 |
|
|
43
|
+
| `fluentui-mcp` facts commit | d595d79 |
|
|
44
|
+
|
|
45
|
+
### Fixes
|
|
46
|
+
|
|
47
|
+
- datagrid: correct the finding kinds and rule provenance
|
|
48
|
+
|
|
49
|
+
### Documentation
|
|
50
|
+
|
|
51
|
+
- plan: correct the datagrid coverage progress count
|
|
52
|
+
- plan: add the datagrid coverage requirements and plan
|
|
53
|
+
|
|
54
|
+
### Features
|
|
55
|
+
|
|
56
|
+
- datagrid: enrich the list pattern and regenerate the skill
|
|
57
|
+
- datagrid: add API-grounded grid rules and refresh coverage
|
|
58
|
+
- datagrid: add the DataGrid evidence source and findings
|
|
59
|
+
|
|
11
60
|
## [0.1.2] - 2026-09-21
|
|
12
61
|
|
|
13
62
|
### Baseline
|
package/README.md
CHANGED
|
@@ -115,8 +115,6 @@ re-verify the rules it uses.
|
|
|
115
115
|
(`SRC-045`) are recorded as a discovered expansion target; `SRC-002` covers only the public
|
|
116
116
|
getting-started page. Rules therefore lean on published guidance and the component library, not on
|
|
117
117
|
Figma files.
|
|
118
|
-
- **The dedicated v9 DataGrid usage page was not analyzed.** Grid rules lean on the accessibility
|
|
119
|
-
practices guide (APG) and the pinned package source (`SRC-027`).
|
|
120
118
|
- **Automated accessibility output is findings, not conformance.** The fixture is scanned with axe
|
|
121
119
|
and the results are reported as defects that were fixed; the project makes no WCAG conformance
|
|
122
120
|
claim.
|
package/package.json
CHANGED
|
@@ -11,22 +11,22 @@ For exact component props and imports, use the sibling `fluentui` skill
|
|
|
11
11
|
| Decision | Patterns | Rules |
|
|
12
12
|
| --- | --- | --- |
|
|
13
13
|
| `command-scope` | PAT-001 | RULE-001, RULE-002, RULE-003 |
|
|
14
|
-
| `data-processing-location` | PAT-002 | RULE-010, RULE-011, RULE-012, RULE-016 |
|
|
15
|
-
| `data-resilience` | PAT-002, PAT-008 | RULE-003, RULE-010, RULE-011, RULE-012, RULE-015, RULE-016 |
|
|
16
|
-
| `data-surface` | PAT-002 | RULE-010, RULE-011, RULE-012, RULE-016 |
|
|
14
|
+
| `data-processing-location` | PAT-002 | RULE-010, RULE-011, RULE-012, RULE-016, RULE-031, RULE-032, RULE-033, RULE-034, RULE-035, RULE-036 |
|
|
15
|
+
| `data-resilience` | PAT-002, PAT-008 | RULE-003, RULE-010, RULE-011, RULE-012, RULE-015, RULE-016, RULE-031, RULE-032, RULE-033, RULE-034, RULE-035, RULE-036 |
|
|
16
|
+
| `data-surface` | PAT-002 | RULE-010, RULE-011, RULE-012, RULE-016, RULE-031, RULE-032, RULE-033, RULE-034, RULE-035, RULE-036 |
|
|
17
17
|
| `edit-surface` | PAT-005 | RULE-008, RULE-009, RULE-029 |
|
|
18
18
|
| `feedback-channel` | PAT-008 | RULE-003, RULE-015, RULE-016 |
|
|
19
|
-
| `field-annotation` | PAT-004 | RULE-005, RULE-006, RULE-007, RULE-029, RULE-030 |
|
|
20
|
-
| `form-layout` | PAT-004 | RULE-005, RULE-006, RULE-007, RULE-029, RULE-030 |
|
|
19
|
+
| `field-annotation` | PAT-004 | RULE-005, RULE-006, RULE-007, RULE-029, RULE-030, RULE-037, RULE-038, RULE-039, RULE-040, RULE-041, RULE-042 |
|
|
20
|
+
| `form-layout` | PAT-004 | RULE-005, RULE-006, RULE-007, RULE-029, RULE-030, RULE-037, RULE-038, RULE-039, RULE-040, RULE-041, RULE-042 |
|
|
21
21
|
| `modal-behavior` | PAT-005 | RULE-008, RULE-009, RULE-029 |
|
|
22
22
|
| `navigation-model` | PAT-001, PAT-006 | RULE-001, RULE-002, RULE-003, RULE-013, RULE-014 |
|
|
23
23
|
| `permission-state` | PAT-003, PAT-008 | RULE-003, RULE-015, RULE-016, RULE-029 |
|
|
24
24
|
| `progressive-disclosure` | PAT-006 | RULE-013, RULE-014 |
|
|
25
|
-
| `row-activation` | PAT-002 | RULE-010, RULE-011, RULE-012, RULE-016 |
|
|
25
|
+
| `row-activation` | PAT-002 | RULE-010, RULE-011, RULE-012, RULE-016, RULE-031, RULE-032, RULE-033, RULE-034, RULE-035, RULE-036 |
|
|
26
26
|
| `save-model` | PAT-007 | RULE-029, RULE-030 |
|
|
27
|
-
| `selection-scope` | PAT-002 | RULE-010, RULE-011, RULE-012, RULE-016 |
|
|
28
|
-
| `submit-feedback` | PAT-004, PAT-007 | RULE-005, RULE-006, RULE-007, RULE-029, RULE-030 |
|
|
29
|
-
| `virtualization` | PAT-002 | RULE-010, RULE-011, RULE-012, RULE-016 |
|
|
27
|
+
| `selection-scope` | PAT-002 | RULE-010, RULE-011, RULE-012, RULE-016, RULE-031, RULE-032, RULE-033, RULE-034, RULE-035, RULE-036 |
|
|
28
|
+
| `submit-feedback` | PAT-004, PAT-007 | RULE-005, RULE-006, RULE-007, RULE-029, RULE-030, RULE-037, RULE-038, RULE-039, RULE-040, RULE-041, RULE-042 |
|
|
29
|
+
| `virtualization` | PAT-002 | RULE-010, RULE-011, RULE-012, RULE-016, RULE-031, RULE-032, RULE-033, RULE-034, RULE-035, RULE-036 |
|
|
30
30
|
|
|
31
31
|
## Application patterns
|
|
32
32
|
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
id: PAT-002
|
|
3
3
|
title: Searchable and filterable list page
|
|
4
4
|
decisions: [data-surface, data-processing-location, selection-scope, row-activation, data-resilience, virtualization]
|
|
5
|
-
rules: [RULE-010, RULE-011, RULE-012, RULE-016]
|
|
6
|
-
components: [DataGrid, DataGridBody, DataGridRow, DataGridCell, DataGridHeader, DataGridHeaderCell, DataGridSelectionCell, createTableColumn, Table, TableHeader, TableRow, TableCell, TableBody, TableCellLayout, Input, Button, MenuButton, Menu, MenuTrigger, MenuPopover, MenuList, MenuItem, Spinner, Skeleton, SkeletonItem, MessageBar, MessageBarBody, Checkbox, Field]
|
|
5
|
+
rules: [RULE-010, RULE-011, RULE-012, RULE-016, RULE-031, RULE-032, RULE-033, RULE-034, RULE-035, RULE-036]
|
|
6
|
+
components: [DataGrid, DataGridBody, DataGridRow, DataGridCell, DataGridHeader, DataGridHeaderCell, DataGridSelectionCell, createTableColumn, TableResizeHandle, Table, TableHeader, TableRow, TableCell, TableBody, TableCellLayout, Input, Button, MenuButton, Menu, MenuTrigger, MenuPopover, MenuList, MenuItem, Spinner, Skeleton, SkeletonItem, MessageBar, MessageBarBody, Checkbox, Field]
|
|
7
7
|
derived: [application-owned FilterBar composition, application-owned query and pagination state]
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -51,27 +51,38 @@ or on the server is explicit in application state, not inferred by the grid.
|
|
|
51
51
|
|
|
52
52
|
Below the project's narrow breakpoint, low-priority columns are hidden behind a detail view and
|
|
53
53
|
filters collapse into a single control that opens a panel. The grid keeps vertical scrolling; it
|
|
54
|
-
never requires two-dimensional scrolling to read a value.
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
never requires two-dimensional scrolling to read a value. When columns can be resized, keep the grid
|
|
55
|
+
inside a region that scrolls horizontally so resizing never pushes the page itself into horizontal
|
|
56
|
+
scrolling, and prefer hiding low-priority columns over relying on resize at narrow widths.
|
|
57
|
+
Virtualize the grid only after measuring a performance need, because virtualization keeps only the
|
|
58
|
+
visible rows in the DOM and can break in-page search and predictable focus movement; when it is
|
|
59
|
+
used, keep the row renderer stable and the row key constant so the rendered window does not churn.
|
|
57
60
|
|
|
58
61
|
## Accessibility
|
|
59
62
|
|
|
60
|
-
The grid uses one tab stop with arrow-key navigation inside it.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
The grid uses one tab stop with arrow-key navigation inside it. A cell that contains controls
|
|
64
|
+
declares its own focus mode: `group` when it holds several focusable elements so Enter enters the
|
|
65
|
+
cell and Escape returns to it, and `none` when it holds exactly one so that control is reached
|
|
66
|
+
directly. A sortable header cell stays a single sort button and must not contain nested focusable
|
|
67
|
+
controls. Sort state, selection changes, and async result updates are announced through a polite
|
|
68
|
+
status region, and every selection control carries an accessible name: the header control states
|
|
69
|
+
its selection scope and each row control names the row. The select-all control states whether it
|
|
70
|
+
selects the current page or all matching results.
|
|
63
71
|
|
|
64
72
|
## Edge cases
|
|
65
73
|
|
|
66
74
|
Loading shows Skeletons in the grid region. No data, no search matches, and a failed load each show a
|
|
67
|
-
distinct message; the failed state offers a retry action. A
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
distinct message; the failed state offers a retry action. A column with no `compare` function stays
|
|
76
|
+
unsortable even when sorting is enabled, so a header that looks sortable can silently do nothing.
|
|
77
|
+
Because the library does not reliably announce a sort change, add a polite status message when the
|
|
78
|
+
result order changes. A server-paged sort re-queries instead of sorting only the loaded page. A
|
|
79
|
+
selection that spans pages keeps its ids when the page changes. When virtualization is enabled, keep
|
|
80
|
+
a stable row key, expose the row's position and total count to assistive technology, and ensure
|
|
81
|
+
focus is not lost when the visible window moves.
|
|
71
82
|
|
|
72
83
|
## Rules applied
|
|
73
84
|
|
|
74
|
-
RULE-010, RULE-011, RULE-012, RULE-016
|
|
85
|
+
RULE-010, RULE-011, RULE-012, RULE-016, RULE-031, RULE-032, RULE-033, RULE-034, RULE-035, RULE-036
|
|
75
86
|
|
|
76
87
|
## Derived decisions
|
|
77
88
|
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
id: PAT-004
|
|
3
3
|
title: Create and edit form page
|
|
4
4
|
decisions: [form-layout, field-annotation, submit-feedback]
|
|
5
|
-
rules: [RULE-005, RULE-006, RULE-007, RULE-029, RULE-030]
|
|
6
|
-
components: [Field, Input, Textarea, Select, Combobox, Dropdown, Option, Checkbox, Radio, RadioGroup, Switch, Slider, Label, Button, MessageBar, MessageBarBody, Spinner]
|
|
5
|
+
rules: [RULE-005, RULE-006, RULE-007, RULE-029, RULE-030, RULE-037, RULE-038, RULE-039, RULE-040, RULE-041, RULE-042]
|
|
6
|
+
components: [Field, Input, Textarea, Select, Combobox, Dropdown, Option, Checkbox, Radio, RadioGroup, Switch, Slider, SpinButton, Label, Button, MessageBar, MessageBarBody, Spinner]
|
|
7
7
|
derived: [application-owned FormSection grouping, application-owned validation schema]
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -29,9 +29,15 @@ page for editing one or two fields in the context of a list; use the contextual-
|
|
|
29
29
|
## Component mapping
|
|
30
30
|
|
|
31
31
|
Field, Input, Textarea, Select, Combobox, Dropdown, Option, Checkbox, Radio, RadioGroup, Switch,
|
|
32
|
-
Slider, Label, Button, MessageBar, and Spinner are verified exports.
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
Slider, SpinButton, Label, Button, MessageBar, and Spinner are verified exports. Each value's domain
|
|
33
|
+
chooses its control: free text uses Input or Textarea, a small exclusive set uses RadioGroup, a short
|
|
34
|
+
fixed list uses a native Select, a long or searchable list uses Combobox or Dropdown, a submitted
|
|
35
|
+
boolean uses Checkbox, an immediate on/off uses Switch, and a bounded quantity uses SpinButton. A
|
|
36
|
+
complex option also carries a plain-text value. A bounded numeric field sets its minimum and
|
|
37
|
+
maximum, a step that divides the range, a page step that is a multiple of the step, and a formatted
|
|
38
|
+
display value that parses back to the stored number. The FormSection grouping and the validation
|
|
39
|
+
schema are application-owned. Validation, persistence, and authorization are application
|
|
40
|
+
responsibilities.
|
|
35
41
|
|
|
36
42
|
## Interaction flow
|
|
37
43
|
|
|
@@ -52,20 +58,24 @@ Short related pairs may share a row above the project's narrow breakpoint only.
|
|
|
52
58
|
|
|
53
59
|
## Accessibility
|
|
54
60
|
|
|
55
|
-
Every control has a programmatic label and, where needed, help text tied to the control.
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
Every control has a programmatic label and, where needed, help text tied to the control. A complex
|
|
62
|
+
option exposes its plain text as the accessible name, and an option popup follows its trigger in DOM
|
|
63
|
+
order so screen-reader navigation reaches the list. A Switch applies immediately while a Checkbox is
|
|
64
|
+
submitted with the form, and a parent Checkbox shows the indeterminate state for a partially
|
|
65
|
+
selected group. The error summary is announced on submit, and focus moves to the summary or the
|
|
66
|
+
first invalid field. The pending submit action keeps an accessible name.
|
|
58
67
|
|
|
59
68
|
## Edge cases
|
|
60
69
|
|
|
61
|
-
Server-side validation errors map onto their fields and are also summarized. A
|
|
62
|
-
|
|
70
|
+
Server-side validation errors map onto their fields and are also summarized. A numeric value with no
|
|
71
|
+
meaningful step, such as a phone number, stays a plain Input rather than a SpinButton. A duplicate
|
|
72
|
+
submission is prevented while a request is pending. Leaving the page with unsaved changes triggers a
|
|
63
73
|
confirmation. A field whose value arrives after load shows a pending state rather than an empty
|
|
64
74
|
value.
|
|
65
75
|
|
|
66
76
|
## Rules applied
|
|
67
77
|
|
|
68
|
-
RULE-005, RULE-006, RULE-007, RULE-029, RULE-030
|
|
78
|
+
RULE-005, RULE-006, RULE-007, RULE-029, RULE-030, RULE-037, RULE-038, RULE-039, RULE-040, RULE-041, RULE-042
|
|
69
79
|
|
|
70
80
|
## Derived decisions
|
|
71
81
|
|
|
@@ -42,6 +42,12 @@ when it applies, and where its evidence comes from. Full provenance lives in
|
|
|
42
42
|
| RULE-005 | must | Wrap each control in a Field that provides a visible label, and place help or error text through the Field's message slot rather than beside it. |
|
|
43
43
|
| RULE-006 | should | Show a field error after the user leaves the field or submits the form, and never before the user has entered a value, so the form does not scold an untouched field. |
|
|
44
44
|
| RULE-007 | should | Lay fields out in one column by default and group related fields under a shared heading, because a single reading path is easier to follow and to complete. |
|
|
45
|
+
| RULE-037 | should | Choose Input or Textarea for free-form text, RadioGroup for a small exclusive set, Select for a short fixed list, Combobox or Dropdown for a long or searchable list, Checkbox for a submitted boolean, Switch for an immediate on/off, and SpinButton for a bounded numeric quantity. |
|
|
46
|
+
| RULE-038 | must | Use a Switch only when the change takes effect immediately, and use a Checkbox for a value submitted with the form; give a parent Checkbox an indeterminate state when it controls a partially selected group. |
|
|
47
|
+
| RULE-039 | should | Prefer a native Select for a short, fixed list of options, and choose Combobox or Dropdown when the list is long, must be searched or typed into, or needs custom option content. |
|
|
48
|
+
| RULE-040 | must | Provide a plain-text value for every Dropdown or Combobox option whose visible content is complex or composed, so the closed field and type-ahead matching use the text. |
|
|
49
|
+
| RULE-041 | should | Prefer an inline option popup that follows the trigger in the DOM so assistive navigation reaches the list where aria-owns is unsupported. |
|
|
50
|
+
| RULE-042 | should | Set the minimum and maximum on a bounded numeric input, choose a step that divides the range, set the larger page step as a multiple, and parse a formatted display value back to a number. |
|
|
45
51
|
|
|
46
52
|
## data-grid
|
|
47
53
|
|
|
@@ -50,6 +56,12 @@ when it applies, and where its evidence comes from. Full provenance lives in
|
|
|
50
56
|
| RULE-010 | should | Use DataGrid when the layout must be controlled by column definitions and keyboard grid behavior is required, and use Table when a native table structure is the goal. |
|
|
51
57
|
| RULE-011 | should | Decide explicitly whether each collection operation runs on loaded rows or on the server, and pass the resulting state into the grid so the component does not imply a data source it does not have. |
|
|
52
58
|
| RULE-012 | must | Make the selection scope explicit to the user, and when a bulk action can apply to all matching results rather than only the loaded page, offer that choice deliberately. |
|
|
59
|
+
| RULE-031 | must | Provide a compare function in every column definition whose header is meant to sort; a column without compare stays unsortable even when the grid enables sorting. |
|
|
60
|
+
| RULE-032 | must | Set focusMode group on a cell with several focusable elements so Enter enters the cell and Escape returns to it, and set focusMode none on a cell with exactly one focusable element so that control receives focus directly. |
|
|
61
|
+
| RULE-033 | must | Keep a sortable header cell free of nested focusable controls; move header actions into a context menu or into the body cells instead. |
|
|
62
|
+
| RULE-034 | should | Use resizableColumns only inside a container that allows horizontal overflow, provide the column sizing options, and keep keyboard resizing available; do not let resizing push the page into two-dimensional scrolling. |
|
|
63
|
+
| RULE-035 | must | Keep the row render function stable with useCallback and a stable row key before enabling virtualization. |
|
|
64
|
+
| RULE-036 | must | Provide an aria-label through the selection cell for both the header select-all control and each row control, naming the action and, for the header, the selection scope. |
|
|
53
65
|
|
|
54
66
|
## overlays
|
|
55
67
|
|