nwl-components 1.8.0 → 2.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/README.md +132 -0
- package/base.css +63 -0
- package/dist/base.css +63 -0
- package/dist/nwl-components.es.js +683 -676
- package/dist/nwl-components.umd.js +6 -6
- package/dist/sort/style.css +14 -5
- package/dist/style.css +2 -1
- package/dist/tokens.css +9 -3
- package/dist/widgets.css +172 -0
- package/package.json +20 -2
- package/sort/style.css +14 -5
- package/tokens.css +9 -3
- package/widgets.css +172 -0
package/README.md
CHANGED
|
@@ -193,6 +193,138 @@ Loading the tokens twice on a page (e.g. `tokens.css` and `dist/style.css`) is h
|
|
|
193
193
|
`npm run lint` fails on a hex colour in `src/**/*.{vue,css}` outside `tokens.css`, and on a
|
|
194
194
|
`var(--nwl-…)` that `tokens.css` doesn't define. Since 1.8.0.
|
|
195
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`: `src/styles/widgets.css`, the widget classes (see "Widgets");
|
|
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
|
+
|
|
248
|
+
## Widgets
|
|
249
|
+
|
|
250
|
+
Since 2.1.0, `src/styles/widgets.css` holds class-based widgets for markup that isn't Vue
|
|
251
|
+
(Mustache pages, the viewers' tool panels); the library's `Button` uses them too. They are in
|
|
252
|
+
`@layer nwl.widgets` and every selector is wrapped in `:where()`, so **an app rule with one
|
|
253
|
+
class wins** over them. Colours, borders and radii come from the semantic tokens.
|
|
254
|
+
|
|
255
|
+
State is an ARIA attribute, not a class, so screen readers get it too: `aria-pressed="true"` on
|
|
256
|
+
a tool button that is on, `aria-selected="true"` on a selected table row, `disabled` (or
|
|
257
|
+
`aria-disabled="true"` on a link) on a button. The apps' classes (`.pressed`, `.mui-pressed`,
|
|
258
|
+
`.selected`) don't style the widgets.
|
|
259
|
+
|
|
260
|
+
Push button (Save, Cancel): 1px `--nwl-border-strong` outline, `--nwl-radius-md`, bold, on a
|
|
261
|
+
`<button>`, `<a>`, `<select>` or `<input type="button|submit">`. Hover: `--nwl-bg-pressed`;
|
|
262
|
+
disabled: opacity .4.
|
|
263
|
+
|
|
264
|
+
```html
|
|
265
|
+
<button class="nwl-push-button">Save</button>
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Tool button (a viewer's tool panel): 24px high, 1px `--nwl-border`, `--nwl-radius-sm`; it fills
|
|
269
|
+
its container's width, less its 1px margins, as the apps' div tools did. On a native `<button>`
|
|
270
|
+
it is in the tab order with no script. Pressed: `aria-pressed="true"` gives `--nwl-bg-pressed`.
|
|
271
|
+
Hover: `--nwl-bg-pressed` on a text button, opacity .5 on a button whose only element is an
|
|
272
|
+
icon (`img`, `svg` or `.nwl-icon`; CSS can't see text, so a button with an icon and text counts
|
|
273
|
+
as an icon button). `.nwl-tool-button--sub`: a tool inside a group (no border, 22px).
|
|
274
|
+
|
|
275
|
+
```html
|
|
276
|
+
<div style="flex: 1"><button class="nwl-tool-button" aria-pressed="true">Sag</button></div>
|
|
277
|
+
<div style="flex: 1">
|
|
278
|
+
<button class="nwl-tool-button" aria-pressed="false" aria-label="Full screen">
|
|
279
|
+
<img class="nwl-icon" src="/img/fullscreen.svg" alt="">
|
|
280
|
+
</button>
|
|
281
|
+
</div>
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Icon button: an icon with no border; opacity .5 on hover. It shows no text, so give it an
|
|
285
|
+
accessible name with `aria-label`, and an empty `alt` to its image.
|
|
286
|
+
|
|
287
|
+
```html
|
|
288
|
+
<button class="nwl-icon-button" aria-label="Zoom in"><img class="nwl-icon" src="/img/zoomIn.svg" alt=""></button>
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Icon: 16px, aligned with the text (`vertical-align: middle`), not selectable.
|
|
292
|
+
|
|
293
|
+
```html
|
|
294
|
+
<img class="nwl-icon" src="/img/home.svg" alt="Home">
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Text field (`<input>`, `<textarea>`): its parent's font size and colour, `--nwl-bg-input`, 1px
|
|
298
|
+
`--nwl-border`, `--nwl-radius-sm`, no padding (as the apps' `.text`), placeholder in
|
|
299
|
+
`--nwl-text-placeholder`.
|
|
300
|
+
|
|
301
|
+
```html
|
|
302
|
+
<input class="nwl-text-field" placeholder="Project name">
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Selected row: `aria-selected="true"` on a `<tr>` gives `--nwl-bg-elevated`.
|
|
306
|
+
|
|
307
|
+
```html
|
|
308
|
+
<tr aria-selected="true"><td>axolotl</td></tr>
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Keyboard focus on the widgets shows `base.css`'s outline (2px `--nwl-focus`), also outside
|
|
312
|
+
`.app`. Links take `--nwl-link` (hover `--nwl-link-hover`), both the text colour: keep their
|
|
313
|
+
underline (the browser's) where they sit in text, so they don't depend on colour alone.
|
|
314
|
+
|
|
315
|
+
`dist/style.css` includes the widgets. A page with no bundle links the three files, in this
|
|
316
|
+
order (microdraw serves `node_modules/nwl-components/dist/` as `/lib/nwl-components/`):
|
|
317
|
+
|
|
318
|
+
```html
|
|
319
|
+
<link rel="stylesheet" href="/lib/nwl-components/tokens.css">
|
|
320
|
+
<link rel="stylesheet" href="/lib/nwl-components/base.css">
|
|
321
|
+
<link rel="stylesheet" href="/lib/nwl-components/widgets.css">
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
With a bundler: `import 'nwl-components/widgets.css'` after the tokens and base (webpack 4 too:
|
|
325
|
+
a copy at the package root). Storybook's `Library/Widgets` shows each widget in plain HTML, with
|
|
326
|
+
its states.
|
|
327
|
+
|
|
196
328
|
## Single File Components
|
|
197
329
|
|
|
198
330
|
This project makes use of Vue SFCs: _Single File Components_, that have the `.vue` extension.
|
package/base.css
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
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. The browser's underline stays: links are
|
|
48
|
+
the text colour (--nwl-link), so the underline is what tells them apart (WCAG 1.4.1). */
|
|
49
|
+
:where(.app a) {
|
|
50
|
+
color: var(--nwl-link);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
:where(.app a:hover) {
|
|
54
|
+
color: var(--nwl-link-hover);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Keyboard focus: a 2px outline in --nwl-focus. Mouse focus shows nothing (browsers match
|
|
58
|
+
:focus-visible on a mouse click only for text fields). */
|
|
59
|
+
:where(.app :focus-visible) {
|
|
60
|
+
outline: 2px solid var(--nwl-focus);
|
|
61
|
+
outline-offset: 2px;
|
|
62
|
+
}
|
|
63
|
+
}
|
package/dist/base.css
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
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. The browser's underline stays: links are
|
|
48
|
+
the text colour (--nwl-link), so the underline is what tells them apart (WCAG 1.4.1). */
|
|
49
|
+
:where(.app a) {
|
|
50
|
+
color: var(--nwl-link);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
:where(.app a:hover) {
|
|
54
|
+
color: var(--nwl-link-hover);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Keyboard focus: a 2px outline in --nwl-focus. Mouse focus shows nothing (browsers match
|
|
58
|
+
:focus-visible on a mouse click only for text fields). */
|
|
59
|
+
:where(.app :focus-visible) {
|
|
60
|
+
outline: 2px solid var(--nwl-focus);
|
|
61
|
+
outline-offset: 2px;
|
|
62
|
+
}
|
|
63
|
+
}
|