@uncinq/css-components 1.16.3 → 1.16.5
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 +1 -0
- package/css/utilities/scrollsnap.css +1 -0
- package/docs/_index.md +0 -86
- package/docs/buttons/_index.md +1 -69
- package/docs/buttons/btn-close.md +1 -1
- package/docs/buttons/btn-filter.md +1 -1
- package/docs/buttons/btn-menu.md +1 -1
- package/docs/buttons/btn-search.md +1 -1
- package/docs/buttons/btn-share.md +1 -1
- package/docs/buttons/btn-toc.md +1 -1
- package/docs/buttons/btn-toggle-video.md +1 -1
- package/docs/buttons/btn.md +1 -1
- package/docs/buttons/overview.md +75 -0
- package/docs/cascade-layers.md +1 -1
- package/docs/content/_index.md +1 -33
- package/docs/content/alert.md +1 -1
- package/docs/content/badge.md +1 -1
- package/docs/content/banner.md +1 -1
- package/docs/content/card.md +1 -1
- package/docs/content/items.md +1 -1
- package/docs/content/list.md +1 -1
- package/docs/content/media.md +1 -1
- package/docs/content/overview.md +39 -0
- package/docs/content/surtitle.md +1 -1
- package/docs/embeds/_index.md +1 -19
- package/docs/embeds/embed.md +1 -1
- package/docs/embeds/map.md +1 -1
- package/docs/embeds/overview.md +25 -0
- package/docs/embeds/video.md +1 -1
- package/docs/forms/_index.md +1 -25
- package/docs/forms/form-check.md +2 -2
- package/docs/forms/form.md +2 -2
- package/docs/forms/overview.md +31 -0
- package/docs/navigation/_index.md +1 -23
- package/docs/navigation/breadcrumb.md +1 -1
- package/docs/navigation/nav-accessibility.md +1 -1
- package/docs/navigation/nav-title.md +1 -1
- package/docs/navigation/nav.md +1 -1
- package/docs/navigation/overview.md +29 -0
- package/docs/navigation/pagination.md +1 -1
- package/docs/overlays/_index.md +1 -28
- package/docs/overlays/drawer.md +1 -1
- package/docs/overlays/dropdown.md +1 -1
- package/docs/overlays/modal.md +1 -1
- package/docs/overlays/overview.md +34 -0
- package/docs/overlays/panel.md +1 -1
- package/docs/overview.md +93 -0
- package/docs/utilities/_index.md +1 -15
- package/docs/utilities/overview.md +21 -0
- package/docs/utilities/scrollsnap.md +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -81,6 +81,7 @@ Full documentation: **[socle.uncinq.dev/docs/css-components/](https://socle.unci
|
|
|
81
81
|
|
|
82
82
|
It is also versioned with the code in [`docs/`](docs/), one page per component, and ships inside the npm package, so it is readable offline and from `node_modules`:
|
|
83
83
|
|
|
84
|
+
- [Overview](docs/overview.md) — installation, import order, what the package leaves out
|
|
84
85
|
- [Cascade layers](docs/cascade-layers.md) — the two layers, and the `:where()` convention
|
|
85
86
|
- [Buttons](docs/buttons/) — [`.btn`](docs/buttons/btn.md) and the seven specialised buttons
|
|
86
87
|
- [Overlays](docs/overlays/) — [the panel skeleton](docs/overlays/panel.md), [`.modal`](docs/overlays/modal.md), [`.drawer`](docs/overlays/drawer.md), [`.dropdown`](docs/overlays/dropdown.md)
|
package/docs/_index.md
CHANGED
|
@@ -5,89 +5,3 @@ description: Framework-agnostic CSS component implementations, driven entirely b
|
|
|
5
5
|
weight: 5
|
|
6
6
|
icon: grid
|
|
7
7
|
---
|
|
8
|
-
|
|
9
|
-
`@uncinq/css-components` is the top of the stack: 29 components and 1 utility, written as plain CSS, reading their values from [@uncinq/component-tokens](../component-tokens/) and adding no values of their own.
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
@uncinq/design-tokens primitive + semantic values
|
|
13
|
-
@uncinq/component-tokens component-scoped values
|
|
14
|
-
@uncinq/css-base reset, native elements, layouts
|
|
15
|
-
@uncinq/css-components ← this package
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
Every rule lives in `@layer components`, except the scroll-snap utility which lives in `@layer utilities`. There is no build step, no preprocessor, and no JavaScript shipped in the package. Three components do expect a script you provide, and each one documents the contract it needs.
|
|
19
|
-
|
|
20
|
-
## The components
|
|
21
|
-
|
|
22
|
-
One page per component, grouped into six sections.
|
|
23
|
-
|
|
24
|
-
| Section | Components |
|
|
25
|
-
| --- | --- |
|
|
26
|
-
| [Buttons](buttons/) | [`.btn`](buttons/btn/), [`.btn-close`](buttons/btn-close/), [`.btn-menu`](buttons/btn-menu/), [`.btn-search`](buttons/btn-search/), [`.btn-filter`](buttons/btn-filter/), [`.btn-share`](buttons/btn-share/), [`.btn-toc`](buttons/btn-toc/), [`.btn-toggle-video`](buttons/btn-toggle-video/) |
|
|
27
|
-
| [Overlays](overlays/) | [panel](overlays/panel/), [`.modal`](overlays/modal/), [`.drawer`](overlays/drawer/), [`.dropdown`](overlays/dropdown/) |
|
|
28
|
-
| [Content](content/) | [`.alert`](content/alert/), [`.badge`](content/badge/), [`.banner`](content/banner/), [`.card`](content/card/), [`.items`](content/items/), [`.list`](content/list/), [`.media`](content/media/), [`.surtitle`](content/surtitle/) |
|
|
29
|
-
| [Navigation](navigation/) | [`.nav`](navigation/nav/), [`.nav-title`](navigation/nav-title/), [`.nav-accessibility`](navigation/nav-accessibility/), [`.breadcrumb-wrapper`](navigation/breadcrumb/), [`.pagination`](navigation/pagination/) |
|
|
30
|
-
| [Embeds](embeds/) | [`.embed`](embeds/embed/), [`.video`](embeds/video/), [`.map`](embeds/map/) |
|
|
31
|
-
| [Forms](forms/) | [`.form`](forms/form/), [`.form-check`](forms/form-check/) |
|
|
32
|
-
| [Utilities](utilities/) | [`.scrollsnap`](utilities/scrollsnap/) |
|
|
33
|
-
|
|
34
|
-
Read [Cascade layers](cascade-layers/) first if you are wiring this into a project for the first time.
|
|
35
|
-
|
|
36
|
-
## Installation
|
|
37
|
-
|
|
38
|
-
All three packages below are required. The tokens resolve the custom properties, and css-base provides the reset and the element styles the components build on.
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
npm install @uncinq/design-tokens @uncinq/component-tokens @uncinq/css-base @uncinq/css-components
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
```css
|
|
45
|
-
@layer reset, tokens, libs, base, vendors, layouts, components, pages, utilities;
|
|
46
|
-
|
|
47
|
-
@import '@uncinq/design-tokens'; /* @layer tokens */
|
|
48
|
-
@import '@uncinq/css-base'; /* @layer reset, base, layouts */
|
|
49
|
-
@import '@uncinq/component-tokens'; /* @layer tokens */
|
|
50
|
-
@import '@uncinq/css-components'; /* @layer components, utilities */
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Per component, when you only need a few:
|
|
54
|
-
|
|
55
|
-
```css
|
|
56
|
-
@import '@uncinq/css-components/css/components/button.css';
|
|
57
|
-
@import '@uncinq/css-components/css/components/alert.css';
|
|
58
|
-
@import '@uncinq/css-components/css/utilities/scrollsnap.css';
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### A CDN link is not enough
|
|
62
|
-
|
|
63
|
-
`@uncinq/design-tokens` and `@uncinq/component-tokens` can be linked straight from a CDN, because they emit nothing but custom properties. **This package cannot**, and neither can `@uncinq/css-base`.
|
|
64
|
-
|
|
65
|
-
Both ship `@media (--sm)` queries that rely on the `@custom-media` rules declared in `css-base/css/mediaqueries.css`, and no browser implements `@custom-media`. Loaded without [postcss-custom-media](https://www.npmjs.com/package/postcss-custom-media), 13 responsive blocks in this package are dropped: `.panel-inline-*`, `.panel-trigger-*` and every `.scrollsnap-*` variant.
|
|
66
|
-
|
|
67
|
-
The failure is silent. No error is raised, the page simply stays at its mobile values on every screen. A build step is required.
|
|
68
|
-
|
|
69
|
-
Note that `@uncinq/css-base` is a genuine prerequisite but is **not** declared in `peerDependencies`. Install it explicitly.
|
|
70
|
-
|
|
71
|
-
## Import order inside the package
|
|
72
|
-
|
|
73
|
-
`css/index.css` imports the components alphabetically, with two deliberate exceptions.
|
|
74
|
-
|
|
75
|
-
`components/button.css` comes **before** the seven `btn-*` files rather than after them, because five of those are modifiers on `.btn` and read better in that order.
|
|
76
|
-
|
|
77
|
-
`utilities/scrollsnap.css` comes after everything, in `@layer utilities`, because it has to win over the grid a component declares for itself in `@layer components`.
|
|
78
|
-
|
|
79
|
-
One constraint is easy to break when importing file by file: `panel.css` must come **after** `modal.css` and `drawer.css`. Alphabetical order already gives that, which is why nothing in the barrel looks unusual, but the `.panel-inline-*` variants beat the two host components on source order rather than on specificity. See [Cascade layers](cascade-layers/).
|
|
80
|
-
|
|
81
|
-
## What this package does not include
|
|
82
|
-
|
|
83
|
-
**No JavaScript.** `.modal`, `.drawer` and `.dropdown` expect a script. The CSS defines the classes and attributes that script must toggle, and each page documents the contract.
|
|
84
|
-
|
|
85
|
-
**No `.item`.** Despite what a couple of source comments still suggest, `.item` is not defined here. It lives in the Hugolify design system theme. This package ships `.card`, a complete implementation in its own right, and `.items`, a grid whose children you provide. See [Content](content/).
|
|
86
|
-
|
|
87
|
-
**No icons for `.icon`.** Components that draw a glyph, the [buttons](buttons/) and [`.pagination`](navigation/pagination/), mask it from an icon token. An `.icon` element you place inside an [alert](content/alert/) or a [video toggle](buttons/btn-toggle-video/) is the theme's to render.
|
|
88
|
-
|
|
89
|
-
## References
|
|
90
|
-
|
|
91
|
-
- [@uncinq/component-tokens](https://github.com/uncinq/component-tokens), the values these components read
|
|
92
|
-
- [@uncinq/css-base](https://github.com/uncinq/css-base), the foundation underneath
|
|
93
|
-
- [MDN: CSS cascade layers](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Cascade_layers)
|
package/docs/buttons/_index.md
CHANGED
|
@@ -2,74 +2,6 @@
|
|
|
2
2
|
isIndex: false
|
|
3
3
|
title: Buttons
|
|
4
4
|
description: The .btn base class with its colour, size and style variants, and the seven specialised buttons built on it.
|
|
5
|
-
weight:
|
|
5
|
+
weight: 3
|
|
6
6
|
icon: hand-index
|
|
7
7
|
---
|
|
8
|
-
|
|
9
|
-
Eight files: one base class, and seven single-purpose buttons.
|
|
10
|
-
|
|
11
|
-
| Page | Class | Needs `.btn` |
|
|
12
|
-
| --- | --- | --- |
|
|
13
|
-
| [Button](btn/) | `.btn` | — |
|
|
14
|
-
| [Close button](btn-close/) | `.btn-close` | no |
|
|
15
|
-
| [Menu button](btn-menu/) | `.btn-menu` | no |
|
|
16
|
-
| [Search button](btn-search/) | `.btn-search` | yes |
|
|
17
|
-
| [Filter button](btn-filter/) | `.btn-filter` | yes |
|
|
18
|
-
| [Share button](btn-share/) | `.btn-share` | yes |
|
|
19
|
-
| [Table of contents button](btn-toc/) | `.btn-toc` | yes |
|
|
20
|
-
| [Video toggle](btn-toggle-video/) | `.btn-toggle-video` | yes |
|
|
21
|
-
|
|
22
|
-
## Two kinds of specialised button
|
|
23
|
-
|
|
24
|
-
Read the third column before using one, because the two kinds behave differently when the base class is missing.
|
|
25
|
-
|
|
26
|
-
`.btn-close` and `.btn-menu` **redeclare everything they need**. Each `--btn-close-*` and `--btn-menu-*` token falls back to the matching `--btn-*` one, so they look consistent with `.btn` without depending on it. Use them on their own.
|
|
27
|
-
|
|
28
|
-
The other five are **modifiers**. They declare nothing but `--btn-color-*` reassignments and an icon, so omitting `.btn` leaves them almost entirely unstyled.
|
|
29
|
-
|
|
30
|
-
```html
|
|
31
|
-
<!-- self-contained -->
|
|
32
|
-
<button class="btn-close" aria-label="Close"></button>
|
|
33
|
-
|
|
34
|
-
<!-- modifier on .btn -->
|
|
35
|
-
<button class="btn btn-search" aria-label="Search"></button>
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## The icons are masks, not images
|
|
39
|
-
|
|
40
|
-
Six of the seven ship their glyph, drawn on `::before` from the icon tokens in [@uncinq/design-tokens](../../design-tokens/reference/#icon):
|
|
41
|
-
|
|
42
|
-
```css
|
|
43
|
-
&::before {
|
|
44
|
-
background-color: currentColor;
|
|
45
|
-
mask: var(--icon-search) center / var(--btn-search-icon-size, var(--icon-size)) no-repeat;
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Because it is a mask over a background colour rather than a background image, the glyph takes `currentColor` and follows the button's text colour through every state, including hover and disabled. Size it globally with `--icon-size`, or per button with `--btn-close-icon-size` and its siblings.
|
|
50
|
-
|
|
51
|
-
`.btn` publishes `--icon-size: var(--btn-font-size)`, so a modifier button scales with its size class for free. A bare `.btn-close` or `.btn-menu` has no such declaration above it and takes whatever `--icon-size` is in scope.
|
|
52
|
-
|
|
53
|
-
[`.btn-toggle-video`](btn-toggle-video/) is the exception: it ships no icon and expects two child elements instead.
|
|
54
|
-
|
|
55
|
-
## None of them names itself
|
|
56
|
-
|
|
57
|
-
When a button has no visible text, give it an accessible name with `aria-label`, or a `.visually-hidden` span from [css-base](../../css-base/base/#accessibility-helpers). No button in this package provides one.
|
|
58
|
-
|
|
59
|
-
## Focus and disabled states
|
|
60
|
-
|
|
61
|
-
`.btn` declares both:
|
|
62
|
-
|
|
63
|
-
```css
|
|
64
|
-
&:focus-visible {
|
|
65
|
-
outline: var(--focus-outline-width) var(--focus-outline-style) var(--focus-color-outline);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
&:disabled,
|
|
69
|
-
&[aria-disabled='true'] {
|
|
70
|
-
cursor: not-allowed;
|
|
71
|
-
opacity: var(--opacity-disabled);
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
The five modifiers inherit that through the base class. **`.btn-close` and `.btn-menu` declare neither**, so they fall back to the browser's own focus ring rather than the design system's, and a disabled one looks no different from an enabled one. Add `.btn` alongside them when either matters.
|
package/docs/buttons/btn-menu.md
CHANGED
package/docs/buttons/btn-toc.md
CHANGED
package/docs/buttons/btn.md
CHANGED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
isIndex: false
|
|
3
|
+
title: Overview
|
|
4
|
+
description: The eight button files, the two kinds of specialised button, and the masked icons they share.
|
|
5
|
+
weight: 1
|
|
6
|
+
icon: book
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Eight files: one base class, and seven single-purpose buttons.
|
|
10
|
+
|
|
11
|
+
| Page | Class | Needs `.btn` |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| [Button](../btn/) | `.btn` | — |
|
|
14
|
+
| [Close button](../btn-close/) | `.btn-close` | no |
|
|
15
|
+
| [Menu button](../btn-menu/) | `.btn-menu` | no |
|
|
16
|
+
| [Search button](../btn-search/) | `.btn-search` | yes |
|
|
17
|
+
| [Filter button](../btn-filter/) | `.btn-filter` | yes |
|
|
18
|
+
| [Share button](../btn-share/) | `.btn-share` | yes |
|
|
19
|
+
| [Table of contents button](../btn-toc/) | `.btn-toc` | yes |
|
|
20
|
+
| [Video toggle](../btn-toggle-video/) | `.btn-toggle-video` | yes |
|
|
21
|
+
|
|
22
|
+
## Two kinds of specialised button
|
|
23
|
+
|
|
24
|
+
Read the third column before using one, because the two kinds behave differently when the base class is missing.
|
|
25
|
+
|
|
26
|
+
`.btn-close` and `.btn-menu` **redeclare everything they need**. Each `--btn-close-*` and `--btn-menu-*` token falls back to the matching `--btn-*` one, so they look consistent with `.btn` without depending on it. Use them on their own.
|
|
27
|
+
|
|
28
|
+
The other five are **modifiers**. They declare nothing but `--btn-color-*` reassignments and an icon, so omitting `.btn` leaves them almost entirely unstyled.
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<!-- self-contained -->
|
|
32
|
+
<button class="btn-close" aria-label="Close"></button>
|
|
33
|
+
|
|
34
|
+
<!-- modifier on .btn -->
|
|
35
|
+
<button class="btn btn-search" aria-label="Search"></button>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## The icons are masks, not images
|
|
39
|
+
|
|
40
|
+
Six of the seven ship their glyph, drawn on `::before` from the icon tokens in [@uncinq/design-tokens](../../../design-tokens/reference/#icon):
|
|
41
|
+
|
|
42
|
+
```css
|
|
43
|
+
&::before {
|
|
44
|
+
background-color: currentColor;
|
|
45
|
+
mask: var(--icon-search) center / var(--btn-search-icon-size, var(--icon-size)) no-repeat;
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Because it is a mask over a background colour rather than a background image, the glyph takes `currentColor` and follows the button's text colour through every state, including hover and disabled. Size it globally with `--icon-size`, or per button with `--btn-close-icon-size` and its siblings.
|
|
50
|
+
|
|
51
|
+
`.btn` publishes `--icon-size: var(--btn-font-size)`, so a modifier button scales with its size class for free. A bare `.btn-close` or `.btn-menu` has no such declaration above it and takes whatever `--icon-size` is in scope.
|
|
52
|
+
|
|
53
|
+
[`.btn-toggle-video`](../btn-toggle-video/) is the exception: it ships no icon and expects two child elements instead.
|
|
54
|
+
|
|
55
|
+
## None of them names itself
|
|
56
|
+
|
|
57
|
+
When a button has no visible text, give it an accessible name with `aria-label`, or a `.visually-hidden` span from [css-base](../../../css-base/base/accessibility/). No button in this package provides one.
|
|
58
|
+
|
|
59
|
+
## Focus and disabled states
|
|
60
|
+
|
|
61
|
+
`.btn` declares both:
|
|
62
|
+
|
|
63
|
+
```css
|
|
64
|
+
&:focus-visible {
|
|
65
|
+
outline: var(--focus-outline-width) var(--focus-outline-style) var(--focus-color-outline);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
&:disabled,
|
|
69
|
+
&[aria-disabled='true'] {
|
|
70
|
+
cursor: not-allowed;
|
|
71
|
+
opacity: var(--opacity-disabled);
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The five modifiers inherit that through the base class. **`.btn-close` and `.btn-menu` declare neither**, so they fall back to the browser's own focus ring rather than the design system's, and a disabled one looks no different from an enabled one. Add `.btn` alongside them when either matters.
|
package/docs/cascade-layers.md
CHANGED
package/docs/content/_index.md
CHANGED
|
@@ -2,38 +2,6 @@
|
|
|
2
2
|
isIndex: false
|
|
3
3
|
title: Content
|
|
4
4
|
description: Alerts, badges, banners, cards, the items grid, labelled lists, media objects and surtitles.
|
|
5
|
-
weight:
|
|
5
|
+
weight: 5
|
|
6
6
|
icon: card-text
|
|
7
7
|
---
|
|
8
|
-
|
|
9
|
-
Eight components for laying out page content.
|
|
10
|
-
|
|
11
|
-
| Page | Class | Purpose |
|
|
12
|
-
| --- | --- | --- |
|
|
13
|
-
| [Alert](alert/) | `.alert` | An inline notification block |
|
|
14
|
-
| [Badge](badge/) | `.badge` | A small inline label |
|
|
15
|
-
| [Banner](banner/) | `.banner` | A centred modifier on `.alert` |
|
|
16
|
-
| [Card](card/) | `.card` | A self-contained content card |
|
|
17
|
-
| [Items](items/) | `.items` | The responsive grid that holds cards |
|
|
18
|
-
| [List](list/) | `.list` | A compact labelled list |
|
|
19
|
-
| [Media](media/) | `.media` | The structural base for images and video |
|
|
20
|
-
| [Surtitle](surtitle/) | `.surtitle` | An eyebrow label above a heading |
|
|
21
|
-
|
|
22
|
-
## Three of them are meant to nest
|
|
23
|
-
|
|
24
|
-
`.items` holds `.card`, a card holds a `.media`, and a `.surtitle` sits above the card's title. Each one reassigns the next one's tokens from its own namespace, so a media block or a surtitle adapts to its context without a variant class. The [card page](card/) covers what it hands down.
|
|
25
|
-
|
|
26
|
-
{{< alert-block state="info" >}}
|
|
27
|
-
Several source comments describe `.card` as a backwards-compatible alias for `.item` and recommend using `.item` directly. That is misleading for anyone consuming this package on its own: **`.item` is not defined here**. It lives in the Hugolify design system theme. Within `@uncinq/css-components`, `.card` is a complete implementation and the class to use.
|
|
28
|
-
{{< /alert-block >}}
|
|
29
|
-
|
|
30
|
-
## Colour variants follow one of two patterns
|
|
31
|
-
|
|
32
|
-
`.alert` and `.badge` both ship the same ten intent names, and they resolve them differently.
|
|
33
|
-
|
|
34
|
-
| | Background | Text |
|
|
35
|
-
| --- | --- | --- |
|
|
36
|
-
| `.alert-*` | `--color-*-muted` | `--color-*-strong` |
|
|
37
|
-
| `.badge-*` | `--color-*` | `--color-text-on-*` |
|
|
38
|
-
|
|
39
|
-
An alert is a tinted block meant to hold a paragraph, so it uses the muted pair. A badge is a solid chip meant to be read at a glance, so it uses the full colour with its guaranteed-contrast text token. Neither ever hardcodes a colour, which is what makes a rebrand a token change rather than a search and replace.
|
package/docs/content/alert.md
CHANGED
package/docs/content/badge.md
CHANGED
package/docs/content/banner.md
CHANGED
package/docs/content/card.md
CHANGED
package/docs/content/items.md
CHANGED
package/docs/content/list.md
CHANGED
package/docs/content/media.md
CHANGED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
isIndex: false
|
|
3
|
+
title: Overview
|
|
4
|
+
description: The eight content components, the three that are meant to nest, and the two colour patterns they follow.
|
|
5
|
+
weight: 1
|
|
6
|
+
icon: book
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Eight components for laying out page content.
|
|
10
|
+
|
|
11
|
+
| Page | Class | Purpose |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| [Alert](../alert/) | `.alert` | An inline notification block |
|
|
14
|
+
| [Badge](../badge/) | `.badge` | A small inline label |
|
|
15
|
+
| [Banner](../banner/) | `.banner` | A centred modifier on `.alert` |
|
|
16
|
+
| [Card](../card/) | `.card` | A self-contained content card |
|
|
17
|
+
| [Items](../items/) | `.items` | The responsive grid that holds cards |
|
|
18
|
+
| [List](../list/) | `.list` | A compact labelled list |
|
|
19
|
+
| [Media](../media/) | `.media` | The structural base for images and video |
|
|
20
|
+
| [Surtitle](../surtitle/) | `.surtitle` | An eyebrow label above a heading |
|
|
21
|
+
|
|
22
|
+
## Three of them are meant to nest
|
|
23
|
+
|
|
24
|
+
`.items` holds `.card`, a card holds a `.media`, and a `.surtitle` sits above the card's title. Each one reassigns the next one's tokens from its own namespace, so a media block or a surtitle adapts to its context without a variant class. The [card page](../card/) covers what it hands down.
|
|
25
|
+
|
|
26
|
+
{{< alert-block state="info" >}}
|
|
27
|
+
Several source comments describe `.card` as a backwards-compatible alias for `.item` and recommend using `.item` directly. That is misleading for anyone consuming this package on its own: **`.item` is not defined here**. It lives in the Hugolify design system theme. Within `@uncinq/css-components`, `.card` is a complete implementation and the class to use.
|
|
28
|
+
{{< /alert-block >}}
|
|
29
|
+
|
|
30
|
+
## Colour variants follow one of two patterns
|
|
31
|
+
|
|
32
|
+
`.alert` and `.badge` both ship the same ten intent names, and they resolve them differently.
|
|
33
|
+
|
|
34
|
+
| | Background | Text |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| `.alert-*` | `--color-*-muted` | `--color-*-strong` |
|
|
37
|
+
| `.badge-*` | `--color-*` | `--color-text-on-*` |
|
|
38
|
+
|
|
39
|
+
An alert is a tinted block meant to hold a paragraph, so it uses the muted pair. A badge is a solid chip meant to be read at a glance, so it uses the full colour with its guaranteed-contrast text token. Neither ever hardcodes a colour, which is what makes a rebrand a token change rather than a search and replace.
|
package/docs/content/surtitle.md
CHANGED
package/docs/embeds/_index.md
CHANGED
|
@@ -2,24 +2,6 @@
|
|
|
2
2
|
isIndex: false
|
|
3
3
|
title: Embeds
|
|
4
4
|
description: Aspect-ratio wrappers for third-party embeds, native video and maps.
|
|
5
|
-
weight:
|
|
5
|
+
weight: 7
|
|
6
6
|
icon: play-btn
|
|
7
7
|
---
|
|
8
|
-
|
|
9
|
-
Three containers, all built on the same idea: hold the space before the content arrives.
|
|
10
|
-
|
|
11
|
-
| Page | Class | For |
|
|
12
|
-
| --- | --- | --- |
|
|
13
|
-
| [Embed](embed/) | `.embed` | Third-party iframes, players, social cards |
|
|
14
|
-
| [Video](video/) | `.video` | A native `<video>`, with an optional pause control |
|
|
15
|
-
| [Map](map/) | `.map` | A Leaflet map container |
|
|
16
|
-
|
|
17
|
-
## They all reserve an aspect ratio
|
|
18
|
-
|
|
19
|
-
An iframe, a video or a map that sizes itself once its content loads pushes the rest of the page down at an unpredictable moment. Each of these components declares `aspect-ratio` from a token, so the box exists at its final size from the first paint.
|
|
20
|
-
|
|
21
|
-
That is also why all three set `overflow: hidden`: the content is stretched to fill a box whose proportions it did not choose.
|
|
22
|
-
|
|
23
|
-
## They stop at the container
|
|
24
|
-
|
|
25
|
-
None of the three ships the thing it wraps. `.embed` gives you no player, `.video` gives you no controls beyond the [toggle button](../buttons/btn-toggle-video/), and `.map` gives you neither Leaflet nor its stylesheet. Loading those, and keeping them out of your own layers, is the consuming project's job. See [Cascade layers](../cascade-layers/) for where third-party CSS belongs.
|
package/docs/embeds/embed.md
CHANGED
package/docs/embeds/map.md
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
isIndex: false
|
|
3
|
+
title: Overview
|
|
4
|
+
description: Three containers that reserve their aspect ratio before the content arrives, and stop at the container.
|
|
5
|
+
weight: 1
|
|
6
|
+
icon: book
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Three containers, all built on the same idea: hold the space before the content arrives.
|
|
10
|
+
|
|
11
|
+
| Page | Class | For |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| [Embed](../embed/) | `.embed` | Third-party iframes, players, social cards |
|
|
14
|
+
| [Video](../video/) | `.video` | A native `<video>`, with an optional pause control |
|
|
15
|
+
| [Map](../map/) | `.map` | A Leaflet map container |
|
|
16
|
+
|
|
17
|
+
## They all reserve an aspect ratio
|
|
18
|
+
|
|
19
|
+
An iframe, a video or a map that sizes itself once its content loads pushes the rest of the page down at an unpredictable moment. Each of these components declares `aspect-ratio` from a token, so the box exists at its final size from the first paint.
|
|
20
|
+
|
|
21
|
+
That is also why all three set `overflow: hidden`: the content is stretched to fill a box whose proportions it did not choose.
|
|
22
|
+
|
|
23
|
+
## They stop at the container
|
|
24
|
+
|
|
25
|
+
None of the three ships the thing it wraps. `.embed` gives you no player, `.video` gives you no controls beyond the [toggle button](../../buttons/btn-toggle-video/), and `.map` gives you neither Leaflet nor its stylesheet. Loading those, and keeping them out of your own layers, is the consuming project's job. See [Cascade layers](../../cascade-layers/) for where third-party CSS belongs.
|
package/docs/embeds/video.md
CHANGED
package/docs/forms/_index.md
CHANGED
|
@@ -2,30 +2,6 @@
|
|
|
2
2
|
isIndex: false
|
|
3
3
|
title: Forms
|
|
4
4
|
description: The .form grid, the .form-check row, and where the actual control styling lives.
|
|
5
|
-
weight:
|
|
5
|
+
weight: 8
|
|
6
6
|
icon: ui-checks
|
|
7
7
|
---
|
|
8
|
-
|
|
9
|
-
Form **controls** are styled by [@uncinq/css-base](../../css-base/base/#forms), on the native elements themselves. There is no `.input` or `.select` class to apply.
|
|
10
|
-
|
|
11
|
-
This package adds only what css-base cannot: the layout around those controls.
|
|
12
|
-
|
|
13
|
-
| Page | Class | Covers |
|
|
14
|
-
| --- | --- | --- |
|
|
15
|
-
| [Form](form/) | `.form` | The two-column grid and its layout helpers |
|
|
16
|
-
| [Check row](form-check/) | `.form-check` | A checkbox or radio laid out beside its label |
|
|
17
|
-
|
|
18
|
-
Both live in `components/form.css`.
|
|
19
|
-
|
|
20
|
-
## Accessibility
|
|
21
|
-
|
|
22
|
-
Nothing here supplies an accessible name. Every control needs a `<label for>` pointing at its `id`, or a `.visually-hidden` label when the design has no room for a visible one.
|
|
23
|
-
|
|
24
|
-
Tie `.help` text to its field with `aria-describedby`, otherwise it is visible but never announced:
|
|
25
|
-
|
|
26
|
-
```html
|
|
27
|
-
<input id="message" aria-describedby="message-help">
|
|
28
|
-
<p class="help" id="message-help">Markdown is supported.</p>
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
For error states, use `aria-invalid="true"` on the control and point `aria-describedby` at the error message.
|
package/docs/forms/form-check.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
isIndex: false
|
|
3
3
|
title: Check row
|
|
4
4
|
description: A checkbox or radio laid out beside its label, and why the class is only one declaration.
|
|
5
|
-
weight:
|
|
5
|
+
weight: 3
|
|
6
6
|
icon: check-square
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -21,7 +21,7 @@ A checkbox or radio laid out inline with its label.
|
|
|
21
21
|
.form-check { display: flex; }
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
That is the entire rule, and it is deliberate. The control's appearance, its size, and the gap between it and the adjacent label all come from [css-base](../../../css-base/base
|
|
24
|
+
That is the entire rule, and it is deliberate. The control's appearance, its size, and the gap between it and the adjacent label all come from [css-base](../../../css-base/base/form-checkbox/), which styles `[type='checkbox'] + label` directly on the native elements.
|
|
25
25
|
|
|
26
26
|
So the only thing missing from a bare input and label is that they sit on separate lines by default. This class fixes that, and stays out of everything else.
|
|
27
27
|
|
package/docs/forms/form.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
isIndex: false
|
|
3
3
|
title: Form
|
|
4
4
|
description: A responsive grid that is one column or two, never three, plus its layout helpers.
|
|
5
|
-
weight:
|
|
5
|
+
weight: 2
|
|
6
6
|
icon: columns-gap
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -64,4 +64,4 @@ Both axes use `--gap`, the same token the grid uses for its column calculation.
|
|
|
64
64
|
|
|
65
65
|
## Controls are not styled here
|
|
66
66
|
|
|
67
|
-
Inputs, selects, textareas and their focus and invalid states come from [css-base](../../../css-base/base
|
|
67
|
+
Inputs, selects, textareas and their focus and invalid states come from [css-base](../../../css-base/base/form/), applied to the native elements. This file adds layout and nothing else, which is why a form built without `.form` still looks right, it is simply stacked.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
isIndex: false
|
|
3
|
+
title: Overview
|
|
4
|
+
description: The two form layout components, why the controls themselves are styled elsewhere, and the accessible names none of it supplies.
|
|
5
|
+
weight: 1
|
|
6
|
+
icon: book
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Form **controls** are styled by [@uncinq/css-base](../../../css-base/base/form/), on the native elements themselves. There is no `.input` or `.select` class to apply.
|
|
10
|
+
|
|
11
|
+
This package adds only what css-base cannot: the layout around those controls.
|
|
12
|
+
|
|
13
|
+
| Page | Class | Covers |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| [Form](../form/) | `.form` | The two-column grid and its layout helpers |
|
|
16
|
+
| [Check row](../form-check/) | `.form-check` | A checkbox or radio laid out beside its label |
|
|
17
|
+
|
|
18
|
+
Both live in `components/form.css`.
|
|
19
|
+
|
|
20
|
+
## Accessibility
|
|
21
|
+
|
|
22
|
+
Nothing here supplies an accessible name. Every control needs a `<label for>` pointing at its `id`, or a `.visually-hidden` label when the design has no room for a visible one.
|
|
23
|
+
|
|
24
|
+
Tie `.help` text to its field with `aria-describedby`, otherwise it is visible but never announced:
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<input id="message" aria-describedby="message-help">
|
|
28
|
+
<p class="help" id="message-help">Markdown is supported.</p>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
For error states, use `aria-invalid="true"` on the control and point `aria-describedby` at the error message.
|
|
@@ -2,28 +2,6 @@
|
|
|
2
2
|
isIndex: false
|
|
3
3
|
title: Navigation
|
|
4
4
|
description: Navigation lists, navigation titles, skip links, breadcrumbs and pagination.
|
|
5
|
-
weight:
|
|
5
|
+
weight: 6
|
|
6
6
|
icon: signpost
|
|
7
7
|
---
|
|
8
|
-
|
|
9
|
-
Five components for moving around a site.
|
|
10
|
-
|
|
11
|
-
| Page | Class | Purpose |
|
|
12
|
-
| --- | --- | --- |
|
|
13
|
-
| [Nav](nav/) | `.nav` | The base navigation list |
|
|
14
|
-
| [Nav title](nav-title/) | `.nav-title` | A label above a group of links |
|
|
15
|
-
| [Skip links](nav-accessibility/) | `.nav-accessibility` | Skip navigation for keyboard and assistive technology |
|
|
16
|
-
| [Breadcrumb](breadcrumb/) | `.breadcrumb-wrapper` | The breadcrumb trail |
|
|
17
|
-
| [Pagination](pagination/) | `.pagination` | Page navigation |
|
|
18
|
-
|
|
19
|
-
## Two of them take the class on the wrapper
|
|
20
|
-
|
|
21
|
-
`.breadcrumb-wrapper` goes on the `<nav>`, not on the `<ol>` inside it. `.nav-accessibility` goes on the list itself, but only alongside `.nav`. Neither is guessable from the name, so check the page before writing the markup.
|
|
22
|
-
|
|
23
|
-
## None of them supplies the landmark
|
|
24
|
-
|
|
25
|
-
`<nav>`, `aria-label` and `aria-current` are yours to write. A page with three navigation regions and no labels on them is harder to use with a screen reader than a page with one, which is the usual reason to add them.
|
|
26
|
-
|
|
27
|
-
## `.item` means two different things
|
|
28
|
-
|
|
29
|
-
In [pagination](pagination/), `.item` is a page number. It is unrelated to the `.item` card unit mentioned throughout the [Content](../content/) section, which is not defined in this package at all.
|
package/docs/navigation/nav.md
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
isIndex: false
|
|
3
|
+
title: Overview
|
|
4
|
+
description: The five navigation components, the two that take their class on the wrapper, and the landmarks none of them supplies.
|
|
5
|
+
weight: 1
|
|
6
|
+
icon: book
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Five components for moving around a site.
|
|
10
|
+
|
|
11
|
+
| Page | Class | Purpose |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| [Nav](../nav/) | `.nav` | The base navigation list |
|
|
14
|
+
| [Nav title](../nav-title/) | `.nav-title` | A label above a group of links |
|
|
15
|
+
| [Skip links](../nav-accessibility/) | `.nav-accessibility` | Skip navigation for keyboard and assistive technology |
|
|
16
|
+
| [Breadcrumb](../breadcrumb/) | `.breadcrumb-wrapper` | The breadcrumb trail |
|
|
17
|
+
| [Pagination](../pagination/) | `.pagination` | Page navigation |
|
|
18
|
+
|
|
19
|
+
## Two of them take the class on the wrapper
|
|
20
|
+
|
|
21
|
+
`.breadcrumb-wrapper` goes on the `<nav>`, not on the `<ol>` inside it. `.nav-accessibility` goes on the list itself, but only alongside `.nav`. Neither is guessable from the name, so check the page before writing the markup.
|
|
22
|
+
|
|
23
|
+
## None of them supplies the landmark
|
|
24
|
+
|
|
25
|
+
`<nav>`, `aria-label` and `aria-current` are yours to write. A page with three navigation regions and no labels on them is harder to use with a screen reader than a page with one, which is the usual reason to add them.
|
|
26
|
+
|
|
27
|
+
## `.item` means two different things
|
|
28
|
+
|
|
29
|
+
In [pagination](../pagination/), `.item` is a page number. It is unrelated to the `.item` card unit mentioned throughout the [Content](../../content/) section, which is not defined in this package at all.
|
package/docs/overlays/_index.md
CHANGED
|
@@ -2,33 +2,6 @@
|
|
|
2
2
|
isIndex: false
|
|
3
3
|
title: Overlays
|
|
4
4
|
description: The shared panel skeleton behind .modal and .drawer, the two opening strategies, and the .dropdown contract.
|
|
5
|
-
weight:
|
|
5
|
+
weight: 4
|
|
6
6
|
icon: window-stack
|
|
7
7
|
---
|
|
8
|
-
|
|
9
|
-
Four files, and a design worth understanding before reading any of them.
|
|
10
|
-
|
|
11
|
-
| Page | Covers |
|
|
12
|
-
| --- | --- |
|
|
13
|
-
| [Panel](panel/) | The shared skeleton, `.panel-inline-*`, `.panel-trigger-*`, the backdrop and the JavaScript contract |
|
|
14
|
-
| [Modal](modal/) | `.modal`, the centred configuration |
|
|
15
|
-
| [Drawer](drawer/) | `.drawer` and its four edge variants |
|
|
16
|
-
| [Dropdown](dropdown/) | `.dropdown`, a contextual menu with its own contract |
|
|
17
|
-
|
|
18
|
-
## `.modal` and `.drawer` are the same panel
|
|
19
|
-
|
|
20
|
-
Same structure, header and content and footer. Same open and closed contract. Same backdrop. They differ only in where they sit: modal centres them, drawer pins them to an edge.
|
|
21
|
-
|
|
22
|
-
`components/panel.css` owns **every rule**. The two variants are pure configuration, declaring nothing but `--panel-*` tokens.
|
|
23
|
-
|
|
24
|
-
There is **no `.panel` class to apply.** The file targets `:where(.modal, .drawer)` directly, so the skeleton arrives with either variant class. `panel` names the shared concept and the token namespace, not a class.
|
|
25
|
-
|
|
26
|
-
Each variant aliases `--panel-*` from its own namespace, so `--modal-*` and `--drawer-*` remain the public API. Override those.
|
|
27
|
-
|
|
28
|
-
## The tag picks the strategy, not the class
|
|
29
|
-
|
|
30
|
-
Either variant works both ways, and the choice is an accessibility one rather than a styling one. See [Two ways to open a panel](panel/#two-ways-to-open-a-panel).
|
|
31
|
-
|
|
32
|
-
## No JavaScript ships here
|
|
33
|
-
|
|
34
|
-
`.modal`, `.drawer` and `.dropdown` all expect a script. The CSS defines the classes and attributes that script must toggle; each page documents the contract it needs.
|
package/docs/overlays/drawer.md
CHANGED
package/docs/overlays/modal.md
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
isIndex: false
|
|
3
|
+
title: Overview
|
|
4
|
+
description: Why .modal and .drawer are the same panel, where the class you apply actually lives, and what the four files expect from your JavaScript.
|
|
5
|
+
weight: 1
|
|
6
|
+
icon: book
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Four files, and a design worth understanding before reading any of them.
|
|
10
|
+
|
|
11
|
+
| Page | Covers |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| [Panel](../panel/) | The shared skeleton, `.panel-inline-*`, `.panel-trigger-*`, the backdrop and the JavaScript contract |
|
|
14
|
+
| [Modal](../modal/) | `.modal`, the centred configuration |
|
|
15
|
+
| [Drawer](../drawer/) | `.drawer` and its four edge variants |
|
|
16
|
+
| [Dropdown](../dropdown/) | `.dropdown`, a contextual menu with its own contract |
|
|
17
|
+
|
|
18
|
+
## `.modal` and `.drawer` are the same panel
|
|
19
|
+
|
|
20
|
+
Same structure, header and content and footer. Same open and closed contract. Same backdrop. They differ only in where they sit: modal centres them, drawer pins them to an edge.
|
|
21
|
+
|
|
22
|
+
`components/panel.css` owns **every rule**. The two variants are pure configuration, declaring nothing but `--panel-*` tokens.
|
|
23
|
+
|
|
24
|
+
There is **no `.panel` class to apply.** The file targets `:where(.modal, .drawer)` directly, so the skeleton arrives with either variant class. `panel` names the shared concept and the token namespace, not a class.
|
|
25
|
+
|
|
26
|
+
Each variant aliases `--panel-*` from its own namespace, so `--modal-*` and `--drawer-*` remain the public API. Override those.
|
|
27
|
+
|
|
28
|
+
## The tag picks the strategy, not the class
|
|
29
|
+
|
|
30
|
+
Either variant works both ways, and the choice is an accessibility one rather than a styling one. See [Two ways to open a panel](../panel/#two-ways-to-open-a-panel).
|
|
31
|
+
|
|
32
|
+
## No JavaScript ships here
|
|
33
|
+
|
|
34
|
+
`.modal`, `.drawer` and `.dropdown` all expect a script. The CSS defines the classes and attributes that script must toggle; each page documents the contract it needs.
|
package/docs/overlays/panel.md
CHANGED
package/docs/overview.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
isIndex: false
|
|
3
|
+
title: Overview
|
|
4
|
+
description: The 29 components and 1 utility, how to install them, the import order inside the package, and what it deliberately leaves out.
|
|
5
|
+
weight: 1
|
|
6
|
+
icon: book
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
`@uncinq/css-components` is the top of the stack: 29 components and 1 utility, written as plain CSS, reading their values from [@uncinq/component-tokens](../../component-tokens/) and adding no values of their own.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
@uncinq/design-tokens primitive + semantic values
|
|
13
|
+
@uncinq/component-tokens component-scoped values
|
|
14
|
+
@uncinq/css-base reset, native elements, layouts
|
|
15
|
+
@uncinq/css-components ← this package
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Every rule lives in `@layer components`, except the scroll-snap utility which lives in `@layer utilities`. There is no build step, no preprocessor, and no JavaScript shipped in the package. Three components do expect a script you provide, and each one documents the contract it needs.
|
|
19
|
+
|
|
20
|
+
## The components
|
|
21
|
+
|
|
22
|
+
One page per component, grouped into six sections.
|
|
23
|
+
|
|
24
|
+
| Section | Components |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| [Buttons](../buttons/) | [`.btn`](../buttons/btn/), [`.btn-close`](../buttons/btn-close/), [`.btn-menu`](../buttons/btn-menu/), [`.btn-search`](../buttons/btn-search/), [`.btn-filter`](../buttons/btn-filter/), [`.btn-share`](../buttons/btn-share/), [`.btn-toc`](../buttons/btn-toc/), [`.btn-toggle-video`](../buttons/btn-toggle-video/) |
|
|
27
|
+
| [Overlays](../overlays/) | [panel](../overlays/panel/), [`.modal`](../overlays/modal/), [`.drawer`](../overlays/drawer/), [`.dropdown`](../overlays/dropdown/) |
|
|
28
|
+
| [Content](../content/) | [`.alert`](../content/alert/), [`.badge`](../content/badge/), [`.banner`](../content/banner/), [`.card`](../content/card/), [`.items`](../content/items/), [`.list`](../content/list/), [`.media`](../content/media/), [`.surtitle`](../content/surtitle/) |
|
|
29
|
+
| [Navigation](../navigation/) | [`.nav`](../navigation/nav/), [`.nav-title`](../navigation/nav-title/), [`.nav-accessibility`](../navigation/nav-accessibility/), [`.breadcrumb-wrapper`](../navigation/breadcrumb/), [`.pagination`](../navigation/pagination/) |
|
|
30
|
+
| [Embeds](../embeds/) | [`.embed`](../embeds/embed/), [`.video`](../embeds/video/), [`.map`](../embeds/map/) |
|
|
31
|
+
| [Forms](../forms/) | [`.form`](../forms/form/), [`.form-check`](../forms/form-check/) |
|
|
32
|
+
| [Utilities](../utilities/) | [`.scrollsnap`](../utilities/scrollsnap/) |
|
|
33
|
+
|
|
34
|
+
Read [Cascade layers](../cascade-layers/) first if you are wiring this into a project for the first time.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
All three packages below are required. The tokens resolve the custom properties, and css-base provides the reset and the element styles the components build on.
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install @uncinq/design-tokens @uncinq/component-tokens @uncinq/css-base @uncinq/css-components
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```css
|
|
45
|
+
@layer reset, tokens, libs, base, vendors, layouts, components, pages, utilities;
|
|
46
|
+
|
|
47
|
+
@import '@uncinq/design-tokens'; /* @layer tokens */
|
|
48
|
+
@import '@uncinq/css-base'; /* @layer reset, base, layouts */
|
|
49
|
+
@import '@uncinq/component-tokens'; /* @layer tokens */
|
|
50
|
+
@import '@uncinq/css-components'; /* @layer components, utilities */
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Per component, when you only need a few:
|
|
54
|
+
|
|
55
|
+
```css
|
|
56
|
+
@import '@uncinq/css-components/css/components/button.css';
|
|
57
|
+
@import '@uncinq/css-components/css/components/alert.css';
|
|
58
|
+
@import '@uncinq/css-components/css/utilities/scrollsnap.css';
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### A CDN link is not enough
|
|
62
|
+
|
|
63
|
+
`@uncinq/design-tokens` and `@uncinq/component-tokens` can be linked straight from a CDN, because they emit nothing but custom properties. **This package cannot**, and neither can `@uncinq/css-base`.
|
|
64
|
+
|
|
65
|
+
Both ship `@media (--sm)` queries that rely on the `@custom-media` rules declared in `css-base/css/mediaqueries.css`, and no browser implements `@custom-media`. Loaded without [postcss-custom-media](https://www.npmjs.com/package/postcss-custom-media), 13 responsive blocks in this package are dropped: `.panel-inline-*`, `.panel-trigger-*` and every `.scrollsnap-*` variant.
|
|
66
|
+
|
|
67
|
+
The failure is silent. No error is raised, the page simply stays at its mobile values on every screen. A build step is required.
|
|
68
|
+
|
|
69
|
+
Note that `@uncinq/css-base` is a genuine prerequisite but is **not** declared in `peerDependencies`. Install it explicitly.
|
|
70
|
+
|
|
71
|
+
## Import order inside the package
|
|
72
|
+
|
|
73
|
+
`css/index.css` imports the components alphabetically, with two deliberate exceptions.
|
|
74
|
+
|
|
75
|
+
`components/button.css` comes **before** the seven `btn-*` files rather than after them, because five of those are modifiers on `.btn` and read better in that order.
|
|
76
|
+
|
|
77
|
+
`utilities/scrollsnap.css` comes after everything, in `@layer utilities`, because it has to win over the grid a component declares for itself in `@layer components`.
|
|
78
|
+
|
|
79
|
+
One constraint is easy to break when importing file by file: `panel.css` must come **after** `modal.css` and `drawer.css`. Alphabetical order already gives that, which is why nothing in the barrel looks unusual, but the `.panel-inline-*` variants beat the two host components on source order rather than on specificity. See [Cascade layers](../cascade-layers/).
|
|
80
|
+
|
|
81
|
+
## What this package does not include
|
|
82
|
+
|
|
83
|
+
**No JavaScript.** `.modal`, `.drawer` and `.dropdown` expect a script. The CSS defines the classes and attributes that script must toggle, and each page documents the contract.
|
|
84
|
+
|
|
85
|
+
**No `.item`.** Despite what a couple of source comments still suggest, `.item` is not defined here. It lives in the Hugolify design system theme. This package ships `.card`, a complete implementation in its own right, and `.items`, a grid whose children you provide. See [Content](../content/).
|
|
86
|
+
|
|
87
|
+
**No icons for `.icon`.** Components that draw a glyph, the [buttons](../buttons/) and [`.pagination`](../navigation/pagination/), mask it from an icon token. An `.icon` element you place inside an [alert](../content/alert/) or a [video toggle](../buttons/btn-toggle-video/) is the theme's to render.
|
|
88
|
+
|
|
89
|
+
## References
|
|
90
|
+
|
|
91
|
+
- [@uncinq/component-tokens](https://github.com/uncinq/component-tokens), the values these components read
|
|
92
|
+
- [@uncinq/css-base](https://github.com/uncinq/css-base), the foundation underneath
|
|
93
|
+
- [MDN: CSS cascade layers](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Cascade_layers)
|
package/docs/utilities/_index.md
CHANGED
|
@@ -2,20 +2,6 @@
|
|
|
2
2
|
isIndex: false
|
|
3
3
|
title: Utilities
|
|
4
4
|
description: The one utility this package ships, and why it is a utility rather than a component rule.
|
|
5
|
-
weight:
|
|
5
|
+
weight: 9
|
|
6
6
|
icon: tools
|
|
7
7
|
---
|
|
8
|
-
|
|
9
|
-
One utility, in its own layer.
|
|
10
|
-
|
|
11
|
-
| Page | Class | Purpose |
|
|
12
|
-
| --- | --- | --- |
|
|
13
|
-
| [Scrollsnap](scrollsnap/) | `.scrollsnap` | Turns a grid into a horizontal snap carousel |
|
|
14
|
-
|
|
15
|
-
## Why it is not a component
|
|
16
|
-
|
|
17
|
-
`.scrollsnap` changes the `grid-template-columns` that a component such as [`.items`](../content/items/) declares for itself in `@layer components`. A later layer beats an earlier one regardless of specificity, so putting it in `@layer utilities` is what lets a single class opt an existing component into carousel behaviour without rewriting the component.
|
|
18
|
-
|
|
19
|
-
That is also the test for anything else that might land here: a utility is a **modifier applied to something else**, not a thing of its own. If it has its own markup, it is a component.
|
|
20
|
-
|
|
21
|
-
`@layer utilities` must come last in your layer declaration for this to hold. See [Cascade layers](../cascade-layers/).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
isIndex: false
|
|
3
|
+
title: Overview
|
|
4
|
+
description: The one utility in the package, and the test for whether anything else belongs here.
|
|
5
|
+
weight: 1
|
|
6
|
+
icon: book
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
One utility, in its own layer.
|
|
10
|
+
|
|
11
|
+
| Page | Class | Purpose |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| [Scrollsnap](../scrollsnap/) | `.scrollsnap` | Turns a grid into a horizontal snap carousel |
|
|
14
|
+
|
|
15
|
+
## Why it is not a component
|
|
16
|
+
|
|
17
|
+
`.scrollsnap` changes the `grid-template-columns` that a component such as [`.items`](../../content/items/) declares for itself in `@layer components`. A later layer beats an earlier one regardless of specificity, so putting it in `@layer utilities` is what lets a single class opt an existing component into carousel behaviour without rewriting the component.
|
|
18
|
+
|
|
19
|
+
That is also the test for anything else that might land here: a utility is a **modifier applied to something else**, not a thing of its own. If it has its own markup, it is a component.
|
|
20
|
+
|
|
21
|
+
`@layer utilities` must come last in your layer declaration for this to hold. See [Cascade layers](../../cascade-layers/).
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
isIndex: false
|
|
3
3
|
title: Scrollsnap
|
|
4
4
|
description: Turns a grid into a horizontal snap carousel below a breakpoint, bleeding into the gutter so the next item peeks in.
|
|
5
|
-
weight:
|
|
5
|
+
weight: 2
|
|
6
6
|
icon: arrow-left-right
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -62,7 +62,7 @@ Items take `--items-min-width`, the same value that drives the grid, capped by `
|
|
|
62
62
|
|
|
63
63
|
## The bleed, and why margin and padding disagree
|
|
64
64
|
|
|
65
|
-
The row pulls out to the screen edge using `--container-bleed`, published by `.container` in [css-base](../../../css-base/layouts/#the---container-bleed-contract). The property inherits, so it reaches the row from a `.container` however far up it sits.
|
|
65
|
+
The row pulls out to the screen edge using `--container-bleed`, published by `.container` in [css-base](../../../css-base/layouts/container/#the---container-bleed-contract). The property inherits, so it reaches the row from a `.container` however far up it sits.
|
|
66
66
|
|
|
67
67
|
Outside a container there is no published value, and the two `var()` fallbacks differ **on purpose**, because margin and padding answer different questions:
|
|
68
68
|
|