nwl-components 1.7.1 → 2.0.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/README.md CHANGED
@@ -143,13 +143,108 @@ render();
143
143
  - For template strings: `renderSortIcon(direction)` (the SVG) and `ariaSort(direction)`.
144
144
 
145
145
  The headers' look is in `nwl-components/sort/style.css`, which has only the
146
- `th.nwl-sortable` and `.nwl-sort-*` rules (1 kB). Load that file, not `dist/style.css`, on a
146
+ `th.nwl-sortable` and `.nwl-sort-*` rules, after the design tokens they read (`:root` custom
147
+ properties, see "Design tokens"; 6 kB in all). Load that file, not `dist/style.css`, on a
147
148
  page not built with nwl-components: `dist/style.css` has global rules (`*` sets the font
148
149
  size and colour of every element). With a bundler, `import 'nwl-components/sort/style.css'`
149
150
  (webpack 4 included); otherwise link `node_modules/nwl-components/dist/sort/style.css`.
150
151
  `dist/style.css` keeps the same rules for `SortableTh`. Story: `Common/PlainSort`.
151
152
  Since 1.6.0.
152
153
 
154
+ ## Design tokens
155
+
156
+ The library's colours, fonts, font sizes and corner radii are CSS custom properties, defined
157
+ in `src/styles/tokens.css` (`:root` rules only) in two tiers:
158
+
159
+ - the raw palette (`--nwl-grey-44`, `--nwl-white`, `--nwl-cyan`, …): the only place with hex
160
+ values;
161
+ - the semantic tokens, to use in components and app CSS: backgrounds (`--nwl-bg`,
162
+ `--nwl-bg-surface`, `--nwl-bg-elevated`, …), borders (`--nwl-border`, …), text
163
+ (`--nwl-text`, `--nwl-text-2`, `--nwl-text-3`, …), accent, links and status colours
164
+ (`--nwl-danger`, `--nwl-success`, `--nwl-warning`), font families (`--nwl-font-body`,
165
+ `--nwl-font-display`, `--nwl-font-mono`), sizes (`--nwl-text-xs` … `--nwl-text-hero`;
166
+ body text is `--nwl-text-md`), weights, line heights, spacing (`--nwl-space-1` …
167
+ `--nwl-space-16`), radii (`--nwl-radius-sm`, `--nwl-radius-md`) and shadows.
168
+
169
+ Their values are those the NAAT apps have today, so loading them changes nothing on screen.
170
+ Storybook's `Library/Tokens` page lists every token with a sample.
171
+
172
+ `dist/style.css` and `nwl-components/sort/style.css` each include the tokens, so a page that
173
+ loads either needs nothing else. To use the tokens in an app's own CSS without those files:
174
+
175
+ ```js
176
+ import 'nwl-components/tokens.css'; // with a bundler (webpack 4 included)
177
+ ```
178
+
179
+ ```html
180
+ <!-- a page with no bundle: serve or copy node_modules/nwl-components/dist/tokens.css -->
181
+ <link rel="stylesheet" href="/lib/nwl-components/tokens.css">
182
+ ```
183
+
184
+ ```css
185
+ .my-panel {
186
+ background: var(--nwl-bg-surface);
187
+ border: 1px solid var(--nwl-border);
188
+ border-radius: var(--nwl-radius-sm);
189
+ }
190
+ ```
191
+
192
+ Loading the tokens twice on a page (e.g. `tokens.css` and `dist/style.css`) is harmless.
193
+ `npm run lint` fails on a hex colour in `src/**/*.{vue,css}` outside `tokens.css`, and on a
194
+ `var(--nwl-…)` that `tokens.css` doesn't define. Since 1.8.0.
195
+
196
+ ## Base styles and cascade layers
197
+
198
+ Since 2.0.0 all the library's CSS is in three cascade layers, declared in this order at the
199
+ top of each stylesheet it ships (`dist/style.css`, `nwl-components/base.css`,
200
+ `nwl-components/sort/style.css`):
201
+
202
+ ```css
203
+ @layer nwl.base, nwl.widgets, nwl.components;
204
+ ```
205
+
206
+ - `nwl.base`: `src/styles/base.css` (below);
207
+ - `nwl.widgets`: empty for now (plain-CSS widget classes, later);
208
+ - `nwl.components`: the components' styles (scoped or not), `sortable.css`, and the CSS of
209
+ bundled dependencies (splitpanes).
210
+
211
+ The tokens (`tokens.css`) stay outside the layers: they only define custom properties.
212
+ **An app's own CSS, which is not in a layer, always wins over the library's**, whatever the
213
+ load order or the selectors' specificity: `button { … }` in an app overrides `Button`'s scoped
214
+ rules. No `!important` and no `html …` prefix are needed. (An app that puts its own CSS in
215
+ layers must declare them after `nwl.components` to keep this.)
216
+
217
+ `base.css` replaces 1.x's global `* { box-sizing: border-box; font-size: 14px; color: white }`
218
+ rule, which is gone. Its selectors are wrapped in `:where()` (no specificity), and they apply
219
+ inside the wrapper (`.app`, the root of `Wrapper`) only, except two:
220
+
221
+ - `html`: `font-size: var(--nwl-text-md)` (1rem = 14px, as in 1.x), and `body`: `margin: 0`;
222
+ - `.app`: font (`--nwl-font-body`, `--nwl-text-md`) and colour (`--nwl-text`), inherited by
223
+ everything inside; `box-sizing: border-box`, inherited by every element and pseudo-element;
224
+ - headings, `small`, `sub`, `sup`, `code`, `pre` and form controls take their parent's font
225
+ size; form controls and `<dialog>` their parent's colour (the controls' font family stays
226
+ the browser's); links `--nwl-link`;
227
+ - keyboard focus: `:focus-visible` gets a 2px solid `--nwl-focus` outline, 2px away
228
+ (`--nwl-focus` is `--nwl-text`, white). Mouse focus shows nothing on buttons; browsers
229
+ show it on text fields and Chromium on `<select>`, as they decide what is `:focus-visible`.
230
+
231
+ `dist/style.css` includes `base.css`. A page without the Vue components (e.g. a Mustache page
232
+ that wants the same font, colour and focus style) can load it alone, after the tokens:
233
+
234
+ ```js
235
+ import 'nwl-components/tokens.css';
236
+ import 'nwl-components/base.css'; // webpack 4 too (a copy at the package root)
237
+ ```
238
+
239
+ ```html
240
+ <link rel="stylesheet" href="/lib/nwl-components/tokens.css">
241
+ <link rel="stylesheet" href="/lib/nwl-components/base.css">
242
+ <div class="app">…</div>
243
+ ```
244
+
245
+ Outside `.app`, nothing sets font, colour or box-sizing any more: an app's own markup on a
246
+ page that loads `dist/style.css` gets them from the app's CSS (or from being inside `.app`).
247
+
153
248
  ## Single File Components
154
249
 
155
250
  This project makes use of Vue SFCs: _Single File Components_, that have the `.vue` extension.
package/base.css ADDED
@@ -0,0 +1,58 @@
1
+ @layer nwl.base, nwl.widgets, nwl.components;
2
+ @layer nwl.base {
3
+ /* nwl-components base styles: `import 'nwl-components/base.css'` (after `nwl-components/tokens.css`,
4
+ whose tokens it reads). dist/style.css includes it.
5
+
6
+ The build puts this file in `@layer nwl.base`, the lowest of the library's layers
7
+ (`@layer nwl.base, nwl.widgets, nwl.components`), so any app rule wins over it. Selectors are
8
+ wrapped in :where(), so they add no specificity.
9
+
10
+ Font and colour are set once, on the wrapper (`.app`, the root of `Wrapper`), and inherited:
11
+ there is no `*` rule setting them on every element. */
12
+
13
+ /* 1rem = 14px, as in 1.x (where the `*` rule set it on <html>): the components' rem sizes */
14
+ :where(html) {
15
+ font-size: var(--nwl-text-md);
16
+ }
17
+
18
+ :where(body) {
19
+ margin: 0;
20
+ }
21
+
22
+ :where(.app) {
23
+ box-sizing: border-box;
24
+ font-family: var(--nwl-font-body);
25
+ font-size: var(--nwl-text-md);
26
+ color: var(--nwl-text);
27
+ }
28
+
29
+ :where(.app) *,
30
+ :where(.app) *::before,
31
+ :where(.app) *::after {
32
+ box-sizing: inherit;
33
+ }
34
+
35
+ /* Elements the browser gives a size of their own (headings, small print, code, form controls)
36
+ take their parent's, as 1.x's `*` rule made them do. */
37
+ :where(.app) :where(h1, h2, h3, h4, h5, h6, small, sub, sup, big, code, kbd, samp, pre, tt, button, input, select, textarea) {
38
+ font-size: inherit;
39
+ }
40
+
41
+ /* Form controls and dialogs don't inherit the colour by default either. The controls' font
42
+ family stays the browser's, as it was in 1.x. */
43
+ :where(.app) :where(button, input, select, textarea, dialog) {
44
+ color: inherit;
45
+ }
46
+
47
+ /* links: the link colour, not the browser's blue */
48
+ :where(.app a) {
49
+ color: var(--nwl-link);
50
+ }
51
+
52
+ /* Keyboard focus: a 2px outline in --nwl-focus. Mouse focus shows nothing (browsers match
53
+ :focus-visible on a mouse click only for text fields). */
54
+ :where(.app :focus-visible) {
55
+ outline: 2px solid var(--nwl-focus);
56
+ outline-offset: 2px;
57
+ }
58
+ }
package/dist/base.css ADDED
@@ -0,0 +1,58 @@
1
+ @layer nwl.base, nwl.widgets, nwl.components;
2
+ @layer nwl.base {
3
+ /* nwl-components base styles: `import 'nwl-components/base.css'` (after `nwl-components/tokens.css`,
4
+ whose tokens it reads). dist/style.css includes it.
5
+
6
+ The build puts this file in `@layer nwl.base`, the lowest of the library's layers
7
+ (`@layer nwl.base, nwl.widgets, nwl.components`), so any app rule wins over it. Selectors are
8
+ wrapped in :where(), so they add no specificity.
9
+
10
+ Font and colour are set once, on the wrapper (`.app`, the root of `Wrapper`), and inherited:
11
+ there is no `*` rule setting them on every element. */
12
+
13
+ /* 1rem = 14px, as in 1.x (where the `*` rule set it on <html>): the components' rem sizes */
14
+ :where(html) {
15
+ font-size: var(--nwl-text-md);
16
+ }
17
+
18
+ :where(body) {
19
+ margin: 0;
20
+ }
21
+
22
+ :where(.app) {
23
+ box-sizing: border-box;
24
+ font-family: var(--nwl-font-body);
25
+ font-size: var(--nwl-text-md);
26
+ color: var(--nwl-text);
27
+ }
28
+
29
+ :where(.app) *,
30
+ :where(.app) *::before,
31
+ :where(.app) *::after {
32
+ box-sizing: inherit;
33
+ }
34
+
35
+ /* Elements the browser gives a size of their own (headings, small print, code, form controls)
36
+ take their parent's, as 1.x's `*` rule made them do. */
37
+ :where(.app) :where(h1, h2, h3, h4, h5, h6, small, sub, sup, big, code, kbd, samp, pre, tt, button, input, select, textarea) {
38
+ font-size: inherit;
39
+ }
40
+
41
+ /* Form controls and dialogs don't inherit the colour by default either. The controls' font
42
+ family stays the browser's, as it was in 1.x. */
43
+ :where(.app) :where(button, input, select, textarea, dialog) {
44
+ color: inherit;
45
+ }
46
+
47
+ /* links: the link colour, not the browser's blue */
48
+ :where(.app a) {
49
+ color: var(--nwl-link);
50
+ }
51
+
52
+ /* Keyboard focus: a 2px outline in --nwl-focus. Mouse focus shows nothing (browsers match
53
+ :focus-visible on a mouse click only for text fields). */
54
+ :where(.app :focus-visible) {
55
+ outline: 2px solid var(--nwl-focus);
56
+ outline-offset: 2px;
57
+ }
58
+ }