@navecss/core 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/ATOMS.md +109 -0
- package/CONSUMER-ATOMS.md +332 -0
- package/LICENSE +21 -0
- package/README.md +264 -0
- package/dist/atomic.css +288 -0
- package/dist/atoms.d.ts +413 -0
- package/dist/atoms.js +1 -0
- package/dist/chunk-BVON7XKC.js +394 -0
- package/dist/cx.d.ts +72 -0
- package/dist/cx.js +9 -0
- package/dist/index.css +48 -0
- package/dist/layers.css +15 -0
- package/dist/no-tokens.css +52 -0
- package/dist/postcss.d.ts +64 -0
- package/dist/postcss.js +228 -0
- package/dist/reset.css +346 -0
- package/package.json +93 -0
package/README.md
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# @navecss/core
|
|
2
|
+
|
|
3
|
+
> Layer architecture, reset, atomic utilities, and PostCSS plugin for Nave.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @navecss/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
- **Browsers: Chrome and Edge 125, Firefox 128, Safari 18 (Baseline 2024).**
|
|
14
|
+
Every semantic colour in Nave's token stylesheet is a `light-dark()` pair, and
|
|
15
|
+
most of them are also derived with relative colour syntax. An older browser
|
|
16
|
+
drops whichever of them it does not support, without an error: surfaces and
|
|
17
|
+
text lose their colours. Your CSS build has to target the same floor, and
|
|
18
|
+
[PostCSS plugin setup](#postcss-plugin-setup) has the line for Vite.
|
|
19
|
+
[Why this floor](https://github.com/navecss/navecss/blob/main/docs/04-adr/0005-browser-floor.md).
|
|
20
|
+
- **A resolver that reads `exports` maps.** Every entry point, the stylesheet
|
|
21
|
+
included, is reachable only through the package's `exports` map: there is no
|
|
22
|
+
`main` field to fall back on.
|
|
23
|
+
- **ES modules.** `@navecss/core/cx`, `@navecss/core/atoms` and
|
|
24
|
+
`@navecss/core/postcss` load through `import` only. A `require()` of any of
|
|
25
|
+
them fails with `ERR_PACKAGE_PATH_NOT_EXPORTED`, which reads as though the
|
|
26
|
+
entry point did not exist. In TypeScript, set `moduleResolution` to `bundler`,
|
|
27
|
+
`node16` or `nodenext`; under `node10` their types are not found. A CommonJS
|
|
28
|
+
file type-checks against them and then fails when it runs, so import them from
|
|
29
|
+
an ES module.
|
|
30
|
+
- **Node 22.18 or later.**
|
|
31
|
+
- **PostCSS 8, for `@nave` only.** `postcss` is an optional peer dependency, so
|
|
32
|
+
nothing installs it for you: add it yourself if you use `@nave`. Without it,
|
|
33
|
+
importing `@navecss/core/postcss` fails with `Cannot find package 'postcss'`.
|
|
34
|
+
The stylesheets and `cx()` need no PostCSS.
|
|
35
|
+
|
|
36
|
+
## Setup
|
|
37
|
+
|
|
38
|
+
Import once at your app entry point:
|
|
39
|
+
|
|
40
|
+
```css
|
|
41
|
+
/* app.css */
|
|
42
|
+
@import url('@navecss/core/layers');
|
|
43
|
+
@import url('@navecss/core');
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
This imports the full layer stack in the correct order:
|
|
47
|
+
`tokens.defaults → tokens.presets → reset → atomic → components.nave → components.consumer → overrides`
|
|
48
|
+
|
|
49
|
+
The order holds only if it is the first `@layer` declaration your page sees:
|
|
50
|
+
a stylesheet of yours that declares a layer and loads earlier fixes that
|
|
51
|
+
layer's position first, and the order inverts with no error. So keep
|
|
52
|
+
`@navecss/core/layers`, the order statement alone, as the first line of
|
|
53
|
+
`app.css`, and import `app.css` in your entry file before anything that brings
|
|
54
|
+
its own stylesheet, components included. The `@navecss/core` import after it
|
|
55
|
+
repeats the same statement, which changes nothing
|
|
56
|
+
([why, and where your CSS goes](https://github.com/navecss/navecss/blob/main/docs/04-adr/0003-layer-cascade-contract.md)).
|
|
57
|
+
|
|
58
|
+
Your component CSS goes in `@layer components.consumer`, and a deliberate
|
|
59
|
+
exception goes in `@layer overrides`, which beats every other layer. Left outside
|
|
60
|
+
any layer, your CSS would beat all of them, `overrides` included. Do not write
|
|
61
|
+
into a bare `@layer components` or `@layer tokens`: a rule written directly into a
|
|
62
|
+
layer outranks everything in that layer's sublayers.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Styling components
|
|
67
|
+
|
|
68
|
+
Nave gives you three ways to apply atomic utilities. Start with @nave directives.
|
|
69
|
+
Every built-in atom, with the declarations it applies, is listed in
|
|
70
|
+
[ATOMS.md](./ATOMS.md).
|
|
71
|
+
|
|
72
|
+
### Primary — @nave directives
|
|
73
|
+
|
|
74
|
+
Requires the PostCSS plugin. Everything stays in CSS files.
|
|
75
|
+
|
|
76
|
+
```css
|
|
77
|
+
/* button.module.css */
|
|
78
|
+
@layer components.consumer {
|
|
79
|
+
.root {
|
|
80
|
+
@nave interactive focusRing transition;
|
|
81
|
+
background: var(--nave-color-action-primary);
|
|
82
|
+
color: var(--nave-color-on-action-primary);
|
|
83
|
+
padding: var(--nave-spacing-control-md) var(--nave-spacing-control-lg);
|
|
84
|
+
border-radius: var(--nave-radius-control);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Declarations are inlined at build time, and nothing of `@nave` is left at run time.
|
|
90
|
+
Pseudo-class rules (`:focus-visible` from `focusRing`), `@media` and
|
|
91
|
+
`@container` blocks are emitted as native CSS nesting inside your rule, so they
|
|
92
|
+
apply to every selector in a selector list. Native nesting is inside the browser
|
|
93
|
+
floor under [Requirements](#requirements).
|
|
94
|
+
|
|
95
|
+
### Escape hatch — cx() utility
|
|
96
|
+
|
|
97
|
+
No PostCSS required. Atom names move to JSX — autocompleted, and type-checked.
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
import { cx } from '@navecss/core/cx'
|
|
101
|
+
import styles from './button.module.css'
|
|
102
|
+
|
|
103
|
+
;<button className={`${cx('interactive', 'focusRing', 'transition')} ${styles.root}`} />
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Use this if you cannot or do not want to add a PostCSS plugin to your build.
|
|
107
|
+
|
|
108
|
+
A `cx()` class is a default, not an override: it sits in the `atomic` layer,
|
|
109
|
+
below your component CSS, so your own rule wins wherever the two set the same
|
|
110
|
+
property.
|
|
111
|
+
|
|
112
|
+
Two channels, because they carry different things. `cx()` takes Nave's built-in
|
|
113
|
+
atoms and nothing else. Your own classes compose in the template literal, the
|
|
114
|
+
way your own declarations sit beside `@nave` in a rule body. `cx.raw()` is for a
|
|
115
|
+
class from outside any system Nave can see — a legacy global class, a
|
|
116
|
+
third-party widget's class — and it returns what you give it, untouched:
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
;<div className={`${cx('interactive')} ${cx.raw('legacy-card')}`} />
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**A conditional class goes in a call, not in a slot.** Both channels filter
|
|
123
|
+
falsy arguments, so `cx('interactive', isActive && 'focusRing')` and
|
|
124
|
+
`cx.raw(isActive && styles.active)` each drop the argument when the condition
|
|
125
|
+
is false. A template-literal slot does not: `${isActive && styles.active}`
|
|
126
|
+
interpolates the string `false`, and an undefined one interpolates `undefined`.
|
|
127
|
+
|
|
128
|
+
What that buys you, and what it does not:
|
|
129
|
+
|
|
130
|
+
- **An unknown name is a compile error**, in your own `tsc`, with nothing
|
|
131
|
+
installed from us. That covers a typo (`cx('interactve')`), a name typed
|
|
132
|
+
from the CSS side (`cx('sr-only')` — the atom is `srOnly`, and the class it
|
|
133
|
+
_emits_ is `nave-sr-only`; neither spelling is the key), and any class that is
|
|
134
|
+
not a Nave atom. **TypeScript only:
|
|
135
|
+
a JavaScript consumer gets none of it.** For a build-level check that does not
|
|
136
|
+
depend on types, use the `@nave` directive with `navePlugin()` — it fails the
|
|
137
|
+
build on an unknown atom by default.
|
|
138
|
+
- **`cx.raw()` cannot shadow one of your classes.** It never consults the atom
|
|
139
|
+
map, so `cx.raw('container')` is the literal `container`. Inside `cx()` an
|
|
140
|
+
atom name still resolves to that atom's global class — `cx('container')` is
|
|
141
|
+
`nave-container` — which is why the ordinary-sounding names (`container`,
|
|
142
|
+
`hidden`, `grid`, `flex`, `block`, `border`, `rounded`, `transition`,
|
|
143
|
+
`relative`, `absolute`, `gap`, `truncate`, `interactive`) belong on the
|
|
144
|
+
`cx.raw()` side when you mean your own.
|
|
145
|
+
- **Nothing checks the rest of the `className` attribute.** A bare
|
|
146
|
+
`'legacy-card'` sitting beside these calls is seen by nothing and still works.
|
|
147
|
+
So `cx.raw()` is a **declared** escape channel, not an enforced one: its value
|
|
148
|
+
today is that every deliberate step outside the system leaves a token you can
|
|
149
|
+
find (`grep -r 'cx.raw'`). A lint that closes the attribute itself is not part
|
|
150
|
+
of this release.
|
|
151
|
+
|
|
152
|
+
### Tokens only
|
|
153
|
+
|
|
154
|
+
For library authors or teams building on top of Base UI or Radix UI.
|
|
155
|
+
CSS custom properties are always available — no atomic layer required.
|
|
156
|
+
|
|
157
|
+
```css
|
|
158
|
+
.root {
|
|
159
|
+
background: var(--nave-color-action-primary);
|
|
160
|
+
border-radius: var(--nave-radius-control);
|
|
161
|
+
transition-duration: var(--nave-motion-duration-base);
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Every custom property Nave declares is in the stylesheet you already installed, at `@navecss/tokens/css`.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## PostCSS plugin setup
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
// vite.config.ts
|
|
173
|
+
import { defineConfig } from 'vite'
|
|
174
|
+
import { navePlugin } from '@navecss/core/postcss'
|
|
175
|
+
|
|
176
|
+
export default defineConfig({
|
|
177
|
+
// your existing options, plugins included, stay as they are
|
|
178
|
+
css: { postcss: { plugins: [navePlugin()] } },
|
|
179
|
+
build: { cssTarget: ['chrome125', 'edge125', 'firefox128', 'safari18', 'ios18'] },
|
|
180
|
+
})
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
`build.cssTarget` is the browser floor, in Vite's terms. Vite's default targets
|
|
184
|
+
older browsers, and building for them gains you nothing, because the output
|
|
185
|
+
still needs the floor. It does cost you something: Vite rewrites `light-dark()`
|
|
186
|
+
in Nave's colours into an emulation that a `color-scheme` set from script, or on
|
|
187
|
+
part of the page, does not switch. If your project already has a
|
|
188
|
+
`postcss.config.js`, put `navePlugin()` there instead: Vite reads no PostCSS
|
|
189
|
+
config file once `css.postcss` is set inline.
|
|
190
|
+
|
|
191
|
+
```js
|
|
192
|
+
// postcss.config.js
|
|
193
|
+
import { navePlugin } from '@navecss/core/postcss'
|
|
194
|
+
|
|
195
|
+
export default {
|
|
196
|
+
plugins: [navePlugin()],
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Options
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
navePlugin({
|
|
204
|
+
// 'error' (default) — throw, failing the build
|
|
205
|
+
// 'warn' — log and skip
|
|
206
|
+
// 'ignore' — silently skip
|
|
207
|
+
onUnknown: 'error',
|
|
208
|
+
})
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
To add atoms of your own to `@nave`, pass them as `extend`: see
|
|
212
|
+
[CONSUMER-ATOMS.md](./CONSUMER-ATOMS.md).
|
|
213
|
+
|
|
214
|
+
`postcss` is an optional peer dependency.
|
|
215
|
+
If you are using only `cx()` or tokens, you do not need to install it.
|
|
216
|
+
|
|
217
|
+
**If your Vite config sets `css.transformer: 'lightningcss'`, this plugin never
|
|
218
|
+
runs.** That option replaces Vite's CSS pipeline with Lightning CSS, which does
|
|
219
|
+
not run PostCSS plugins at all: the build stays green, `@nave` reaches the
|
|
220
|
+
browser as an unknown at-rule, and the browser drops it, so the rule renders
|
|
221
|
+
with none of the declarations its atoms were going to give it. Leave the
|
|
222
|
+
default transformer in place on a project using `@nave`.
|
|
223
|
+
|
|
224
|
+
### Plugin order
|
|
225
|
+
|
|
226
|
+
Put `navePlugin()` before any autoprefixing or syntax-down-levelling plugin (`autoprefixer`,
|
|
227
|
+
`postcss-preset-env`, and the like) in your `plugins` array. `navePlugin()` resolves `@nave`
|
|
228
|
+
directives into literal declarations; a prefixer ordered before it only ever sees the
|
|
229
|
+
unexpanded directive, so it has nothing of Nave's to add a prefix to. Nave's own atoms already
|
|
230
|
+
ship the vendor-prefixed properties their declarations need (`interactive`'s
|
|
231
|
+
`-webkit-user-select` alongside `user-select`, for one), so this is only a concern for your own
|
|
232
|
+
CSS sharing the same pipeline.
|
|
233
|
+
|
|
234
|
+
### Where `@nave` is valid
|
|
235
|
+
|
|
236
|
+
`@nave` must be the direct child of a CSS rule selector block. Any rule will
|
|
237
|
+
do and the nesting depth does not matter, so `.card { @nave flex; }`,
|
|
238
|
+
`.card { &:hover { @nave flex; } }`, `.card { .badge { @nave flex; } }` and
|
|
239
|
+
`@supports (display: grid) { .card { @nave flex; } }` are all valid. Two
|
|
240
|
+
shapes that parse without error are still rejected, through the same
|
|
241
|
+
`onUnknown` option as an unknown atom name (so the default is a build
|
|
242
|
+
failure, not a silently incomplete build):
|
|
243
|
+
|
|
244
|
+
- **Nested inside `@media` or `@container` with no rule in between** —
|
|
245
|
+
`.card { @media (width >= 37.5em) { @nave flex; } }`. Write the directive
|
|
246
|
+
inside a rule instead: `.card { @media (width >= 37.5em) { & { @nave flex; } } }`.
|
|
247
|
+
- **Inside `@keyframes`** — a keyframe step (`to`, `from`, `50%`) parses as a
|
|
248
|
+
rule, but `&` has no meaning there and a browser drops the nesting with no
|
|
249
|
+
other symptom, so it is rejected the same way.
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Exports
|
|
254
|
+
|
|
255
|
+
| Export | Description |
|
|
256
|
+
| ------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
257
|
+
| `@navecss/core` | CSS entry point — `@import url('@navecss/core')` |
|
|
258
|
+
| `@navecss/core/layers` | The `@layer` order statement alone. Import it first, before any other stylesheet |
|
|
259
|
+
| `@navecss/core/no-tokens` | Entry point for projects that generate their own Nave token layer; see the header comment in the file |
|
|
260
|
+
| `@navecss/core/reset` | Reset stylesheet only. It reads Nave's custom properties, so it needs a token layer beside it |
|
|
261
|
+
| `@navecss/core/atomic` | Generated atomic CSS (global `nave-` classes) |
|
|
262
|
+
| `@navecss/core/cx` | `cx()` / `cx.raw()` utilities + `AtomName` type |
|
|
263
|
+
| `@navecss/core/atoms` | Atom definitions + `atomClassMap` |
|
|
264
|
+
| `@navecss/core/postcss` | PostCSS plugin — `navePlugin()` |
|
package/dist/atomic.css
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Nave atomic utilities — generated from src/atoms.ts
|
|
3
|
+
* Do not edit directly. Run `pnpm build` in packages/core to regenerate.
|
|
4
|
+
*
|
|
5
|
+
* Primary path: .root { @nave interactive focusRing; } (postcss plugin)
|
|
6
|
+
* Escape hatch: `${cx('interactive', 'focusRing')} ${styles.root}`
|
|
7
|
+
*
|
|
8
|
+
* Classes are global, namespaced with nave- prefix.
|
|
9
|
+
* Consumer atoms (navePlugin extend) are NOT included —
|
|
10
|
+
* they are resolved inline by the PostCSS plugin only.
|
|
11
|
+
*
|
|
12
|
+
* Self-layered under @layer atomic: this file ships as a published subpath
|
|
13
|
+
* export (./atomic) and is imported directly by some consumers, so the
|
|
14
|
+
* layer guarantee has to be a property of the artifact rather than of
|
|
15
|
+
* index.css's import site.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
@layer tokens.defaults, tokens.presets, reset, atomic, components.nave, components.consumer, overrides;
|
|
19
|
+
|
|
20
|
+
@layer atomic {
|
|
21
|
+
.nave-flex {
|
|
22
|
+
display: flex;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.nave-inline-flex {
|
|
26
|
+
display: inline-flex;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.nave-grid {
|
|
30
|
+
display: grid;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.nave-block {
|
|
34
|
+
display: block;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.nave-inline-block {
|
|
38
|
+
display: inline-block;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.nave-hidden {
|
|
42
|
+
display: none;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.nave-flex-col {
|
|
46
|
+
flex-direction: column;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.nave-flex-wrap {
|
|
50
|
+
flex-wrap: wrap;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.nave-items-center {
|
|
54
|
+
align-items: center;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.nave-items-start {
|
|
58
|
+
align-items: flex-start;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.nave-items-end {
|
|
62
|
+
align-items: flex-end;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.nave-justify-center {
|
|
66
|
+
justify-content: center;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.nave-justify-between {
|
|
70
|
+
justify-content: space-between;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.nave-justify-end {
|
|
74
|
+
justify-content: flex-end;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.nave-flex-grow {
|
|
78
|
+
flex-grow: 1;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.nave-flex-shrink0 {
|
|
82
|
+
flex-shrink: 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.nave-gap {
|
|
86
|
+
gap: var(--nave-spacing-content-md);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.nave-relative {
|
|
90
|
+
position: relative;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.nave-absolute {
|
|
94
|
+
position: absolute;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.nave-inset-full {
|
|
98
|
+
inset: 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.nave-w-full {
|
|
102
|
+
width: 100%;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.nave-h-full {
|
|
106
|
+
height: 100%;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.nave-min-w0 {
|
|
110
|
+
min-width: 0;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.nave-truncate {
|
|
114
|
+
overflow: hidden;
|
|
115
|
+
text-overflow: ellipsis;
|
|
116
|
+
white-space: nowrap;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.nave-sr-only {
|
|
120
|
+
position: absolute;
|
|
121
|
+
width: 1px;
|
|
122
|
+
height: 1px;
|
|
123
|
+
padding: 0;
|
|
124
|
+
margin: -1px;
|
|
125
|
+
overflow: hidden;
|
|
126
|
+
clip-path: inset(50%);
|
|
127
|
+
white-space: nowrap;
|
|
128
|
+
border-width: 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.nave-sr-only-focusable {
|
|
132
|
+
position: absolute;
|
|
133
|
+
width: 1px;
|
|
134
|
+
height: 1px;
|
|
135
|
+
padding: 0;
|
|
136
|
+
margin: -1px;
|
|
137
|
+
overflow: hidden;
|
|
138
|
+
clip-path: inset(50%);
|
|
139
|
+
white-space: nowrap;
|
|
140
|
+
border-width: 0;
|
|
141
|
+
|
|
142
|
+
&:focus-visible {
|
|
143
|
+
position: static;
|
|
144
|
+
width: auto;
|
|
145
|
+
height: auto;
|
|
146
|
+
margin: 0;
|
|
147
|
+
overflow: visible;
|
|
148
|
+
clip-path: none;
|
|
149
|
+
white-space: normal;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
&:focus-within {
|
|
153
|
+
position: static;
|
|
154
|
+
width: auto;
|
|
155
|
+
height: auto;
|
|
156
|
+
margin: 0;
|
|
157
|
+
overflow: visible;
|
|
158
|
+
clip-path: none;
|
|
159
|
+
white-space: normal;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.nave-no-wrap {
|
|
164
|
+
white-space: nowrap;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.nave-break-word {
|
|
168
|
+
overflow-wrap: break-word;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.nave-text-left {
|
|
172
|
+
text-align: left;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.nave-text-center {
|
|
176
|
+
text-align: center;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.nave-text-right {
|
|
180
|
+
text-align: right;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.nave-interactive {
|
|
184
|
+
cursor: pointer;
|
|
185
|
+
-webkit-user-select: none;
|
|
186
|
+
user-select: none;
|
|
187
|
+
-webkit-tap-highlight-color: transparent;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.nave-focus-ring {
|
|
191
|
+
outline: none;
|
|
192
|
+
|
|
193
|
+
&:focus-visible {
|
|
194
|
+
outline: var(--nave-border-width-focus) solid var(--nave-color-border-focus);
|
|
195
|
+
outline-offset: 2px;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.nave-disabled-state {
|
|
200
|
+
&:disabled, &[aria-disabled="true"] {
|
|
201
|
+
color: var(--nave-color-content-disabled);
|
|
202
|
+
border-color: var(--nave-color-border-disabled);
|
|
203
|
+
pointer-events: none;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.nave-rounded {
|
|
208
|
+
border-radius: var(--nave-radius-control);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.nave-rounded-card {
|
|
212
|
+
border-radius: var(--nave-radius-card);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.nave-rounded-full {
|
|
216
|
+
border-radius: var(--nave-radius-full);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.nave-border {
|
|
220
|
+
border: var(--nave-border-width-sm) solid var(--nave-color-border-default);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.nave-overflow-hidden {
|
|
224
|
+
overflow: hidden;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.nave-overflow-auto {
|
|
228
|
+
overflow: auto;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.nave-transition {
|
|
232
|
+
transition-property: color, background-color, border-color, opacity, box-shadow;
|
|
233
|
+
transition-duration: var(--nave-motion-duration-base);
|
|
234
|
+
transition-timing-function: var(--nave-motion-easing-standard);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.nave-container {
|
|
238
|
+
container-type: inline-size;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.nave-hide-phone-only {
|
|
242
|
+
@media (width < 37.5em) {
|
|
243
|
+
& {
|
|
244
|
+
display: none;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.nave-hide-tablet-portrait-up {
|
|
250
|
+
@media (width >= 37.5em) {
|
|
251
|
+
& {
|
|
252
|
+
display: none;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.nave-hide-tablet-landscape-up {
|
|
258
|
+
@media (width >= 56.25em) {
|
|
259
|
+
& {
|
|
260
|
+
display: none;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.nave-hide-desktop-up {
|
|
266
|
+
@media (width >= 75em) {
|
|
267
|
+
& {
|
|
268
|
+
display: none;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.nave-stack-phone-only {
|
|
274
|
+
@media (width < 37.5em) {
|
|
275
|
+
& {
|
|
276
|
+
flex-direction: column;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.nave-w-full-phone-only {
|
|
282
|
+
@media (width < 37.5em) {
|
|
283
|
+
& {
|
|
284
|
+
width: 100%;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|