@slotted/angular 0.1.0-beta.1 → 0.1.0-beta.3
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/README.md +4 -0
- package/docs/AGENTS.snippet.md +10 -0
- package/docs/app-shell.json +1 -1
- package/docs/button-group.json +1 -0
- package/docs/button-group.md +1 -1
- package/docs/button.json +45 -11
- package/docs/button.md +10 -6
- package/docs/chart.json +7 -0
- package/docs/chart.md +1 -0
- package/docs/checkbox.json +7 -0
- package/docs/checkbox.md +1 -0
- package/docs/currency-field.json +32 -1
- package/docs/currency-field.md +4 -1
- package/docs/dialog.examples.md +20 -0
- package/docs/dialog.json +14 -2
- package/docs/dialog.md +1 -1
- package/docs/event-calendar.json +7 -0
- package/docs/event-calendar.md +1 -0
- package/docs/guidelines/README.md +27 -0
- package/docs/guidelines/async-feedback.md +108 -0
- package/docs/guidelines/browsing.md +74 -0
- package/docs/guidelines/builders.md +97 -0
- package/docs/guidelines/composition.md +129 -0
- package/docs/guidelines/conversations.md +59 -0
- package/docs/guidelines/errors-and-conflicts.md +71 -0
- package/docs/guidelines/forms.md +192 -0
- package/docs/guidelines/index.md +121 -0
- package/docs/guidelines/layout-alignment.md +95 -0
- package/docs/guidelines/ledgers.md +45 -0
- package/docs/guidelines/list-pages.md +165 -0
- package/docs/guidelines/overviews.md +66 -0
- package/docs/guidelines/own-elements.md +115 -0
- package/docs/guidelines/reading-permissions.md +55 -0
- package/docs/guidelines/record-pages.md +178 -0
- package/docs/guidelines/reports.md +123 -0
- package/docs/guidelines/shell-composition.md +94 -0
- package/docs/guidelines/workspaces.md +46 -0
- package/docs/index.md +12 -0
- package/docs/list.json +19 -1
- package/docs/list.md +3 -1
- package/docs/popover.json +1 -1
- package/docs/progress-indicator.json +1 -2
- package/docs/progress-indicator.md +2 -2
- package/docs/segmented-control.json +29 -1
- package/docs/segmented-control.md +17 -1
- package/docs/skills/build-own-element/SKILL.md +90 -0
- package/docs/skills/compose-screen/SKILL.md +76 -0
- package/docs/skills/index.md +9 -0
- package/docs/skills/review-screen/SKILL.md +70 -0
- package/docs/skills/theme-app/SKILL.md +79 -0
- package/docs/skills/waiting-states/SKILL.md +139 -0
- package/docs/split-button.json +1 -0
- package/docs/split-button.md +1 -1
- package/docs/stat-card.json +2 -0
- package/docs/stat-card.md +1 -1
- package/docs/table.examples.md +1 -1
- package/docs/table.json +70 -1
- package/docs/table.md +10 -1
- package/docs/tabs.json +1 -4
- package/docs/tabs.md +1 -1
- package/docs/toggle-group.json +14 -3
- package/docs/toggle-group.md +3 -3
- package/docs/toggle.json +12 -3
- package/docs/toggle.md +3 -3
- package/docs/tokens.md +448 -0
- package/docs/tour.json +1 -1
- package/fesm2022/slotted-angular-app-shell.mjs +48 -16
- package/fesm2022/slotted-angular-app-shell.mjs.map +1 -1
- package/fesm2022/slotted-angular-button-group.mjs +4 -4
- package/fesm2022/slotted-angular-button-group.mjs.map +1 -1
- package/fesm2022/slotted-angular-button.mjs +51 -19
- package/fesm2022/slotted-angular-button.mjs.map +1 -1
- package/fesm2022/slotted-angular-cascader.mjs +1 -1
- package/fesm2022/slotted-angular-cascader.mjs.map +1 -1
- package/fesm2022/slotted-angular-chart.mjs +41 -20
- package/fesm2022/slotted-angular-chart.mjs.map +1 -1
- package/fesm2022/slotted-angular-checkbox.mjs +11 -2
- package/fesm2022/slotted-angular-checkbox.mjs.map +1 -1
- package/fesm2022/slotted-angular-column-manager.mjs +1 -1
- package/fesm2022/slotted-angular-column-manager.mjs.map +1 -1
- package/fesm2022/slotted-angular-combobox.mjs +12 -6
- package/fesm2022/slotted-angular-combobox.mjs.map +1 -1
- package/fesm2022/slotted-angular-currency-field.mjs +59 -8
- package/fesm2022/slotted-angular-currency-field.mjs.map +1 -1
- package/fesm2022/slotted-angular-dashboard-grid.mjs +18 -22
- package/fesm2022/slotted-angular-dashboard-grid.mjs.map +1 -1
- package/fesm2022/slotted-angular-data-grid.mjs +7 -3
- package/fesm2022/slotted-angular-data-grid.mjs.map +1 -1
- package/fesm2022/slotted-angular-data-list.mjs +2 -2
- package/fesm2022/slotted-angular-data-list.mjs.map +1 -1
- package/fesm2022/slotted-angular-dialog.mjs +4 -4
- package/fesm2022/slotted-angular-dialog.mjs.map +1 -1
- package/fesm2022/slotted-angular-drawer.mjs +5 -1
- package/fesm2022/slotted-angular-drawer.mjs.map +1 -1
- package/fesm2022/slotted-angular-event-calendar.mjs +18 -8
- package/fesm2022/slotted-angular-event-calendar.mjs.map +1 -1
- package/fesm2022/slotted-angular-filter-bar.mjs +8 -8
- package/fesm2022/slotted-angular-filter-bar.mjs.map +1 -1
- package/fesm2022/slotted-angular-import-export-center.mjs +1 -1
- package/fesm2022/slotted-angular-import-export-center.mjs.map +1 -1
- package/fesm2022/slotted-angular-list.mjs +28 -17
- package/fesm2022/slotted-angular-list.mjs.map +1 -1
- package/fesm2022/slotted-angular-loading-overlay.mjs +2 -2
- package/fesm2022/slotted-angular-markdown.mjs +1 -1
- package/fesm2022/slotted-angular-markdown.mjs.map +1 -1
- package/fesm2022/slotted-angular-multi-select.mjs +32 -27
- package/fesm2022/slotted-angular-multi-select.mjs.map +1 -1
- package/fesm2022/slotted-angular-notification-center.mjs +1 -1
- package/fesm2022/slotted-angular-notification-center.mjs.map +1 -1
- package/fesm2022/slotted-angular-number-field.mjs +2 -2
- package/fesm2022/slotted-angular-number-field.mjs.map +1 -1
- package/fesm2022/slotted-angular-progress-indicator.mjs +6 -6
- package/fesm2022/slotted-angular-saved-views.mjs +1 -1
- package/fesm2022/slotted-angular-saved-views.mjs.map +1 -1
- package/fesm2022/slotted-angular-segmented-control.mjs +25 -5
- package/fesm2022/slotted-angular-segmented-control.mjs.map +1 -1
- package/fesm2022/slotted-angular-select.mjs +1 -25
- package/fesm2022/slotted-angular-select.mjs.map +1 -1
- package/fesm2022/slotted-angular-split-button.mjs +4 -4
- package/fesm2022/slotted-angular-split-button.mjs.map +1 -1
- package/fesm2022/slotted-angular-stat-card.mjs +2 -2
- package/fesm2022/slotted-angular-stat-card.mjs.map +1 -1
- package/fesm2022/slotted-angular-table.mjs +97 -10
- package/fesm2022/slotted-angular-table.mjs.map +1 -1
- package/fesm2022/slotted-angular-tabs.mjs +2 -2
- package/fesm2022/slotted-angular-tabs.mjs.map +1 -1
- package/fesm2022/slotted-angular-toggle-group.mjs +17 -4
- package/fesm2022/slotted-angular-toggle-group.mjs.map +1 -1
- package/fesm2022/slotted-angular-toggle.mjs +2 -2
- package/fesm2022/slotted-angular-toggle.mjs.map +1 -1
- package/fesm2022/slotted-angular-tour.mjs +1 -1
- package/fesm2022/slotted-angular-tour.mjs.map +1 -1
- package/fesm2022/slotted-angular-transfer.mjs +1 -1
- package/fesm2022/slotted-angular-transfer.mjs.map +1 -1
- package/fesm2022/slotted-angular-upload.mjs +2 -2
- package/fesm2022/slotted-angular-wizard.mjs +1 -1
- package/fesm2022/slotted-angular-wizard.mjs.map +1 -1
- package/package.json +3 -3
- package/types/slotted-angular-app-shell.d.ts +6 -0
- package/types/slotted-angular-app-shell.d.ts.map +1 -1
- package/types/slotted-angular-button-group.d.ts +1 -1
- package/types/slotted-angular-button.d.ts +33 -13
- package/types/slotted-angular-button.d.ts.map +1 -1
- package/types/slotted-angular-chart.d.ts +9 -0
- package/types/slotted-angular-chart.d.ts.map +1 -1
- package/types/slotted-angular-checkbox.d.ts +7 -1
- package/types/slotted-angular-checkbox.d.ts.map +1 -1
- package/types/slotted-angular-combobox.d.ts.map +1 -1
- package/types/slotted-angular-currency-field.d.ts +25 -3
- package/types/slotted-angular-currency-field.d.ts.map +1 -1
- package/types/slotted-angular-dashboard-grid.d.ts.map +1 -1
- package/types/slotted-angular-data-grid.d.ts.map +1 -1
- package/types/slotted-angular-drawer.d.ts.map +1 -1
- package/types/slotted-angular-event-calendar.d.ts +9 -2
- package/types/slotted-angular-event-calendar.d.ts.map +1 -1
- package/types/slotted-angular-list.d.ts +42 -27
- package/types/slotted-angular-list.d.ts.map +1 -1
- package/types/slotted-angular-multi-select.d.ts +10 -0
- package/types/slotted-angular-multi-select.d.ts.map +1 -1
- package/types/slotted-angular-segmented-control.d.ts +15 -2
- package/types/slotted-angular-segmented-control.d.ts.map +1 -1
- package/types/slotted-angular-select.d.ts.map +1 -1
- package/types/slotted-angular-split-button.d.ts +2 -2
- package/types/slotted-angular-table.d.ts +43 -3
- package/types/slotted-angular-table.d.ts.map +1 -1
- package/types/slotted-angular-toggle-group.d.ts +8 -2
- package/types/slotted-angular-toggle-group.d.ts.map +1 -1
- package/types/slotted-angular-toggle.d.ts +1 -1
- package/types/slotted-angular-toggle.d.ts.map +1 -1
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
---
|
|
2
|
+
topic: forms
|
|
3
|
+
prefix: FM
|
|
4
|
+
triggers:
|
|
5
|
+
[
|
|
6
|
+
form,
|
|
7
|
+
create,
|
|
8
|
+
new record,
|
|
9
|
+
edit,
|
|
10
|
+
save,
|
|
11
|
+
submit,
|
|
12
|
+
validation,
|
|
13
|
+
field error,
|
|
14
|
+
server error,
|
|
15
|
+
draft,
|
|
16
|
+
required,
|
|
17
|
+
optional,
|
|
18
|
+
read-only,
|
|
19
|
+
permission,
|
|
20
|
+
conflict,
|
|
21
|
+
]
|
|
22
|
+
families: [form, field, text-field, select, currency-field, checkbox, section, grid, page-header]
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Forms
|
|
26
|
+
|
|
27
|
+
Where a form that writes a record stands, how a rule the backend owns reaches
|
|
28
|
+
the control it is about, and what happens to what a reader typed when they
|
|
29
|
+
leave. The library gives `form` an error map, a summary and an action row,
|
|
30
|
+
`field` a label, a description and a message, and the controls their states;
|
|
31
|
+
it does not say which route a create form lives on, which key the error map
|
|
32
|
+
is written with, or whether a draft outlives the page.
|
|
33
|
+
|
|
34
|
+
### FM-01 · A create form is a page of its own
|
|
35
|
+
|
|
36
|
+
Level: SHOULD
|
|
37
|
+
Applies to: a form that creates a record a module lists — an account, an order, a ticket
|
|
38
|
+
Rule: The form stands on its own route under the list it returns to, and the way back is the header's `back` part; a layer holds a form of one or two fields over a record already on screen.
|
|
39
|
+
Why: A form of several sections has a link a colleague can paste, a place in the history the phone's back gesture answers, and the whole height of a phone; a layer has none of the three.
|
|
40
|
+
Do: Give the route a segment of its own before the list's record segment, gate it on the permission the command requires, and name the list in the back link. The page header carries the title and the sentence that says what the record will be on arrival; the actions that confirm stand in the form's own action row.
|
|
41
|
+
Don't: Open the create form as a dialog over the list, or route it through the record page under a reserved id.
|
|
42
|
+
Check: Open the create route: the form draws with the list's name and the arrow above the title, and the system back gesture returns to the list.
|
|
43
|
+
|
|
44
|
+
### FM-02 · A control is named as the backend names the field
|
|
45
|
+
|
|
46
|
+
Level: MUST
|
|
47
|
+
Applies to: every control in a form whose value a command validates
|
|
48
|
+
Rule: The control's `name` is the field name the command answers with, and the page's error map is keyed by the same name; a nested field is the leaf name the backend uses, prefixed by its group.
|
|
49
|
+
Why: A server answers field errors keyed by its own field names, and a map keyed by anything else needs a translation table that drifts from the backend on the first rename.
|
|
50
|
+
Do: Name each control as the command names the value it writes, and translate only the leaf of a nested group — a contact's first name becomes the group's name, a dot and the leaf — in one place the store owns.
|
|
51
|
+
Don't: Name controls after the label a reader sees, or after the shape of the draft.
|
|
52
|
+
Check: Every `name` in the form is a field of the command's input.
|
|
53
|
+
|
|
54
|
+
### FM-03 · A refusal is said at the control and in the summary
|
|
55
|
+
|
|
56
|
+
Level: MUST
|
|
57
|
+
Applies to: a form whose submit can fail — on the platform's own check or on the backend's answer
|
|
58
|
+
Rule: One error map feeds the form's summary and each field's message: every message a reader is given stands under the control it is about, and the same words stand in the summary.
|
|
59
|
+
Why: A refusal that lives only in a toast leaves the reader to find which of twelve controls it meant; one that lives only beside a control is missed by a reader who was sent to the top of a long form.
|
|
60
|
+
Do: Hold the map in the screen's store, bind it to the form, accept the form's own request back into it — the family drops a field's error the moment that field is edited — and render the message as the field's `error` part. Where the backend answers a code the product has words for, the words are the product's; where it does not, the server's sentence is shown as it came.
|
|
61
|
+
Don't: Report a failed submit through a toast alone, or write a second sentence beside the control that does not match the summary's.
|
|
62
|
+
Check: A submit the backend refuses shows the message under its control and in the form's summary.
|
|
63
|
+
|
|
64
|
+
### FM-04 · A value read but not written is a read-only field
|
|
65
|
+
|
|
66
|
+
Level: SHOULD
|
|
67
|
+
Applies to: a field whose value one permission lets a persona see and another lets them change — a credit limit under a permission to read it and a permission to change it
|
|
68
|
+
Rule: The field stands in its read-only state with the value and one sentence naming who does change it; a value the persona may not see at all is not drawn.
|
|
69
|
+
Why: A field that disappears reads as a fact the record does not hold, and a disabled control reads as something that could become available by trying again.
|
|
70
|
+
Do: Bind the field's read-only state to the permission that writes, and its presence to the permission that reads. The sentence under it names the holder of the other permission, not the permission.
|
|
71
|
+
Don't: Hide a value the reader is allowed to see, or leave a control the reader can type into and the backend will refuse.
|
|
72
|
+
Check: Signed in as a reader who may read the value and not change it, the field is present, read-only, and says who sets it.
|
|
73
|
+
|
|
74
|
+
### FM-05 · A draft outlives the page
|
|
75
|
+
|
|
76
|
+
Level: SHOULD
|
|
77
|
+
Applies to: a create form a reader can leave without submitting
|
|
78
|
+
Rule: What was typed lives in the screen's store rather than in the component: leaving the form and opening it again finds it; a successful create empties it.
|
|
79
|
+
Why: On a phone the back gesture is the way out of everything, and a form that empties itself on the way back is a form typed twice.
|
|
80
|
+
Do: Keep the draft in the module's store, read it from the component, and clear it on the answer that made the record. Offer no guard that refuses to leave: the draft is not lost, so there is nothing to warn about.
|
|
81
|
+
Don't: Hold the values in the component's own signals, or register an unsaved-changes guard over a draft that survives.
|
|
82
|
+
Check: Type a value, leave for the list, open the form again: the value is there.
|
|
83
|
+
|
|
84
|
+
### FM-06 · An optional group is opened by a choice
|
|
85
|
+
|
|
86
|
+
Level: MAY
|
|
87
|
+
Applies to: a group of fields a command accepts and does not require — a primary contact, a billing address, a first note
|
|
88
|
+
Rule: The group stands behind a checkbox that opens it, and while it is open its fields carry the platform's `required`.
|
|
89
|
+
Why: A group half filled is a record the backend accepts and nobody meant — a contact with an email and no name — and a form that asks for everything at once reads as a form that requires everything.
|
|
90
|
+
Do: Word the choice as what it adds ("Add the primary contact now"), keep it closed at first, and send the group only while it is open.
|
|
91
|
+
Don't: Draw the optional fields open and guess intent from which of them were filled.
|
|
92
|
+
Check: The groups are closed on arrival; opening one makes its fields required.
|
|
93
|
+
|
|
94
|
+
### FM-07 · A record's facts are edited where they are read
|
|
95
|
+
|
|
96
|
+
Level: SHOULD
|
|
97
|
+
Applies to: the fields of a record already on screen — the account's own facts, a contact, a term
|
|
98
|
+
Rule: The section that shows the facts becomes the form that writes them: the record's header, its figures and its tabs stay where they are, and the section's body is the form.
|
|
99
|
+
Why: The reader came to this record for these values; a page of its own or a layer over it hides the figures the edit is judged against and costs the way back.
|
|
100
|
+
Do: Put the control that opens the form in the section's `actions`, keep the heading, and let the form's own action row carry Save and Cancel. A create form is the other case, and FM-01 says where it stands.
|
|
101
|
+
Don't: Route to a page of its own for one section of a record, or open a layer that covers the record's figures.
|
|
102
|
+
Check: Press Edit: the title row, the figures and the tabs stay, and the form stands in the section.
|
|
103
|
+
|
|
104
|
+
### FM-08 · A version someone else moved past is answered field by field
|
|
105
|
+
|
|
106
|
+
Level: MUST
|
|
107
|
+
Applies to: any command carrying the last observed version
|
|
108
|
+
Rule: A stale-version refusal re-reads the record and states which fields moved under the open form, what the record holds now and what the form holds; the reader keeps what they wrote and chooses between writing it over the version now stored and starting again from the record.
|
|
109
|
+
Why: A conflict the screen answers with "try again" makes the reader guess what they would overwrite, and a form that reloads itself throws away what they typed.
|
|
110
|
+
Do: Compare the values the form opened on with the values now stored, list only what differs, and mark the fields the reader also changed. Offer two controls with the two outcomes named.
|
|
111
|
+
Don't: Show the server's sentence alone, reload the form, or re-send the same command on the new version without saying what changed.
|
|
112
|
+
Check: Write to the record from elsewhere while a form is open, then save: the panel names the field, both values and the two answers.
|
|
113
|
+
|
|
114
|
+
### FM-09 · A command carries only what the reader changed
|
|
115
|
+
|
|
116
|
+
Level: SHOULD
|
|
117
|
+
Applies to: an edit of a record that several people write
|
|
118
|
+
Rule: The command carries the fields whose value moved since the form opened, not every field the form draws.
|
|
119
|
+
Why: A whole-form patch writes a colleague's change back to what it was, and a value covered by its own permission — a credit limit — refuses an edit the persona is otherwise allowed to make.
|
|
120
|
+
Do: Keep the values the form opened on and compare against them, including after a conflict: "keep what I wrote" writes the reader's own fields over the newer version and leaves the rest as the other writer left them.
|
|
121
|
+
Don't: Send the draft whole, or re-base the comparison on the record read back after a conflict.
|
|
122
|
+
Check: Change one field of an edit form and submit: the request carries that field alone.
|
|
123
|
+
|
|
124
|
+
### FM-10 · Partial success is reported row by row
|
|
125
|
+
|
|
126
|
+
Level: MUST
|
|
127
|
+
Applies to: a command that writes many records at once and refuses some of them — a CSV import, a bulk action over a selection
|
|
128
|
+
Rule: The screen reports what was written and what was refused in the same answer: the counts of both, and one line per refused record with its position, its field and the reason.
|
|
129
|
+
Why: "Some rows failed" leaves the reader to find which, and a screen that reports only the failures hides that the rest of the file is already in the system.
|
|
130
|
+
Do: Draw the counts as figures — written, written with a value changed, refused, read — and the refusals as a table keyed by the row number the file has. Say what the reader does next, including what happens if they import the same file again.
|
|
131
|
+
Don't: Report a partial result as an error, as a success, or as a toast.
|
|
132
|
+
Check: Import a file in which some rows are refused: the figures state both counts, and the table names each refused row with its position and reason.
|
|
133
|
+
|
|
134
|
+
### FM-11 · A threshold the backend enforces is said before the submit
|
|
135
|
+
|
|
136
|
+
Level: MUST
|
|
137
|
+
Applies to: a field a command requires only above a size — a note from ten units or US$1,000, an approval from a variance of US$2,500
|
|
138
|
+
Rule: The form applies the backend's threshold as the reader types: the field becomes required, and the sentence under it names the threshold and the value that crossed it; a value the reader may not be shown is replaced by the rule in words.
|
|
139
|
+
Why: A requirement the reader meets only as a refusal is a form filled twice, and a note asked for after the submit reads as a punishment for the size of the change.
|
|
140
|
+
Do: Compute the size the backend measures — the quantity, and the value at standard cost where the reader holds the permission — and bind the field's `required` and its description to it. Where the value is withheld (PM-01), state the rule and who sees the value, and let the backend's refusal land on the same field (FM-03).
|
|
141
|
+
Don't: Leave the field optional until the backend refuses, or compute the value from a cost the backend handed to a reader who may not see it.
|
|
142
|
+
Check: Type a value across the threshold: before the submit the field becomes required and its sentence names the threshold and the value; for a reader who may not see the value, the sentence states the rule in words.
|
|
143
|
+
|
|
144
|
+
### FM-12 · A form written in place is a query parameter
|
|
145
|
+
|
|
146
|
+
Level: SHOULD
|
|
147
|
+
Applies to: a form that takes the place of a record's section (FM-07) — an adjustment, a receipt, a count
|
|
148
|
+
Rule: Opening the form adds a query parameter to the record's address, so the platform's back gesture closes it and stays on the record; a successful save leaves the history as it came.
|
|
149
|
+
Why: A form held in the component alone is closed by the back gesture only by leaving the record, and a save that pushes the record again makes the next back gesture land on the same page.
|
|
150
|
+
Do: Open the form with a link that adds the parameter, derive "the form is open" from the address, and on success pop the entry that opened it — or replace it where the form was opened from a pasted link.
|
|
151
|
+
Don't: Open the form with a component flag, or navigate forward to the record after the save.
|
|
152
|
+
Check: Open the form, save, then press back twice: the first back leaves the record for the page before it, not for the same record.
|
|
153
|
+
|
|
154
|
+
### FM-13 · A submission that asks for an approval says so before it is sent
|
|
155
|
+
|
|
156
|
+
Level: MUST
|
|
157
|
+
Applies to: a form or a record whose submit is decided by an approval policy the backend runs — a purchase order, a quote, a count
|
|
158
|
+
Rule: Before the submit, the screen states whether the submission will wait on an approval, the roles of its steps in order and each reason, from the values on screen; the submit control's own label says it asks for approval.
|
|
159
|
+
Why: A buyer who learns after the submit that an order waits on a manager has sent it without choosing to, and a submit labelled the same whether it approves at once or waits for days hides the one thing that differs.
|
|
160
|
+
Do: Run the backend's own policy on what the form holds as it changes, list the reasons in the product's sentence form, give the value the threshold is measured in with its currency, and name the control "Submit for approval" while one is needed.
|
|
161
|
+
Don't: Announce the approval only in the toast after the submit, or state the thresholds without saying which of them the order crosses.
|
|
162
|
+
Check: Fill the form with values that need an approval: before the submit the screen lists the steps' roles in order with each reason, and the submit control's label says it asks for approval.
|
|
163
|
+
|
|
164
|
+
### FM-14 · A quantity sent to several places says where each part goes
|
|
165
|
+
|
|
166
|
+
Level: SHOULD
|
|
167
|
+
Applies to: a command that splits one line into destinations — a receipt's accepted, damaged and rejected units, a return's restock and scrap
|
|
168
|
+
Rule: Before the confirm, the form states in lines what each destination receives and what the record becomes after it, including a state the command changes on its own.
|
|
169
|
+
Why: The three numbers of a line are typed one at a time and read as one; the reader confirms a movement of stock and a change of the order they did not see stated.
|
|
170
|
+
Do: Count the lines per destination (RP-08: the units differ), say what a destination does with what it receives — into the stock, into its damaged bucket, back to the supplier — and say whether the record closes, with the rule that closes it.
|
|
171
|
+
Don't: Leave the outcome to the answer after the confirm, or sum the quantities of different units into one number.
|
|
172
|
+
Check: Before the confirm of a command that splits a quantity, the form states in lines what each destination receives and the state the record takes after it.
|
|
173
|
+
|
|
174
|
+
### FM-15 · An action no command writes is the record that says it
|
|
175
|
+
|
|
176
|
+
Level: SHOULD
|
|
177
|
+
Applies to: an action the domain names and the backend has no command for — a contact attempt on an invoice, a call logged against an account
|
|
178
|
+
Rule: The action is written through the command whose record says the same thing, with a fixed prefix that names the document it is about, and the document reads its own entries back by that prefix; no endpoint is invented in the client.
|
|
179
|
+
Why: An action a screen fakes in its own state is lost on the next read, and one written as a free note cannot be found from the document it was about.
|
|
180
|
+
Do: Name the nearest record the domain gives the action — a collection note is a customer note — write it with the prefix, the document's identifier and the fields the action carries (channel, what was agreed, a promised date), and read it back on the document's own tab. The control's holders are the command's: the note's permission at the note's scope.
|
|
181
|
+
Don't: Keep the attempt in the page's state, write it as a note with no prefix, or draw the control for a reader the note command refuses.
|
|
182
|
+
Check: Write the action and read the document: the entry reads back by its fixed prefix, and the client calls no endpoint the backend does not declare.
|
|
183
|
+
|
|
184
|
+
### FM-16 · A date chosen in a form opens a calendar
|
|
185
|
+
|
|
186
|
+
Level: SHOULD
|
|
187
|
+
Applies to: a date a form asks for — a due date, a promised date, a day of receipt, a validity
|
|
188
|
+
Rule: A date entered in a form is a `date-picker`, which keeps typing in its field and adds the calendar behind its trigger; a `date-field` alone is not used in a form.
|
|
189
|
+
Why: A reader who has to type a date they could have pointed at is doing what the calendar exists to spare them, and the weekday the calendar shows is often the fact the date is chosen by.
|
|
190
|
+
Do: Write the picker with the limits the backend enforces as the picker's minimum and maximum — a due date not before the issue date — and read the one date a single-mode picker reports.
|
|
191
|
+
Don't: Write `date-field` for every date because it is the smaller family; a form that does so states no reason for it.
|
|
192
|
+
Check: Every date control of a form opens a calendar from its trigger, and a date the backend limits refuses the days outside the limit.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Guidelines index
|
|
2
|
+
|
|
3
|
+
Every active rule, one line each. Load this first; load a topic file when the task matches its `triggers`.
|
|
4
|
+
|
|
5
|
+
| ID | Level | Rule | File |
|
|
6
|
+
| --- | --- | --- | --- |
|
|
7
|
+
| AF-01 | MUST | A region whose first answer has not arrived shows its pending state; the empty state appears only after an answer holding zero items. | `async-feedback.md` |
|
|
8
|
+
| AF-02 | SHOULD | A region with no items yet draws placeholders; a region that already shows items keeps them on screen and marks itself busy while a newer answer is on its way. | `async-feedback.md` |
|
|
9
|
+
| AF-03 | MUST | From activation until the answer, the control is in its `loading` state: it refuses a second activation and shows the family's indicator. | `async-feedback.md` |
|
|
10
|
+
| AF-04 | SHOULD | When the reader asks for different rows, the rows on screen are removed and placeholders stand in their place until the answer arrives. | `async-feedback.md` |
|
|
11
|
+
| AF-05 | MAY | A control's indicator may be delayed by the family's loading delay, so a request that answers first shows no indicator; a region's placeholders are never delayed. | `async-feedback.md` |
|
|
12
|
+
| AF-06 | SHOULD | The application states one minimum duration for the whole product: once placeholders are painted they stay for it, even when the answer has already arrived. | `async-feedback.md` |
|
|
13
|
+
| AF-07 | SHOULD | The page offers Refresh among the header's actions, and a refresh keeps the values on screen, marks the page busy and replaces them when the answer arrives. | `async-feedback.md` |
|
|
14
|
+
| BR-01 | SHOULD | The branch a reader chose is the list's heading and its `breadcrumb`; the filter bar keeps the facets and holds no pill for it. | `browsing.md` |
|
|
15
|
+
| BR-02 | MUST | The query covers the branch and every node beneath it, and the page states how many nodes that is beside how many records they hold. | `browsing.md` |
|
|
16
|
+
| BR-03 | MUST | The number on a row is one of the two and the screen says which; where a node holds records of its own and has nodes under it, the second number is said apart from the first. | `browsing.md` |
|
|
17
|
+
| BR-04 | SHOULD | Each grain is its own route with its own columns and its own filters, and each page names the other above its rows. | `browsing.md` |
|
|
18
|
+
| BD-01 | SHOULD | The record shows the rule as it reads — When, If, Then, Otherwise — every later line of the condition tree led by its join in words and every nested group opened by its own ("any of:", "all of:"); the editor opens from that reading in the section it is read in; a reader without the permission to edit reads the rule and is not shown an editor. | `builders.md` |
|
|
19
|
+
| BD-02 | SHOULD | Under the tree the builder states what it holds and what remains of each limit, and a control that would cross a limit is disabled with the limit as its stated reason. | `builders.md` |
|
|
20
|
+
| BD-03 | MUST | The builder runs the backend's own check on every change and, once a save is tried, marks each node it would refuse with its message before any request is sent; a group with nothing in it is marked from the moment it is empty. | `builders.md` |
|
|
21
|
+
| BD-04 | SHOULD | Every node's menu carries its moves and its removal, the grip's drag makes the same moves, and both refuse the same places — a group into itself, a level past the limit — with the reason said. | `builders.md` |
|
|
22
|
+
| BD-05 | SHOULD | Each level steps in by one space step behind a rule, and below the width a condition's field, operator and value fit on one line the field takes its own line and the operator and the value share the next; the tree never scrolls sideways. | `builders.md` |
|
|
23
|
+
| BD-06 | SHOULD | The record opens on how the rule runs — every event of a stated period split where the conditions decide, the events let through split again by how their run ended, each band as thick as the events in it, the three totals over its columns — and then the rule itself, with each step's own figure at the end of its line. A run opens on the same rule as its trace, the rail lit as far as the run went; the editor, where the container has room, sets the draft the same way beside the form. | `builders.md` |
|
|
24
|
+
| CP-01 | MUST | Before writing an element next to a family, the family's anatomy is read; when it names a slot for that element, the element stands in the slot. | `composition.md` |
|
|
25
|
+
| CP-02 | MUST | Sibling elements of the page's own stand in `inline` (one row) or `stack` (one column) with a gap from the space scale, and text of the page's own takes its size from the typography family; bare inline siblings and bare text are not written. | `composition.md` |
|
|
26
|
+
| CP-03 | MUST | The track the family stands in is written with a zero minimum (`minmax(0, 1fr)`, or `min-inline-size: 0` on a flex child), so the family's scroller is what scrolls. | `composition.md` |
|
|
27
|
+
| CP-04 | MAY | When the families' anatomies have been read and none of them answers the problem, the screen writes an element of its own rather than bending a family into a shape it does not have. | `composition.md` |
|
|
28
|
+
| CP-05 | MUST | Every value the element paints comes from the theme — space, type, ink, border, radius, elevation and motion — where the theme has a token for it; a literal is written only beside a comment that says what decided it and why no token covers it. | `composition.md` |
|
|
29
|
+
| CP-06 | SHOULD | A screen states a state once. Where the family has a state for it, the screen sets that state and adds nothing louder beside it. | `composition.md` |
|
|
30
|
+
| CP-07 | SHOULD | A list page is `bleed` with `fill`; a record, a dashboard and an overview keep the default `wide`; a create or edit form is `content`; a page of preferences read as prose is `measure`. | `composition.md` |
|
|
31
|
+
| CP-08 | MUST | Switching the mode changes the words and the values in the region, never the size, the line count or the position of any box in it or around it; text whose length differs between modes stands on one line, cut with an ellipsis and read whole from its title. | `composition.md` |
|
|
32
|
+
| CV-01 | MUST | From 600 pixels the conversation fills its region and scrolls on its own with the composer under it, and the record's context scrolls on its own beside it or behind a tab of the header; below 600 pixels the page scrolls, the composer is stuck to the bottom of the screen, and the record opens on its last message. | `conversations.md` |
|
|
33
|
+
| CV-02 | SHOULD | A running clock says the business time left and the hour it falls due in the organization's zone, a passed one by how much and when it was due, a paused one that it is stopped and why; a queue's row says the span alone, and no clock is ever said in raw minutes. | `conversations.md` |
|
|
34
|
+
| CV-03 | SHOULD | Each queue is a view of the list's `filter-bar`, a tree of the bar's own fields, labelled with the count of the rows it opens on; choosing it writes its pills, and editing a pill leaves a view the bar marks as changed. | `conversations.md` |
|
|
35
|
+
| ER-01 | MUST | The screen sorts the backend's answer into the class the reader must act on — a conflict (the record moved), a transport failure (nothing was written), a permission (this persona never will) or a state (the record cannot do this now) — and says the class, not the code. | `errors-and-conflicts.md` |
|
|
36
|
+
| ER-02 | MUST | The screen re-reads the record before it shows the message, so what the reader sees under the message is what the backend now holds; the message says that it has done so. | `errors-and-conflicts.md` |
|
|
37
|
+
| ER-03 | MUST | The screen holds the version as a number at the moment it read the record, and sends that; it never reads the version out of an answer it is still holding at the moment it sends. | `errors-and-conflicts.md` |
|
|
38
|
+
| ER-04 | SHOULD | A conflict and a transport failure carry different tones and different second lines: the conflict is a warning that the page has been read again, the transport failure is a danger that nothing was written and the same action can be tried again. | `errors-and-conflicts.md` |
|
|
39
|
+
| FM-01 | SHOULD | The form stands on its own route under the list it returns to, and the way back is the header's `back` part; a layer holds a form of one or two fields over a record already on screen. | `forms.md` |
|
|
40
|
+
| FM-02 | MUST | The control's `name` is the field name the command answers with, and the page's error map is keyed by the same name; a nested field is the leaf name the backend uses, prefixed by its group. | `forms.md` |
|
|
41
|
+
| FM-03 | MUST | One error map feeds the form's summary and each field's message: every message a reader is given stands under the control it is about, and the same words stand in the summary. | `forms.md` |
|
|
42
|
+
| FM-04 | SHOULD | The field stands in its read-only state with the value and one sentence naming who does change it; a value the persona may not see at all is not drawn. | `forms.md` |
|
|
43
|
+
| FM-05 | SHOULD | What was typed lives in the screen's store rather than in the component: leaving the form and opening it again finds it; a successful create empties it. | `forms.md` |
|
|
44
|
+
| FM-06 | MAY | The group stands behind a checkbox that opens it, and while it is open its fields carry the platform's `required`. | `forms.md` |
|
|
45
|
+
| FM-07 | SHOULD | The section that shows the facts becomes the form that writes them: the record's header, its figures and its tabs stay where they are, and the section's body is the form. | `forms.md` |
|
|
46
|
+
| FM-08 | MUST | A stale-version refusal re-reads the record and states which fields moved under the open form, what the record holds now and what the form holds; the reader keeps what they wrote and chooses between writing it over the version now stored and starting again from the record. | `forms.md` |
|
|
47
|
+
| FM-09 | SHOULD | The command carries the fields whose value moved since the form opened, not every field the form draws. | `forms.md` |
|
|
48
|
+
| FM-10 | MUST | The screen reports what was written and what was refused in the same answer: the counts of both, and one line per refused record with its position, its field and the reason. | `forms.md` |
|
|
49
|
+
| FM-11 | MUST | The form applies the backend's threshold as the reader types: the field becomes required, and the sentence under it names the threshold and the value that crossed it; a value the reader may not be shown is replaced by the rule in words. | `forms.md` |
|
|
50
|
+
| FM-12 | SHOULD | Opening the form adds a query parameter to the record's address, so the platform's back gesture closes it and stays on the record; a successful save leaves the history as it came. | `forms.md` |
|
|
51
|
+
| FM-13 | MUST | Before the submit, the screen states whether the submission will wait on an approval, the roles of its steps in order and each reason, from the values on screen; the submit control's own label says it asks for approval. | `forms.md` |
|
|
52
|
+
| FM-14 | SHOULD | Before the confirm, the form states in lines what each destination receives and what the record becomes after it, including a state the command changes on its own. | `forms.md` |
|
|
53
|
+
| FM-15 | SHOULD | The action is written through the command whose record says the same thing, with a fixed prefix that names the document it is about, and the document reads its own entries back by that prefix; no endpoint is invented in the client. | `forms.md` |
|
|
54
|
+
| FM-16 | SHOULD | A date entered in a form is a `date-picker`, which keeps typing in its field and adds the calendar behind its trigger; a `date-field` alone is not used in a form. | `forms.md` |
|
|
55
|
+
| LA-01 | SHOULD | A pager under a paged region is aligned to the end of the line. | `layout-alignment.md` |
|
|
56
|
+
| LA-02 | MUST | A consumer's row in the navigation column's pinned parts is inset by `--slotted-app-shell-row-inset` and starts with a mark column `--slotted-app-shell-row-mark` wide, the avatar centred in it. | `layout-alignment.md` |
|
|
57
|
+
| LA-03 | SHOULD | Below the header's narrow step the actions beside a plain title fit on the title's line: a labelled action becomes its icon-only form, and two or more actions stand in a `toolbar` that folds into its menu. | `layout-alignment.md` |
|
|
58
|
+
| LA-04 | SHOULD | Tabs that change the page's content stand in `page-header`'s `tabs` slot, not in the body. | `layout-alignment.md` |
|
|
59
|
+
| LA-05 | MUST | Fields on one line are aligned to the start of the block axis, so every control of the line starts at the same height and has the same height whatever stands under it. A button on the line stands on the controls' row, not on the labels' or the help's. | `layout-alignment.md` |
|
|
60
|
+
| LA-06 | MUST | The element's offset starts at the page's published `--slotted-page-sticky-top`, the measured height of the chrome that stays (the stuck page-header's title area, a sticky section's header), and an element that may be taller than what stays visible caps its height by the same property and scrolls inside. | `layout-alignment.md` |
|
|
61
|
+
| LG-01 | SHOULD | The row states the signed change at the unit's own precision, what caused it as words that lead to that record, where and when it happened and who did it; a cause without a screen leads to the ledger narrowed to what that cause moved, and no identifier is shown raw. | `ledgers.md` |
|
|
62
|
+
| LG-02 | SHOULD | The balance after each movement is drawn only where the ledger is narrowed to one item in one place, and it is walked back from that position's current quantity. | `ledgers.md` |
|
|
63
|
+
| LP-01 | SHOULD | The grid shows the selection column, the row header and the columns of highest priority that fit; the others move into the row's pop-in as labelled values, by `priority`, outside the column state, and no row is wider than the frame. | `list-pages.md` |
|
|
64
|
+
| LP-02 | SHOULD | The search field, the filter pills and the saved views stand in one `filter-bar` as the first block of the page body, above the grid; the header keeps the title and the actions that create or leave the list. | `list-pages.md` |
|
|
65
|
+
| LP-03 | SHOULD | The actions a selection allows stand in an `action-bar` in `page`'s footer part, open while the selection is not empty, with the count and Clear at the start and the action that confirms at the end. | `list-pages.md` |
|
|
66
|
+
| LP-04 | MUST | A value longer than its column is cut with an ellipsis and kept whole in the cell's title; a cell template that replaces the family's value carries the cut, the title and the value's own maximum. | `list-pages.md` |
|
|
67
|
+
| LP-05 | SHOULD | The filter bar states how many rows the query kept of how many there are; the pager states the range on screen and moves the page; the grid's own range line is off. | `list-pages.md` |
|
|
68
|
+
| LP-06 | SHOULD | A sort, a filter, a search, a page or a view removes the rows before the request and the grid draws its placeholders; a mutation read back keeps the rows in the grid's loading state, and the grid dims them. | `list-pages.md` |
|
|
69
|
+
| LP-08 | SHOULD | The bar's count, the pager's range and its page size name their unit in words. | `list-pages.md` |
|
|
70
|
+
| LP-09 | SHOULD | The queue is the list of the records the work is written against, narrowed by the states in which the work can be done and by the reader's scope, stated as the page's place; opening a row opens the form that does the work for a reader who can do it. | `list-pages.md` |
|
|
71
|
+
| LP-10 | SHOULD | The chart stands in the header's second tab, beside the list's own, and never as a block above the list. | `list-pages.md` |
|
|
72
|
+
| LP-11 | SHOULD | Where the primary input is a touch screen, the list tools leave out the row density: the theme raises every density's rows to the touch target, and the tools keep the sort, the views and the columns on one line. | `list-pages.md` |
|
|
73
|
+
| LP-12 | MUST | From 600 pixels of the page's width the listing takes the height the bar and the messages leave and scrolls its own rows while the page does not scroll; below 600 the page's `fill` does not apply, the listing is as tall as its rows and the page scrolls. | `list-pages.md` |
|
|
74
|
+
| LP-13 | SHOULD | The mark takes the `sm` `size`; the default `md` belongs to a record's header and to a region with room around it. | `list-pages.md` |
|
|
75
|
+
| OV-01 | SHOULD | The figure leads to the list page of the records it counts, and that list opens with the figure's condition applied as the bar's own pills, which the reader removes like any other. | `overviews.md` |
|
|
76
|
+
| OV-02 | SHOULD | Below 600 pixels the figures are one `list` of rows that are destinations — label, comparison, number — followed by the records to act on, the work in flight, the charts, and the history last. | `overviews.md` |
|
|
77
|
+
| OV-03 | SHOULD | Where the reader's scope holds one category, the chart is not drawn and one sentence states the numbers it would have compared. | `overviews.md` |
|
|
78
|
+
| OV-04 | SHOULD | The thresholds are stated once in words beside the figures, and a figure past one says so in its own comparison line, on the line the placeholder reserves. | `overviews.md` |
|
|
79
|
+
| OV-05 | SHOULD | A chart takes the `card` `variant` when it is one of two or more peer tiles in one grid with no section heading of its own, and stays `plain` when it is the body of a titled section or the only content of a tab. | `overviews.md` |
|
|
80
|
+
| OE-01 | MUST | An element of the application's own reads only tokens of the groups `node_modules/@slotted/angular/docs/tokens.md` lists for the application. | `own-elements.md` |
|
|
81
|
+
| OE-02 | MUST | Where two states hold at once, the element paints the ground, the edge and the text colour of the stronger, in the order `disabled`, `loading`, `readonly`, `invalid`, `checked`, `selected`, `pressed`, `current`, `complete`, `active`, `hover`; the focus ring of OE-03 is drawn over every state. | `own-elements.md` |
|
|
82
|
+
| OE-03 | MUST | In its `focus-visible` state the element draws an outline of `--slotted-focus-ring-width` in `--slotted-focus-ring-color`, offset by `--slotted-focus-ring-offset`. | `own-elements.md` |
|
|
83
|
+
| OE-04 | MUST | The element's hit area measures at least `--slotted-target-min` in both axes, and at least `--slotted-target-comfortable` under `pointer: coarse`. | `own-elements.md` |
|
|
84
|
+
| OE-05 | SHOULD | The element takes its height, inline padding, font size and gap from `--slotted-control-*` tokens of one size step, the step of the controls beside it. | `own-elements.md` |
|
|
85
|
+
| OE-06 | MUST | Under `forced-colors: active`, each state the element shows differs from rest by a border, an outline or text, not by a ground or a shadow alone. | `own-elements.md` |
|
|
86
|
+
| OE-07 | MUST | A transition takes its duration from the `duration` group or `--slotted-control-transition-duration`, its curve from the `easing` group or `--slotted-control-transition-easing`, and an animation that repeats stops under `prefers-reduced-motion: reduce`. | `own-elements.md` |
|
|
87
|
+
| OE-08 | SHOULD | The element's rules stand in a layer of the application ordered after the library's, and never select or set `data-ui` or `data-part`. | `own-elements.md` |
|
|
88
|
+
| OE-09 | SHOULD | The element reflows by a container query on a `container-name` of its own; a change that follows the page uses the size classes, at 600 and 1024 pixels. | `own-elements.md` |
|
|
89
|
+
| OE-10 | SHOULD | A surface above another takes `--slotted-surface-raised` with one step of the `shadow` group, and a layer that floats over the page takes its stacking order from the `z-index` group. | `own-elements.md` |
|
|
90
|
+
| PM-01 | MUST | The column, the figure and the section that would carry the value are not built for that reader; nothing is drawn for the value, and nothing is hidden in a place the reader can bring back. | `reading-permissions.md` |
|
|
91
|
+
| PM-02 | SHOULD | One statement names the permission the value needs and the roles that hold it; two missing permissions are one statement, not two. | `reading-permissions.md` |
|
|
92
|
+
| RP-01 | SHOULD | The title row holds the record's visual, its name as the heading, its lifecycle state and its health as two `tag` marks at the small size, and one subheading line with the identifier, the owner and the place; the way back to the list is the header's `back` part. | `record-pages.md` |
|
|
93
|
+
| RP-02 | SHOULD | The record's figures are `stat-card`s in a `grid` at the top of the page body, before the section's content, and they stay while the section changes; the header's collapsible area does not hold them. | `record-pages.md` |
|
|
94
|
+
| RP-03 | SHOULD | Each kind of related record is a tab in the header's `tabs` slot with its count in the label; a tab's content is a `table` of that kind with a caption, or a `timeline` for activity; the empty state is the table's own `empty` part. | `record-pages.md` |
|
|
95
|
+
| RP-04 | MUST | The page keeps its header with the way back and shows a `result-state` in the body: `not-found` for an id that does not exist, `error` with Try again for a transport failure; the URL stays. | `record-pages.md` |
|
|
96
|
+
| RP-05 | SHOULD | While its tab is open, the action stands in the record header's `toolbar` beside the record's own actions, and the form it opens takes the place of the tab's listing. | `record-pages.md` |
|
|
97
|
+
| RP-06 | SHOULD | The page answers "where is this" above the record's contents: the steps it has passed, the step it is on, what that step is waiting on, and one sentence naming what happens next. | `record-pages.md` |
|
|
98
|
+
| RP-07 | SHOULD | The table carries the column summaries the table element has for it, holding the same totals as the figures above, and says in one line what the rows are counted in. | `record-pages.md` |
|
|
99
|
+
| RP-08 | SHOULD | Where the records do not share a unit the figure counts records; a quantity is summed only where one unit covers the whole set, and the page says which unit that is. | `record-pages.md` |
|
|
100
|
+
| RP-09 | SHOULD | The step names the role it waits on and the page draws no control for the command that the decision gates; the control appears in the one state the backend accepts it. | `record-pages.md` |
|
|
101
|
+
| RP-10 | SHOULD | The figure's comparison line gives the median of the record's peers, one sentence under the figures says what each score counts and who the peers are, and a score with nothing behind it is not drawn as a number. | `record-pages.md` |
|
|
102
|
+
| RP-11 | MUST | The record's sentence states, before any control, which authority the current value needs, measured in the unit the policy states, and the command is drawn only in the form that authority gives the reader. | `record-pages.md` |
|
|
103
|
+
| RP-12 | SHOULD | The document's list and record stand under the destination whose records it changes, declared before that destination's own record address, and every record of that destination that issued or took one links to it. | `record-pages.md` |
|
|
104
|
+
| RP-13 | SHOULD | An entry written by a workflow's action names the workflow as its actor and, for a reader of workflows, opens the run that wrote it; it never reads as the work of the person whose command set the workflow off. | `record-pages.md` |
|
|
105
|
+
| RE-01 | SHOULD | A figure of the report is a flow over its period against a period of the same length; a state of today is read through the operational screen's own read, says "as of today", and opens the operational screen's door. | `reports.md` |
|
|
106
|
+
| RE-02 | SHOULD | They are query parameters of the report's address; a report opened without them takes the ones last chosen on any report, and the back gesture from a list it opened returns to the same period. | `reports.md` |
|
|
107
|
+
| RE-03 | MUST | The period control offers only the periods the report's records are kept for; a figure, a cell or a breakdown whose records start after its range says "not kept" and from when, and is never drawn as a number. | `reports.md` |
|
|
108
|
+
| RE-04 | SHOULD | The comparison line names the value compared with and the period it belongs to; an amount and a count move by a percentage, a share by points, a duration in its own unit. | `reports.md` |
|
|
109
|
+
| RE-05 | SHOULD | A value is flagged only by a rule the page states in words, and the flag names the value, the range it fell in, the band it left and opens the records of that range. | `reports.md` |
|
|
110
|
+
| RE-06 | SHOULD | They stand in `page-header`'s `content`, under the header's `toggle` and `pin`; below 600 pixels the area opens collapsed, so the figures lead the screen. | `reports.md` |
|
|
111
|
+
| RE-07 | SHOULD | Each opens the list of the records it counts, with its condition and its period as the list's own pills and the same total, and a record named by its id is named in the pill by its record's words. | `reports.md` |
|
|
112
|
+
| RE-08 | SHOULD | The chart draws at most the ten first categories and says so in its title; the table under it holds every row and its summary. | `reports.md` |
|
|
113
|
+
| RE-09 | SHOULD | The download is the section's table as the reader sees it — its columns, its rows and its summary row, in its words — built in the browser from the answer the page drew, for every reader of the report. | `reports.md` |
|
|
114
|
+
| SC-01 | MUST | Below the bar's medium step, the magnifier opens the palette directly; the search region is never expanded over the bar. | `shell-composition.md` |
|
|
115
|
+
| SC-02 | MUST | A component host inside the banner that draws no box of its own contributes no box to the banner's row. | `shell-composition.md` |
|
|
116
|
+
| SC-03 | SHOULD | The consumer states the content's inline size, and its block cap, on the content; the popover's measure alone does not size it. | `shell-composition.md` |
|
|
117
|
+
| SC-04 | SHOULD | The search region carries one space step of leading margin beyond the bar's own gap. | `shell-composition.md` |
|
|
118
|
+
| SC-05 | SHOULD | Below the bar's high step the actions hold the search toggle, the bell, the help and the account; a product's own `action` leaves the bar and stays reachable from the navigation column or the palette. | `shell-composition.md` |
|
|
119
|
+
| SC-06 | SHOULD | Where the primary input is a touch screen — `(hover: none) and (pointer: coarse)` — a shortcut drawn as a hint is not shown. | `shell-composition.md` |
|
|
120
|
+
| WS-01 | SHOULD | Below 600 pixels the workspace shows the queue, and opening a row goes to the row's own address, where the record's page holds the other two regions, the third under the second; the back gesture returns to the queue. | `workspaces.md` |
|
|
121
|
+
| WS-02 | SHOULD | The score is shown as a table of its criteria, each with the points it earned or none of its points, ending in the summary row that adds back up to the score and says where a cap applies, and its band is one mark beside one sentence giving the thresholds. | `workspaces.md` |
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
topic: layout alignment
|
|
3
|
+
prefix: LA
|
|
4
|
+
triggers:
|
|
5
|
+
[
|
|
6
|
+
pagination,
|
|
7
|
+
pager,
|
|
8
|
+
align,
|
|
9
|
+
alignment,
|
|
10
|
+
right,
|
|
11
|
+
end,
|
|
12
|
+
left,
|
|
13
|
+
start,
|
|
14
|
+
header,
|
|
15
|
+
footer,
|
|
16
|
+
column,
|
|
17
|
+
sidebar,
|
|
18
|
+
nav,
|
|
19
|
+
inset,
|
|
20
|
+
padding,
|
|
21
|
+
row,
|
|
22
|
+
avatar,
|
|
23
|
+
workspace,
|
|
24
|
+
sticky,
|
|
25
|
+
preview,
|
|
26
|
+
]
|
|
27
|
+
families: [pagination, page, page-header, app-shell, side-navigation, list]
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
# Layout alignment
|
|
31
|
+
|
|
32
|
+
Where a control stands inside the row or region that holds it. The library
|
|
33
|
+
sizes each family and publishes the measures a frame's rows stand on; it does
|
|
34
|
+
not decide which end of a line a pager takes or that a consumer's header row
|
|
35
|
+
inside the navigation column reads the same inset the destinations do.
|
|
36
|
+
|
|
37
|
+
### LA-01 · The pager stands at the end of the line
|
|
38
|
+
|
|
39
|
+
Level: SHOULD
|
|
40
|
+
Applies to: `pagination` under a `list`, a `data-grid` or any paged region
|
|
41
|
+
Rule: A pager under a paged region is aligned to the end of the line.
|
|
42
|
+
Why: The reader's eye rests at the end of the last row, where the row actions are; a pager at the start sits under the labels and reads as part of the content.
|
|
43
|
+
Do: Align the pager's row to the end. Where a summary of the page ("1–25 of 112") accompanies it, the summary takes the start and the pager the end of the same line.
|
|
44
|
+
Don't: Leave the pager at the start of the line because that is where a block begins.
|
|
45
|
+
Check: Under a paged list, the pager's last control ends on the region's end edge, the edge the rows' actions are inset from.
|
|
46
|
+
|
|
47
|
+
### LA-02 · Pinned rows of the column write the row inset and the mark
|
|
48
|
+
|
|
49
|
+
Level: MUST
|
|
50
|
+
Applies to: what a consumer places in `app-shell`'s `nav-header` and `nav-footer` — a workspace row, an account row, a status row
|
|
51
|
+
Rule: A consumer's row in the navigation column's pinned parts is inset by `--slotted-app-shell-row-inset` and starts with a mark column `--slotted-app-shell-row-mark` wide, the avatar centred in it.
|
|
52
|
+
Why: The destinations under it are `side-navigation` rows on the same measures; a header row without them stands on the region's edge and its avatar off the icon column.
|
|
53
|
+
Do: Read the two published measures on the row. In the rail the words are hidden and the mark stays centred; in the overlay card the frame adds its own inset and the row's inset stacks on it, as the destinations' does.
|
|
54
|
+
Don't: Write a bare avatar and text into the header, or pad the header by a number.
|
|
55
|
+
Check: The header's avatar and the first destination's icon share a left edge, in the column, in the rail and in the overlay.
|
|
56
|
+
|
|
57
|
+
### LA-03 · A phone's header keeps its actions on the title's line
|
|
58
|
+
|
|
59
|
+
Level: SHOULD
|
|
60
|
+
Applies to: what a consumer places in `page-header`'s `actions`, beside a plain title — one heading, no visual, no subheading
|
|
61
|
+
Rule: Below the header's narrow step the actions beside a plain title fit on the title's line: a labelled action becomes its icon-only form, and two or more actions stand in a `toolbar` that folds into its menu.
|
|
62
|
+
Why: The row wraps when the actions cannot share the line with the title, and a wrapped row under a one-line heading puts the title at the start of one line and the actions at the end of the next, aligned with nothing.
|
|
63
|
+
Do: Write the action twice — the labelled control and its icon-only twin with the same accessible name, the same states and the same handler — and show one per side of the header's own container query. Under a rich title (visual, marks, subheading), the actions row below the title reads as a toolbar row of its own and may stay.
|
|
64
|
+
Don't: Leave a labelled button that wraps, or shrink the control under the touch target to make it fit.
|
|
65
|
+
Check: At the narrowest phone width with a coarse pointer, the title and its action share one line; the icon-only control has the labelled control's name.
|
|
66
|
+
|
|
67
|
+
### LA-04 · A page's views are the header's tabs
|
|
68
|
+
|
|
69
|
+
Level: SHOULD
|
|
70
|
+
Applies to: `tabs` that switch what a page's body shows — views, filters by state, sections of one record
|
|
71
|
+
Rule: Tabs that change the page's content stand in `page-header`'s `tabs` slot, not in the body.
|
|
72
|
+
Why: The header sticks and its tabs slot is the bottom of it, so the views stay in reach while the list scrolls; tabs in the body scroll away with the first rows and the reader loses where they are.
|
|
73
|
+
Do: Place the `tabs` root in the header's `tabs` slot; the family draws the rule under the title area and keeps the row pinned.
|
|
74
|
+
Don't: Write the tab strip as the first block of the body with a margin under it.
|
|
75
|
+
Check: Scroll a long list under the header: the tab strip stays visible under the title.
|
|
76
|
+
|
|
77
|
+
### LA-05 · Controls side by side share their top
|
|
78
|
+
|
|
79
|
+
Level: MUST
|
|
80
|
+
Applies to: fields on one line — a table row of editable cells, an inline group of fields, a grid of fields with an action button — where some carry a line of help or an error and others do not
|
|
81
|
+
Rule: Fields on one line are aligned to the start of the block axis, so every control of the line starts at the same height and has the same height whatever stands under it. A button on the line stands on the controls' row, not on the labels' or the help's.
|
|
82
|
+
Why: Centred or aligned to the end, a field with a line of help under it stands its control higher than its neighbour without one, and the line of controls the eye follows across the row breaks by the help's height.
|
|
83
|
+
Do: Set the `cellAlign` axis to `start` on a `table` whose cells hold fields, and the `align` axis to `start` on an `inline` of fields. In a grid of fields with a button, give the grid three rows — label, control, help — each field spanning them with `grid-template-rows: subgrid`, and place the button in the control row; a value read beside the controls is centred on the controls' height.
|
|
84
|
+
Don't: Keep the table's centred cells for a row of fields, where a quantity with help stood 21 pixels above the cost beside it. Align a grid of fields with `align-items: end` to bring a button level with the controls: the field with help lifts its control by the help's height.
|
|
85
|
+
Check: On a line where one field carries help and another does not, every control and the button share one top and one height, measured by bounding box.
|
|
86
|
+
|
|
87
|
+
### LA-06 · A sticky element of the screen's own stops under the page's chrome
|
|
88
|
+
|
|
89
|
+
Level: MUST
|
|
90
|
+
Applies to: an element a screen makes `position: sticky` inside a page — a preview beside a form, a summary beside a list, a column's own header
|
|
91
|
+
Rule: The element's offset starts at the page's published `--slotted-page-sticky-top`, the measured height of the chrome that stays (the stuck page-header's title area, a sticky section's header), and an element that may be taller than what stays visible caps its height by the same property and scrolls inside.
|
|
92
|
+
Why: An offset from the scroller's edge alone — `inset-block-start: var(--slotted-space-4)` — sticks the element behind the stuck header, which is painted above it: its top is hidden for as long as it is stuck.
|
|
93
|
+
Do: Write `inset-block-start: calc(var(--slotted-page-sticky-top, 0px) + <gap>)` and, when the element can outgrow the view, `max-block-size: calc(100dvh - var(--slotted-page-sticky-top, 0px) - <room for the app's own bars>)` with `overflow: auto`.
|
|
94
|
+
Don't: Measure the header in the screen's own code, or hard-code its height: the header collapses, wraps and changes with the density, and the page already measures it.
|
|
95
|
+
Check: Scroll the page until the header sticks, at two scroll positions: the sticky element's top stands at or below the bottom of the stuck header's title area each time.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
topic: ledgers
|
|
3
|
+
prefix: LG
|
|
4
|
+
triggers:
|
|
5
|
+
[
|
|
6
|
+
ledger,
|
|
7
|
+
movement,
|
|
8
|
+
stock movement,
|
|
9
|
+
posting,
|
|
10
|
+
history,
|
|
11
|
+
audit trail,
|
|
12
|
+
delta,
|
|
13
|
+
balance,
|
|
14
|
+
source,
|
|
15
|
+
immutable,
|
|
16
|
+
]
|
|
17
|
+
families: [data-grid, table, drawer, description-list, link]
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Ledgers
|
|
21
|
+
|
|
22
|
+
How an immutable record of changes reads: one movement, the record that
|
|
23
|
+
caused it, and the balance it left. The library draws rows and cells; it does
|
|
24
|
+
not say how a signed change is written, where a movement's cause leads, or
|
|
25
|
+
when a running balance can be trusted.
|
|
26
|
+
|
|
27
|
+
### LG-01 · A movement names its change, its cause and its place
|
|
28
|
+
|
|
29
|
+
Level: SHOULD
|
|
30
|
+
Applies to: a row of a ledger — a stock movement, a posting, an entry of an audit trail
|
|
31
|
+
Rule: The row states the signed change at the unit's own precision, what caused it as words that lead to that record, where and when it happened and who did it; a cause without a screen leads to the ledger narrowed to what that cause moved, and no identifier is shown raw.
|
|
32
|
+
Why: A ledger is read to answer "why did this change", and a row that shows an id or no way to the cause answers only "that it changed".
|
|
33
|
+
Do: Write the change with its sign, and give the tone as a second signal beside the sign. Keep a word for every cause type the backend writes and a word for an unknown one, and link a cause to its record or to the ledger filtered by the cause's id. Open one movement over the ledger it belongs to, so the list stays under it and the address names it.
|
|
34
|
+
Don't: Print a cause type as the backend spells it, a correlation id or an entity id as the cause, or link a cause to a screen that does not exist.
|
|
35
|
+
Check: Read the cause of a row of each cause type: it is words, it leads to the record that caused the movement or to the ledger narrowed to what that cause moved, and no row shows an identifier.
|
|
36
|
+
|
|
37
|
+
### LG-02 · A running balance is drawn where one position is read
|
|
38
|
+
|
|
39
|
+
Level: SHOULD
|
|
40
|
+
Applies to: a ledger table that shows the quantity each movement left
|
|
41
|
+
Rule: The balance after each movement is drawn only where the ledger is narrowed to one item in one place, and it is walked back from that position's current quantity.
|
|
42
|
+
Why: A balance over many items or places is a sum of unrelated quantities, and a balance computed forward from the first page misses every movement before it.
|
|
43
|
+
Do: Take the current quantity from the position the page already reads, subtract each newer change in turn, and say under the table how the balance was derived.
|
|
44
|
+
Don't: Add a balance column to the whole ledger, or compute it forward from the oldest row on screen.
|
|
45
|
+
Check: Record a movement on one item in one place: the first row's balance equals the position's new quantity, and the unfiltered ledger shows no balance column.
|