@masmarino/gabarit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ACCESSIBILITY.md +216 -0
- package/LICENSE +21 -0
- package/README.md +188 -0
- package/fesm2022/masmarino-gabarit.mjs +2398 -0
- package/fesm2022/masmarino-gabarit.mjs.map +1 -0
- package/package.json +49 -0
- package/src/lib/tokens/_palette.scss +58 -0
- package/src/lib/tokens/_semantic.scss +114 -0
- package/src/lib/tokens/_utilities.scss +145 -0
- package/src/lib/tokens/index.scss +3 -0
- package/types/masmarino-gabarit.d.ts +786 -0
package/ACCESSIBILITY.md
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# Accessibility
|
|
2
|
+
|
|
3
|
+
Target standard: **RGAA 4.1.2** (the current version of the French
|
|
4
|
+
accessibility standard, 106 criteria, aligned with WCAG 2.1 AA and EN 301
|
|
5
|
+
549), plus the WCAG 2.2 AA additions that RGAA 5 will fold in by the end
|
|
6
|
+
of 2026 — 2.4.11 focus not obscured and 2.5.8 target size.
|
|
7
|
+
|
|
8
|
+
Text contrast targets level **AAA (7:1)**, beyond RGAA's own requirement
|
|
9
|
+
of AA (4.5:1). UI component contrast stays at 3:1: criterion 3.3 has no
|
|
10
|
+
AAA level.
|
|
11
|
+
|
|
12
|
+
## What Gabarit guarantees, and what it can't guarantee
|
|
13
|
+
|
|
14
|
+
**RGAA is assessed on a page or a service, never on a library.** Gabarit
|
|
15
|
+
is therefore not "RGAA-compliant" and cannot be: it's your application
|
|
16
|
+
that is, or isn't. What Gabarit guarantees is that **the 30 criteria that
|
|
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 thirteen manual audit
|
|
19
|
+
checklists (`AUDIT.md`) — one alone covers seven chart-base components,
|
|
20
|
+
another covers both tab components, and five components have none. The
|
|
21
|
+
first two means run locally via `npm test`, not in continuous
|
|
22
|
+
integration: this repository has no CI. The checklists are handwritten
|
|
23
|
+
and reviewed by a human.
|
|
24
|
+
|
|
25
|
+
## How it's actually verified, and where that stops
|
|
26
|
+
|
|
27
|
+
**This describes what actually runs, not what would be desirable.**
|
|
28
|
+
This repository has no continuous integration, and no `axe-core` pass
|
|
29
|
+
runs on Storybook stories. What does exist:
|
|
30
|
+
|
|
31
|
+
- **`axe-core`, run in the unit tests (`npm test`, local).** Each
|
|
32
|
+
component has its own `expectNoA11yViolations` test. It covers only
|
|
33
|
+
around 30% of RGAA criteria: necessary, and very insufficient on its
|
|
34
|
+
own.
|
|
35
|
+
- **`@storybook/addon-a11y`** is registered in Storybook and gives a
|
|
36
|
+
visual inspection panel per story — useful in manual review, but
|
|
37
|
+
**nothing runs it as a test**: it isn't wired to a test runner, so no
|
|
38
|
+
story can "fail" on an accessibility violation. Reading it is part of
|
|
39
|
+
the manual audit checklist below, not of automated verification.
|
|
40
|
+
- **A dedicated contrast test** (`tokens/contrast.spec.ts`), which
|
|
41
|
+
recomputes the ratio of a **hand-maintained** list of token pairs in
|
|
42
|
+
that file against the thresholds above, in both themes — not "every
|
|
43
|
+
token pair" in an exhaustive sense: a token added without being added
|
|
44
|
+
to that list is checked by nothing, and the test measures token
|
|
45
|
+
values in isolation without asking which token a component actually
|
|
46
|
+
uses — a component can paint text with a graphic-only token at 3:1
|
|
47
|
+
and this test still comes back green. It also covers **hover
|
|
48
|
+
states**, checking that every hovered fill stays perceptibly distinct
|
|
49
|
+
from its resting state.
|
|
50
|
+
- **A token-usage test** (`tokens/token-usage.spec.ts`), which closes the
|
|
51
|
+
blind spot described above in three parts, under an explicit exemption
|
|
52
|
+
you need to know before them. **A `*-base` token (validated at 3:1,
|
|
53
|
+
never a text threshold) may paint a purely graphic HTML fill if its
|
|
54
|
+
declaration carries the `// token-graphique-sans-texte` marker at the
|
|
55
|
+
end of the line**, and this exemption is refused outright as soon as
|
|
56
|
+
the selector of the rule carrying it itself denotes text (BEM word
|
|
57
|
+
`label`, `text`, `caption`, or `title`). It is used in three places
|
|
58
|
+
today: the fill of `gbt-gauge-bar`, which carries no text, and the
|
|
59
|
+
fills of `gbt-dimension-card` and `gbt-funnel-chart`, themselves
|
|
60
|
+
translucent, on which opaque text is laid — never in the exempted
|
|
61
|
+
declaration itself. That said, the three parts: the test re-reads the
|
|
62
|
+
components' stylesheets — and the `styles:` blocks declared inline in
|
|
63
|
+
decorators — and fails the suite as soon as a direct reference to the
|
|
64
|
+
raw palette appears (the families are **derived from
|
|
65
|
+
`_palette.scss`**, never hand-enumerated) or a `color` declaration
|
|
66
|
+
tied to a `*-base` token. Its third part measures the **actual
|
|
67
|
+
pairing**: for a rule's own `background` declaration, it resolves the
|
|
68
|
+
**effective** text color — the rule's own if it sets one, otherwise
|
|
69
|
+
its nearest ancestor's that does — up to the palette, composites
|
|
70
|
+
translucent overlays over the real background, and checks the ratio as
|
|
71
|
+
it will actually be painted. It's the only check in this repository
|
|
72
|
+
that measures a pair under rendering conditions, rather than two
|
|
73
|
+
tokens side by side.
|
|
74
|
+
- **Thirteen manual audit checklists** (`AUDIT.md` in the folder of the
|
|
75
|
+
components that have one — not all of them). One (`chart-frame/AUDIT.md`)
|
|
76
|
+
alone covers seven chart-base components (`chart-frame`, `chart-axis`,
|
|
77
|
+
`chart-tooltip`, `chart-legend`, `chart-empty`, `chart-table`,
|
|
78
|
+
`chart-context`), another (`tabs/AUDIT.md`) covers both the `Tabs` and
|
|
79
|
+
`Tab` components. Each checklist records what automation doesn't see —
|
|
80
|
+
actual keyboard use, screen reader, measurements in Storybook, reading
|
|
81
|
+
the `@storybook/addon-a11y` panel. Conversely, five components
|
|
82
|
+
(`bar-chart`, `funnel-chart`, `icon`, `sparkline`, `timeline-chart`)
|
|
83
|
+
have none.
|
|
84
|
+
|
|
85
|
+
Two measured limits of `axe-core` in this tooling, worth knowing before
|
|
86
|
+
reproducing this approach:
|
|
87
|
+
|
|
88
|
+
- **`color-contrast` can't be evaluated under jsdom.** The rule needs a
|
|
89
|
+
real canvas; under jsdom it consistently returns "incomplete" rather
|
|
90
|
+
than a verdict. It's therefore disabled in the test helper
|
|
91
|
+
(`expectNoA11yViolations`) and replaced by the dedicated contrast test
|
|
92
|
+
above — which is actually a **more rigorous** check, since it measures
|
|
93
|
+
the tokens' real values rather than inspecting rendered output.
|
|
94
|
+
- **`axe` doesn't infer the implicit role of an unknown custom
|
|
95
|
+
element.** Measured empirically: the `aria-prohibited-attr` rule fires
|
|
96
|
+
on `<div role="generic" aria-label="x">` but **not** on
|
|
97
|
+
`<gbt-icon aria-label="x">`. And the host of every Gabarit component is
|
|
98
|
+
a custom element of that kind. Consequence: no ARIA assertion about the
|
|
99
|
+
host of a `gbt-*` component relies on `axe` alone — it's also checked
|
|
100
|
+
by direct DOM inspection in that component's tests.
|
|
101
|
+
|
|
102
|
+
A different kind of gap is worth distinguishing from the two axe
|
|
103
|
+
limits above: a duplicate-id defect between two instances of
|
|
104
|
+
`gbt-tabs` on the same page is only observable when a fixture actually
|
|
105
|
+
renders two instances at once — a single-instance fixture can't
|
|
106
|
+
surface it, however thorough the test. The `duplicate-id` and
|
|
107
|
+
`duplicate-id-aria` rules are part of the default rule set used here
|
|
108
|
+
(`wcag2a`/`wcag2aa`/`wcag21a`/`wcag21aa`/`wcag22aa`) and do catch this
|
|
109
|
+
class of defect, given that scenario; `tabs.spec.ts` includes it, and
|
|
110
|
+
`gbt-tabs` namespaces every instance's generated ids accordingly (see
|
|
111
|
+
`tabs/AUDIT.md`). The distinction matters for anyone adopting this
|
|
112
|
+
verification method: a rule with no violation to show isn't the same
|
|
113
|
+
as a rule with nothing to check — check the scenario, not just the
|
|
114
|
+
rule.
|
|
115
|
+
|
|
116
|
+
## Criteria covered by Gabarit
|
|
117
|
+
|
|
118
|
+
| Topic | Criteria |
|
|
119
|
+
| --------------- | --------------------------------------------------------- |
|
|
120
|
+
| 3 Colors | 3.1, 3.2, 3.3 |
|
|
121
|
+
| 5 Tables | 5.4, 5.5, 5.6, 5.7, 5.8 |
|
|
122
|
+
| 7 Scripting | 7.1, 7.3, 7.4, 7.5 |
|
|
123
|
+
| 9 Structure | 9.3 |
|
|
124
|
+
| 10 Presentation | 10.5, 10.7, 10.8, 10.9, 10.10, 10.11, 10.12, 10.13, 10.14 |
|
|
125
|
+
| 11 Forms | 11.1, 11.4, 11.9, 11.11 |
|
|
126
|
+
| 12 Navigation | 12.8, 12.9, 12.11 |
|
|
127
|
+
| 13 Consultation | 13.8 |
|
|
128
|
+
|
|
129
|
+
That's 30 out of the 106 criteria in RGAA 4.1.2. Two topics that might
|
|
130
|
+
look like they belong here don't: **Topic 6 Links (6.1, 6.2)** isn't
|
|
131
|
+
listed because no `<a>` element exists anywhere in the library — a
|
|
132
|
+
library that never produces a link cannot guarantee a criterion about
|
|
133
|
+
links. And **11.2, 11.10, and 11.13** sit under "What remains your
|
|
134
|
+
responsibility" below rather than here, since the components only
|
|
135
|
+
provide the mechanism (`label`/field association, `role="alert"`,
|
|
136
|
+
`aria-describedby`, an `autocomplete` you can override) — never the
|
|
137
|
+
label text, the error text, or the field-specific `autocomplete`
|
|
138
|
+
value itself.
|
|
139
|
+
|
|
140
|
+
## What remains your responsibility
|
|
141
|
+
|
|
142
|
+
The other 76 criteria. The main ones:
|
|
143
|
+
|
|
144
|
+
| Topic | What you need to do |
|
|
145
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
146
|
+
| 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. No Gabarit component renders an `<a>`: nothing to delegate. |
|
|
148
|
+
| 8 Mandatory elements | Doctype, `lang`, page `<title>`, absence of validity errors. |
|
|
149
|
+
| 9 Structure | Heading hierarchy of the page. `gbt-card` lets you choose its level via `headingLevel` — it's up to you to set it correctly. |
|
|
150
|
+
| 10 Presentation | 200% zoom, page-wide reflow. The components hold up their end; the layout is yours. |
|
|
151
|
+
| 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
|
+
| 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. |
|
|
153
|
+
| 13 Consultation | Time limits, opening new windows, downloadable documents, screen orientation. |
|
|
154
|
+
|
|
155
|
+
## Points to watch when integrating
|
|
156
|
+
|
|
157
|
+
- **`gbt-table`** — `caption` is a **required** input (criteria 5.4 and
|
|
158
|
+
5.5): the component won't compile without it. As soon as you listen to
|
|
159
|
+
`rowClick`, pass `clickableRows`, otherwise the feature is inaccessible
|
|
160
|
+
from the keyboard (criterion 7.3).
|
|
161
|
+
- **`gbt-search-bar`** — the outputs are `queryChange` and
|
|
162
|
+
`itemSelected` (not `search` / `select`: `@angular-eslint/no-output-native`
|
|
163
|
+
forbids those, they're native DOM events).
|
|
164
|
+
- **`gbt-card`** — `headingLevel` defaults to 2. Adjust it to the card's
|
|
165
|
+
actual place in the page (criterion 9.1).
|
|
166
|
+
- **`gbt-button`** — a button with no `text` must have an `ariaLabel`
|
|
167
|
+
(criterion 11.9).
|
|
168
|
+
- **`gbt-modal` restores focus on both closing paths, regardless of how
|
|
169
|
+
you mount it.** Whether you unmount the component on close
|
|
170
|
+
(`@if (open()) { <gbt-modal ... /> }`) or keep it mounted and toggle it
|
|
171
|
+
(`[isOpen]="open()"`), focus returns to the element that held it before
|
|
172
|
+
opening — respectively on the component's destruction and on the
|
|
173
|
+
`isOpen()` transition from `true` to `false`. Both usages are therefore
|
|
174
|
+
safe; neither lets focus fall onto `<body>`.
|
|
175
|
+
- **`gbt-icon` is unconditionally decorative.** It receives no input to
|
|
176
|
+
carry an accessible name: its host carries a bound `aria-hidden="true"`,
|
|
177
|
+
set after any attribute written by the consumer — an `aria-label` you
|
|
178
|
+
set on `<gbt-icon>` is ignored by assistive technology regardless. The
|
|
179
|
+
accessible name of an action belongs to the control that contains it
|
|
180
|
+
(button, field, link), never to the icon itself.
|
|
181
|
+
- **The four standalone charts** (`gbt-sparkline`, `gbt-gauge-bar`,
|
|
182
|
+
`gbt-dimension-card`, `gbt-funnel-chart`) have neither an axis nor a
|
|
183
|
+
frame: each carries its own text alternative rather than assembling the
|
|
184
|
+
`gbt-chart-frame` base. Three inputs there distinguish similar-sounding
|
|
185
|
+
roles, not to be confused: `tableCaption` is the caption of a chart's
|
|
186
|
+
non-visual table (`gbt-sparkline`, `gbt-funnel-chart`); `caption` is the
|
|
187
|
+
caption of a **visible** table, taking the name of the HTML element
|
|
188
|
+
(`gbt-dimension-card`); `label` is the visible, accessible name of the
|
|
189
|
+
component itself — the heading of `gbt-gauge-bar`, and the `aria-label`
|
|
190
|
+
of `gbt-funnel-chart`'s `<ol>`, distinct from its `tableCaption`.
|
|
191
|
+
- **`gbt-gauge-bar` expresses its ARIA as a percentage, never in the
|
|
192
|
+
consumer's own scale.** `aria-valuenow`, `aria-valuemin`, and
|
|
193
|
+
`aria-valuemax` are always bounded to [0, 100]: with `[max]="500"` and
|
|
194
|
+
`[value]="62"`, a screen reader reads `aria-valuenow="12.4"` — neither
|
|
195
|
+
"62" nor "62 out of 500". Only `aria-valuetext` (your `formattedValue`)
|
|
196
|
+
carries the human-readable quantity; it's the only one of the five ARIA
|
|
197
|
+
values worth reading if you inspect the attribute rather than letting
|
|
198
|
+
assistive technology announce it.
|
|
199
|
+
- **Default strings in English, to override in a non-English
|
|
200
|
+
application** — these components carry visible or announced labels
|
|
201
|
+
with no localized default:
|
|
202
|
+
- `gbt-button`: `loadingLabel` (`'Loading'`).
|
|
203
|
+
- `gbt-input`: `showPasswordLabel` (`'Show password'`),
|
|
204
|
+
`hidePasswordLabel` (`'Hide password'`).
|
|
205
|
+
- `gbt-select`: `placeholder` (`'Select…'`), `selectedCountLabel`
|
|
206
|
+
(function, `` `${count} selected` ``).
|
|
207
|
+
- `gbt-modal`: `closeLabel` (`'Close'`).
|
|
208
|
+
- `gbt-table`: `emptyMessage` (`'No data'`).
|
|
209
|
+
- `gbt-search-bar`: `placeholder` (`'Search…'`), `noResultsMessage`
|
|
210
|
+
(`'No results'`), `noResultsHint` (`'Try a different search.'`),
|
|
211
|
+
`clearLabel` (`'Clear search'`), `resultsAnnouncement` (function,
|
|
212
|
+
announces the result count — criterion 7.5), `navigateHint`
|
|
213
|
+
(`'Navigate'`), `selectHint` (`'Select'`), `closeHint` (`'Close'`).
|
|
214
|
+
- **Token overrides** — if you redefine the semantic colors, you take on
|
|
215
|
+
criteria 3.2 and 3.3 yourself. Gabarit's contrast test only checks its
|
|
216
|
+
own values.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Florian Simon
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# Gabarit
|
|
2
|
+
|
|
3
|
+
[](https://github.com/Masmarino/Gabarit/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@masmarino/gabarit)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
Angular design system for self-hosted applications — UI components and
|
|
8
|
+
dataviz, no external dependency.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @masmarino/gabarit
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Components
|
|
17
|
+
|
|
18
|
+
Each component has its own README, with the detail of its inputs and
|
|
19
|
+
outputs — the link is on its name.
|
|
20
|
+
|
|
21
|
+
### Atoms
|
|
22
|
+
|
|
23
|
+
| Component | Selector | Role |
|
|
24
|
+
| -------------------------------------------------------------------------- | --------------- | ------------------------------------- |
|
|
25
|
+
| [Button](projects/gabarit/src/lib/components/atoms/button/README.md) | `gbt-button` | Action button. |
|
|
26
|
+
| [Checkbox](projects/gabarit/src/lib/components/atoms/checkbox/README.md) | `gbt-checkbox` | Checkbox, integrated with forms. |
|
|
27
|
+
| [GaugeBar](projects/gabarit/src/lib/components/atoms/gauge-bar/README.md) | `gbt-gauge-bar` | Progress gauge with alert thresholds. |
|
|
28
|
+
| [Icon](projects/gabarit/src/lib/components/atoms/icon/README.md) | `gbt-icon` | Registered SVG icon. |
|
|
29
|
+
| [Input](projects/gabarit/src/lib/components/atoms/input/README.md) | `gbt-input` | Text or password field. |
|
|
30
|
+
| [Sparkline](projects/gabarit/src/lib/components/atoms/sparkline/README.md) | `gbt-sparkline` | Fixed-size trend mini-chart. |
|
|
31
|
+
|
|
32
|
+
### Molecules
|
|
33
|
+
|
|
34
|
+
| Component | Selector | Role |
|
|
35
|
+
| --------------------------------------------------------------------------------------- | ---------------------- | ------------------------------------------- |
|
|
36
|
+
| [Card](projects/gabarit/src/lib/components/molecules/card/README.md) | `gbt-card` | Titled container. |
|
|
37
|
+
| [DimensionCard](projects/gabarit/src/lib/components/molecules/dimension-card/README.md) | `gbt-dimension-card` | Dimension table with an accented hover row. |
|
|
38
|
+
| [FunnelChart](projects/gabarit/src/lib/components/molecules/funnel-chart/README.md) | `gbt-funnel-chart` | Step-by-step conversion funnel. |
|
|
39
|
+
| [Menu](projects/gabarit/src/lib/components/molecules/menu/README.md) | `gbt-menu` | Generic dropdown menu. |
|
|
40
|
+
| [Select](projects/gabarit/src/lib/components/molecules/select/README.md) | `gbt-select` | Dropdown list, single or multiple. |
|
|
41
|
+
| [Table](projects/gabarit/src/lib/components/molecules/table/README.md) | `gbt-table` | Data table. |
|
|
42
|
+
| [Tabs](projects/gabarit/src/lib/components/molecules/tabs/README.md) | `gbt-tabs` / `gbt-tab` | Tab navigation. |
|
|
43
|
+
|
|
44
|
+
### Organisms
|
|
45
|
+
|
|
46
|
+
| Component | Selector | Role |
|
|
47
|
+
| --------------------------------------------------------------------------------------- | -------------------- | ------------------------------------------ |
|
|
48
|
+
| [BarChart](projects/gabarit/src/lib/components/organisms/bar-chart/README.md) | `gbt-bar-chart` | Bar chart on the dataviz base. |
|
|
49
|
+
| [ChartAxis](projects/gabarit/src/lib/components/organisms/chart-axis/README.md) | `g[gbtChartAxis]` | Axis ticks — base building block. |
|
|
50
|
+
| [ChartEmpty](projects/gabarit/src/lib/components/organisms/chart-empty/README.md) | `gbt-chart-empty` | Empty state — base building block. |
|
|
51
|
+
| [ChartFrame](projects/gabarit/src/lib/components/organisms/chart-frame/README.md) | `gbt-chart-frame` | Low-level base, for a custom chart. |
|
|
52
|
+
| [ChartLegend](projects/gabarit/src/lib/components/organisms/chart-legend/README.md) | `gbt-chart-legend` | Multi-series legend — base building block. |
|
|
53
|
+
| [ChartTable](projects/gabarit/src/lib/components/organisms/chart-table/README.md) | `gbt-chart-table` | Non-visual table — base building block. |
|
|
54
|
+
| [ChartTooltip](projects/gabarit/src/lib/components/organisms/chart-tooltip/README.md) | `gbt-chart-tooltip` | Tooltip — base building block. |
|
|
55
|
+
| [LineChart](projects/gabarit/src/lib/components/organisms/line-chart/README.md) | `gbt-line-chart` | Line(s) on the dataviz base. |
|
|
56
|
+
| [Modal](projects/gabarit/src/lib/components/organisms/modal/README.md) | `gbt-modal` | Modal dialog box. |
|
|
57
|
+
| [SearchBar](projects/gabarit/src/lib/components/organisms/search-bar/README.md) | `gbt-search-bar` | Search with grouped results. |
|
|
58
|
+
| [TimelineChart](projects/gabarit/src/lib/components/organisms/timeline-chart/README.md) | `gbt-timeline-chart` | Timeline on the dataviz base. |
|
|
59
|
+
|
|
60
|
+
### Templates
|
|
61
|
+
|
|
62
|
+
| Component | Selector | Role |
|
|
63
|
+
| ----------------------------------------------------------------------------- | --------------- | -------------------------------------- |
|
|
64
|
+
| [AppShell](projects/gabarit/src/lib/components/templates/app-shell/README.md) | `gbt-app-shell` | Page shell: side nav, header, content. |
|
|
65
|
+
|
|
66
|
+
## Styles
|
|
67
|
+
|
|
68
|
+
Import the tokens in the application's `styles.scss`:
|
|
69
|
+
|
|
70
|
+
```scss
|
|
71
|
+
@use 'gabarit/tokens' as *;
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Gabarit declares **no** `@font-face` rule. The tokens expose
|
|
75
|
+
`--font-family: 'Inter', sans-serif`, but serving and declaring the font
|
|
76
|
+
is the application's responsibility.
|
|
77
|
+
|
|
78
|
+
### Color tokens
|
|
79
|
+
|
|
80
|
+
Every component exclusively reads the custom properties below, set on
|
|
81
|
+
`:root` by `_semantic.scss`. **These, and only these, are what an
|
|
82
|
+
application should override to re-theme itself** — the raw palette
|
|
83
|
+
(`--brand-*`, `--grey-*`, `--red-*`…) is an internal detail, never
|
|
84
|
+
referenced outside `_semantic.scss` (enforced by `token-usage.spec.ts`).
|
|
85
|
+
|
|
86
|
+
| Category | Token | Role |
|
|
87
|
+
| ----------- | ------------------------------------------------------------------------ | --------------------------------------------------------------- |
|
|
88
|
+
| Brand | `--primary` / `--primary-hover` | Action color (buttons, active links, focus) and its hover state |
|
|
89
|
+
| Backgrounds | `--bg-principal` | Page and surface background (cards, panels) |
|
|
90
|
+
| | `--bg-panel` | Background of persistent navigation areas (nav, header) |
|
|
91
|
+
| | `--bg-hover` | Hover state of an interactive element on a neutral background |
|
|
92
|
+
| Border | `--border-color` | All borders |
|
|
93
|
+
| Text | `--text-primary` / `--text-secondary` / `--text-discret` | From most to least emphasized |
|
|
94
|
+
| | `--text-on-primary` / `--text-on-error` / `--text-on-color` | Text set on a `--primary` fill, an error fill, or a solid color |
|
|
95
|
+
| Success | `--color-success-base` / `-hover` / `-text` / `-bg` / `-bg-text` | Fill, hover, text, light background, text on that background |
|
|
96
|
+
| Warning | `--color-warning-base` / `-hover` / `-text` / `-bg` / `-bg-text` | Same |
|
|
97
|
+
| Error | `--color-error-base` / `-fill` / `-hover` / `-text` / `-bg` / `-bg-text` | Same (`-fill`: solid fill, e.g. an icon) |
|
|
98
|
+
| Dataviz | `--chart-series-1-base`, `-2-base`, `-3-base` | The three chart series, in order |
|
|
99
|
+
| | `--chart-grid` | Chart grid and axes |
|
|
100
|
+
|
|
101
|
+
Other tokens live on `:root` without being colors — border radii
|
|
102
|
+
(`--site-border-radius*`), shadows (`--site-shadow-*`), transition
|
|
103
|
+
durations (`--site-transition-*`) — overridable the same way.
|
|
104
|
+
|
|
105
|
+
Overriding a token after the import:
|
|
106
|
+
|
|
107
|
+
```scss
|
|
108
|
+
@use 'gabarit/tokens' as *;
|
|
109
|
+
|
|
110
|
+
:root {
|
|
111
|
+
--primary: #7c3aed;
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Dark mode activates via `prefers-color-scheme` or `[data-theme='dark']`
|
|
116
|
+
on `<html>`, and reapplies to the same tokens.** An override set on a bare
|
|
117
|
+
`:root` applies to both themes indifferently; for a value specific to
|
|
118
|
+
dark mode, redeclare it under the same conditions as Gabarit, after its
|
|
119
|
+
import:
|
|
120
|
+
|
|
121
|
+
```scss
|
|
122
|
+
@media (prefers-color-scheme: dark) {
|
|
123
|
+
:root {
|
|
124
|
+
--primary: #a78bfa;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Internationalization
|
|
130
|
+
|
|
131
|
+
Gabarit ships no translation mechanism. Every visible string is a
|
|
132
|
+
component input, supplied by the application.
|
|
133
|
+
|
|
134
|
+
## Accessibility
|
|
135
|
+
|
|
136
|
+
[`ACCESSIBILITY.md`](./ACCESSIBILITY.md) documents what Gabarit
|
|
137
|
+
guarantees with respect to RGAA (30 out of 106 criteria, checked on every
|
|
138
|
+
push by CI — `axe-core` in the unit tests, a dedicated contrast test, and
|
|
139
|
+
a manual audit per component), what remains the application's
|
|
140
|
+
responsibility (76 criteria), and the points to watch when integrating
|
|
141
|
+
each component. Read it before writing your application's accessibility
|
|
142
|
+
statement — without it, that statement will be incomplete.
|
|
143
|
+
|
|
144
|
+
## Known limitations
|
|
145
|
+
|
|
146
|
+
**Not every non-resting state is covered by a test.** Hover and focus
|
|
147
|
+
are: `contrast.spec.ts` checks every hover fill and its perceptibility,
|
|
148
|
+
and `token-usage.spec.ts` measures the text/fill pairing as it will
|
|
149
|
+
actually be painted, translucent overlays and compositing included. The
|
|
150
|
+
`:active` and `:disabled` states are not — the latter is out of scope
|
|
151
|
+
for RGAA, which exempts inactive controls.
|
|
152
|
+
|
|
153
|
+
**Token-usage checking only reads the library's own CSS.** If your
|
|
154
|
+
application overrides a semantic token, verifying the resulting contrast
|
|
155
|
+
is your responsibility: Gabarit's tests only measure its own values. See
|
|
156
|
+
`ACCESSIBILITY.md`.
|
|
157
|
+
|
|
158
|
+
**Two global utility classes are not prefixed: `.sr-only` and
|
|
159
|
+
`.skip-link`.** They live in `_utilities.scss`, which `@use
|
|
160
|
+
'gabarit/tokens'` pours unencapsulated into the application's **global**
|
|
161
|
+
stylesheet — deliberately, so they stay usable outside the library's
|
|
162
|
+
components. An application that already defines one of these two common
|
|
163
|
+
names collides with it. Inside the library's own components
|
|
164
|
+
(`gbt-search-bar`, `gbt-button`), it's safe: each carries its own local
|
|
165
|
+
`.sr-only`, and the scoping attribute Angular adds under encapsulation
|
|
166
|
+
(specificity 0-2-0) beats the unscoped global rule (0-1-0). The other
|
|
167
|
+
utilities in the same file do carry the `gbt-` prefix.
|
|
168
|
+
|
|
169
|
+
## Release
|
|
170
|
+
|
|
171
|
+
The published version is the one in `projects/gabarit/package.json`. To
|
|
172
|
+
cut a new release:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
npm version <patch|minor|major> --prefix projects/gabarit --no-git-tag-version
|
|
176
|
+
git add projects/gabarit/package.json
|
|
177
|
+
git commit -m "chore(release): vX.Y.Z"
|
|
178
|
+
git tag vX.Y.Z
|
|
179
|
+
git push origin main --follow-tags
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The tag triggers the `release.yml` workflow: full rebuild, verification
|
|
183
|
+
that the tag matches the package version, then publishing to npm with
|
|
184
|
+
provenance attestation.
|
|
185
|
+
|
|
186
|
+
## License
|
|
187
|
+
|
|
188
|
+
MIT.
|