@claralight-design/react 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.
Files changed (45) hide show
  1. package/dist/index.d.ts +12 -0
  2. package/dist/index.js +12 -0
  3. package/dist/lib/anchored.d.ts +152 -0
  4. package/dist/lib/anchored.js +821 -0
  5. package/dist/lib/anchored.js.map +1 -0
  6. package/dist/lib/morph.js +484 -0
  7. package/dist/lib/morph.js.map +1 -0
  8. package/dist/lib/squircle.d.ts +95 -0
  9. package/dist/lib/squircle.js +220 -0
  10. package/dist/lib/squircle.js.map +1 -0
  11. package/dist/lib/utils.d.ts +30 -0
  12. package/dist/lib/utils.js +76 -0
  13. package/dist/lib/utils.js.map +1 -0
  14. package/dist/ui/button.d.ts +40 -0
  15. package/dist/ui/button.js +104 -0
  16. package/dist/ui/button.js.map +1 -0
  17. package/dist/ui/card.d.ts +54 -0
  18. package/dist/ui/card.js +82 -0
  19. package/dist/ui/card.js.map +1 -0
  20. package/dist/ui/dialog.d.ts +82 -0
  21. package/dist/ui/dialog.js +129 -0
  22. package/dist/ui/dialog.js.map +1 -0
  23. package/dist/ui/input.d.ts +34 -0
  24. package/dist/ui/input.js +60 -0
  25. package/dist/ui/input.js.map +1 -0
  26. package/dist/ui/popover.d.ts +67 -0
  27. package/dist/ui/popover.js +93 -0
  28. package/dist/ui/popover.js.map +1 -0
  29. package/dist/ui/scroll-area.d.ts +110 -0
  30. package/dist/ui/scroll-area.js +125 -0
  31. package/dist/ui/scroll-area.js.map +1 -0
  32. package/dist/ui/select.d.ts +113 -0
  33. package/dist/ui/select.js +213 -0
  34. package/dist/ui/select.js.map +1 -0
  35. package/dist/ui/tooltip.d.ts +108 -0
  36. package/dist/ui/tooltip.js +142 -0
  37. package/dist/ui/tooltip.js.map +1 -0
  38. package/package.json +72 -0
  39. package/styles/anchored.css +115 -0
  40. package/styles/base.css +309 -0
  41. package/styles/fonts/README.md +63 -0
  42. package/styles/index.css +28 -0
  43. package/styles/scroll-area.css +299 -0
  44. package/styles/theme.css +540 -0
  45. package/styles/tooltip.css +156 -0
@@ -0,0 +1,540 @@
1
+ /**
2
+ * ClaraLight Design — tokens.
3
+ *
4
+ * This file is the source of truth for hand-authored design values.
5
+ * Components, verification and spring generation consume these tokens.
6
+ *
7
+ * ClaraLight is a *quiet, layered* design language. Surfaces stack from
8
+ * `background` (window) through `panel` (panes, sheets) to `control`
9
+ * (rows, fields, buttons). Control fills are translucent overlays of the
10
+ * layer beneath, so the same layer reads correctly over any surface.
11
+ * Color is spent sparingly: `accent` marks the primary action and
12
+ * selection, status colors carry meaning, everything else stays neutral.
13
+ *
14
+ * Dark is the default scheme when no explicit scheme class is present.
15
+ *
16
+ * Consume:
17
+ * @import "tailwindcss";
18
+ * @import "@claralight-design/react/styles.css";
19
+ */
20
+
21
+ /* ---------------------------------------------------------------------------
22
+ * Scheme switching
23
+ * ------------------------------------------------------------------------- */
24
+
25
+ /**
26
+ * `dark` is the default, so it needs no class. `.light` opts into the warm
27
+ * scheme; `.dark` is accepted too, for consumers already using the shadcn
28
+ * convention of toggling a `dark` class on <html>.
29
+ *
30
+ * The runtime values live on `--cl-*` custom properties rather than directly
31
+ * in `@theme`, because Tailwind inlines `@theme` values at build time. The
32
+ * `@theme inline` block below maps them so utilities compile to
33
+ * `var(--cl-background)` and follow the active scheme.
34
+ */
35
+ @custom-variant light (&:where(.light, .light *));
36
+
37
+ /* ---------------------------------------------------------------------------
38
+ * Type ramp
39
+ * ------------------------------------------------------------------------- */
40
+
41
+ @theme static {
42
+ /*
43
+ * Preferred families and platform fallbacks. Font files are not shipped
44
+ * yet — see fonts/README.md. Fallback metrics depend on installed fonts.
45
+ */
46
+ --font-sans:
47
+ "MiSans VF", "MiSans", "PingFang SC", "SF Pro Text", system-ui, Roboto,
48
+ sans-serif;
49
+ --font-mono:
50
+ "Sarasa Mono SC", ui-monospace, SFMono-Regular, "SF Mono", Menlo,
51
+ monospace;
52
+ --font-display:
53
+ "ChillDINGothic", "MiSans VF", "MiSans", "PingFang SC", system-ui,
54
+ sans-serif;
55
+ --font-serif: "Clara Serif Pro", ui-serif, Georgia, serif;
56
+
57
+ /*
58
+ * Step scale. Weights are the ClaraLight intent, not MiSans' axis values —
59
+ * see fonts/README.md for the non-standard VF wght axis (w400 sits at 330).
60
+ * `--text-*--font-weight` therefore only lands correctly once the real
61
+ * font is loaded; with fallback fonts the browser approximates.
62
+ */
63
+ --text-display: 30px;
64
+ --text-display--line-height: 1.2667;
65
+ --text-display--font-weight: 700;
66
+ --text-display--letter-spacing: 0;
67
+
68
+ --text-headline: 18px;
69
+ --text-headline--line-height: 1.3333;
70
+ --text-headline--font-weight: 700;
71
+ --text-headline--letter-spacing: -0.55px;
72
+
73
+ --text-title: 16px;
74
+ --text-title--line-height: 1.3125;
75
+ --text-title--font-weight: 600;
76
+ --text-title--letter-spacing: -0.4px;
77
+
78
+ --text-body: 15px;
79
+ --text-body--line-height: 1.3333;
80
+ --text-body--font-weight: 500;
81
+ --text-body--letter-spacing: -0.5px;
82
+
83
+ --text-callout: 14px;
84
+ --text-callout--line-height: 1.3571;
85
+ --text-callout--font-weight: 600;
86
+ --text-callout--letter-spacing: -0.5px;
87
+
88
+ --text-label: 13px;
89
+ --text-label--line-height: 1.3077;
90
+ --text-label--font-weight: 700;
91
+ --text-label--letter-spacing: -0.2px;
92
+
93
+ --text-caption: 12px;
94
+ --text-caption--line-height: 1.3333;
95
+ --text-caption--font-weight: 400;
96
+ --text-caption--letter-spacing: 0;
97
+
98
+ /* Numeric readouts: dimensions, memory, time codes. */
99
+ --text-mono: 14px;
100
+ --text-mono--line-height: 1.3;
101
+ --text-mono--font-weight: 400;
102
+
103
+ --text-mono-strong: 14px;
104
+ --text-mono-strong--line-height: 1.3;
105
+ --text-mono-strong--font-weight: 600;
106
+ }
107
+
108
+ /* ---------------------------------------------------------------------------
109
+ * Shape (smooth corners, see below)
110
+ * ------------------------------------------------------------------------- */
111
+
112
+ @theme static {
113
+ --radius-control: 8px; /* fields, rows, chips, small buttons */
114
+ --radius-medium: 12px; /* cards, grouped lists, banners, popovers */
115
+ --radius-panel: 18px; /* panels and sidebars */
116
+ --radius-sheet: 36px; /* floating bottom sheets */
117
+ --radius-dialog: 36px; /* modal dialogs */
118
+ --radius-capsule: 999px; /* segmented pills, toolbar buttons */
119
+ }
120
+
121
+ /**
122
+ * Corner smoothing.
123
+ *
124
+ * ClaraLight surfaces use smooth corners ("squircles"), not circular arcs.
125
+ *
126
+ * On the web this is *not* CSS `corner-shape`, and the distinction matters:
127
+ *
128
+ * corner-shape: superellipse() a true Lamé superellipse (squircle == n=4).
129
+ * Chromium 139+ only; Safari and Firefox drop
130
+ * the property at parse time.
131
+ * Figma corner smoothing cubic Bezier shoulders bracketing a circular
132
+ * arc, `p = (1 + xi) * R` with a `90 * (1 - xi)`
133
+ * residual arc.
134
+ *
135
+ * Those are different curve families and do not coincide. ClaraLight follows
136
+ * the design source, and the design lives in Figma, so the Figma construction
137
+ * is the correct one — it is also the same family as Apple's
138
+ * `cornerCurve = .continuous`, the closest available match to iOS.
139
+ *
140
+ * `corner-shape` is therefore deliberately unused. The shape is produced by
141
+ * `@lisse/react`, which emits the same SVG path in every engine, so Safari,
142
+ * Firefox and Chromium agree pixel for pixel. See `src/lib/squircle.tsx`.
143
+ *
144
+ * `--cl-corner-smoothing` is Figma's xi: 0 gives a plain circular arc
145
+ * identical to `border-radius`, 1 removes the arc entirely and leaves only
146
+ * Beziers. ClaraLight sits at Figma's own default.
147
+ */
148
+ @theme static {
149
+ --cl-corner-smoothing: 0.6;
150
+ }
151
+
152
+ /* ---------------------------------------------------------------------------
153
+ * Motion (spring samples generated by scripts/gen-spring.mjs)
154
+ * ------------------------------------------------------------------------- */
155
+
156
+ @theme static {
157
+ /*
158
+ * Finite transitions. ClaraLight is deliberately quick: 140/160ms, where
159
+ * a typical web design system would sit at 200-300ms.
160
+ */
161
+ --ease-cl-out: cubic-bezier(
162
+ 0.23,
163
+ 1,
164
+ 0.32,
165
+ 1
166
+ ); /* strong deceleration, entrances */
167
+ --ease-cl-in: cubic-bezier(
168
+ 0.32,
169
+ 0,
170
+ 0.67,
171
+ 0
172
+ ); /* strong acceleration, exits */
173
+ --ease-cl-in-out: cubic-bezier(0.77, 0, 0.175, 1); /* symmetric movement */
174
+ --ease-cl-drawer: cubic-bezier(
175
+ 0.32,
176
+ 0.72,
177
+ 0,
178
+ 1
179
+ ); /* iOS-like sheet/drawer */
180
+
181
+ /* Tooltip switching uses one motion curve for position and content. */
182
+ --ease-cl-tooltip-morph: var(--ease-cl-in-out);
183
+
184
+ /*
185
+ * Derived samples, not hand-authored values. Run `pnpm tokens` after
186
+ * changing the spring parameter tokens below. Overlay time is normalized
187
+ * progress; press time is seconds mapped through its release duration.
188
+ */
189
+ --ease-cl-spring-overlay: linear(0, 0.0132 1.85%, 0.0481 3.7%, 0.0986 5.56%, 0.1595 7.41%, 0.2268 9.26%, 0.2973 11.11%, 0.3683 12.96%, 0.438 14.81%, 0.5048 16.67%, 0.5679 18.52%, 0.6265 20.37%, 0.6803 22.22%, 0.729 24.07%, 0.7728 25.93%, 0.8115 27.78%, 0.8456 29.63%, 0.8753 31.48%, 0.9009 33.33%, 0.9228 35.19%, 0.9413 37.04%, 0.9567 38.89%, 0.9695 40.74%, 0.9799 42.59%, 0.9883 44.44%, 0.995 46.3%, 1.0001 48.15%, 1.004 50%, 1.0069 51.85%, 1.0089 53.7%, 1.0101 55.56%, 1.0108 57.41%, 1.0111 59.26%, 1.011 61.11%, 1.0107 62.96%, 1.0101 64.81%, 1.0095 66.67%, 1.0087 68.52%, 1.008 70.37%, 1.0072 72.22%, 1.0064 74.07%, 1.0057 75.93%, 1.0049 77.78%, 1.0043 79.63%, 1.0037 81.48%, 1.0031 83.33%, 1.0026 85.19%, 1.0022 87.04%, 1.0018 88.89%, 1.0015 90.74%, 1.0012 92.59%, 1.0009 94.44%, 1.0007 96.3%, 1.0005 98.15%, 1);
190
+ --ease-cl-spring-press: linear(0, 0.0172 1.52%, 0.0654 3.03%, 0.1391 4.55%, 0.2326 6.06%, 0.3403 7.58%, 0.4568 9.09%, 0.5771 10.61%, 0.6966 12.12%, 0.8114 13.64%, 0.9182 15.15%, 1.0145 16.67%, 1.0982 18.18%, 1.1682 19.7%, 1.2238 21.21%, 1.2649 22.73%, 1.2919 24.24%, 1.3058 25.76%, 1.3076 27.27%, 1.2988 28.79%, 1.281 30.3%, 1.256 31.82%, 1.2255 33.33%, 1.1911 34.85%, 1.1547 36.36%, 1.1175 37.88%, 1.0811 39.39%, 1.0464 40.91%, 1.0145 42.42%, 0.9862 43.94%, 0.9618 45.45%, 0.9417 46.97%, 0.9261 48.48%, 0.915 50%, 0.9081 51.52%, 0.9052 53.03%, 0.9058 54.55%, 0.9095 56.06%, 0.9158 57.58%, 0.9242 59.09%, 0.9341 60.61%, 0.9449 62.12%, 0.9563 63.64%, 0.9677 65.15%, 0.9788 66.67%, 0.9892 68.18%, 0.9987 69.7%, 1.007 71.21%, 1.0141 72.73%, 1.0198 74.24%, 1.0241 75.76%, 1.0271 77.27%, 1.0288 78.79%, 1.0293 80.3%, 1.0287 81.82%, 1.0273 83.33%, 1.0251 84.85%, 1.0224 86.36%, 1.0192 87.88%, 1.0158 89.39%, 1.0123 90.91%, 1.0088 92.42%, 1.0054 93.94%, 1.0023 95.45%, 0.9995 96.97%, 0.997 98.48%, 1);
191
+
192
+ /* Perceptual surfacing of frosted floating layers. */
193
+ --blur-frost: 36px;
194
+ }
195
+
196
+ /* ---------------------------------------------------------------------------
197
+ * Control geometry and interaction
198
+ * ------------------------------------------------------------------------- */
199
+
200
+ @theme static {
201
+ /* Numeric spacing utilities derive from this shared unit. */
202
+ --spacing: 4px;
203
+ --container-lg: 32rem;
204
+ --spacing-control-sm: 28px;
205
+ --spacing-control-md: 36px;
206
+ --spacing-control-lg: 44px;
207
+ --spacing-icon-sm: 15px;
208
+ --spacing-icon-md: 18px;
209
+ --spacing-icon-lg: 24px;
210
+ --radius-item: 6px;
211
+
212
+ --text-button: 17px;
213
+ --text-button--line-height: 22px;
214
+ --text-button--font-weight: 500;
215
+ --text-button--letter-spacing: -0.43px;
216
+
217
+ --cl-press-scale-sm: 1.0714;
218
+ --cl-press-scale-md: 1.0556;
219
+ --cl-press-scale-lg: 1.0455;
220
+ --cl-duration-fast: 140ms;
221
+ --cl-duration-surface: 160ms;
222
+ --cl-duration-press: 170ms;
223
+ --cl-duration-release: 550ms;
224
+ --cl-duration-enter: 250ms;
225
+ --cl-duration-morph: 380ms;
226
+ --cl-duration-exit: 110ms;
227
+ --cl-duration-reduced: 125ms;
228
+ --cl-duration-tooltip-morph: 180ms;
229
+ --cl-duration-tooltip-tail: 60ms;
230
+ --cl-duration-tooltip-content-exit: 90ms;
231
+ --cl-tooltip-content-scale: 0.98;
232
+ --cl-tooltip-content-blur: 5px;
233
+ --cl-tooltip-content-offset: 8px;
234
+ --cl-tooltip-content-offset-negative: -8px;
235
+ --ease-cl-press-in: cubic-bezier(0.25, 1, 0.5, 1);
236
+ --cl-focus-width: 2px;
237
+ --cl-focus-offset: 2px;
238
+ --cl-enter-scale: 0.95;
239
+
240
+ --cl-spring-overlay-omega: 9.2;
241
+ --cl-spring-overlay-zeta: 0.82;
242
+ --cl-spring-overlay-sample-duration: 450ms;
243
+ --cl-spring-press-mass: 1;
244
+ --cl-spring-press-stiffness: 520;
245
+ --cl-spring-press-damping: 16;
246
+
247
+ --cl-hover-base-weight: 92%;
248
+ --cl-hover-tint: #ffffff;
249
+ --cl-select-max-width: 28rem;
250
+ --cl-select-max-height: 20rem;
251
+ --cl-select-side-offset: 6px;
252
+
253
+ /*
254
+ * Scroll area.
255
+ *
256
+ * `edge` is how far a side fades over; `blur` is the Gaussian sigma that
257
+ * fade reaches at the very edge. Setting one side's edge to zero removes
258
+ * both the fade and the blur there, so the four sides are independently
259
+ * switchable without a prop.
260
+ *
261
+ * The sides are logical, because the overflow state they follow is: in a
262
+ * vertical LTR area `block-start` is the top and `block-end` the bottom, and
263
+ * an RTL area needs no overrides at all.
264
+ */
265
+ --cl-scroll-edge: 24px;
266
+ --cl-scroll-edge-block-start: var(--cl-scroll-edge);
267
+ --cl-scroll-edge-block-end: var(--cl-scroll-edge);
268
+ --cl-scroll-edge-inline-start: var(--cl-scroll-edge);
269
+ --cl-scroll-edge-inline-end: var(--cl-scroll-edge);
270
+ --cl-scroll-blur: 5px;
271
+
272
+ /*
273
+ * The three-layer ramp that stands in for the continuously varying sigma a
274
+ * shader would use: each layer reaches half as far into the band as the one
275
+ * before it and blurs half as hard, so strength falls off geometrically from
276
+ * the very edge. The strongest layer is `--cl-scroll-blur` over the full
277
+ * band, so it needs no multiplier of its own.
278
+ */
279
+ --cl-scroll-blur-mid: 0.5;
280
+ --cl-scroll-blur-far: 0.25;
281
+ --cl-scroll-reach-near: 25%;
282
+ --cl-scroll-reach-mid: 50%;
283
+
284
+ /* The thumb is `--cl-selection`; `inset` keeps both tracks clear of a
285
+ * surface's own padding, and `margin` shortens the thumb within its track. */
286
+ --cl-scrollbar-thickness: 4px;
287
+ --cl-scrollbar-margin: 2px;
288
+ --cl-scrollbar-inset: 0px;
289
+ --cl-scrollbar-fade-delay: 300ms;
290
+ --cl-scrollbar-fade-duration: 180ms;
291
+
292
+ /*
293
+ * Anchored overlays (popover, tooltip).
294
+ *
295
+ * The arrow is not a separate element: it is spliced into the surface's own
296
+ * smooth-corner path, so `--cl-arrow-*` are the tail's geometry inside that
297
+ * path rather than the size of a box. `extent` is how far the tail reaches
298
+ * past the body; `width` is its full base along the body edge.
299
+ *
300
+ * `gap` is measured from the tail's tip, not the body, so an overlay sits the
301
+ * same distance from its anchor whether or not it draws an arrow.
302
+ */
303
+ --cl-arrow-extent: 7px;
304
+ --cl-arrow-width: 24px;
305
+ --cl-anchor-gap: 4px;
306
+ --cl-anchor-margin: 8px;
307
+ --cl-popover-padding: 12px;
308
+ --cl-tooltip-padding-x: 10px;
309
+ --cl-tooltip-padding-y: 6px;
310
+ --cl-tooltip-delay: 450ms;
311
+ --cl-tooltip-close-delay: 50ms;
312
+ /* Reopening another tooltip within this window skips the dwell entirely. */
313
+ --cl-tooltip-grace: 500ms;
314
+ }
315
+
316
+ @theme inline static {
317
+ --color-accent-hover: color-mix(
318
+ in oklab,
319
+ var(--cl-accent) var(--cl-hover-base-weight),
320
+ var(--cl-hover-tint)
321
+ );
322
+ --color-floating-hover: color-mix(
323
+ in oklab,
324
+ var(--cl-floating) var(--cl-hover-base-weight),
325
+ var(--cl-hover-tint)
326
+ );
327
+ --color-danger-hover: color-mix(
328
+ in oklab,
329
+ var(--cl-danger) var(--cl-hover-base-weight),
330
+ var(--cl-hover-tint)
331
+ );
332
+ }
333
+
334
+ /* ---------------------------------------------------------------------------
335
+ * Shadow ladder
336
+ * ------------------------------------------------------------------------- */
337
+
338
+ /**
339
+ * Two-layer shadows: a wide soft ambient pass and a tight contact pass.
340
+ */
341
+ @theme static {
342
+ --shadow-frost:
343
+ 0 16px 48px -12px rgb(0 0 0 / 0.55), 0 2px 8px -2px rgb(0 0 0 / 0.32);
344
+ --shadow-panel:
345
+ 0 8px 32px -8px rgb(0 0 0 / 0.42), 0 1px 3px rgb(0 0 0 / 0.24);
346
+ --shadow-dialog:
347
+ 0 32px 72px -16px rgb(0 0 0 / 0.6), 0 4px 16px -4px rgb(0 0 0 / 0.36);
348
+ }
349
+
350
+ /* ---------------------------------------------------------------------------
351
+ * Scheme tokens
352
+ * ------------------------------------------------------------------------- */
353
+
354
+ /**
355
+ * `@theme inline` so utilities compile to `var(--cl-*)` and pick up whichever
356
+ * scheme is active, instead of being inlined at build time.
357
+ *
358
+ * `static` keeps every variable in the output even when no utility happens to
359
+ * reference it. Tailwind drops unused theme variables by default, which is a
360
+ * reasonable default for an app and the wrong one for a design system: these
361
+ * names are the public API, and consumers read them at runtime
362
+ * (`getComputedStyle(el).getPropertyValue("--radius-sheet")`) or reference them
363
+ * from hand-written CSS. A token that silently disappears because the current
364
+ * component set does not use it is a break nobody can see.
365
+
366
+ */
367
+ @theme inline static {
368
+ /* --- Layered surface stack --- */
369
+ --color-background: var(--cl-background); /* window / canvas */
370
+ --color-panel: var(--cl-panel); /* panes, sheets, sidebars */
371
+ --color-frost: var(--cl-frost); /* translucent wash under a backdrop blur */
372
+ --color-control: var(--cl-control); /* rows, fields, buttons, chips */
373
+ --color-control-highlight: var(
374
+ --cl-control-highlight
375
+ ); /* hovered / gently raised */
376
+ --color-floating: var(
377
+ --cl-floating
378
+ ); /* dark fill over arbitrary canvas content */
379
+ --color-on-floating: var(--cl-on-floating);
380
+ --color-selection: var(
381
+ --cl-selection
382
+ ); /* selected row / segment, scrollbar thumb */
383
+ --color-track: var(
384
+ --cl-track
385
+ ); /* recessed track behind segmented / slider / switch */
386
+
387
+ /* --- Lines --- */
388
+ --color-separator: var(
389
+ --cl-separator
390
+ ); /* hairline between rows and groups */
391
+ --color-outline: var(--cl-outline); /* 1px around controls and dialogs */
392
+ --color-outline-strong: var(
393
+ --cl-outline-strong
394
+ ); /* floating panels and sheets */
395
+
396
+ /* --- Foreground ramp --- */
397
+ --color-foreground: var(
398
+ --cl-foreground
399
+ ); /* primary: titles, selected rows */
400
+ --color-foreground-secondary: var(
401
+ --cl-foreground-secondary
402
+ ); /* row and body text */
403
+ --color-foreground-tertiary: var(
404
+ --cl-foreground-tertiary
405
+ ); /* subtitles, units, prefixes */
406
+ --color-foreground-hint: var(
407
+ --cl-foreground-hint
408
+ ); /* section headers, placeholders */
409
+ --color-foreground-disabled: var(--cl-foreground-disabled);
410
+
411
+ /* --- Accent --- */
412
+ --color-accent: var(--cl-accent);
413
+ --color-accent-background: var(--cl-accent-background);
414
+ --color-on-accent: var(--cl-on-accent);
415
+ --color-selection-accent: var(--cl-selection-accent);
416
+
417
+ /* --- Status --- */
418
+ --color-success: var(--cl-success);
419
+ --color-warning: var(--cl-warning);
420
+ --color-warning-background: var(--cl-warning-background);
421
+ --color-danger: var(--cl-danger);
422
+ --color-danger-background: var(--cl-danger-background);
423
+ --color-on-danger: var(--cl-on-danger);
424
+
425
+ /* --- Scrim --- */
426
+ --color-scrim: var(--cl-scrim);
427
+ }
428
+
429
+ /**
430
+ * Dark — the default scheme. Explicit `rgb(... / alpha)` keeps translucent
431
+ * layers readable and editable.
432
+ */
433
+ :root,
434
+ .dark {
435
+ --cl-background: #191919;
436
+ --cl-panel: #111111;
437
+ --cl-frost: rgb(22 22 22 / 0.749);
438
+
439
+ --cl-control: rgb(255 255 255 / 0.102);
440
+ --cl-control-highlight: rgb(255 255 255 / 0.149);
441
+ --cl-floating: rgb(0 0 0 / 0.608);
442
+ --cl-on-floating: #ffffff;
443
+ --cl-selection: rgb(255 255 255 / 0.161);
444
+ --cl-track: rgb(255 255 255 / 0.102);
445
+
446
+ --cl-separator: rgb(255 255 255 / 0.102);
447
+ --cl-outline: rgb(255 255 255 / 0.149);
448
+ --cl-outline-strong: rgb(255 255 255 / 0.302);
449
+
450
+ --cl-foreground: #ffffff;
451
+ --cl-foreground-secondary: rgb(255 255 255 / 0.898);
452
+ --cl-foreground-tertiary: rgb(255 255 255 / 0.749);
453
+ --cl-foreground-hint: rgb(255 255 255 / 0.4);
454
+ --cl-foreground-disabled: rgb(255 255 255 / 0.349);
455
+
456
+ --cl-accent: #0090ff;
457
+ --cl-accent-background: rgb(0 136 246 / 0.325);
458
+ --cl-on-accent: #ffffff;
459
+ --cl-selection-accent: #3e63dd;
460
+
461
+ --cl-success: #30d158;
462
+ --cl-warning: #ffba18;
463
+ --cl-warning-background: rgb(244 209 0 / 0.086);
464
+ --cl-danger: #e5484d;
465
+ --cl-danger-background: rgb(243 0 13 / 0.078);
466
+ --cl-on-danger: #ffffff;
467
+
468
+ --cl-scrim: rgb(0 0 0 / 0.451);
469
+
470
+ color-scheme: dark;
471
+ }
472
+
473
+ /**
474
+ * Light — a warm scheme: cream paper and near-black with a brown cast,
475
+ * rather than neutral grey.
476
+ */
477
+ .light {
478
+ --cl-background: #f9f6ee;
479
+ --cl-panel: #f4f2ea;
480
+ --cl-frost: rgb(255 255 255 / 0.612);
481
+
482
+ --cl-control: rgb(176 160 148 / 0.102);
483
+ --cl-control-highlight: rgb(176 160 148 / 0.2);
484
+ --cl-floating: rgb(255 255 255 / 0.612);
485
+ --cl-on-floating: #160a01;
486
+ --cl-selection: rgb(176 160 148 / 0.102);
487
+ --cl-track: rgb(176 160 148 / 0.102);
488
+
489
+ --cl-separator: rgb(22 10 1 / 0.102);
490
+ --cl-outline: rgb(22 10 1 / 0.161);
491
+ --cl-outline-strong: rgb(22 10 1 / 0.302);
492
+
493
+ --cl-foreground: #160a01;
494
+ /* Secondary text is slightly more opaque than in the dark scheme. */
495
+ --cl-foreground-secondary: rgb(22 10 1 / 0.902);
496
+ --cl-foreground-tertiary: rgb(22 10 1 / 0.749);
497
+ --cl-foreground-hint: rgb(22 10 1 / 0.62);
498
+ --cl-foreground-disabled: rgb(22 10 1 / 0.322);
499
+
500
+ --cl-accent: #0090ff;
501
+ --cl-accent-background: rgb(0 144 255 / 0.161);
502
+ --cl-on-accent: #ffffff;
503
+ --cl-selection-accent: #3e63dd;
504
+
505
+ --cl-success: #34c759;
506
+ --cl-warning: #c7871e;
507
+ --cl-warning-background: rgb(244 209 0 / 0.086);
508
+ --cl-danger: #e5484d;
509
+ --cl-danger-background: rgb(243 0 13 / 0.078);
510
+ --cl-on-danger: #ffffff;
511
+
512
+ --cl-scrim: rgb(0 0 0 / 0.349);
513
+
514
+ color-scheme: light;
515
+ }
516
+
517
+ /* ---------------------------------------------------------------------------
518
+ * Reduced motion
519
+ * ------------------------------------------------------------------------- */
520
+
521
+ /**
522
+ * Keep a short fade under reduced motion rather than removing feedback
523
+ * entirely, so state changes stay legible.
524
+ */
525
+ @media (prefers-reduced-motion: reduce) {
526
+ :root {
527
+ --ease-cl-spring-overlay: linear(0, 1);
528
+ --ease-cl-spring-press: linear(0, 1);
529
+ }
530
+
531
+ *,
532
+ ::before,
533
+ ::after {
534
+ animation-duration: var(--cl-duration-reduced) !important;
535
+ animation-iteration-count: 1 !important;
536
+ transition-duration: var(--cl-duration-reduced) !important;
537
+ transition-timing-function: var(--ease-cl-out) !important;
538
+ scroll-behavior: auto !important;
539
+ }
540
+ }
@@ -0,0 +1,156 @@
1
+ /**
2
+ * ClaraLight Design — the shared-tooltip morph.
3
+ *
4
+ * Tooltip only, and only the part where one mounted tooltip travels to its next
5
+ * trigger: the positioner's inset channel, the popup's size channel, and the
6
+ * cross-fade between the outgoing and incoming labels.
7
+ *
8
+ * Requires `anchored.css`, which owns the surface itself.
9
+ *
10
+ * @import "tailwindcss";
11
+ * @import "@claralight-design/react/styles.css";
12
+ */
13
+
14
+ @layer components {
15
+ /**
16
+ * A shared tooltip follows its next trigger on the positioner while Base UI
17
+ * keeps the popup mounted. The position and popup/content channels share one
18
+ * duration and curve, so the tail and label settle as a single gesture.
19
+ */
20
+ .cl-tooltip-positioner {
21
+ width: var(--positioner-width, max-content);
22
+ height: var(--positioner-height, max-content);
23
+ transition:
24
+ top var(--cl-duration-tooltip-morph) var(--ease-cl-tooltip-morph),
25
+ right var(--cl-duration-tooltip-morph) var(--ease-cl-tooltip-morph),
26
+ bottom var(--cl-duration-tooltip-morph) var(--ease-cl-tooltip-morph),
27
+ left var(--cl-duration-tooltip-morph) var(--ease-cl-tooltip-morph);
28
+ }
29
+
30
+ .cl-tooltip-popup {
31
+ /* Base UI anchors morphing content with inline position/bottom/left styles.
32
+ * This surface draws its outline as a sibling, so both must stay in flow. */
33
+ position: relative !important;
34
+ inset: auto !important;
35
+ box-sizing: border-box;
36
+ width: var(--popup-width, auto);
37
+ height: var(--popup-height, auto);
38
+ transition:
39
+ width var(--cl-duration-tooltip-morph) var(--ease-cl-tooltip-morph),
40
+ height var(--cl-duration-tooltip-morph) var(--ease-cl-tooltip-morph);
41
+ }
42
+
43
+ /** Base UI owns the previous/current snapshots and their auto-resize. */
44
+ .cl-tooltip-viewport {
45
+ position: relative;
46
+ overflow: visible;
47
+ }
48
+
49
+ .cl-tooltip-viewport > [data-current],
50
+ .cl-tooltip-viewport > [data-previous] {
51
+ width: var(--popup-width, auto);
52
+ opacity: 1;
53
+ scale: 1;
54
+ translate: 0 0;
55
+ filter: blur(0);
56
+ transition:
57
+ translate var(--cl-duration-tooltip-morph) var(--ease-cl-tooltip-morph),
58
+ scale var(--cl-duration-tooltip-morph) var(--ease-cl-tooltip-morph),
59
+ opacity var(--cl-duration-tooltip-content-exit) var(--ease-cl-out),
60
+ filter var(--cl-duration-tooltip-content-exit) var(--ease-cl-out);
61
+ }
62
+
63
+ .cl-tooltip-viewport > [data-previous] {
64
+ inset: 0;
65
+ }
66
+
67
+ /** Keep both labels present at the midpoint, then cross-fade the old one. */
68
+ .cl-tooltip-viewport:has(> [data-previous]) > [data-previous] {
69
+ transition-duration:
70
+ var(--cl-duration-tooltip-morph),
71
+ var(--cl-duration-tooltip-morph),
72
+ var(--cl-duration-tooltip-content-exit),
73
+ var(--cl-duration-tooltip-content-exit);
74
+ transition-delay:
75
+ 0ms,
76
+ 0ms,
77
+ var(--cl-duration-tooltip-content-exit),
78
+ 0ms;
79
+ }
80
+
81
+ .cl-tooltip-viewport:has(> [data-previous]) > [data-current] {
82
+ transition-duration:
83
+ var(--cl-duration-tooltip-morph),
84
+ var(--cl-duration-tooltip-morph),
85
+ var(--cl-duration-tooltip-content-exit),
86
+ var(--cl-duration-tooltip-content-exit);
87
+ transition-delay:
88
+ 0ms,
89
+ 0ms,
90
+ 0ms,
91
+ var(--cl-duration-tooltip-content-exit);
92
+ }
93
+
94
+ .cl-tooltip-viewport > [data-current][data-starting-style] {
95
+ opacity: 0;
96
+ scale: var(--cl-tooltip-content-scale);
97
+ translate:
98
+ var(--cl-tooltip-content-enter-x, 0)
99
+ var(--cl-tooltip-content-enter-y, 0);
100
+ filter: blur(var(--cl-tooltip-content-blur));
101
+ }
102
+
103
+ .cl-tooltip-viewport > [data-previous][data-ending-style] {
104
+ opacity: 0;
105
+ scale: var(--cl-tooltip-content-scale);
106
+ translate:
107
+ var(--cl-tooltip-content-exit-x, 0)
108
+ var(--cl-tooltip-content-exit-y, 0);
109
+ filter: blur(var(--cl-tooltip-content-blur));
110
+ }
111
+
112
+ .cl-tooltip-viewport[data-activation-direction~="left"] {
113
+ --cl-tooltip-content-enter-x: var(--cl-tooltip-content-offset-negative);
114
+ --cl-tooltip-content-exit-x: var(--cl-tooltip-content-offset);
115
+ }
116
+
117
+ .cl-tooltip-viewport[data-activation-direction~="right"] {
118
+ --cl-tooltip-content-enter-x: var(--cl-tooltip-content-offset);
119
+ --cl-tooltip-content-exit-x: var(--cl-tooltip-content-offset-negative);
120
+ }
121
+
122
+ .cl-tooltip-viewport[data-activation-direction~="up"] {
123
+ --cl-tooltip-content-enter-y: var(--cl-tooltip-content-offset-negative);
124
+ --cl-tooltip-content-exit-y: var(--cl-tooltip-content-offset);
125
+ }
126
+
127
+ .cl-tooltip-viewport[data-activation-direction~="down"] {
128
+ --cl-tooltip-content-enter-y: var(--cl-tooltip-content-offset);
129
+ --cl-tooltip-content-exit-y: var(--cl-tooltip-content-offset-negative);
130
+ }
131
+
132
+ @media (prefers-reduced-motion: reduce) {
133
+ .cl-tooltip-positioner,
134
+ .cl-tooltip-popup {
135
+ transition: none !important;
136
+ }
137
+
138
+ .cl-tooltip-viewport > [data-current],
139
+ .cl-tooltip-viewport > [data-previous] {
140
+ transition:
141
+ opacity var(--cl-duration-reduced) var(--ease-cl-out),
142
+ filter var(--cl-duration-reduced) var(--ease-cl-out);
143
+ transition-delay: 0ms;
144
+ scale: 1;
145
+ translate: none;
146
+ }
147
+
148
+ .cl-tooltip-viewport:has(> [data-previous]) > [data-current],
149
+ .cl-tooltip-viewport:has(> [data-previous]) > [data-previous] {
150
+ transition:
151
+ opacity var(--cl-duration-reduced) var(--ease-cl-out),
152
+ filter var(--cl-duration-reduced) var(--ease-cl-out);
153
+ transition-delay: 0ms;
154
+ }
155
+ }
156
+ }