plass-ui 0.0.1
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/LICENSE +21 -0
- package/README.md +111 -0
- package/dist/components/button/Button.d.ts +42 -0
- package/dist/components/button/Button.js +1 -0
- package/dist/components/button/index.d.ts +2 -0
- package/dist/components/button/index.js +1 -0
- package/dist/components/text-field/TextField.d.ts +65 -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/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/internal/icons.d.ts +18 -0
- package/dist/internal/icons.js +1 -0
- package/dist/internal/styles.d.ts +181 -0
- package/dist/internal/styles.js +1 -0
- package/dist/styles.css +2 -0
- package/dist/tailwind.css +498 -0
- package/dist/types.d.ts +74 -0
- package/dist/types.js +8 -0
- package/package.json +141 -0
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plass design tokens.
|
|
3
|
+
*
|
|
4
|
+
* This file ships as `plass-ui/tailwind.css`, for a project that runs Tailwind
|
|
5
|
+
* itself and wants the components' utilities generated in the same pass as its
|
|
6
|
+
* own:
|
|
7
|
+
*
|
|
8
|
+
* @import 'tailwindcss';
|
|
9
|
+
* @import 'plass-ui/tailwind.css';
|
|
10
|
+
*
|
|
11
|
+
* Two lines, and no `@source` of their own — the `@source` below does that job.
|
|
12
|
+
*
|
|
13
|
+
* A project with no Tailwind imports `plass-ui/styles.css` instead, which is this
|
|
14
|
+
* file plus a reset plus the compiled utilities, built by
|
|
15
|
+
* `scripts/build-styles.mjs` from `src/standalone.css`. The tokens below are
|
|
16
|
+
* the same in both.
|
|
17
|
+
*
|
|
18
|
+
* Components never hardcode a colour; they map a `color` prop onto the `--p-*`
|
|
19
|
+
* local slots and let the cascade resolve the rest.
|
|
20
|
+
*
|
|
21
|
+
* Dark mode responds to `prefers-color-scheme`, and can be forced either way
|
|
22
|
+
* with `.dark` / `[data-theme='dark'|'light']` on any ancestor.
|
|
23
|
+
*
|
|
24
|
+
* The surface model is **a moulded plastic key resting on a sheet of glass**: a
|
|
25
|
+
* control is a gradient fill with a specular highlight along its top edge and a
|
|
26
|
+
* drop shadow tinted with its own colour; everything that holds content is a
|
|
27
|
+
* translucent, heavily blurred sheet with a white hairline around it.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
* The components' classes are Tailwind utilities, so Tailwind has to see the
|
|
32
|
+
* files that spell them out — otherwise every component renders unstyled.
|
|
33
|
+
*
|
|
34
|
+
* `@source` resolves relative to the file it is written in, not to whatever
|
|
35
|
+
* imported it. In a consumer's install that is `node_modules/plass-ui/dist/`, next
|
|
36
|
+
* to the compiled components; in this repository it is `src/`, next to the
|
|
37
|
+
* `.tsx`. One line covers both, and an explicitly registered source is scanned
|
|
38
|
+
* even inside `node_modules`, which automatic detection skips.
|
|
39
|
+
*
|
|
40
|
+
* This is why consumers do not need an `@source '../node_modules/plass-ui'` of
|
|
41
|
+
* their own — a path that would depend on where their CSS file happens to sit.
|
|
42
|
+
*/
|
|
43
|
+
@source '.';
|
|
44
|
+
|
|
45
|
+
/* ---------------------------------------------------------------------------
|
|
46
|
+
* The colour families
|
|
47
|
+
*
|
|
48
|
+
* These sit outside every theme block on purpose, and it is the one place Plass
|
|
49
|
+
* departs hardest from the libraries it was learned from: **a key's own colour
|
|
50
|
+
* does not change with the theme.** A piece of plastic is the same piece of
|
|
51
|
+
* plastic in a dark room. What changes is the sheet it rests on, the glass
|
|
52
|
+
* around it, and the `accent` — the one value that has to be *read* off a
|
|
53
|
+
* surface rather than looked at.
|
|
54
|
+
*
|
|
55
|
+
* Two values are hand-picked per family and everything else is derived with
|
|
56
|
+
* `color-mix()`, so **adding a colour family is two edits**: one entry in
|
|
57
|
+
* `PlassColor` and two lines here (plus its `accent` in each theme).
|
|
58
|
+
*
|
|
59
|
+
* Every `solid` was chosen against one number: the *lightest* stop of the
|
|
60
|
+
* gradient derived from it has to clear 4.5:1 against its own `on-solid`. That
|
|
61
|
+
* stop is a 5% lift toward white, which is why the fills sit where they do —
|
|
62
|
+
* they are not "dark blue", they are as bright as a white label allows.
|
|
63
|
+
* ------------------------------------------------------------------------- */
|
|
64
|
+
|
|
65
|
+
:root {
|
|
66
|
+
--plass-primary-solid: #3558ef;
|
|
67
|
+
--plass-primary-on-solid: #ffffff;
|
|
68
|
+
|
|
69
|
+
--plass-secondary-solid: #4f5a70;
|
|
70
|
+
--plass-secondary-on-solid: #ffffff;
|
|
71
|
+
|
|
72
|
+
--plass-success-solid: #157845;
|
|
73
|
+
--plass-success-on-solid: #ffffff;
|
|
74
|
+
|
|
75
|
+
/* The one family with dark ink. White on amber does not reach 4.5:1 at any
|
|
76
|
+
lightness worth calling amber, and changing the ink is the right answer —
|
|
77
|
+
distorting the family to preserve a white label is not. */
|
|
78
|
+
--plass-warning-solid: #e2921c;
|
|
79
|
+
--plass-warning-on-solid: #3b2405;
|
|
80
|
+
|
|
81
|
+
--plass-danger-solid: #c4383e;
|
|
82
|
+
--plass-danger-on-solid: #ffffff;
|
|
83
|
+
|
|
84
|
+
--plass-info-solid: #186cb3;
|
|
85
|
+
--plass-info-on-solid: #ffffff;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* ---------------------------------------------------------------------------
|
|
89
|
+
* Light theme (default)
|
|
90
|
+
*
|
|
91
|
+
* `.light` and `[data-theme='light']` carry the same block rather than only
|
|
92
|
+
* `:root`, because forcing light has to work on a nested element too — a
|
|
93
|
+
* preview box inside a dark page has nowhere else to get these values from.
|
|
94
|
+
* Everything here that is not a colour (the radii, the motion) is identical in
|
|
95
|
+
* both themes, so re-declaring it costs a duplicate that resolves to what was
|
|
96
|
+
* inherited anyway.
|
|
97
|
+
* ------------------------------------------------------------------------- */
|
|
98
|
+
|
|
99
|
+
:root,
|
|
100
|
+
.light,
|
|
101
|
+
[data-theme='light'] {
|
|
102
|
+
/* Neutral surfaces and content */
|
|
103
|
+
--plass-surface: #ffffff;
|
|
104
|
+
--plass-fg: #1b1e27;
|
|
105
|
+
--plass-muted-fg: #5b6376;
|
|
106
|
+
--plass-border: #d5deef;
|
|
107
|
+
|
|
108
|
+
/* The page a Plass screen is laid on. Not used by any component — a library
|
|
109
|
+
has no business painting the body — but it is what the docs, the demos and
|
|
110
|
+
the focus ring's offset are drawn against, and it is the backdrop the glass
|
|
111
|
+
was tuned over. */
|
|
112
|
+
--plass-bg-from: #eef2fb;
|
|
113
|
+
--plass-bg-to: #dfe8f8;
|
|
114
|
+
|
|
115
|
+
/* Glass ---------------------------------------------------------------
|
|
116
|
+
|
|
117
|
+
Three strengths of one translucent sheet, and the ladder is **opacity
|
|
118
|
+
rather than lightness**: as a surface is engaged it holds more light,
|
|
119
|
+
instead of turning grey.
|
|
120
|
+
|
|
121
|
+
Undyed on purpose. A sheet holds other people's content, which arrives
|
|
122
|
+
with its own colours; tinting it puts every one of them on a background
|
|
123
|
+
they were not chosen against. The family shows up in the hairline, the
|
|
124
|
+
focus ring and the caret, and the glass stays clear. */
|
|
125
|
+
--plass-glass: rgb(255 255 255 / 0.62);
|
|
126
|
+
--plass-glass-hover: rgb(255 255 255 / 0.76);
|
|
127
|
+
--plass-glass-press: rgb(255 255 255 / 0.88);
|
|
128
|
+
--plass-glass-line: rgb(255 255 255 / 0.6);
|
|
129
|
+
|
|
130
|
+
/* How hard the backdrop is blurred, and how much colour is pulled out of it.
|
|
131
|
+
22px is a deliberate, generous smear: unlike a frosted-acrylic language,
|
|
132
|
+
Plass is not trying to let you read what is behind the sheet — it is trying
|
|
133
|
+
to make the sheet look thick. Below about 14px the glass reads as a flat
|
|
134
|
+
white box with an alpha on it. */
|
|
135
|
+
--plass-blur: blur(22px) saturate(160%);
|
|
136
|
+
|
|
137
|
+
/* The two edges. `gloss-glass` is the light lying along the top of a sheet;
|
|
138
|
+
`gloss-solid` is the same light on a moulded key, which is dimmer because
|
|
139
|
+
the key is not clear. There is deliberately **no dark bevel underneath**:
|
|
140
|
+
the drop shadow is what puts the key above the sheet. */
|
|
141
|
+
--plass-gloss-glass: inset 0 1px 0 rgb(255 255 255 / 0.55);
|
|
142
|
+
--plass-gloss-solid: inset 0 1px 0 rgb(255 255 255 / 0.34);
|
|
143
|
+
|
|
144
|
+
/* A well cut into the glass — what a filled field is drawn as. The only
|
|
145
|
+
inset shadow in the library that goes *downward*. */
|
|
146
|
+
--plass-well: inset 0 1px 2px rgb(20 40 90 / 0.1);
|
|
147
|
+
|
|
148
|
+
/* The specular highlight `.plass-gloss` lays over a key. It stops at 62%
|
|
149
|
+
rather than running the whole height, because a gradient that reaches the
|
|
150
|
+
bottom edge reads as a colour change and not as light. */
|
|
151
|
+
--plass-specular: linear-gradient(
|
|
152
|
+
180deg,
|
|
153
|
+
rgb(255 255 255 / 0.3) 0%,
|
|
154
|
+
rgb(255 255 255 / 0.06) 46%,
|
|
155
|
+
rgb(255 255 255 / 0) 62%
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
/* Elevation, and how strongly a key's own colour bleeds into the shadow it
|
|
159
|
+
casts. The ambient is a blue-grey rather than black: a neutral shadow over
|
|
160
|
+
a blue-tinted page reads as dirt. */
|
|
161
|
+
--plass-shadow-ambient: rgb(20 40 90 / 0.16);
|
|
162
|
+
--plass-glow-strength: 35%;
|
|
163
|
+
|
|
164
|
+
/* The scrim behind a modal surface. */
|
|
165
|
+
--plass-scrim: rgb(16 24 40 / 0.4);
|
|
166
|
+
|
|
167
|
+
/* Corner radius: roughly 30% of the control height, and roughly constant in
|
|
168
|
+
feel across the ladder — a Plass corner is a moulded fillet, not a pill and
|
|
169
|
+
not a chamfer. */
|
|
170
|
+
--plass-radius-xs: 0.5rem;
|
|
171
|
+
--plass-radius-sm: 0.625rem;
|
|
172
|
+
--plass-radius-md: 0.75rem;
|
|
173
|
+
--plass-radius-lg: 0.875rem;
|
|
174
|
+
--plass-radius-xl: 1rem;
|
|
175
|
+
|
|
176
|
+
/* Motion. One duration, one curve, and the same both ways — a key going down
|
|
177
|
+
and a key coming back up are the same spring. */
|
|
178
|
+
--plass-ease: cubic-bezier(0.16, 0.9, 0.3, 1);
|
|
179
|
+
--plass-duration: 150ms;
|
|
180
|
+
--plass-duration-slow: 260ms;
|
|
181
|
+
|
|
182
|
+
/* Readable on a surface. This is the one family value that is per-theme,
|
|
183
|
+
because it is the one that has to be read rather than looked at. */
|
|
184
|
+
--plass-primary-accent: #2c49d6;
|
|
185
|
+
--plass-secondary-accent: #46506a;
|
|
186
|
+
--plass-success-accent: #146b41;
|
|
187
|
+
--plass-warning-accent: #96600c;
|
|
188
|
+
--plass-danger-accent: #bb3339;
|
|
189
|
+
--plass-info-accent: #1668ae;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* ---------------------------------------------------------------------------
|
|
193
|
+
* Dark theme
|
|
194
|
+
*
|
|
195
|
+
* The fills do not move — see the note above the families. What moves is the
|
|
196
|
+
* ground under them: the glass loses its white and becomes a smoked pane, the
|
|
197
|
+
* shadow goes black and deepens, and the accents lighten far enough to be read
|
|
198
|
+
* off the dark sheet.
|
|
199
|
+
* ------------------------------------------------------------------------- */
|
|
200
|
+
|
|
201
|
+
@media (prefers-color-scheme: dark) {
|
|
202
|
+
:root:not(.light):not([data-theme='light']) {
|
|
203
|
+
--plass-surface: #141b30;
|
|
204
|
+
--plass-fg: #e7eaf3;
|
|
205
|
+
--plass-muted-fg: #99a2ba;
|
|
206
|
+
--plass-border: rgb(255 255 255 / 0.12);
|
|
207
|
+
|
|
208
|
+
--plass-bg-from: #111731;
|
|
209
|
+
--plass-bg-to: #0a0e1c;
|
|
210
|
+
|
|
211
|
+
--plass-glass: rgb(255 255 255 / 0.07);
|
|
212
|
+
--plass-glass-hover: rgb(255 255 255 / 0.11);
|
|
213
|
+
--plass-glass-press: rgb(255 255 255 / 0.15);
|
|
214
|
+
--plass-glass-line: rgb(255 255 255 / 0.12);
|
|
215
|
+
|
|
216
|
+
--plass-blur: blur(22px) saturate(150%);
|
|
217
|
+
|
|
218
|
+
--plass-gloss-glass: inset 0 1px 0 rgb(255 255 255 / 0.1);
|
|
219
|
+
--plass-gloss-solid: inset 0 1px 0 rgb(255 255 255 / 0.22);
|
|
220
|
+
|
|
221
|
+
--plass-well: inset 0 1px 2px rgb(0 0 0 / 0.45);
|
|
222
|
+
|
|
223
|
+
--plass-specular: linear-gradient(
|
|
224
|
+
180deg,
|
|
225
|
+
rgb(255 255 255 / 0.18) 0%,
|
|
226
|
+
rgb(255 255 255 / 0.04) 46%,
|
|
227
|
+
rgb(255 255 255 / 0) 62%
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
/* A tinted shadow has almost nothing to sit on over a near-black page, so
|
|
231
|
+
the tint is turned up rather than the shadow being made bigger. */
|
|
232
|
+
--plass-shadow-ambient: rgb(0 0 0 / 0.5);
|
|
233
|
+
--plass-glow-strength: 55%;
|
|
234
|
+
|
|
235
|
+
--plass-scrim: rgb(0 0 0 / 0.6);
|
|
236
|
+
|
|
237
|
+
--plass-primary-accent: #93a8ff;
|
|
238
|
+
--plass-secondary-accent: #aab3c6;
|
|
239
|
+
--plass-success-accent: #4fd08d;
|
|
240
|
+
--plass-warning-accent: #f2b74e;
|
|
241
|
+
--plass-danger-accent: #ff8a8f;
|
|
242
|
+
--plass-info-accent: #5fb4ee;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.dark,
|
|
247
|
+
[data-theme='dark'] {
|
|
248
|
+
--plass-surface: #141b30;
|
|
249
|
+
--plass-fg: #e7eaf3;
|
|
250
|
+
--plass-muted-fg: #99a2ba;
|
|
251
|
+
--plass-border: rgb(255 255 255 / 0.12);
|
|
252
|
+
|
|
253
|
+
--plass-bg-from: #111731;
|
|
254
|
+
--plass-bg-to: #0a0e1c;
|
|
255
|
+
|
|
256
|
+
--plass-glass: rgb(255 255 255 / 0.07);
|
|
257
|
+
--plass-glass-hover: rgb(255 255 255 / 0.11);
|
|
258
|
+
--plass-glass-press: rgb(255 255 255 / 0.15);
|
|
259
|
+
--plass-glass-line: rgb(255 255 255 / 0.12);
|
|
260
|
+
|
|
261
|
+
--plass-blur: blur(22px) saturate(150%);
|
|
262
|
+
|
|
263
|
+
--plass-gloss-glass: inset 0 1px 0 rgb(255 255 255 / 0.1);
|
|
264
|
+
--plass-gloss-solid: inset 0 1px 0 rgb(255 255 255 / 0.22);
|
|
265
|
+
|
|
266
|
+
--plass-well: inset 0 1px 2px rgb(0 0 0 / 0.45);
|
|
267
|
+
|
|
268
|
+
--plass-specular: linear-gradient(
|
|
269
|
+
180deg,
|
|
270
|
+
rgb(255 255 255 / 0.18) 0%,
|
|
271
|
+
rgb(255 255 255 / 0.04) 46%,
|
|
272
|
+
rgb(255 255 255 / 0) 62%
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
--plass-shadow-ambient: rgb(0 0 0 / 0.5);
|
|
276
|
+
--plass-glow-strength: 55%;
|
|
277
|
+
|
|
278
|
+
--plass-scrim: rgb(0 0 0 / 0.6);
|
|
279
|
+
|
|
280
|
+
--plass-primary-accent: #93a8ff;
|
|
281
|
+
--plass-secondary-accent: #aab3c6;
|
|
282
|
+
--plass-success-accent: #4fd08d;
|
|
283
|
+
--plass-warning-accent: #f2b74e;
|
|
284
|
+
--plass-danger-accent: #ff8a8f;
|
|
285
|
+
--plass-info-accent: #5fb4ee;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/* ---------------------------------------------------------------------------
|
|
289
|
+
* Derived tokens
|
|
290
|
+
*
|
|
291
|
+
* Gradients, glows, tints, hairlines and focus rings are all one base colour at
|
|
292
|
+
* different strengths, so they are computed rather than hand-picked per theme.
|
|
293
|
+
*
|
|
294
|
+
* **This block is repeated for every theme root**, because a custom property
|
|
295
|
+
* resolves its `var()`s on the element that declares it — declaring these only
|
|
296
|
+
* on `:root` would freeze `--plass-*-glow` to the light theme's
|
|
297
|
+
* `--plass-glow-strength` inside a `.dark` subtree.
|
|
298
|
+
* ------------------------------------------------------------------------- */
|
|
299
|
+
|
|
300
|
+
:root,
|
|
301
|
+
.dark,
|
|
302
|
+
.light,
|
|
303
|
+
[data-theme='dark'],
|
|
304
|
+
[data-theme='light'] {
|
|
305
|
+
/* The elevation ladder. Neutral, and it climbs by *blur* far more than by
|
|
306
|
+
offset: a key that moves 20px down the page when it is raised has left the
|
|
307
|
+
sheet, and everything in this library is still sitting on one. */
|
|
308
|
+
--plass-shadow-0: 0 0 #0000;
|
|
309
|
+
--plass-shadow-1: 0 2px 8px -2px var(--plass-shadow-ambient);
|
|
310
|
+
--plass-shadow-2: 0 6px 20px -4px var(--plass-shadow-ambient);
|
|
311
|
+
--plass-shadow-3: 0 12px 32px -8px var(--plass-shadow-ambient);
|
|
312
|
+
--plass-shadow-4: 0 20px 48px -12px var(--plass-shadow-ambient);
|
|
313
|
+
|
|
314
|
+
/* The moulded fill. Three stops rather than two: light lands on the top-left
|
|
315
|
+
corner, the family's own colour holds the middle where the label sits, and
|
|
316
|
+
the far corner falls away. 135deg is the light direction the whole library
|
|
317
|
+
agrees on — the specular highlight, the gloss line and this all assume it.
|
|
318
|
+
|
|
319
|
+
The lift is 5% and the fall is 10%, which is smaller than it looks like it
|
|
320
|
+
should be. Anything more and the top-left corner stops clearing 4.5:1
|
|
321
|
+
against the label. */
|
|
322
|
+
--plass-primary-fill: linear-gradient(
|
|
323
|
+
135deg,
|
|
324
|
+
color-mix(in srgb, var(--plass-primary-solid) 95%, white) 0%,
|
|
325
|
+
var(--plass-primary-solid) 46%,
|
|
326
|
+
color-mix(in srgb, var(--plass-primary-solid) 90%, black) 100%
|
|
327
|
+
);
|
|
328
|
+
--plass-primary-glow: color-mix(
|
|
329
|
+
in srgb,
|
|
330
|
+
var(--plass-primary-solid) var(--plass-glow-strength),
|
|
331
|
+
transparent
|
|
332
|
+
);
|
|
333
|
+
--plass-primary-soft: color-mix(in srgb, var(--plass-primary-accent) 10%, transparent);
|
|
334
|
+
--plass-primary-soft-hover: color-mix(in srgb, var(--plass-primary-accent) 18%, transparent);
|
|
335
|
+
--plass-primary-soft-press: color-mix(in srgb, var(--plass-primary-accent) 26%, transparent);
|
|
336
|
+
--plass-primary-line: color-mix(in srgb, var(--plass-primary-accent) 30%, transparent);
|
|
337
|
+
--plass-primary-line-hover: color-mix(in srgb, var(--plass-primary-accent) 48%, transparent);
|
|
338
|
+
--plass-primary-ring: color-mix(in srgb, var(--plass-primary-solid) 55%, transparent);
|
|
339
|
+
|
|
340
|
+
--plass-secondary-fill: linear-gradient(
|
|
341
|
+
135deg,
|
|
342
|
+
color-mix(in srgb, var(--plass-secondary-solid) 95%, white) 0%,
|
|
343
|
+
var(--plass-secondary-solid) 46%,
|
|
344
|
+
color-mix(in srgb, var(--plass-secondary-solid) 90%, black) 100%
|
|
345
|
+
);
|
|
346
|
+
--plass-secondary-glow: color-mix(
|
|
347
|
+
in srgb,
|
|
348
|
+
var(--plass-secondary-solid) var(--plass-glow-strength),
|
|
349
|
+
transparent
|
|
350
|
+
);
|
|
351
|
+
--plass-secondary-soft: color-mix(in srgb, var(--plass-secondary-accent) 10%, transparent);
|
|
352
|
+
--plass-secondary-soft-hover: color-mix(in srgb, var(--plass-secondary-accent) 18%, transparent);
|
|
353
|
+
--plass-secondary-soft-press: color-mix(in srgb, var(--plass-secondary-accent) 26%, transparent);
|
|
354
|
+
--plass-secondary-line: color-mix(in srgb, var(--plass-secondary-accent) 30%, transparent);
|
|
355
|
+
--plass-secondary-line-hover: color-mix(in srgb, var(--plass-secondary-accent) 48%, transparent);
|
|
356
|
+
--plass-secondary-ring: color-mix(in srgb, var(--plass-secondary-solid) 55%, transparent);
|
|
357
|
+
|
|
358
|
+
--plass-success-fill: linear-gradient(
|
|
359
|
+
135deg,
|
|
360
|
+
color-mix(in srgb, var(--plass-success-solid) 95%, white) 0%,
|
|
361
|
+
var(--plass-success-solid) 46%,
|
|
362
|
+
color-mix(in srgb, var(--plass-success-solid) 90%, black) 100%
|
|
363
|
+
);
|
|
364
|
+
--plass-success-glow: color-mix(
|
|
365
|
+
in srgb,
|
|
366
|
+
var(--plass-success-solid) var(--plass-glow-strength),
|
|
367
|
+
transparent
|
|
368
|
+
);
|
|
369
|
+
--plass-success-soft: color-mix(in srgb, var(--plass-success-accent) 10%, transparent);
|
|
370
|
+
--plass-success-soft-hover: color-mix(in srgb, var(--plass-success-accent) 18%, transparent);
|
|
371
|
+
--plass-success-soft-press: color-mix(in srgb, var(--plass-success-accent) 26%, transparent);
|
|
372
|
+
--plass-success-line: color-mix(in srgb, var(--plass-success-accent) 30%, transparent);
|
|
373
|
+
--plass-success-line-hover: color-mix(in srgb, var(--plass-success-accent) 48%, transparent);
|
|
374
|
+
--plass-success-ring: color-mix(in srgb, var(--plass-success-solid) 55%, transparent);
|
|
375
|
+
|
|
376
|
+
--plass-warning-fill: linear-gradient(
|
|
377
|
+
135deg,
|
|
378
|
+
color-mix(in srgb, var(--plass-warning-solid) 95%, white) 0%,
|
|
379
|
+
var(--plass-warning-solid) 46%,
|
|
380
|
+
color-mix(in srgb, var(--plass-warning-solid) 90%, black) 100%
|
|
381
|
+
);
|
|
382
|
+
--plass-warning-glow: color-mix(
|
|
383
|
+
in srgb,
|
|
384
|
+
var(--plass-warning-solid) var(--plass-glow-strength),
|
|
385
|
+
transparent
|
|
386
|
+
);
|
|
387
|
+
--plass-warning-soft: color-mix(in srgb, var(--plass-warning-accent) 12%, transparent);
|
|
388
|
+
--plass-warning-soft-hover: color-mix(in srgb, var(--plass-warning-accent) 20%, transparent);
|
|
389
|
+
--plass-warning-soft-press: color-mix(in srgb, var(--plass-warning-accent) 28%, transparent);
|
|
390
|
+
--plass-warning-line: color-mix(in srgb, var(--plass-warning-accent) 34%, transparent);
|
|
391
|
+
--plass-warning-line-hover: color-mix(in srgb, var(--plass-warning-accent) 52%, transparent);
|
|
392
|
+
--plass-warning-ring: color-mix(in srgb, var(--plass-warning-solid) 55%, transparent);
|
|
393
|
+
|
|
394
|
+
--plass-danger-fill: linear-gradient(
|
|
395
|
+
135deg,
|
|
396
|
+
color-mix(in srgb, var(--plass-danger-solid) 95%, white) 0%,
|
|
397
|
+
var(--plass-danger-solid) 46%,
|
|
398
|
+
color-mix(in srgb, var(--plass-danger-solid) 90%, black) 100%
|
|
399
|
+
);
|
|
400
|
+
--plass-danger-glow: color-mix(
|
|
401
|
+
in srgb,
|
|
402
|
+
var(--plass-danger-solid) var(--plass-glow-strength),
|
|
403
|
+
transparent
|
|
404
|
+
);
|
|
405
|
+
--plass-danger-soft: color-mix(in srgb, var(--plass-danger-accent) 10%, transparent);
|
|
406
|
+
--plass-danger-soft-hover: color-mix(in srgb, var(--plass-danger-accent) 18%, transparent);
|
|
407
|
+
--plass-danger-soft-press: color-mix(in srgb, var(--plass-danger-accent) 26%, transparent);
|
|
408
|
+
--plass-danger-line: color-mix(in srgb, var(--plass-danger-accent) 30%, transparent);
|
|
409
|
+
--plass-danger-line-hover: color-mix(in srgb, var(--plass-danger-accent) 48%, transparent);
|
|
410
|
+
--plass-danger-ring: color-mix(in srgb, var(--plass-danger-solid) 55%, transparent);
|
|
411
|
+
|
|
412
|
+
--plass-info-fill: linear-gradient(
|
|
413
|
+
135deg,
|
|
414
|
+
color-mix(in srgb, var(--plass-info-solid) 95%, white) 0%,
|
|
415
|
+
var(--plass-info-solid) 46%,
|
|
416
|
+
color-mix(in srgb, var(--plass-info-solid) 90%, black) 100%
|
|
417
|
+
);
|
|
418
|
+
--plass-info-glow: color-mix(
|
|
419
|
+
in srgb,
|
|
420
|
+
var(--plass-info-solid) var(--plass-glow-strength),
|
|
421
|
+
transparent
|
|
422
|
+
);
|
|
423
|
+
--plass-info-soft: color-mix(in srgb, var(--plass-info-accent) 10%, transparent);
|
|
424
|
+
--plass-info-soft-hover: color-mix(in srgb, var(--plass-info-accent) 18%, transparent);
|
|
425
|
+
--plass-info-soft-press: color-mix(in srgb, var(--plass-info-accent) 26%, transparent);
|
|
426
|
+
--plass-info-line: color-mix(in srgb, var(--plass-info-accent) 30%, transparent);
|
|
427
|
+
--plass-info-line-hover: color-mix(in srgb, var(--plass-info-accent) 48%, transparent);
|
|
428
|
+
--plass-info-ring: color-mix(in srgb, var(--plass-info-solid) 55%, transparent);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/* ---------------------------------------------------------------------------
|
|
432
|
+
* Sheet titles
|
|
433
|
+
*
|
|
434
|
+
* A `title` is styled by the element the component renders around it, so a
|
|
435
|
+
* plain string needs nothing. But a sheet that belongs in the document outline
|
|
436
|
+
* has to be given a real heading, `title={<h2>…</h2>}`, and that heading
|
|
437
|
+
* arrives with the browser's own 1.5em bold and its margins, which would ignore
|
|
438
|
+
* the type scale just set.
|
|
439
|
+
*
|
|
440
|
+
* This is in CSS rather than in Tailwind because the selector is the point:
|
|
441
|
+
* `[&_:where(h1,h2,h3,h4,h5,h6)]:[font:inherit]` is expressible and nobody
|
|
442
|
+
* would want to read it twice.
|
|
443
|
+
* ------------------------------------------------------------------------- */
|
|
444
|
+
|
|
445
|
+
.plass-title :where(h1, h2, h3, h4, h5, h6) {
|
|
446
|
+
font: inherit;
|
|
447
|
+
margin: 0;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/* ---------------------------------------------------------------------------
|
|
451
|
+
* The gloss
|
|
452
|
+
*
|
|
453
|
+
* One layer over a moulded surface: the specular highlight that says the light
|
|
454
|
+
* is coming from the top-left and that the thing under it is not flat.
|
|
455
|
+
*
|
|
456
|
+
* It is **the material, not a state** — it is there when nothing is happening,
|
|
457
|
+
* which is exactly what makes it plastic rather than an effect. The only thing
|
|
458
|
+
* that moves it is a press: the key tips away from the light and the highlight
|
|
459
|
+
* drops out, which is the whole of the press signature together with the
|
|
460
|
+
* shadow contracting under it.
|
|
461
|
+
*
|
|
462
|
+
* This lives in CSS rather than in Tailwind arbitrary variants because the
|
|
463
|
+
* selector is a pseudo-element carrying a gradient: `[&::before]:[background:
|
|
464
|
+
* linear-gradient(...)]` is technically expressible and completely unreadable.
|
|
465
|
+
*
|
|
466
|
+
* Cost per control: one composited layer that never repaints. There is no
|
|
467
|
+
* pointer tracking, no ripple element, no timer and no JavaScript.
|
|
468
|
+
* ------------------------------------------------------------------------- */
|
|
469
|
+
|
|
470
|
+
.plass-gloss::before {
|
|
471
|
+
content: '';
|
|
472
|
+
position: absolute;
|
|
473
|
+
inset: 0;
|
|
474
|
+
border-radius: inherit;
|
|
475
|
+
pointer-events: none;
|
|
476
|
+
background-image: var(--plass-specular);
|
|
477
|
+
opacity: 1;
|
|
478
|
+
transition: opacity var(--plass-duration) var(--plass-ease);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
.plass-gloss:active::before {
|
|
482
|
+
opacity: 0.3;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/* ---------------------------------------------------------------------------
|
|
486
|
+
* Reduced motion
|
|
487
|
+
*
|
|
488
|
+
* Nothing in Plass animates on its own except a spinner, so this is about the
|
|
489
|
+
* transitions: someone who has asked for less movement is asking for state
|
|
490
|
+
* changes to *arrive*, not to be taken away. The colours still change; they
|
|
491
|
+
* simply stop easing.
|
|
492
|
+
* ------------------------------------------------------------------------- */
|
|
493
|
+
|
|
494
|
+
@media (prefers-reduced-motion: reduce) {
|
|
495
|
+
.plass-gloss::before {
|
|
496
|
+
transition-duration: 1ms;
|
|
497
|
+
}
|
|
498
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared prop vocabulary for every Plass component.
|
|
3
|
+
*
|
|
4
|
+
* These names and values are deliberately generic: a `size` of `md` or a
|
|
5
|
+
* `color` of `primary` has to mean the same thing on a Button, a TextField, a
|
|
6
|
+
* Card or a Dialog. Components pick the subset they need from here and never
|
|
7
|
+
* invent a parallel spelling of the same idea.
|
|
8
|
+
*/
|
|
9
|
+
/** Scale of a component. `md` is the desktop default. */
|
|
10
|
+
export type PlassSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
11
|
+
/** Semantic color role. Maps to a token family in `styles.css`. */
|
|
12
|
+
export type PlassColor = 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info';
|
|
13
|
+
/**
|
|
14
|
+
* How tightly a component packs its content. Only spacing changes — never the
|
|
15
|
+
* type scale or the control's own height — so a compact and a default control
|
|
16
|
+
* of the same `size` still line up on a shared baseline.
|
|
17
|
+
*/
|
|
18
|
+
export type PlassDensity = 'default' | 'compact';
|
|
19
|
+
/**
|
|
20
|
+
* Which way a component runs. `horizontal` everywhere it is offered, because a
|
|
21
|
+
* vertical control is the exception and an exception should have to be asked
|
|
22
|
+
* for.
|
|
23
|
+
*/
|
|
24
|
+
export type PlassOrientation = 'horizontal' | 'vertical';
|
|
25
|
+
/**
|
|
26
|
+
* Which edge of an anchor something is placed against.
|
|
27
|
+
*
|
|
28
|
+
* Physical rather than logical — `start`/`end` would be wrong here, because a
|
|
29
|
+
* tooltip above a button is above it in every writing direction.
|
|
30
|
+
*/
|
|
31
|
+
export type PlassSide = 'top' | 'right' | 'bottom' | 'left';
|
|
32
|
+
/**
|
|
33
|
+
* Where something sits along the axis it is not placed on.
|
|
34
|
+
*
|
|
35
|
+
* `start`/`end` rather than `left`/`right` because these flip under RTL, which
|
|
36
|
+
* is the whole reason the library never says `left`.
|
|
37
|
+
*/
|
|
38
|
+
export type PlassAlign = 'start' | 'center' | 'end';
|
|
39
|
+
/**
|
|
40
|
+
* What a surface is made of. This is the library's own name, and the two
|
|
41
|
+
* materials in it are the whole design language.
|
|
42
|
+
*
|
|
43
|
+
* - `solid` — **plastic.** A moulded key: a gradient fill, a specular highlight
|
|
44
|
+
* along its top edge, and a drop shadow tinted with its own colour. One per
|
|
45
|
+
* view, for the action the screen is about.
|
|
46
|
+
* - `glass` — **glass.** A translucent sheet over a blurred backdrop with a
|
|
47
|
+
* white hairline around it. Secondary actions, and the default for anything
|
|
48
|
+
* that *holds* content rather than being pressed.
|
|
49
|
+
* - `ghost` — neither. No surface at all until the pointer is on it.
|
|
50
|
+
* Tertiary and inline actions.
|
|
51
|
+
*/
|
|
52
|
+
export type PlassVariant = 'solid' | 'glass' | 'ghost';
|
|
53
|
+
/**
|
|
54
|
+
* How far a surface sits off the page, as a drop shadow.
|
|
55
|
+
*
|
|
56
|
+
* A plastic key rests **on** the sheet rather than flush with it, so a Button
|
|
57
|
+
* defaults to `1` and not to `0`. Hovering adds a level and pressing removes
|
|
58
|
+
* one, which is what puts the key down against the glass under the finger.
|
|
59
|
+
*
|
|
60
|
+
* `0` is flat, and it is the right default for anything a reader looks *into*
|
|
61
|
+
* rather than presses — a field, a well, a panel behind other content.
|
|
62
|
+
*/
|
|
63
|
+
export type PlassElevation = 0 | 1 | 2 | 3;
|
|
64
|
+
/** Style props shared by most components; spread into their own prop types. */
|
|
65
|
+
export interface PlassStyleProps {
|
|
66
|
+
/** @default 'solid' */
|
|
67
|
+
variant?: PlassVariant;
|
|
68
|
+
/** @default 'md' */
|
|
69
|
+
size?: PlassSize;
|
|
70
|
+
/** @default 'primary' */
|
|
71
|
+
color?: PlassColor;
|
|
72
|
+
/** @default 'default' */
|
|
73
|
+
density?: PlassDensity;
|
|
74
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared prop vocabulary for every Plass component.
|
|
3
|
+
*
|
|
4
|
+
* These names and values are deliberately generic: a `size` of `md` or a
|
|
5
|
+
* `color` of `primary` has to mean the same thing on a Button, a TextField, a
|
|
6
|
+
* Card or a Dialog. Components pick the subset they need from here and never
|
|
7
|
+
* invent a parallel spelling of the same idea.
|
|
8
|
+
*/
|