neba 0.0.1 → 1.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 +169 -2
- package/dist/components/accordion/Accordion.d.ts +97 -0
- package/dist/components/accordion/Accordion.js +1 -0
- package/dist/components/accordion/index.d.ts +2 -0
- package/dist/components/accordion/index.js +1 -0
- package/dist/components/alert/Alert.d.ts +47 -0
- package/dist/components/alert/Alert.js +1 -0
- package/dist/components/alert/index.d.ts +2 -0
- package/dist/components/alert/index.js +1 -0
- package/dist/components/badge/Badge.d.ts +80 -0
- package/dist/components/badge/Badge.js +1 -0
- package/dist/components/badge/index.d.ts +2 -0
- package/dist/components/badge/index.js +1 -0
- package/dist/components/box/Box.d.ts +50 -0
- package/dist/components/box/Box.js +1 -0
- package/dist/components/box/index.d.ts +2 -0
- package/dist/components/box/index.js +1 -0
- package/dist/components/button/Button.d.ts +25 -3
- package/dist/components/button/Button.js +1 -1
- package/dist/components/button/index.d.ts +1 -0
- package/dist/components/button-group/ButtonGroup.d.ts +31 -0
- package/dist/components/button-group/ButtonGroup.js +1 -0
- package/dist/components/button-group/index.d.ts +2 -0
- package/dist/components/button-group/index.js +1 -0
- package/dist/components/card/Card.d.ts +45 -0
- package/dist/components/card/Card.js +1 -0
- package/dist/components/card/index.d.ts +2 -0
- package/dist/components/card/index.js +1 -0
- package/dist/components/checkbox/Checkbox.d.ts +39 -0
- package/dist/components/checkbox/Checkbox.js +1 -0
- package/dist/components/checkbox/index.d.ts +2 -0
- package/dist/components/checkbox/index.js +1 -0
- package/dist/components/chip/Chip.d.ts +50 -0
- package/dist/components/chip/Chip.js +1 -0
- package/dist/components/chip/index.d.ts +2 -0
- package/dist/components/chip/index.js +1 -0
- package/dist/components/combobox/Combobox.d.ts +131 -0
- package/dist/components/combobox/Combobox.js +1 -0
- package/dist/components/combobox/index.d.ts +2 -0
- package/dist/components/combobox/index.js +1 -0
- package/dist/components/dialog/Dialog.d.ts +111 -0
- package/dist/components/dialog/Dialog.js +1 -0
- package/dist/components/dialog/index.d.ts +2 -0
- package/dist/components/dialog/index.js +1 -0
- package/dist/components/divider/Divider.d.ts +48 -0
- package/dist/components/divider/Divider.js +1 -0
- package/dist/components/divider/index.d.ts +2 -0
- package/dist/components/divider/index.js +1 -0
- package/dist/components/file-picker/FilePicker.d.ts +103 -0
- package/dist/components/file-picker/FilePicker.js +1 -0
- package/dist/components/file-picker/index.d.ts +2 -0
- package/dist/components/file-picker/index.js +1 -0
- package/dist/components/list/List.d.ts +81 -0
- package/dist/components/list/List.js +1 -0
- package/dist/components/list/index.d.ts +2 -0
- package/dist/components/list/index.js +1 -0
- package/dist/components/menu/Menu.d.ts +216 -0
- package/dist/components/menu/Menu.js +1 -0
- package/dist/components/menu/index.d.ts +2 -0
- package/dist/components/menu/index.js +1 -0
- package/dist/components/number-field/NumberField.d.ts +113 -0
- package/dist/components/number-field/NumberField.js +1 -0
- package/dist/components/number-field/index.d.ts +2 -0
- package/dist/components/number-field/index.js +1 -0
- package/dist/components/overlay/Overlay.d.ts +85 -0
- package/dist/components/overlay/Overlay.js +1 -0
- package/dist/components/overlay/index.d.ts +2 -0
- package/dist/components/overlay/index.js +1 -0
- package/dist/components/pagination/Pagination.d.ts +65 -0
- package/dist/components/pagination/Pagination.js +1 -0
- package/dist/components/pagination/index.d.ts +2 -0
- package/dist/components/pagination/index.js +1 -0
- package/dist/components/progress-box/ProgressBox.d.ts +33 -0
- package/dist/components/progress-box/ProgressBox.js +1 -0
- package/dist/components/progress-box/index.d.ts +2 -0
- package/dist/components/progress-box/index.js +1 -0
- package/dist/components/progress-circular/ProgressCircular.d.ts +19 -0
- package/dist/components/progress-circular/ProgressCircular.js +1 -0
- package/dist/components/progress-circular/index.d.ts +2 -0
- package/dist/components/progress-circular/index.js +1 -0
- package/dist/components/progress-linear/ProgressLinear.d.ts +20 -0
- package/dist/components/progress-linear/ProgressLinear.js +1 -0
- package/dist/components/progress-linear/index.d.ts +2 -0
- package/dist/components/progress-linear/index.js +1 -0
- package/dist/components/radio-group/RadioGroup.d.ts +51 -0
- package/dist/components/radio-group/RadioGroup.js +1 -0
- package/dist/components/radio-group/index.d.ts +2 -0
- package/dist/components/radio-group/index.js +1 -0
- package/dist/components/select/Select.d.ts +76 -0
- package/dist/components/select/Select.js +1 -0
- package/dist/components/select/index.d.ts +2 -0
- package/dist/components/select/index.js +1 -0
- package/dist/components/slider/Slider.d.ts +38 -0
- package/dist/components/slider/Slider.js +1 -0
- package/dist/components/slider/index.d.ts +2 -0
- package/dist/components/slider/index.js +1 -0
- package/dist/components/switch/Switch.d.ts +39 -0
- package/dist/components/switch/Switch.js +1 -0
- package/dist/components/switch/index.d.ts +2 -0
- package/dist/components/switch/index.js +1 -0
- package/dist/components/table/Table.d.ts +80 -0
- package/dist/components/table/Table.js +1 -0
- package/dist/components/table/index.d.ts +2 -0
- package/dist/components/table/index.js +1 -0
- package/dist/components/tabs/Tabs.d.ts +92 -0
- package/dist/components/tabs/Tabs.js +1 -0
- package/dist/components/tabs/index.d.ts +2 -0
- package/dist/components/tabs/index.js +1 -0
- package/dist/components/text-field/TextField.d.ts +63 -0
- package/dist/components/text-field/TextField.js +1 -0
- package/dist/components/text-field/index.d.ts +2 -0
- package/dist/components/text-field/index.js +1 -0
- package/dist/components/toast/Toast.d.ts +116 -0
- package/dist/components/toast/Toast.js +1 -0
- package/dist/components/toast/index.d.ts +2 -0
- package/dist/components/toast/index.js +1 -0
- package/dist/components/tooltip/Tooltip.d.ts +81 -0
- package/dist/components/tooltip/Tooltip.js +1 -0
- package/dist/components/tooltip/index.d.ts +2 -0
- package/dist/components/tooltip/index.js +1 -0
- package/dist/components/typography/Typography.d.ts +62 -0
- package/dist/components/typography/Typography.js +1 -0
- package/dist/components/typography/index.d.ts +2 -0
- package/dist/components/typography/index.js +1 -0
- package/dist/index.d.ts +32 -1
- package/dist/index.js +1 -1
- package/dist/internal/button-group.d.ts +25 -0
- package/dist/internal/button-group.js +1 -0
- package/dist/internal/icons.d.ts +48 -0
- package/dist/internal/icons.js +1 -0
- package/dist/internal/menu.d.ts +20 -0
- package/dist/internal/menu.js +1 -0
- package/dist/internal/progress.d.ts +122 -0
- package/dist/internal/progress.js +1 -0
- package/dist/internal/styles.d.ts +224 -0
- package/dist/internal/styles.js +1 -0
- package/dist/styles.css +758 -0
- package/dist/types.d.ts +77 -0
- package/dist/types.js +8 -0
- package/package.json +75 -19
- package/pnpm-workspace.yaml +0 -2
package/dist/styles.css
ADDED
|
@@ -0,0 +1,758 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Neba design tokens.
|
|
3
|
+
*
|
|
4
|
+
* Consumers import this once, next to Tailwind:
|
|
5
|
+
*
|
|
6
|
+
* @import 'tailwindcss';
|
|
7
|
+
* @import 'neba/styles.css';
|
|
8
|
+
*
|
|
9
|
+
* Two lines, and no `@source` of their own — the `@source` below does that job.
|
|
10
|
+
* Components never hardcode a color; they map a `color` prop onto the `--n-*`
|
|
11
|
+
* local slots and let the cascade resolve the rest.
|
|
12
|
+
*
|
|
13
|
+
* Dark mode responds to `prefers-color-scheme`, and can be forced either way
|
|
14
|
+
* with `.dark` / `[data-theme='dark'|'light']` on any ancestor.
|
|
15
|
+
*
|
|
16
|
+
* The surface model is a sheet of acrylic, not a moulded plastic key: a
|
|
17
|
+
* slightly translucent fill, a blurred backdrop, and a hairline edge catching
|
|
18
|
+
* the light. Depth is not part of the surface — it is opt-in, via `elevation`.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
* The components' classes are Tailwind utilities, so Tailwind has to see the
|
|
23
|
+
* files that spell them out — otherwise every component renders unstyled.
|
|
24
|
+
*
|
|
25
|
+
* `@source` resolves relative to the file it is written in, not to whatever
|
|
26
|
+
* imported it. In a consumer's install that is `node_modules/neba/dist/`, next
|
|
27
|
+
* to the compiled components; in this repository it is `src/`, next to the
|
|
28
|
+
* `.tsx`. One line covers both, and an explicitly registered source is scanned
|
|
29
|
+
* even inside `node_modules`, which automatic detection skips.
|
|
30
|
+
*
|
|
31
|
+
* This is why consumers do not need an `@source '../node_modules/neba'` of
|
|
32
|
+
* their own — a path that would depend on where their CSS file happens to sit.
|
|
33
|
+
*/
|
|
34
|
+
@source '.';
|
|
35
|
+
|
|
36
|
+
/* ---------------------------------------------------------------------------
|
|
37
|
+
* Light theme (default)
|
|
38
|
+
* ------------------------------------------------------------------------- */
|
|
39
|
+
|
|
40
|
+
:root {
|
|
41
|
+
/* Neutral surfaces and content */
|
|
42
|
+
--neba-surface: oklch(100% 0 0);
|
|
43
|
+
--neba-fg: oklch(24% 0.015 262);
|
|
44
|
+
--neba-muted-fg: oklch(56% 0.014 262);
|
|
45
|
+
--neba-border: oklch(91% 0.008 262);
|
|
46
|
+
|
|
47
|
+
/* Inactive controls: muted neutral rather than a faded copy of the color.
|
|
48
|
+
A greyed-out surface reads as "unavailable"; 50% opacity just reads blurry. */
|
|
49
|
+
--neba-disabled-bg: oklch(94.5% 0.005 262);
|
|
50
|
+
--neba-disabled-fg: oklch(73% 0.012 262);
|
|
51
|
+
--neba-disabled-border: oklch(90% 0.008 262);
|
|
52
|
+
|
|
53
|
+
/* Acrylic -------------------------------------------------------------- */
|
|
54
|
+
|
|
55
|
+
/* How opaque a filled surface is, and how hard the backdrop is blurred.
|
|
56
|
+
The blur radius is what decides whether anything behind is *legible*: at
|
|
57
|
+
16px a grid line behind the button smears into flat colour and the surface
|
|
58
|
+
reads opaque no matter how low the alpha goes. Held at 9px so the backdrop
|
|
59
|
+
is present but never resolves into something you could read.
|
|
60
|
+
88% is the floor for 4.5:1 white-on-fill over a white page; fill lightness
|
|
61
|
+
is picked against this number, not against opaque. */
|
|
62
|
+
--neba-fill-alpha: 88%;
|
|
63
|
+
--neba-blur: blur(9px) saturate(1.5);
|
|
64
|
+
|
|
65
|
+
/* Frosted, not polished. A single tile of greyscale fractal noise laid over
|
|
66
|
+
the fill in `overlay` is what separates sandblasted acrylic from a pane of
|
|
67
|
+
glass — and it is the one thing a flat fill can never fake. Kept at 12% in
|
|
68
|
+
the tile and blended, so it reads as tooth rather than as dirt.
|
|
69
|
+
One 120px tile, decoded once, reused by every surface on the page. */
|
|
70
|
+
--neba-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='0.12'/%3E%3C/svg%3E");
|
|
71
|
+
|
|
72
|
+
/* The hairline that reads as the cut edge of an acrylic sheet, plus the
|
|
73
|
+
brighter top edge where the light lands. There is deliberately no dark
|
|
74
|
+
bottom bevel — that is what made the surface read as moulded plastic. */
|
|
75
|
+
--neba-plate-edge: rgb(255 255 255 / 0.18);
|
|
76
|
+
--neba-plate-top: rgb(255 255 255 / 0.26);
|
|
77
|
+
--neba-plate-solid: inset 0 1px 0 var(--neba-plate-top), inset 0 0 0 1px var(--neba-plate-edge);
|
|
78
|
+
--neba-plate-glass: inset 0 1px 0 var(--neba-plate-top);
|
|
79
|
+
/* Off-vertical on purpose: light falling across a sheet at an angle, rather
|
|
80
|
+
than the symmetric top-down gradient every framework ships. */
|
|
81
|
+
--neba-sheen: linear-gradient(148deg, rgb(255 255 255 / 0.13), rgb(255 255 255 / 0) 52%);
|
|
82
|
+
|
|
83
|
+
/* The acrylic with no dye in it — what a colored panel is mixed *into*.
|
|
84
|
+
|
|
85
|
+
At 42% the sheet was letting through more of the page than of itself, so on
|
|
86
|
+
any backdrop that is not pure white it settled into grey. Raising it to 66%
|
|
87
|
+
is the one place alpha is the right lever rather than the blur: the blur
|
|
88
|
+
decides whether the backdrop is *legible*, and 9px still hides it. This
|
|
89
|
+
decides whether the sheet reads as white, and it has to. */
|
|
90
|
+
--neba-glass-bg: rgb(255 255 255 / 0.66);
|
|
91
|
+
|
|
92
|
+
/* The container surface, in the three strengths a panel-shaped component
|
|
93
|
+
needs — Box, Card and TextField read these directly.
|
|
94
|
+
|
|
95
|
+
Undyed on purpose, and this is the one place the color family deliberately
|
|
96
|
+
stops at the edge. A container holds other people's content, which arrives
|
|
97
|
+
with its own colors; tinting the sheet under it puts every one of them on a
|
|
98
|
+
background they were not chosen against. So the family shows up in the
|
|
99
|
+
hairline, the focus ring and the caret, and the sheet stays white.
|
|
100
|
+
|
|
101
|
+
Controls are the opposite case and keep their tinted `--neba-{color}-panel`:
|
|
102
|
+
a Button's surface *is* the thing being colored.
|
|
103
|
+
|
|
104
|
+
The ladder is opacity, not lightness — the sheet catches more light as it
|
|
105
|
+
is engaged, rather than turning grey. */
|
|
106
|
+
--neba-panel: rgb(255 255 255 / 0.66);
|
|
107
|
+
--neba-panel-hover: rgb(255 255 255 / 0.82);
|
|
108
|
+
--neba-panel-press: rgb(255 255 255 / 0.92);
|
|
109
|
+
|
|
110
|
+
/* Pointer spotlight and release afterglow, over a filled surface. Tinted
|
|
111
|
+
variants use their own accent instead — see the derived block. The flash is
|
|
112
|
+
only a shade brighter than the spotlight it replaces: the press is carried
|
|
113
|
+
by the fill going dark, and this is the highlight riding on top of it, not
|
|
114
|
+
the effect itself. */
|
|
115
|
+
--neba-glow-on-fill: rgb(255 255 255 / 0.16);
|
|
116
|
+
--neba-flash-on-fill: rgb(255 255 255 / 0.22);
|
|
117
|
+
|
|
118
|
+
/* The scrim behind a modal surface. Neutral rather than tinted, and dim
|
|
119
|
+
rather than opaque: what a dialog needs is for the page to stop being
|
|
120
|
+
reachable, not for it to stop existing. */
|
|
121
|
+
--neba-scrim: rgb(16 24 40 / 0.34);
|
|
122
|
+
|
|
123
|
+
/* Elevation ------------------------------------------------------------
|
|
124
|
+
Neutral, never tinted with the control's own color: a colored glow is the
|
|
125
|
+
loudest thing a small control can do, and the job here is to place a
|
|
126
|
+
surface in space, not to advertise it. Level 4 is only reachable by
|
|
127
|
+
hovering a level-3 surface. */
|
|
128
|
+
--neba-shadow-ambient: rgb(16 24 40 / 0.13);
|
|
129
|
+
--neba-shadow-0: 0 0 #0000;
|
|
130
|
+
--neba-shadow-1: 0 1px 2px -1px var(--neba-shadow-ambient);
|
|
131
|
+
--neba-shadow-2:
|
|
132
|
+
0 2px 4px -2px var(--neba-shadow-ambient), 0 5px 12px -7px var(--neba-shadow-ambient);
|
|
133
|
+
--neba-shadow-3:
|
|
134
|
+
0 4px 8px -3px var(--neba-shadow-ambient), 0 12px 24px -11px var(--neba-shadow-ambient);
|
|
135
|
+
--neba-shadow-4:
|
|
136
|
+
0 6px 12px -4px var(--neba-shadow-ambient), 0 20px 40px -15px var(--neba-shadow-ambient);
|
|
137
|
+
|
|
138
|
+
/* Corner radius: ~45% of the control height at every step. Held just short of
|
|
139
|
+
the 50% that would make it a pill — the flat run along the top and bottom
|
|
140
|
+
edge is what still reads as a sheet with corners cut off it. */
|
|
141
|
+
--neba-radius-xs: 0.625rem;
|
|
142
|
+
--neba-radius-sm: 0.75rem;
|
|
143
|
+
--neba-radius-md: 0.875rem;
|
|
144
|
+
--neba-radius-lg: 1.125rem;
|
|
145
|
+
--neba-radius-xl: 1.375rem;
|
|
146
|
+
|
|
147
|
+
/* Motion. Controls answer in color and depth, never by moving: a transform on
|
|
148
|
+
a control drags its label with it, and text that shifts under the cursor is
|
|
149
|
+
the thing that reads as cheap. */
|
|
150
|
+
--neba-ease: cubic-bezier(0.32, 0.72, 0, 1);
|
|
151
|
+
--neba-duration: 160ms;
|
|
152
|
+
/* Fills settle more slowly than edges and shadows. Pressing overrides this to
|
|
153
|
+
0ms, so the colour lands on the frame of the click and then takes this long
|
|
154
|
+
to drain back out — the button itself holds the press, not just the bloom
|
|
155
|
+
under the cursor. */
|
|
156
|
+
--neba-duration-fill: 340ms;
|
|
157
|
+
|
|
158
|
+
/* Color families -------------------------------------------------------
|
|
159
|
+
Chroma sits just under the sRGB gamut boundary for each family's lightness
|
|
160
|
+
— around 90% of the maximum, close enough to be vivid and far enough that
|
|
161
|
+
the browser never has to clip. The old values used about two thirds of what
|
|
162
|
+
was available, which is what made the palette read muddy: the fills were
|
|
163
|
+
not too dark, they were too grey.
|
|
164
|
+
|
|
165
|
+
Lightness is not the free variable it looks like. `on-solid` is white, the
|
|
166
|
+
fill is only 88% opaque, and the pair has to clear 4.5:1 over a white page
|
|
167
|
+
— which pins every family with white text to the high 40s / low 50s. A
|
|
168
|
+
brighter *fill* means a dark ink, which is why `warning` is the one family
|
|
169
|
+
that already goes there. Verified per step, including hover and active.
|
|
170
|
+
|
|
171
|
+
`success` moved 152 → 148 and `info` 218 → 223. Both are hue regions where
|
|
172
|
+
sRGB is starved at mid lightness, and a few degrees toward the gamut's wide
|
|
173
|
+
side buys chroma that no amount of tuning at the original hue could. */
|
|
174
|
+
|
|
175
|
+
--neba-primary-solid: oklch(50% 0.198 262);
|
|
176
|
+
--neba-primary-solid-hover: oklch(45.5% 0.196 262);
|
|
177
|
+
--neba-primary-solid-active: oklch(38% 0.172 262);
|
|
178
|
+
--neba-primary-on-solid: oklch(99% 0.004 262);
|
|
179
|
+
--neba-primary-accent: oklch(55% 0.222 262);
|
|
180
|
+
|
|
181
|
+
--neba-secondary-solid: oklch(48% 0.038 262);
|
|
182
|
+
--neba-secondary-solid-hover: oklch(43.5% 0.036 262);
|
|
183
|
+
--neba-secondary-solid-active: oklch(36% 0.03 262);
|
|
184
|
+
--neba-secondary-on-solid: oklch(99% 0.003 262);
|
|
185
|
+
--neba-secondary-accent: oklch(54% 0.045 262);
|
|
186
|
+
|
|
187
|
+
--neba-success-solid: oklch(48.5% 0.136 148);
|
|
188
|
+
--neba-success-solid-hover: oklch(44% 0.126 148);
|
|
189
|
+
--neba-success-solid-active: oklch(36.5% 0.106 148);
|
|
190
|
+
--neba-success-on-solid: oklch(99% 0.004 148);
|
|
191
|
+
--neba-success-accent: oklch(52.5% 0.143 148);
|
|
192
|
+
|
|
193
|
+
--neba-warning-solid: oklch(80% 0.146 80);
|
|
194
|
+
--neba-warning-solid-hover: oklch(75.5% 0.148 78);
|
|
195
|
+
--neba-warning-solid-active: oklch(66.5% 0.14 74);
|
|
196
|
+
--neba-warning-on-solid: oklch(28% 0.06 70);
|
|
197
|
+
--neba-warning-accent: oklch(54.5% 0.111 68);
|
|
198
|
+
|
|
199
|
+
--neba-danger-solid: oklch(52.5% 0.194 30);
|
|
200
|
+
--neba-danger-solid-hover: oklch(48% 0.186 30);
|
|
201
|
+
--neba-danger-solid-active: oklch(40.5% 0.162 30);
|
|
202
|
+
--neba-danger-on-solid: oklch(99% 0.004 30);
|
|
203
|
+
--neba-danger-accent: oklch(56.5% 0.212 30);
|
|
204
|
+
|
|
205
|
+
--neba-info-solid: oklch(48.5% 0.088 223);
|
|
206
|
+
--neba-info-solid-hover: oklch(44% 0.081 223);
|
|
207
|
+
--neba-info-solid-active: oklch(36.5% 0.068 223);
|
|
208
|
+
--neba-info-on-solid: oklch(99% 0.004 223);
|
|
209
|
+
--neba-info-accent: oklch(53.5% 0.096 223);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/* ---------------------------------------------------------------------------
|
|
213
|
+
* Dark theme
|
|
214
|
+
*
|
|
215
|
+
* Fills stay mid-tone rather than pale, so a filled button on a dark surface
|
|
216
|
+
* does not glare; the readable-on-surface `accent` is what lightens.
|
|
217
|
+
* ------------------------------------------------------------------------- */
|
|
218
|
+
|
|
219
|
+
@media (prefers-color-scheme: dark) {
|
|
220
|
+
:root:not(.light):not([data-theme='light']) {
|
|
221
|
+
--neba-surface: oklch(19% 0.012 262);
|
|
222
|
+
--neba-fg: oklch(95% 0.008 262);
|
|
223
|
+
--neba-muted-fg: oklch(66% 0.014 262);
|
|
224
|
+
--neba-border: oklch(30% 0.012 262);
|
|
225
|
+
|
|
226
|
+
--neba-disabled-bg: oklch(27% 0.012 262);
|
|
227
|
+
--neba-disabled-fg: oklch(48% 0.012 262);
|
|
228
|
+
--neba-disabled-border: oklch(32% 0.012 262);
|
|
229
|
+
|
|
230
|
+
--neba-fill-alpha: 87%;
|
|
231
|
+
--neba-blur: blur(9px) saturate(1.3);
|
|
232
|
+
|
|
233
|
+
--neba-plate-edge: rgb(255 255 255 / 0.12);
|
|
234
|
+
--neba-plate-top: rgb(255 255 255 / 0.16);
|
|
235
|
+
--neba-sheen: linear-gradient(148deg, rgb(255 255 255 / 0.09), rgb(255 255 255 / 0) 52%);
|
|
236
|
+
|
|
237
|
+
--neba-glass-bg: rgb(255 255 255 / 0.07);
|
|
238
|
+
|
|
239
|
+
--neba-panel: rgb(255 255 255 / 0.07);
|
|
240
|
+
--neba-panel-hover: rgb(255 255 255 / 0.1);
|
|
241
|
+
--neba-panel-press: rgb(255 255 255 / 0.13);
|
|
242
|
+
|
|
243
|
+
--neba-glow-on-fill: rgb(255 255 255 / 0.13);
|
|
244
|
+
--neba-flash-on-fill: rgb(255 255 255 / 0.18);
|
|
245
|
+
|
|
246
|
+
--neba-scrim: rgb(0 0 0 / 0.58);
|
|
247
|
+
|
|
248
|
+
--neba-shadow-ambient: rgb(0 0 0 / 0.55);
|
|
249
|
+
|
|
250
|
+
--neba-primary-solid: oklch(57% 0.208 262);
|
|
251
|
+
--neba-primary-solid-hover: oklch(62% 0.181 262);
|
|
252
|
+
--neba-primary-solid-active: oklch(48% 0.196 262);
|
|
253
|
+
--neba-primary-on-solid: oklch(99% 0.004 262);
|
|
254
|
+
--neba-primary-accent: oklch(78% 0.103 262);
|
|
255
|
+
|
|
256
|
+
--neba-secondary-solid: oklch(50% 0.036 262);
|
|
257
|
+
--neba-secondary-solid-hover: oklch(55% 0.036 262);
|
|
258
|
+
--neba-secondary-solid-active: oklch(41% 0.03 262);
|
|
259
|
+
--neba-secondary-on-solid: oklch(99% 0.003 262);
|
|
260
|
+
--neba-secondary-accent: oklch(78% 0.026 262);
|
|
261
|
+
|
|
262
|
+
--neba-success-solid: oklch(54% 0.147 148);
|
|
263
|
+
--neba-success-solid-hover: oklch(59% 0.161 148);
|
|
264
|
+
--neba-success-solid-active: oklch(45% 0.123 148);
|
|
265
|
+
--neba-success-on-solid: oklch(99% 0.004 148);
|
|
266
|
+
--neba-success-accent: oklch(78% 0.17 148);
|
|
267
|
+
|
|
268
|
+
--neba-warning-solid: oklch(76% 0.145 80);
|
|
269
|
+
--neba-warning-solid-hover: oklch(81% 0.154 80);
|
|
270
|
+
--neba-warning-solid-active: oklch(66% 0.126 80);
|
|
271
|
+
--neba-warning-on-solid: oklch(25% 0.06 70);
|
|
272
|
+
--neba-warning-accent: oklch(82% 0.14 80);
|
|
273
|
+
|
|
274
|
+
--neba-danger-solid: oklch(55% 0.207 30);
|
|
275
|
+
--neba-danger-solid-hover: oklch(60% 0.226 30);
|
|
276
|
+
--neba-danger-solid-active: oklch(46% 0.174 30);
|
|
277
|
+
--neba-danger-on-solid: oklch(99% 0.004 30);
|
|
278
|
+
--neba-danger-accent: oklch(76% 0.136 32);
|
|
279
|
+
|
|
280
|
+
--neba-info-solid: oklch(55% 0.098 223);
|
|
281
|
+
--neba-info-solid-hover: oklch(60% 0.107 223);
|
|
282
|
+
--neba-info-solid-active: oklch(46% 0.082 223);
|
|
283
|
+
--neba-info-on-solid: oklch(99% 0.004 223);
|
|
284
|
+
--neba-info-accent: oklch(79% 0.11 223);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.dark,
|
|
289
|
+
[data-theme='dark'] {
|
|
290
|
+
--neba-surface: oklch(19% 0.012 262);
|
|
291
|
+
--neba-fg: oklch(95% 0.008 262);
|
|
292
|
+
--neba-muted-fg: oklch(66% 0.014 262);
|
|
293
|
+
--neba-border: oklch(30% 0.012 262);
|
|
294
|
+
|
|
295
|
+
--neba-disabled-bg: oklch(27% 0.012 262);
|
|
296
|
+
--neba-disabled-fg: oklch(48% 0.012 262);
|
|
297
|
+
--neba-disabled-border: oklch(32% 0.012 262);
|
|
298
|
+
|
|
299
|
+
--neba-fill-alpha: 87%;
|
|
300
|
+
--neba-blur: blur(9px) saturate(1.3);
|
|
301
|
+
|
|
302
|
+
--neba-plate-edge: rgb(255 255 255 / 0.12);
|
|
303
|
+
--neba-plate-top: rgb(255 255 255 / 0.16);
|
|
304
|
+
--neba-sheen: linear-gradient(148deg, rgb(255 255 255 / 0.09), rgb(255 255 255 / 0) 52%);
|
|
305
|
+
|
|
306
|
+
--neba-glass-bg: rgb(255 255 255 / 0.07);
|
|
307
|
+
|
|
308
|
+
--neba-panel: rgb(255 255 255 / 0.07);
|
|
309
|
+
--neba-panel-hover: rgb(255 255 255 / 0.1);
|
|
310
|
+
--neba-panel-press: rgb(255 255 255 / 0.13);
|
|
311
|
+
|
|
312
|
+
--neba-glow-on-fill: rgb(255 255 255 / 0.13);
|
|
313
|
+
--neba-flash-on-fill: rgb(255 255 255 / 0.18);
|
|
314
|
+
|
|
315
|
+
--neba-scrim: rgb(0 0 0 / 0.58);
|
|
316
|
+
|
|
317
|
+
--neba-shadow-ambient: rgb(0 0 0 / 0.55);
|
|
318
|
+
|
|
319
|
+
--neba-primary-solid: oklch(57% 0.208 262);
|
|
320
|
+
--neba-primary-solid-hover: oklch(62% 0.181 262);
|
|
321
|
+
--neba-primary-solid-active: oklch(48% 0.196 262);
|
|
322
|
+
--neba-primary-on-solid: oklch(99% 0.004 262);
|
|
323
|
+
--neba-primary-accent: oklch(78% 0.103 262);
|
|
324
|
+
|
|
325
|
+
--neba-secondary-solid: oklch(50% 0.036 262);
|
|
326
|
+
--neba-secondary-solid-hover: oklch(55% 0.036 262);
|
|
327
|
+
--neba-secondary-solid-active: oklch(41% 0.03 262);
|
|
328
|
+
--neba-secondary-on-solid: oklch(99% 0.003 262);
|
|
329
|
+
--neba-secondary-accent: oklch(78% 0.026 262);
|
|
330
|
+
|
|
331
|
+
--neba-success-solid: oklch(54% 0.147 148);
|
|
332
|
+
--neba-success-solid-hover: oklch(59% 0.161 148);
|
|
333
|
+
--neba-success-solid-active: oklch(45% 0.123 148);
|
|
334
|
+
--neba-success-on-solid: oklch(99% 0.004 148);
|
|
335
|
+
--neba-success-accent: oklch(78% 0.17 148);
|
|
336
|
+
|
|
337
|
+
--neba-warning-solid: oklch(76% 0.145 80);
|
|
338
|
+
--neba-warning-solid-hover: oklch(81% 0.154 80);
|
|
339
|
+
--neba-warning-solid-active: oklch(66% 0.126 80);
|
|
340
|
+
--neba-warning-on-solid: oklch(25% 0.06 70);
|
|
341
|
+
--neba-warning-accent: oklch(82% 0.14 80);
|
|
342
|
+
|
|
343
|
+
--neba-danger-solid: oklch(55% 0.207 30);
|
|
344
|
+
--neba-danger-solid-hover: oklch(60% 0.226 30);
|
|
345
|
+
--neba-danger-solid-active: oklch(46% 0.174 30);
|
|
346
|
+
--neba-danger-on-solid: oklch(99% 0.004 30);
|
|
347
|
+
--neba-danger-accent: oklch(76% 0.136 32);
|
|
348
|
+
|
|
349
|
+
--neba-info-solid: oklch(55% 0.098 223);
|
|
350
|
+
--neba-info-solid-hover: oklch(60% 0.107 223);
|
|
351
|
+
--neba-info-solid-active: oklch(46% 0.082 223);
|
|
352
|
+
--neba-info-on-solid: oklch(99% 0.004 223);
|
|
353
|
+
--neba-info-accent: oklch(79% 0.11 223);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/* ---------------------------------------------------------------------------
|
|
357
|
+
* Derived tokens
|
|
358
|
+
*
|
|
359
|
+
* Fills, tints, hairlines and focus rings are all one base color at different
|
|
360
|
+
* strengths, so they are computed rather than hand-picked per theme. This block
|
|
361
|
+
* is repeated for every theme root because a custom property resolves its
|
|
362
|
+
* `var()`s on the element that declares it — declaring these only on `:root`
|
|
363
|
+
* would freeze them to the light values inside a `.dark` subtree.
|
|
364
|
+
* ------------------------------------------------------------------------- */
|
|
365
|
+
|
|
366
|
+
:root,
|
|
367
|
+
.dark,
|
|
368
|
+
.light,
|
|
369
|
+
[data-theme='dark'],
|
|
370
|
+
[data-theme='light'] {
|
|
371
|
+
--neba-primary-fill: color-mix(
|
|
372
|
+
in srgb,
|
|
373
|
+
var(--neba-primary-solid) var(--neba-fill-alpha),
|
|
374
|
+
transparent
|
|
375
|
+
);
|
|
376
|
+
--neba-primary-fill-hover: color-mix(
|
|
377
|
+
in srgb,
|
|
378
|
+
var(--neba-primary-solid-hover) var(--neba-fill-alpha),
|
|
379
|
+
transparent
|
|
380
|
+
);
|
|
381
|
+
--neba-primary-fill-active: color-mix(
|
|
382
|
+
in srgb,
|
|
383
|
+
var(--neba-primary-solid-active) var(--neba-fill-alpha),
|
|
384
|
+
transparent
|
|
385
|
+
);
|
|
386
|
+
--neba-primary-soft: color-mix(in srgb, var(--neba-primary-accent) 10%, transparent);
|
|
387
|
+
--neba-primary-soft-hover: color-mix(in srgb, var(--neba-primary-accent) 17%, transparent);
|
|
388
|
+
--neba-primary-soft-press: color-mix(in srgb, var(--neba-primary-accent) 25%, transparent);
|
|
389
|
+
--neba-primary-panel: color-mix(in srgb, var(--neba-primary-accent) 8%, var(--neba-glass-bg));
|
|
390
|
+
--neba-primary-panel-hover: color-mix(
|
|
391
|
+
in srgb,
|
|
392
|
+
var(--neba-primary-accent) 16%,
|
|
393
|
+
var(--neba-glass-bg)
|
|
394
|
+
);
|
|
395
|
+
--neba-primary-panel-press: color-mix(
|
|
396
|
+
in srgb,
|
|
397
|
+
var(--neba-primary-accent) 24%,
|
|
398
|
+
var(--neba-glass-bg)
|
|
399
|
+
);
|
|
400
|
+
--neba-primary-line: color-mix(in srgb, var(--neba-primary-accent) 22%, transparent);
|
|
401
|
+
--neba-primary-line-hover: color-mix(in srgb, var(--neba-primary-accent) 40%, transparent);
|
|
402
|
+
--neba-primary-ring: color-mix(in srgb, var(--neba-primary-accent) 55%, transparent);
|
|
403
|
+
|
|
404
|
+
--neba-secondary-fill: color-mix(
|
|
405
|
+
in srgb,
|
|
406
|
+
var(--neba-secondary-solid) var(--neba-fill-alpha),
|
|
407
|
+
transparent
|
|
408
|
+
);
|
|
409
|
+
--neba-secondary-fill-hover: color-mix(
|
|
410
|
+
in srgb,
|
|
411
|
+
var(--neba-secondary-solid-hover) var(--neba-fill-alpha),
|
|
412
|
+
transparent
|
|
413
|
+
);
|
|
414
|
+
--neba-secondary-fill-active: color-mix(
|
|
415
|
+
in srgb,
|
|
416
|
+
var(--neba-secondary-solid-active) var(--neba-fill-alpha),
|
|
417
|
+
transparent
|
|
418
|
+
);
|
|
419
|
+
--neba-secondary-soft: color-mix(in srgb, var(--neba-secondary-accent) 10%, transparent);
|
|
420
|
+
--neba-secondary-soft-hover: color-mix(in srgb, var(--neba-secondary-accent) 17%, transparent);
|
|
421
|
+
--neba-secondary-soft-press: color-mix(in srgb, var(--neba-secondary-accent) 25%, transparent);
|
|
422
|
+
--neba-secondary-panel: color-mix(in srgb, var(--neba-secondary-accent) 8%, var(--neba-glass-bg));
|
|
423
|
+
--neba-secondary-panel-hover: color-mix(
|
|
424
|
+
in srgb,
|
|
425
|
+
var(--neba-secondary-accent) 16%,
|
|
426
|
+
var(--neba-glass-bg)
|
|
427
|
+
);
|
|
428
|
+
--neba-secondary-panel-press: color-mix(
|
|
429
|
+
in srgb,
|
|
430
|
+
var(--neba-secondary-accent) 24%,
|
|
431
|
+
var(--neba-glass-bg)
|
|
432
|
+
);
|
|
433
|
+
--neba-secondary-line: color-mix(in srgb, var(--neba-secondary-accent) 22%, transparent);
|
|
434
|
+
--neba-secondary-line-hover: color-mix(in srgb, var(--neba-secondary-accent) 40%, transparent);
|
|
435
|
+
--neba-secondary-ring: color-mix(in srgb, var(--neba-secondary-accent) 55%, transparent);
|
|
436
|
+
|
|
437
|
+
--neba-success-fill: color-mix(
|
|
438
|
+
in srgb,
|
|
439
|
+
var(--neba-success-solid) var(--neba-fill-alpha),
|
|
440
|
+
transparent
|
|
441
|
+
);
|
|
442
|
+
--neba-success-fill-hover: color-mix(
|
|
443
|
+
in srgb,
|
|
444
|
+
var(--neba-success-solid-hover) var(--neba-fill-alpha),
|
|
445
|
+
transparent
|
|
446
|
+
);
|
|
447
|
+
--neba-success-fill-active: color-mix(
|
|
448
|
+
in srgb,
|
|
449
|
+
var(--neba-success-solid-active) var(--neba-fill-alpha),
|
|
450
|
+
transparent
|
|
451
|
+
);
|
|
452
|
+
--neba-success-soft: color-mix(in srgb, var(--neba-success-accent) 10%, transparent);
|
|
453
|
+
--neba-success-soft-hover: color-mix(in srgb, var(--neba-success-accent) 17%, transparent);
|
|
454
|
+
--neba-success-soft-press: color-mix(in srgb, var(--neba-success-accent) 25%, transparent);
|
|
455
|
+
--neba-success-panel: color-mix(in srgb, var(--neba-success-accent) 8%, var(--neba-glass-bg));
|
|
456
|
+
--neba-success-panel-hover: color-mix(
|
|
457
|
+
in srgb,
|
|
458
|
+
var(--neba-success-accent) 16%,
|
|
459
|
+
var(--neba-glass-bg)
|
|
460
|
+
);
|
|
461
|
+
--neba-success-panel-press: color-mix(
|
|
462
|
+
in srgb,
|
|
463
|
+
var(--neba-success-accent) 24%,
|
|
464
|
+
var(--neba-glass-bg)
|
|
465
|
+
);
|
|
466
|
+
--neba-success-line: color-mix(in srgb, var(--neba-success-accent) 22%, transparent);
|
|
467
|
+
--neba-success-line-hover: color-mix(in srgb, var(--neba-success-accent) 40%, transparent);
|
|
468
|
+
--neba-success-ring: color-mix(in srgb, var(--neba-success-accent) 55%, transparent);
|
|
469
|
+
|
|
470
|
+
--neba-warning-fill: color-mix(
|
|
471
|
+
in srgb,
|
|
472
|
+
var(--neba-warning-solid) var(--neba-fill-alpha),
|
|
473
|
+
transparent
|
|
474
|
+
);
|
|
475
|
+
--neba-warning-fill-hover: color-mix(
|
|
476
|
+
in srgb,
|
|
477
|
+
var(--neba-warning-solid-hover) var(--neba-fill-alpha),
|
|
478
|
+
transparent
|
|
479
|
+
);
|
|
480
|
+
--neba-warning-fill-active: color-mix(
|
|
481
|
+
in srgb,
|
|
482
|
+
var(--neba-warning-solid-active) var(--neba-fill-alpha),
|
|
483
|
+
transparent
|
|
484
|
+
);
|
|
485
|
+
--neba-warning-soft: color-mix(in srgb, var(--neba-warning-accent) 12%, transparent);
|
|
486
|
+
--neba-warning-soft-hover: color-mix(in srgb, var(--neba-warning-accent) 20%, transparent);
|
|
487
|
+
--neba-warning-soft-press: color-mix(in srgb, var(--neba-warning-accent) 28%, transparent);
|
|
488
|
+
--neba-warning-panel: color-mix(in srgb, var(--neba-warning-accent) 8%, var(--neba-glass-bg));
|
|
489
|
+
--neba-warning-panel-hover: color-mix(
|
|
490
|
+
in srgb,
|
|
491
|
+
var(--neba-warning-accent) 16%,
|
|
492
|
+
var(--neba-glass-bg)
|
|
493
|
+
);
|
|
494
|
+
--neba-warning-panel-press: color-mix(
|
|
495
|
+
in srgb,
|
|
496
|
+
var(--neba-warning-accent) 24%,
|
|
497
|
+
var(--neba-glass-bg)
|
|
498
|
+
);
|
|
499
|
+
--neba-warning-line: color-mix(in srgb, var(--neba-warning-accent) 26%, transparent);
|
|
500
|
+
--neba-warning-line-hover: color-mix(in srgb, var(--neba-warning-accent) 44%, transparent);
|
|
501
|
+
--neba-warning-ring: color-mix(in srgb, var(--neba-warning-accent) 55%, transparent);
|
|
502
|
+
|
|
503
|
+
--neba-danger-fill: color-mix(
|
|
504
|
+
in srgb,
|
|
505
|
+
var(--neba-danger-solid) var(--neba-fill-alpha),
|
|
506
|
+
transparent
|
|
507
|
+
);
|
|
508
|
+
--neba-danger-fill-hover: color-mix(
|
|
509
|
+
in srgb,
|
|
510
|
+
var(--neba-danger-solid-hover) var(--neba-fill-alpha),
|
|
511
|
+
transparent
|
|
512
|
+
);
|
|
513
|
+
--neba-danger-fill-active: color-mix(
|
|
514
|
+
in srgb,
|
|
515
|
+
var(--neba-danger-solid-active) var(--neba-fill-alpha),
|
|
516
|
+
transparent
|
|
517
|
+
);
|
|
518
|
+
--neba-danger-soft: color-mix(in srgb, var(--neba-danger-accent) 10%, transparent);
|
|
519
|
+
--neba-danger-soft-hover: color-mix(in srgb, var(--neba-danger-accent) 17%, transparent);
|
|
520
|
+
--neba-danger-soft-press: color-mix(in srgb, var(--neba-danger-accent) 25%, transparent);
|
|
521
|
+
--neba-danger-panel: color-mix(in srgb, var(--neba-danger-accent) 8%, var(--neba-glass-bg));
|
|
522
|
+
--neba-danger-panel-hover: color-mix(
|
|
523
|
+
in srgb,
|
|
524
|
+
var(--neba-danger-accent) 16%,
|
|
525
|
+
var(--neba-glass-bg)
|
|
526
|
+
);
|
|
527
|
+
--neba-danger-panel-press: color-mix(
|
|
528
|
+
in srgb,
|
|
529
|
+
var(--neba-danger-accent) 24%,
|
|
530
|
+
var(--neba-glass-bg)
|
|
531
|
+
);
|
|
532
|
+
--neba-danger-line: color-mix(in srgb, var(--neba-danger-accent) 22%, transparent);
|
|
533
|
+
--neba-danger-line-hover: color-mix(in srgb, var(--neba-danger-accent) 40%, transparent);
|
|
534
|
+
--neba-danger-ring: color-mix(in srgb, var(--neba-danger-accent) 55%, transparent);
|
|
535
|
+
|
|
536
|
+
--neba-info-fill: color-mix(in srgb, var(--neba-info-solid) var(--neba-fill-alpha), transparent);
|
|
537
|
+
--neba-info-fill-hover: color-mix(
|
|
538
|
+
in srgb,
|
|
539
|
+
var(--neba-info-solid-hover) var(--neba-fill-alpha),
|
|
540
|
+
transparent
|
|
541
|
+
);
|
|
542
|
+
--neba-info-fill-active: color-mix(
|
|
543
|
+
in srgb,
|
|
544
|
+
var(--neba-info-solid-active) var(--neba-fill-alpha),
|
|
545
|
+
transparent
|
|
546
|
+
);
|
|
547
|
+
--neba-info-soft: color-mix(in srgb, var(--neba-info-accent) 10%, transparent);
|
|
548
|
+
--neba-info-soft-hover: color-mix(in srgb, var(--neba-info-accent) 17%, transparent);
|
|
549
|
+
--neba-info-soft-press: color-mix(in srgb, var(--neba-info-accent) 25%, transparent);
|
|
550
|
+
--neba-info-panel: color-mix(in srgb, var(--neba-info-accent) 8%, var(--neba-glass-bg));
|
|
551
|
+
--neba-info-panel-hover: color-mix(in srgb, var(--neba-info-accent) 16%, var(--neba-glass-bg));
|
|
552
|
+
--neba-info-panel-press: color-mix(in srgb, var(--neba-info-accent) 24%, var(--neba-glass-bg));
|
|
553
|
+
--neba-info-line: color-mix(in srgb, var(--neba-info-accent) 22%, transparent);
|
|
554
|
+
--neba-info-line-hover: color-mix(in srgb, var(--neba-info-accent) 40%, transparent);
|
|
555
|
+
--neba-info-ring: color-mix(in srgb, var(--neba-info-accent) 55%, transparent);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/* ---------------------------------------------------------------------------
|
|
559
|
+
* Sheet titles
|
|
560
|
+
*
|
|
561
|
+
* A `title` is styled by the element the component renders around it — Card,
|
|
562
|
+
* Alert and Dialog all do this — so a plain string needs nothing. But a sheet
|
|
563
|
+
* that belongs in the document outline has to be given a real heading,
|
|
564
|
+
* `title={<h2>…</h2>}`, and that heading arrives with the browser's own 1.5em
|
|
565
|
+
* bold and its margins, which would ignore the type scale just set.
|
|
566
|
+
*
|
|
567
|
+
* This is in CSS rather than in Tailwind because the selector is the point:
|
|
568
|
+
* `[&_:where(h1,h2,h3,h4,h5,h6)]:[font:inherit]` is expressible and nobody
|
|
569
|
+
* would want to read it twice.
|
|
570
|
+
* ------------------------------------------------------------------------- */
|
|
571
|
+
|
|
572
|
+
.neba-title :where(h1, h2, h3, h4, h5, h6) {
|
|
573
|
+
font: inherit;
|
|
574
|
+
margin: 0;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/* ---------------------------------------------------------------------------
|
|
578
|
+
* Interaction light
|
|
579
|
+
*
|
|
580
|
+
* Two stacked layers on an interactive surface, both reading `--n-mx`/`--n-my`
|
|
581
|
+
* — the pointer position, written straight to the element's inline style on
|
|
582
|
+
* `pointermove` — and both no-ops until those slots have colour in them.
|
|
583
|
+
*
|
|
584
|
+
* This lives in CSS rather than in Tailwind arbitrary variants because the
|
|
585
|
+
* selectors are pseudo-elements carrying gradients: `[&::before]:[background:
|
|
586
|
+
* radial-gradient(...)]` is technically expressible and completely unreadable.
|
|
587
|
+
*
|
|
588
|
+
* Cost per hovered button: two composited layers and a gradient repaint of one
|
|
589
|
+
* small box, on frames the pointer already moved in. Nothing reflows, and React
|
|
590
|
+
* never re-renders — the component writes the two custom properties directly.
|
|
591
|
+
* ------------------------------------------------------------------------- */
|
|
592
|
+
|
|
593
|
+
.neba-glow::before,
|
|
594
|
+
.neba-glow::after {
|
|
595
|
+
content: '';
|
|
596
|
+
position: absolute;
|
|
597
|
+
inset: 0;
|
|
598
|
+
border-radius: inherit;
|
|
599
|
+
pointer-events: none;
|
|
600
|
+
opacity: 0;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/* Pointer spotlight: a soft bloom trailing the cursor across the surface. */
|
|
604
|
+
.neba-glow::before {
|
|
605
|
+
background: radial-gradient(
|
|
606
|
+
5.5rem circle at var(--n-mx, 50%) var(--n-my, 50%),
|
|
607
|
+
var(--n-glow, transparent),
|
|
608
|
+
transparent 70%
|
|
609
|
+
);
|
|
610
|
+
transition: opacity 240ms var(--neba-ease);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
@media (hover: hover) {
|
|
614
|
+
.neba-glow:hover::before {
|
|
615
|
+
opacity: 1;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/*
|
|
620
|
+
* Release afterglow. The asymmetry is the whole trick: 0ms in, ~900ms out, so
|
|
621
|
+
* the flash lands on the frame of the press and is still visibly draining a
|
|
622
|
+
* beat after the finger lifts. No JavaScript, no ripple element, no timers.
|
|
623
|
+
*/
|
|
624
|
+
.neba-glow::after {
|
|
625
|
+
background: radial-gradient(
|
|
626
|
+
4.5rem circle at var(--n-mx, 50%) var(--n-my, 50%),
|
|
627
|
+
var(--n-flash, transparent),
|
|
628
|
+
transparent 72%
|
|
629
|
+
);
|
|
630
|
+
transition: opacity 900ms cubic-bezier(0.22, 1, 0.36, 1);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
.neba-glow:active::after {
|
|
634
|
+
opacity: 1;
|
|
635
|
+
transition-duration: 0ms;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/* ---------------------------------------------------------------------------
|
|
639
|
+
* Loading
|
|
640
|
+
*
|
|
641
|
+
* The progress indicators are the one place in the library where something
|
|
642
|
+
* moves on its own, and the only place it is allowed to: an indeterminate
|
|
643
|
+
* indicator that does not move is a decoration.
|
|
644
|
+
*
|
|
645
|
+
* The rule against transforms still holds, because none of these moves anything
|
|
646
|
+
* with text in it. The sweep slides an empty box along a 4px groove, the ring
|
|
647
|
+
* turns a glyph — the same allowance the Select chevron takes — and the plates
|
|
648
|
+
* only change colour.
|
|
649
|
+
*
|
|
650
|
+
* They are real CSS rather than Tailwind arbitrary variants for the reason
|
|
651
|
+
* everything else in this file is: keyframes are not a variant, so there is
|
|
652
|
+
* nothing to express them with.
|
|
653
|
+
* ------------------------------------------------------------------------- */
|
|
654
|
+
|
|
655
|
+
/*
|
|
656
|
+
* The indeterminate bar: a short segment crossing the groove.
|
|
657
|
+
*
|
|
658
|
+
* `inset-inline-start` rather than a transform, so it runs the other way under
|
|
659
|
+
* RTL without being told. The cost is a layout pass per frame, confined to a
|
|
660
|
+
* box a few pixels tall — which is the trade that makes the rule affordable
|
|
661
|
+
* here rather than an exception to it.
|
|
662
|
+
*/
|
|
663
|
+
@keyframes neba-sweep {
|
|
664
|
+
from {
|
|
665
|
+
inset-inline-start: -45%;
|
|
666
|
+
}
|
|
667
|
+
to {
|
|
668
|
+
inset-inline-start: 100%;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
.neba-sweep {
|
|
673
|
+
position: absolute;
|
|
674
|
+
inset-block: 0;
|
|
675
|
+
inline-size: 45%;
|
|
676
|
+
animation: neba-sweep 1.15s var(--neba-ease) infinite;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
@keyframes neba-ring-spin {
|
|
680
|
+
to {
|
|
681
|
+
rotate: 360deg;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
.neba-ring-spin {
|
|
686
|
+
transform-origin: center;
|
|
687
|
+
animation: neba-ring-spin 900ms linear infinite;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
/*
|
|
691
|
+
* The plates light in sequence, each one held back by its own index. Colour
|
|
692
|
+
* only — the plates never move, so a row of them reads as a surface being
|
|
693
|
+
* written to rather than as something bouncing.
|
|
694
|
+
*/
|
|
695
|
+
@keyframes neba-plate-wave {
|
|
696
|
+
0%,
|
|
697
|
+
70%,
|
|
698
|
+
100% {
|
|
699
|
+
background-color: var(--n-soft);
|
|
700
|
+
box-shadow: var(--neba-plate-glass);
|
|
701
|
+
}
|
|
702
|
+
35% {
|
|
703
|
+
background-color: var(--n-fill);
|
|
704
|
+
box-shadow: var(--neba-plate-solid);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
.neba-plate-wave {
|
|
709
|
+
animation: neba-plate-wave 1.2s var(--neba-ease) infinite;
|
|
710
|
+
animation-delay: calc(var(--n-i, 0) * 120ms);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/* The reduced-motion stand-in for the sweep: the segment stops travelling and
|
|
714
|
+
the whole groove pulses instead. Colour, which is the axis every other state
|
|
715
|
+
in the library already uses. */
|
|
716
|
+
@keyframes neba-progress-pulse {
|
|
717
|
+
0%,
|
|
718
|
+
100% {
|
|
719
|
+
background-color: var(--n-soft-press);
|
|
720
|
+
}
|
|
721
|
+
50% {
|
|
722
|
+
background-color: var(--n-fill);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/* Respect a reduced-motion preference. Both layers track the pointer, so they
|
|
727
|
+
are motion in the sense that matters here — drop them entirely. */
|
|
728
|
+
@media (prefers-reduced-motion: reduce) {
|
|
729
|
+
:root {
|
|
730
|
+
--neba-duration: 0ms;
|
|
731
|
+
--neba-duration-fill: 0ms;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
.neba-glow::before,
|
|
735
|
+
.neba-glow::after {
|
|
736
|
+
display: none;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/*
|
|
740
|
+
* The indicators are not switched off, because an indeterminate one that
|
|
741
|
+
* holds still says the opposite of what it is for. The travelling segment
|
|
742
|
+
* becomes a colour pulse, and the two that genuinely have to keep turning or
|
|
743
|
+
* cycling are slowed to where they stop reading as motion.
|
|
744
|
+
*/
|
|
745
|
+
.neba-sweep {
|
|
746
|
+
inset-inline-start: 0;
|
|
747
|
+
inline-size: 100%;
|
|
748
|
+
animation: neba-progress-pulse 1.8s var(--neba-ease) infinite;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
.neba-ring-spin {
|
|
752
|
+
animation-duration: 2.4s;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
.neba-plate-wave {
|
|
756
|
+
animation-duration: 2.4s;
|
|
757
|
+
}
|
|
758
|
+
}
|