@masmarino/gabarit 1.1.0 → 1.2.1
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/ACCESSIBILITY.md +55 -22
- package/README.md +295 -60
- package/fesm2022/masmarino-gabarit.mjs +7263 -2907
- package/fesm2022/masmarino-gabarit.mjs.map +1 -1
- package/package.json +1 -1
- package/src/lib/tokens/_semantic.scss +16 -5
- package/src/lib/tokens/_utilities.scss +54 -15
- package/types/masmarino-gabarit.d.ts +1671 -193
package/ACCESSIBILITY.md
CHANGED
|
@@ -15,20 +15,25 @@ AAA level.
|
|
|
15
15
|
is therefore not "RGAA-compliant" and cannot be: it's your application
|
|
16
16
|
that is, or isn't. What Gabarit guarantees is that **the 30 criteria that
|
|
17
17
|
depend on its components are met**, verified by `axe-core` in the unit
|
|
18
|
-
tests, by a contrast test on the tokens, and by
|
|
18
|
+
tests, by a contrast test on the tokens, and by 69 manual audit
|
|
19
19
|
checklists (`AUDIT.md`) — one alone covers seven chart-base components,
|
|
20
|
-
another covers both tab components, and
|
|
21
|
-
first two means run
|
|
22
|
-
integration
|
|
23
|
-
and
|
|
20
|
+
another covers both tab components, and eight components have none. The
|
|
21
|
+
first two means run with `npm test`, locally and in continuous
|
|
22
|
+
integration (`.github/workflows/ci.yml` runs lint, tests, the library
|
|
23
|
+
build and the Storybook build on every push and pull request to `main`,
|
|
24
|
+
plus `npm audit --audit-level=high`; the release workflow re-runs lint,
|
|
25
|
+
tests and build before publishing). The checklists are handwritten and
|
|
26
|
+
reviewed by a human.
|
|
24
27
|
|
|
25
28
|
## How it's actually verified, and where that stops
|
|
26
29
|
|
|
27
30
|
**This describes what actually runs, not what would be desirable.**
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
CI runs the unit tests, but no `axe-core` pass runs on Storybook
|
|
32
|
+
stories: for 1.2.0 such a pass (colour contrast included, light, dark and
|
|
33
|
+
375px) was run once by hand over the stories, and nothing repeats it
|
|
34
|
+
automatically. What does exist:
|
|
30
35
|
|
|
31
|
-
- **`axe-core`, run in the unit tests (`npm test`,
|
|
36
|
+
- **`axe-core`, run in the unit tests (`npm test`, locally and in CI).** Each
|
|
32
37
|
component has its own `expectNoA11yViolations` test. It covers only
|
|
33
38
|
around 30% of RGAA criteria: necessary, and very insufficient on its
|
|
34
39
|
own.
|
|
@@ -71,16 +76,21 @@ runs on Storybook stories. What does exist:
|
|
|
71
76
|
it will actually be painted. It's the only check in this repository
|
|
72
77
|
that measures a pair under rendering conditions, rather than two
|
|
73
78
|
tokens side by side.
|
|
74
|
-
- **
|
|
75
|
-
components that have one — not all of them
|
|
79
|
+
- **69 manual audit checklists** (`AUDIT.md` in the folder of the
|
|
80
|
+
components that have one — not all of them; 86 component folders in
|
|
81
|
+
all). One (`chart-frame/AUDIT.md`)
|
|
76
82
|
alone covers seven chart-base components (`chart-frame`, `chart-axis`,
|
|
77
83
|
`chart-tooltip`, `chart-legend`, `chart-empty`, `chart-table`,
|
|
78
84
|
`chart-context`), another (`tabs/AUDIT.md`) covers both the `Tabs` and
|
|
79
85
|
`Tab` components. Each checklist records what automation doesn't see —
|
|
80
86
|
actual keyboard use, screen reader, measurements in Storybook, reading
|
|
81
|
-
the `@storybook/addon-a11y` panel. Conversely,
|
|
82
|
-
(`
|
|
83
|
-
have none.
|
|
87
|
+
the `@storybook/addon-a11y` panel. Conversely, eight components
|
|
88
|
+
(`app-shell`, `bar-chart`, `breadcrumb`, `confirm-danger-modal`,
|
|
89
|
+
`funnel-chart`, `icon`, `sparkline`, `timeline-chart`) have none.
|
|
90
|
+
Together the checklists record a verdict on 39 distinct RGAA criteria
|
|
91
|
+
(counted from their criterion column; some rows also cover WCAG 2.2
|
|
92
|
+
criteria 2.4.11 and 2.5.8) — more than the 30 below, see the note that
|
|
93
|
+
follows that table.
|
|
84
94
|
|
|
85
95
|
Two measured limits of `axe-core` in this tooling, worth knowing before
|
|
86
96
|
reproducing this approach:
|
|
@@ -126,11 +136,21 @@ rule.
|
|
|
126
136
|
| 12 Navigation | 12.8, 12.9, 12.11 |
|
|
127
137
|
| 13 Consultation | 13.8 |
|
|
128
138
|
|
|
129
|
-
That's 30 out of the 106 criteria in RGAA 4.1.2.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
139
|
+
That's 30 out of the 106 criteria in RGAA 4.1.2. Of these 30, 26 appear
|
|
140
|
+
as rows in the `AUDIT.md` files; 10.5, 10.9, 10.10 and 10.14 do not.
|
|
141
|
+
Conversely, the checklists also record verdicts on 13 criteria that are
|
|
142
|
+
not in the table: 1.1, 1.2, 6.1, 6.2, 8.9, 9.1, 9.2, 10.4, 11.2, 11.5,
|
|
143
|
+
11.10, 11.13 and 12.6. Those are observations on the components, each for
|
|
144
|
+
its documented usage, not a guarantee, because the text or the structure
|
|
145
|
+
that decides them is yours. Two topics that might look like they belong
|
|
146
|
+
in the table are worth explaining: **Topic 6 Links (6.1, 6.2)** isn't
|
|
147
|
+
listed because the wording and destination of a link are the
|
|
148
|
+
application's. Since 1.2.0 the library styles the consumer's own `<a>` elements
|
|
149
|
+
(`a[gbtButton]`, `a[gbtNavTab]`, `a[gbtMenuItem]`, `a[gbtCardLink]`,
|
|
150
|
+
`a[gbtStatTileLink]`) and renders a few links itself (the card's
|
|
151
|
+
link mode, the brand link of `gbt-app-shell`, the link of
|
|
152
|
+
`gbt-stat-tile`), but none of them writes the link text for you. And
|
|
153
|
+
**11.2, 11.10, and 11.13** sit under "What remains your
|
|
134
154
|
responsibility" below rather than here, since the components only
|
|
135
155
|
provide the mechanism (`label`/field association, `role="alert"`,
|
|
136
156
|
`aria-describedby`, an `autocomplete` you can override) — never the
|
|
@@ -144,9 +164,9 @@ The other 76 criteria. The main ones:
|
|
|
144
164
|
| Topic | What you need to do |
|
|
145
165
|
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
146
166
|
| 1 Images | Text alternatives for your images. `gbt-icon` is unconditionally decorative — see "Points to watch" below — a meaningful icon must be accompanied by text on your side. |
|
|
147
|
-
| 6 Links | Explicit (6.1) and relevant (6.2) wording for every link in your application.
|
|
167
|
+
| 6 Links | Explicit (6.1) and relevant (6.2) wording for every link in your application. The link components style or render an `<a>`, the text and the destination stay yours: an icon-only link needs an `aria-label`. |
|
|
148
168
|
| 8 Mandatory elements | Doctype, `lang`, page `<title>`, absence of validity errors. |
|
|
149
|
-
| 9 Structure | Heading hierarchy of the page. `gbt-card`
|
|
169
|
+
| 9 Structure | Heading hierarchy of the page. `gbt-card`, `gbt-page-header` and `gbt-empty-state` let you choose their level via `headingLevel` — it's up to you to set it correctly. |
|
|
150
170
|
| 10 Presentation | 200% zoom, page-wide reflow. The components hold up their end; the layout is yours. |
|
|
151
171
|
| 11 Forms | Field grouping (`fieldset` / `legend`), **relevance** of your labels (11.2 — the component associates `label`/field, the text is yours), **content** of your error messages (11.10 — the component announces them via `role="alert"`, you write the text in `errorMessage`), and a correct `autocomplete` value (11.13 — `gbt-input` sets it to `'off'` by default, to override field by field). |
|
|
152
172
|
| 12 Navigation | Two navigation systems, sitemap, skip link, ARIA regions. The `.skip-link` utility is provided (`tokens/_utilities.scss`), using it is up to you. |
|
|
@@ -197,8 +217,12 @@ The other 76 criteria. The main ones:
|
|
|
197
217
|
values worth reading if you inspect the attribute rather than letting
|
|
198
218
|
assistive technology announce it.
|
|
199
219
|
- **Default strings in English, to override in a non-English
|
|
200
|
-
application** —
|
|
201
|
-
|
|
220
|
+
application** — the components added in 1.2.0 follow the same rule
|
|
221
|
+
(every visible or announced string is an input, for instance
|
|
222
|
+
`closeLabel` on `gbt-search-bar` in compact mode, the labels of
|
|
223
|
+
`gbt-copy-button` and `gbt-secret-reveal`; see each README's inputs
|
|
224
|
+
table), and the pipes and formatters take a locale. These components
|
|
225
|
+
carry visible or announced labels with no localized default:
|
|
202
226
|
- `gbt-button`: `loadingLabel` (`'Loading'`).
|
|
203
227
|
- `gbt-input`: `showPasswordLabel` (`'Show password'`),
|
|
204
228
|
`hidePasswordLabel` (`'Hide password'`).
|
|
@@ -216,6 +240,15 @@ The other 76 criteria. The main ones:
|
|
|
216
240
|
`clearLabel` (`'Clear search'`), `resultsAnnouncement` (function,
|
|
217
241
|
announces the result count — criterion 7.5), `navigateHint`
|
|
218
242
|
(`'Navigate'`), `selectHint` (`'Select'`), `closeHint` (`'Close'`).
|
|
243
|
+
- **Known gaps in 1.2.0.** Not fixed, stated here so you can decide: the
|
|
244
|
+
flyout label of the collapsed rail of `gbt-app-shell` cannot be
|
|
245
|
+
dismissed with `Escape` (WCAG 1.4.13, "dismissible"); `gbt-toaster`
|
|
246
|
+
expires every toast after 5 s, errors included, and has no pause on
|
|
247
|
+
hover and no `live` input (warnings are announced assertively — see its
|
|
248
|
+
README); and controls that already existed keep their sizes: the close
|
|
249
|
+
buttons of the toaster, drawer and modal are 24px hit areas on a fine
|
|
250
|
+
pointer, and only the controls added or reworked in 1.2.0 reach 44px on
|
|
251
|
+
a coarse pointer.
|
|
219
252
|
- **Token overrides** — if you redefine the semantic colors, you take on
|
|
220
253
|
criteria 3.2 and 3.3 yourself. Gabarit's contrast test only checks its
|
|
221
254
|
own values.
|
package/README.md
CHANGED
|
@@ -20,49 +20,268 @@ outputs — the link is on its name.
|
|
|
20
20
|
|
|
21
21
|
### Atoms
|
|
22
22
|
|
|
23
|
-
| Component
|
|
24
|
-
|
|
|
25
|
-
| [
|
|
26
|
-
| [
|
|
27
|
-
| [
|
|
28
|
-
| [
|
|
29
|
-
| [
|
|
30
|
-
| [
|
|
23
|
+
| Component | Selector | Role |
|
|
24
|
+
| --------------------------------------------------------------------------------------- | ---------------------- | -------------------------------------------------------------------- |
|
|
25
|
+
| [Avatar](projects/gabarit/src/lib/components/atoms/avatar/README.md) | `gbt-avatar` | User picture with an initials fallback. |
|
|
26
|
+
| [Badge](projects/gabarit/src/lib/components/atoms/badge/README.md) | `gbt-badge` | Status/category label pill. |
|
|
27
|
+
| [Button](projects/gabarit/src/lib/components/atoms/button/README.md) | `gbt-button` | Action button. |
|
|
28
|
+
| [ButtonLink](projects/gabarit/src/lib/components/atoms/button-link/README.md) | `a[gbtButton]` | Anchor styled as a button (router-agnostic). |
|
|
29
|
+
| [Checkbox](projects/gabarit/src/lib/components/atoms/checkbox/README.md) | `gbt-checkbox` | Checkbox, integrated with forms. |
|
|
30
|
+
| [CodeChip](projects/gabarit/src/lib/components/atoms/code-chip/README.md) | `gbt-code-chip` | Monospace chip for a SHA, tag or branch; truncates, optional copy. |
|
|
31
|
+
| [CopyButton](projects/gabarit/src/lib/components/atoms/copy-button/README.md) | `gbt-copy-button` | Copies a value to the clipboard, with a live-region confirmation. |
|
|
32
|
+
| [Counter](projects/gabarit/src/lib/components/atoms/counter/README.md) | `gbt-counter` | Small number pill: cap (`99+`), neutral / primary. |
|
|
33
|
+
| [Divider](projects/gabarit/src/lib/components/atoms/divider/README.md) | `gbt-divider` | Separating line with an optional centred label. |
|
|
34
|
+
| [GaugeBar](projects/gabarit/src/lib/components/atoms/gauge-bar/README.md) | `gbt-gauge-bar` | Progress gauge with alert thresholds. |
|
|
35
|
+
| [Icon](projects/gabarit/src/lib/components/atoms/icon/README.md) | `gbt-icon` | Registered SVG icon, with generic built-in glyphs (`Gallery` story). |
|
|
36
|
+
| [IconMarker](projects/gabarit/src/lib/components/atoms/icon-marker/README.md) | `gbt-icon-marker` | Icon on a soft tinted disc or tile, six tones. |
|
|
37
|
+
| [Input](projects/gabarit/src/lib/components/atoms/input/README.md) | `gbt-input` | Text or password field. |
|
|
38
|
+
| [JobStatus](projects/gabarit/src/lib/components/atoms/job-status/README.md) | `gbt-job-status` | CI job status glyph (extracted from the job graph). |
|
|
39
|
+
| [NotificationDot](projects/gabarit/src/lib/components/atoms/notification-dot/README.md) | `gbt-notification-dot` | Dot or count overlaid on the corner of what it wraps. |
|
|
40
|
+
| [SaveStatus](projects/gabarit/src/lib/components/atoms/save-status/README.md) | `gbt-save-status` | Saving / saved / not saved status, live region. |
|
|
41
|
+
| [Skeleton](projects/gabarit/src/lib/components/atoms/skeleton/README.md) | `gbt-skeleton` | Loading placeholder: line, circle or rectangle. |
|
|
42
|
+
| [Slider](projects/gabarit/src/lib/components/atoms/slider/README.md) | `gbt-slider` | Native range slider, integrated with forms. |
|
|
43
|
+
| [Sparkline](projects/gabarit/src/lib/components/atoms/sparkline/README.md) | `gbt-sparkline` | Fixed-size trend mini-chart. |
|
|
44
|
+
| [Spinner](projects/gabarit/src/lib/components/atoms/spinner/README.md) | `gbt-spinner` | Standalone loading indicator. |
|
|
45
|
+
| [Switch](projects/gabarit/src/lib/components/atoms/switch/README.md) | `gbt-switch` | On/off toggle. |
|
|
46
|
+
| [Tag](projects/gabarit/src/lib/components/atoms/tag/README.md) | `gbt-tag` | Custom-colored, optionally removable label. |
|
|
47
|
+
| [Textarea](projects/gabarit/src/lib/components/atoms/textarea/README.md) | `gbt-textarea` | Multiline text field. |
|
|
31
48
|
|
|
32
49
|
### Molecules
|
|
33
50
|
|
|
34
|
-
| Component
|
|
35
|
-
|
|
|
36
|
-
| [
|
|
37
|
-
| [
|
|
38
|
-
| [
|
|
39
|
-
| [
|
|
40
|
-
| [
|
|
41
|
-
| [
|
|
42
|
-
| [
|
|
43
|
-
| [
|
|
51
|
+
| Component | Selector | Role |
|
|
52
|
+
| --------------------------------------------------------------------------------------------- | ---------------------------------------- | ---------------------------------------------------------------------- |
|
|
53
|
+
| [Accordion](projects/gabarit/src/lib/components/molecules/accordion/README.md) | `gbt-accordion` / `gbt-accordion-item` | Collapsible sections. |
|
|
54
|
+
| [Alert](projects/gabarit/src/lib/components/molecules/alert/README.md) | `gbt-alert` | Persistent inline banner message. |
|
|
55
|
+
| [Autocomplete](projects/gabarit/src/lib/components/molecules/autocomplete/README.md) | `gbt-autocomplete` | Text field with async suggestions. |
|
|
56
|
+
| [AvatarGroup](projects/gabarit/src/lib/components/molecules/avatar-group/README.md) | `gbt-avatar-group` | Overlapping avatars with a +N overflow menu. |
|
|
57
|
+
| [Breadcrumb](projects/gabarit/src/lib/components/molecules/breadcrumb/README.md) | `gbt-breadcrumb` | Ancestor trail plus current segment. |
|
|
58
|
+
| [Card](projects/gabarit/src/lib/components/molecules/card/README.md) | `gbt-card` | Titled container. |
|
|
59
|
+
| [CheckboxGroup](projects/gabarit/src/lib/components/molecules/checkbox-group/README.md) | `gbt-checkbox-group` | Group of checkboxes (fieldset + legend), value is an array. |
|
|
60
|
+
| [CopyField](projects/gabarit/src/lib/components/molecules/copy-field/README.md) | `gbt-copy-field` | Read-only monospace value with a copy button. |
|
|
61
|
+
| [DatePicker](projects/gabarit/src/lib/components/molecules/date-picker/README.md) | `gbt-date-picker` | Single date, calendar dropdown, integrated with forms. |
|
|
62
|
+
| [DateRangePicker](projects/gabarit/src/lib/components/molecules/date-range-picker/README.md) | `gbt-date-range-picker` | Start and end dates, calendar dropdown. |
|
|
63
|
+
| [DescriptionList](projects/gabarit/src/lib/components/molecules/description-list/README.md) | `gbt-description-list` | Label/value pairs on a `dl`, `valueAlign`, opt-in stacking. |
|
|
64
|
+
| [DimensionCard](projects/gabarit/src/lib/components/molecules/dimension-card/README.md) | `gbt-dimension-card` | Dimension table with an accented hover row. |
|
|
65
|
+
| [Disclosure](projects/gabarit/src/lib/components/molecules/disclosure/README.md) | `gbt-disclosure` | Single disclosure: toggle button and panel, `open` model. |
|
|
66
|
+
| [EmptyState](projects/gabarit/src/lib/components/molecules/empty-state/README.md) | `gbt-empty-state` | Placeholder for an empty list/grid. |
|
|
67
|
+
| [FileUpload](projects/gabarit/src/lib/components/molecules/file-upload/README.md) | `gbt-file-upload` | Drag-and-drop or click file selection, removable list. |
|
|
68
|
+
| [FunnelChart](projects/gabarit/src/lib/components/molecules/funnel-chart/README.md) | `gbt-funnel-chart` | Step-by-step conversion funnel. |
|
|
69
|
+
| [JobGraph](projects/gabarit/src/lib/components/molecules/job-graph/README.md) | `gbt-job-graph` | Pipeline jobs by stage, linked by their dependencies. |
|
|
70
|
+
| [ListCard](projects/gabarit/src/lib/components/molecules/list-card/README.md) | `gbt-list-card` | Card for a list: header band, loading / failed / empty / ready states. |
|
|
71
|
+
| [ListRow](projects/gabarit/src/lib/components/molecules/list-row/README.md) | `gbt-list-row` | List item: leading status, title, meta, trailing actions. |
|
|
72
|
+
| [ListToolbar](projects/gabarit/src/lib/components/molecules/list-toolbar/README.md) | `gbt-list-toolbar` | Search + sort controls for a list. |
|
|
73
|
+
| [Menu](projects/gabarit/src/lib/components/molecules/menu/README.md) | `gbt-menu` | Generic dropdown menu. |
|
|
74
|
+
| [MenuItem](projects/gabarit/src/lib/components/molecules/menu-item/README.md) | `button[gbtMenuItem]` / `a[gbtMenuItem]` | Menu item: icon, danger variant, disabled, link form. |
|
|
75
|
+
| [NavTabs](projects/gabarit/src/lib/components/molecules/nav-tabs/README.md) | `gbt-nav-tabs` / `a[gbtNavTab]` | Router-agnostic nav links: icon, badge, orientation, fades. |
|
|
76
|
+
| [PageHeader](projects/gabarit/src/lib/components/molecules/page-header/README.md) | `gbt-page-header` | Page title block: heading, badges, meta, actions. |
|
|
77
|
+
| [Pagination](projects/gabarit/src/lib/components/molecules/pagination/README.md) | `gbt-pagination` | Page navigation for a list/table. |
|
|
78
|
+
| [Panel](projects/gabarit/src/lib/components/molecules/panel/README.md) | `gbt-panel` | Flat side-panel section: heading, actions, content. |
|
|
79
|
+
| [Popover](projects/gabarit/src/lib/components/molecules/popover/README.md) | `gbt-popover` | Floating panel opened by a click on its trigger. |
|
|
80
|
+
| [RadioGroup](projects/gabarit/src/lib/components/molecules/radio-group/README.md) | `gbt-radio-group` | Radio button group, integrated with forms. |
|
|
81
|
+
| [SecretReveal](projects/gabarit/src/lib/components/molecules/secret-reveal/README.md) | `gbt-secret-reveal` | Masked secret: show / hide and copy. |
|
|
82
|
+
| [SegmentedControl](projects/gabarit/src/lib/components/molecules/segmented-control/README.md) | `gbt-segmented-control` | Exclusive-choice button group (`tinted`, `fullWidth`, `wrap`). |
|
|
83
|
+
| [Select](projects/gabarit/src/lib/components/molecules/select/README.md) | `gbt-select` | Dropdown list, single or multiple. |
|
|
84
|
+
| [SkeletonList](projects/gabarit/src/lib/components/molecules/skeleton-list/README.md) | `gbt-skeleton-list` | Placeholder rows for a loading list, with a polite status. |
|
|
85
|
+
| [StatGrid](projects/gabarit/src/lib/components/molecules/stat-grid/README.md) | `gbt-stat-grid` | Responsive grid of stat tiles (container query), loading state. |
|
|
86
|
+
| [StatTile](projects/gabarit/src/lib/components/molecules/stat-tile/README.md) | `gbt-stat-tile` | Figure with label, icon, hint, trend and optional link. |
|
|
87
|
+
| [Stepper](projects/gabarit/src/lib/components/molecules/stepper/README.md) | `gbt-stepper` | Informational progress through numbered steps. |
|
|
88
|
+
| [Table](projects/gabarit/src/lib/components/molecules/table/README.md) | `gbt-table` | Data table. |
|
|
89
|
+
| [Tabs](projects/gabarit/src/lib/components/molecules/tabs/README.md) | `gbt-tabs` / `gbt-tab` | Tab navigation. |
|
|
90
|
+
| [TagInput](projects/gabarit/src/lib/components/molecules/tag-input/README.md) | `gbt-tag-input` | Free-typed values shown as removable tags. |
|
|
91
|
+
| [Tooltip](projects/gabarit/src/lib/components/molecules/tooltip/README.md) | `gbt-tooltip` | Hover/focus info bubble for any content. |
|
|
92
|
+
| [Tree](projects/gabarit/src/lib/components/molecules/tree/README.md) | `gbt-tree` | Expandable hierarchical list (WAI-ARIA tree view). |
|
|
93
|
+
| [UserChip](projects/gabarit/src/lib/components/molecules/user-chip/README.md) | `gbt-user-chip` | Avatar + name on one line. |
|
|
44
94
|
|
|
45
95
|
### Organisms
|
|
46
96
|
|
|
47
|
-
| Component
|
|
48
|
-
|
|
|
49
|
-
| [BarChart](projects/gabarit/src/lib/components/organisms/bar-chart/README.md)
|
|
50
|
-
| [ChartAxis](projects/gabarit/src/lib/components/organisms/chart-axis/README.md)
|
|
51
|
-
| [ChartEmpty](projects/gabarit/src/lib/components/organisms/chart-empty/README.md)
|
|
52
|
-
| [ChartFrame](projects/gabarit/src/lib/components/organisms/chart-frame/README.md)
|
|
53
|
-
| [ChartLegend](projects/gabarit/src/lib/components/organisms/chart-legend/README.md)
|
|
54
|
-
| [ChartTable](projects/gabarit/src/lib/components/organisms/chart-table/README.md)
|
|
55
|
-
| [ChartTooltip](projects/gabarit/src/lib/components/organisms/chart-tooltip/README.md)
|
|
56
|
-
| [
|
|
57
|
-
| [
|
|
58
|
-
| [
|
|
59
|
-
| [
|
|
97
|
+
| Component | Selector | Role |
|
|
98
|
+
| -------------------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------ |
|
|
99
|
+
| [BarChart](projects/gabarit/src/lib/components/organisms/bar-chart/README.md) | `gbt-bar-chart` | Bar chart on the dataviz base. |
|
|
100
|
+
| [ChartAxis](projects/gabarit/src/lib/components/organisms/chart-axis/README.md) | `g[gbtChartAxis]` | Axis ticks — base building block. |
|
|
101
|
+
| [ChartEmpty](projects/gabarit/src/lib/components/organisms/chart-empty/README.md) | `gbt-chart-empty` | Empty state — base building block. |
|
|
102
|
+
| [ChartFrame](projects/gabarit/src/lib/components/organisms/chart-frame/README.md) | `gbt-chart-frame` | Low-level base, for a custom chart. |
|
|
103
|
+
| [ChartLegend](projects/gabarit/src/lib/components/organisms/chart-legend/README.md) | `gbt-chart-legend` | Multi-series legend — base building block. |
|
|
104
|
+
| [ChartTable](projects/gabarit/src/lib/components/organisms/chart-table/README.md) | `gbt-chart-table` | Non-visual table — base building block. |
|
|
105
|
+
| [ChartTooltip](projects/gabarit/src/lib/components/organisms/chart-tooltip/README.md) | `gbt-chart-tooltip` | Tooltip — base building block. |
|
|
106
|
+
| [ConfirmDangerModal](projects/gabarit/src/lib/components/organisms/confirm-danger-modal/README.md) | `gbt-confirm-danger-modal` | Type-to-confirm destructive-action dialog. |
|
|
107
|
+
| [Drawer](projects/gabarit/src/lib/components/organisms/drawer/README.md) | `gbt-drawer` | Side panel from a screen edge, focus trapped. |
|
|
108
|
+
| [GbtToastService](projects/gabarit/src/lib/components/organisms/toaster/README.md) | `GbtToastService` | Signal store of toasts; `gbt-toaster` shows it when `toasts` is omitted. |
|
|
109
|
+
| [LineChart](projects/gabarit/src/lib/components/organisms/line-chart/README.md) | `gbt-line-chart` | Line(s) on the dataviz base. |
|
|
110
|
+
| [Modal](projects/gabarit/src/lib/components/organisms/modal/README.md) | `gbt-modal` | Modal dialog box. |
|
|
111
|
+
| [PieChart](projects/gabarit/src/lib/components/organisms/pie-chart/README.md) | `gbt-pie-chart` | Pie or donut chart. |
|
|
112
|
+
| [SearchBar](projects/gabarit/src/lib/components/organisms/search-bar/README.md) | `gbt-search-bar` | Search with grouped results. |
|
|
113
|
+
| [TimelineChart](projects/gabarit/src/lib/components/organisms/timeline-chart/README.md) | `gbt-timeline-chart` | Timeline on the dataviz base. |
|
|
114
|
+
| [Toaster](projects/gabarit/src/lib/components/organisms/toaster/README.md) | `gbt-toaster` | Stack of temporary notifications. |
|
|
60
115
|
|
|
61
116
|
### Templates
|
|
62
117
|
|
|
63
|
-
| Component
|
|
64
|
-
|
|
|
65
|
-
| [AppShell](projects/gabarit/src/lib/components/templates/app-shell/README.md)
|
|
118
|
+
| Component | Selector | Role |
|
|
119
|
+
| ----------------------------------------------------------------------------------------------- | ------------------------- | --------------------------------------------------------- |
|
|
120
|
+
| [AppShell](projects/gabarit/src/lib/components/templates/app-shell/README.md) | `gbt-app-shell` | Page shell: side nav, header, content. |
|
|
121
|
+
| [AppShellNavGroup](projects/gabarit/src/lib/components/templates/app-shell-nav-group/README.md) | `gbt-app-shell-nav-group` | Collapsible nav group, works in the collapsed rail. |
|
|
122
|
+
| [PageLayout](projects/gabarit/src/lib/components/templates/page-layout/README.md) | `gbt-page-layout` | Page grid: main, aside and nav columns (container query). |
|
|
123
|
+
|
|
124
|
+
### Directives and helper components to import
|
|
125
|
+
|
|
126
|
+
These are not standalone widgets: they decorate a projected element of a
|
|
127
|
+
component above. **They must be imported next to the component** (`imports:
|
|
128
|
+
[Card, CardHeader]`); without the import the element is still rendered
|
|
129
|
+
but plain, without the layout the directive provides.
|
|
130
|
+
|
|
131
|
+
| Class | Selector | Used with |
|
|
132
|
+
| -------------- | -------------------- | -------------------------------------------------------------------- |
|
|
133
|
+
| `CardHeader` | `[card-header]` | `gbt-card`: your own header above the box, actions on the right. |
|
|
134
|
+
| `CardLink` | `a[gbtCardLink]` | `gbt-card`: link mode, the card's box is clickable (stretched link). |
|
|
135
|
+
| `MenuTrigger` | `[gbtMenuTrigger]` | `gbt-menu`: a custom trigger element instead of the default button. |
|
|
136
|
+
| `StatTileLink` | `a[gbtStatTileLink]` | `gbt-stat-tile`: the router-agnostic link, its text is the label. |
|
|
137
|
+
|
|
138
|
+
## Primitives and pipes
|
|
139
|
+
|
|
140
|
+
Pure functions exported from `@masmarino/gabarit`, usable in any TypeScript
|
|
141
|
+
file (no component, no injection context, no browser API beyond `Intl`) and
|
|
142
|
+
tree-shakable. Every formatter takes the **locale first**, because Gabarit
|
|
143
|
+
has no i18n of its own; the pipes default it to Angular's `LOCALE_ID`.
|
|
144
|
+
A missing value (`null`/`undefined`) prints `''`; a value that is not a
|
|
145
|
+
finite number or a valid date prints `—`.
|
|
146
|
+
|
|
147
|
+
| Function | Role |
|
|
148
|
+
| ------------------------------------------------------------- | -------------------------------------------------------------------- |
|
|
149
|
+
| `formatBytes(bytes, locale, { base, decimals, binaryUnits })` | A file size: `1.5 KiB`, `1,5 Kio`, `1,5 ko` (base 1000). |
|
|
150
|
+
| `formatRelativeTime(date, locale, now?, options?)` | "5 minutes ago" through `Intl.RelativeTimeFormat`. |
|
|
151
|
+
| `formatDateTime(date, locale, options?)` | A date and time through `Intl.DateTimeFormat`. |
|
|
152
|
+
| `formatDuration(ms, locale, { days })` | `1 min 30 s`, `2 h 5 min`; `{ days: true }` adds `2 d 3 h`. |
|
|
153
|
+
| `formatNumber`, `formatCompact`, `formatPercent` | Locale-aware numbers (`1,234`, `1.2K`, `12.3%`). |
|
|
154
|
+
| `computeInitials(name)` | Up to two capitals for an avatar: `Ada Lovelace` gives `AL`. |
|
|
155
|
+
| `createListToolbarState(config)` | Search and sort signals for a `gbt-list-toolbar`. |
|
|
156
|
+
| `copyToClipboard`, `ClipboardFeedback`, `selectContents` | The clipboard helpers behind `gbt-copy-button` and `gbt-copy-field`. |
|
|
157
|
+
|
|
158
|
+
Numbers and units in `formatBytes` are joined by a no-break space (`U+00A0`).
|
|
159
|
+
The examples below write it as a plain space.
|
|
160
|
+
|
|
161
|
+
| Call | `en` | `fr` |
|
|
162
|
+
| --------------------------------------------------- | ----------------------- | ---------------------- |
|
|
163
|
+
| `formatBytes(1536, l)` | `1.5 KiB` | `1,5 Kio` |
|
|
164
|
+
| `formatBytes(1536, l, { binaryUnits: 'legacy' })` | `1.5 KB` | `1,5 Ko` |
|
|
165
|
+
| `formatBytes(1500, l, { base: 1000 })` | `1.5 kB` | `1,5 ko` |
|
|
166
|
+
| `formatBytes(512, l)`, `formatBytes(NaN, l)` | `512 B`, `—` | `512 o`, `—` |
|
|
167
|
+
| `formatRelativeTime(d, l, now)`, 5 minutes earlier | `5 minutes ago` | `il y a 5 minutes` |
|
|
168
|
+
| the same, 26 hours earlier | `yesterday` | `hier` |
|
|
169
|
+
| the same, 3 days earlier | `3 days ago` | `il y a 3 jours` |
|
|
170
|
+
| the same, 2 hours later | `in 2 hours` | `dans 2 heures` |
|
|
171
|
+
| the same, less than 10 s away | `now` | `maintenant` |
|
|
172
|
+
| `formatRelativeTime(d, l, now, { style: 'short' })` | `5 min. ago` | `il y a 5 min` |
|
|
173
|
+
| `formatDateTime(d, l)` | `Sep 26, 2026, 2:05 PM` | `26 sept. 2026, 14:05` |
|
|
174
|
+
| `formatDateTime(d, l, { dateStyle: 'long' })` | `September 26, 2026` | `26 septembre 2026` |
|
|
175
|
+
| `formatDuration(90_000_000, l, { days: true })` | `1 d 1 h` | `1 j 1 h` |
|
|
176
|
+
|
|
177
|
+
Details worth knowing:
|
|
178
|
+
|
|
179
|
+
- **`formatBytes`** counts in 1024 by default (as a file manager does) and
|
|
180
|
+
labels with the unambiguous binary units; `base: 1000` counts in thousands
|
|
181
|
+
and labels with the SI units of the locale (`kB`, `ko`). Bytes are never
|
|
182
|
+
fractional, the ranks above show at most `decimals` (default 1) digits and
|
|
183
|
+
roll over (`1023.96 KiB` is `1 MiB`), a negative size keeps its sign. The
|
|
184
|
+
binary label is the locale's SI label with an `i` (`Kio` in `fr`, `KiB` in
|
|
185
|
+
`en`, `de`, `ja`), except where the locale writes its byte in another script
|
|
186
|
+
(`ru`, `uk`, `ar`): those get the Latin `KiB`, `MiB`... so a label never mixes
|
|
187
|
+
two scripts. `binaryUnits: 'legacy'` prints `KB` / `Ko` instead.
|
|
188
|
+
- **`formatRelativeTime`** picks the unit from the gap, rounding toward zero:
|
|
189
|
+
under 10 s `now`, seconds under a minute, then minutes, hours, days (under
|
|
190
|
+
7 days), weeks (under 30 days), months (30 days each, under a year), years.
|
|
191
|
+
Past and future are handled. `now` defaults to the current time; pass it for
|
|
192
|
+
a deterministic render. The dates are `Date`, ISO strings or epoch
|
|
193
|
+
milliseconds. Options:
|
|
194
|
+
- `style`: `'long'` (default, `5 minutes ago`), `'short'` (`5 min. ago`),
|
|
195
|
+
`'narrow'`.
|
|
196
|
+
- `numeric`: `'auto'` (default) says `yesterday` / `hier`; `'always'` says
|
|
197
|
+
`1 day ago` / `il y a 1 jour`.
|
|
198
|
+
- `maxUnit`: `'hour' | 'day' | 'week' | 'month'` caps the largest unit, so
|
|
199
|
+
`'day'` gives `il y a 12 jours` instead of `il y a 2 semaines` (and
|
|
200
|
+
`il y a 400 jours` instead of years). Without it weeks and months always
|
|
201
|
+
appear.
|
|
202
|
+
- `absoluteAfterDays: 30` switches to the numeric date (`26/08/2026`) from
|
|
203
|
+
that gap on; `timeZone` sets the zone of that date.
|
|
204
|
+
- **`formatDateTime`** uses the runtime's time zone unless `options.timeZone`
|
|
205
|
+
says otherwise. Options that select fields replace the default medium date
|
|
206
|
+
and short time, other options (a time zone) apply on top of it.
|
|
207
|
+
- **`formatDuration`** keeps its existing output unless `days: true`; with it
|
|
208
|
+
a duration of a day or more prints days and hours (minutes are dropped, as
|
|
209
|
+
with hours and seconds) using the locale's day letter (`d`, `j`).
|
|
210
|
+
|
|
211
|
+
### Pipes
|
|
212
|
+
|
|
213
|
+
Standalone, **pure** pipes that call the primitives. The locale is
|
|
214
|
+
`options.locale`, else Angular's `LOCALE_ID` (`en-US` unless the application
|
|
215
|
+
provides another, for instance `{ provide: LOCALE_ID, useValue: 'fr' }`); the
|
|
216
|
+
document's `lang` is deliberately not read, so server and browser render
|
|
217
|
+
alike.
|
|
218
|
+
|
|
219
|
+
| Pipe | Example | Output (`fr`) |
|
|
220
|
+
| ----------------- | --------------------------------------------- | ---------------------- |
|
|
221
|
+
| `gbtRelativeTime` | `{{ event.at \| gbtRelativeTime }}` | `il y a 5 minutes` |
|
|
222
|
+
| `gbtBytes` | `{{ file.size \| gbtBytes: { base: 1000 } }}` | `1,5 ko` |
|
|
223
|
+
| `gbtDateTime` | `{{ event.at \| gbtDateTime }}` | `26 sept. 2026, 14:05` |
|
|
224
|
+
|
|
225
|
+
Relative time goes stale, and a pure pipe is not re-evaluated as time passes:
|
|
226
|
+
the text is right as of the last time the value or the options changed. That
|
|
227
|
+
is what most lists want (no timer per row). For a view that must stay live,
|
|
228
|
+
update one signal on a timer and pass it as `now`:
|
|
229
|
+
|
|
230
|
+
```html
|
|
231
|
+
{{ event.at | gbtRelativeTime: { now: clock() } }}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### List toolbar state
|
|
235
|
+
|
|
236
|
+
`createListToolbarState(config)` holds the three signals behind a
|
|
237
|
+
`gbt-list-toolbar` (`search`, `sortValue`, `direction`) and the filter and sort
|
|
238
|
+
that go with them, so a list page does not re-declare them. It needs no
|
|
239
|
+
injection context.
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
readonly toolbar = createListToolbarState({
|
|
243
|
+
sortOptions: [
|
|
244
|
+
{ value: 'name', label: 'Name' },
|
|
245
|
+
{ value: 'created', label: 'Created' },
|
|
246
|
+
],
|
|
247
|
+
defaultSort: 'name', // defaults to the first option
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
readonly rows = this.toolbar.filtered(() => this.repos(), {
|
|
251
|
+
text: (repo) => [repo.name, repo.description], // searched, case-insensitive
|
|
252
|
+
sortBy: { name: (repo) => repo.name, created: (repo) => repo.createdAt },
|
|
253
|
+
})
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
```html
|
|
257
|
+
<gbt-list-toolbar
|
|
258
|
+
searchLabel="Search"
|
|
259
|
+
[sortOptions]="toolbar.sortOptions"
|
|
260
|
+
[searchValue]="toolbar.search()"
|
|
261
|
+
(searchValueChange)="toolbar.search.set($event)"
|
|
262
|
+
[sortValue]="toolbar.sortValue()"
|
|
263
|
+
(sortValueChange)="toolbar.sortValue.set($event)"
|
|
264
|
+
[sortDirection]="toolbar.direction()"
|
|
265
|
+
(sortDirectionChange)="toolbar.direction.set($event)"
|
|
266
|
+
/>
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
| Member | Role |
|
|
270
|
+
| ---------------------------------- | --------------------------------------------------------------------------------- |
|
|
271
|
+
| `search`, `sortValue`, `direction` | The writable signals. |
|
|
272
|
+
| `sortOptions` | The options given in the config, ready to bind. |
|
|
273
|
+
| `dirty()`, `reset()` | Whether anything differs from the start values, and back to them. |
|
|
274
|
+
| `apply(items, accessors)` | Filters then sorts a list now; call it inside a `computed` to follow the signals. |
|
|
275
|
+
| `filtered(source, accessors)` | A `computed` of `apply(source(), accessors)`; `source` is read lazily. |
|
|
276
|
+
|
|
277
|
+
The accessors are `text` (a string or an array of strings, matched as a
|
|
278
|
+
case-insensitive substring of the trimmed search) and `sortBy` (one accessor
|
|
279
|
+
per sort field, returning a string, number, boolean or `Date`; missing or
|
|
280
|
+
non-finite values sort last in both directions). Strings compare with `Intl.Collator` (case-insensitive, numeric: `runner
|
|
281
|
+
2` before `runner 10`; pass `locale`). To take over, give `matches(item,
|
|
282
|
+
query)` and/or `compare(a, b, key)` instead. There is no debounce: the search
|
|
283
|
+
updates on every keystroke. With `sortBy`, `desc` sorts descending (equal items
|
|
284
|
+
keep their source order); with `compare`, `desc` reverses the ascending result.
|
|
66
285
|
|
|
67
286
|
## Styles
|
|
68
287
|
|
|
@@ -84,24 +303,26 @@ application should override to re-theme itself** — the raw palette
|
|
|
84
303
|
(`--brand-*`, `--grey-*`, `--red-*`…) is an internal detail, never
|
|
85
304
|
referenced outside `_semantic.scss` (enforced by `token-usage.spec.ts`).
|
|
86
305
|
|
|
87
|
-
| Category | Token | Role
|
|
88
|
-
| ----------- | ------------------------------------------------------------------------ |
|
|
89
|
-
| Brand | `--primary` / `--primary-hover` | Action color (buttons, active links, focus) and its hover state
|
|
90
|
-
| Backgrounds | `--bg-principal` | Page and surface background (cards, panels)
|
|
91
|
-
| | `--bg-panel` | Background of persistent navigation areas (nav, header)
|
|
92
|
-
| | `--bg-hover` | Hover state of an interactive element on a neutral background
|
|
93
|
-
|
|
|
94
|
-
|
|
|
95
|
-
| | `--
|
|
96
|
-
|
|
|
97
|
-
|
|
|
98
|
-
|
|
|
99
|
-
|
|
|
100
|
-
|
|
|
306
|
+
| Category | Token | Role |
|
|
307
|
+
| ----------- | ------------------------------------------------------------------------ | ---------------------------------------------------------------- |
|
|
308
|
+
| Brand | `--primary` / `--primary-hover` | Action color (buttons, active links, focus) and its hover state |
|
|
309
|
+
| Backgrounds | `--bg-principal` | Page and surface background (cards, panels) |
|
|
310
|
+
| | `--bg-panel` | Background of persistent navigation areas (nav, header) |
|
|
311
|
+
| | `--bg-hover` | Hover state of an interactive element on a neutral background |
|
|
312
|
+
| | `--bg-track` | Track of a segmented control, visible on the page and on a panel |
|
|
313
|
+
| Border | `--border-color` | All borders |
|
|
314
|
+
| | `--gbt-hairline` / `--gbt-card-border` | Quiet separators and card edges, derived from `--border-color` |
|
|
315
|
+
| Text | `--text-primary` / `--text-secondary` / `--text-discret` | From most to least emphasized |
|
|
316
|
+
| | `--text-on-primary` / `--text-on-error` / `--text-on-color` | Text set on a `--primary` fill, an error fill, or a solid color |
|
|
317
|
+
| Success | `--color-success-base` / `-hover` / `-text` / `-bg` / `-bg-text` | Fill, hover, text, light background, text on that background |
|
|
318
|
+
| Warning | `--color-warning-base` / `-hover` / `-text` / `-bg` / `-bg-text` | Same |
|
|
319
|
+
| Error | `--color-error-base` / `-fill` / `-hover` / `-text` / `-bg` / `-bg-text` | Same (`-fill`: solid fill, e.g. an icon) |
|
|
320
|
+
| Dataviz | `--chart-series-1-base`, `-2-base`, `-3-base` | The three chart series, in order |
|
|
321
|
+
| | `--chart-grid` | Chart grid and axes |
|
|
101
322
|
|
|
102
323
|
Other tokens live on `:root` without being colors — border radii
|
|
103
324
|
(`--site-border-radius*`), shadows (`--site-shadow-*`), transition
|
|
104
|
-
durations (`--site-transition-*`) — overridable the same way.
|
|
325
|
+
durations (`--site-transition-*`), the monospace stack `--gbt-font-mono` — overridable the same way.
|
|
105
326
|
|
|
106
327
|
Overriding a token after the import:
|
|
107
328
|
|
|
@@ -136,8 +357,8 @@ component input, supplied by the application.
|
|
|
136
357
|
|
|
137
358
|
[`ACCESSIBILITY.md`](./ACCESSIBILITY.md) documents what Gabarit
|
|
138
359
|
guarantees with respect to RGAA (30 out of 106 criteria, checked on every
|
|
139
|
-
push by CI — `axe-core` in the unit tests
|
|
140
|
-
a manual audit
|
|
360
|
+
push by CI — `axe-core` in the unit tests and a dedicated contrast test —
|
|
361
|
+
plus a manual audit checklist for 69 components), what remains the application's
|
|
141
362
|
responsibility (76 criteria), and the points to watch when integrating
|
|
142
363
|
each component. Read it before writing your application's accessibility
|
|
143
364
|
statement — without it, that statement will be incomplete.
|
|
@@ -169,20 +390,34 @@ utilities in the same file do carry the `gbt-` prefix.
|
|
|
169
390
|
|
|
170
391
|
## Release
|
|
171
392
|
|
|
172
|
-
The
|
|
173
|
-
|
|
393
|
+
The version lives in **five files**, bumped together in one commit:
|
|
394
|
+
`package.json`, `package-lock.json` (the root package and its `projects/gabarit`
|
|
395
|
+
workspace entry), `projects/gabarit/package.json`,
|
|
396
|
+
`projects/gabarit/src/lib/version.ts` (`GABARIT_VERSION`, asserted equal to the
|
|
397
|
+
library's `package.json` by `version.spec.ts`) and the version string in
|
|
398
|
+
`projects/gabarit/src/lib/public-api.spec.ts`. To cut a release:
|
|
174
399
|
|
|
175
400
|
```bash
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
git
|
|
401
|
+
# 1. bump the five files, then check the whole thing
|
|
402
|
+
npm run lint && npm test && npm run build && npm run build-storybook
|
|
403
|
+
git add package.json package-lock.json projects/gabarit/package.json \
|
|
404
|
+
projects/gabarit/src/lib/version.ts projects/gabarit/src/lib/public-api.spec.ts
|
|
405
|
+
git commit -m "bump(): version X.Y.Z"
|
|
406
|
+
# 2. publish: push main, then the tag
|
|
407
|
+
git push origin main
|
|
179
408
|
git tag vX.Y.Z
|
|
180
|
-
git push origin
|
|
409
|
+
git push origin vX.Y.Z
|
|
181
410
|
```
|
|
182
411
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
provenance
|
|
412
|
+
Pushing the tag triggers the `release.yml` workflow (environment
|
|
413
|
+
`npm-release`): full lint, test and build, verification that the tag matches
|
|
414
|
+
the package version, then `npm publish --provenance --access public` from
|
|
415
|
+
`dist/gabarit`. There is no changelog file.
|
|
416
|
+
|
|
417
|
+
Before tagging, an unpublished build can be tried in an application with
|
|
418
|
+
`npm run build`, then `npm pack` in `dist/gabarit` and, in the application,
|
|
419
|
+
`npm install --no-save <path>/masmarino-gabarit-X.Y.Z.tgz` (revert with
|
|
420
|
+
`npm ci`).
|
|
186
421
|
|
|
187
422
|
## License
|
|
188
423
|
|