@boyernick/standard-ui-react 0.3.1-canary.44 → 0.3.1-canary.46

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boyernick/standard-ui-react",
3
- "version": "0.3.1-canary.44",
3
+ "version": "0.3.1-canary.46",
4
4
  "description": "React components for StandardUI",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/carousel.tsx CHANGED
@@ -79,8 +79,8 @@ export type CarouselNextProps = ComponentProps<typeof Button>
79
79
  export type CarouselDotsProps = ComponentProps<"div">
80
80
 
81
81
  const carouselControlClassName = cn(
82
- "absolute z-20 !size-6 border glass [--glass-tint:var(--surface)] [--glass-opacity:55%] text-fg-primary shadow-md [&_svg:not([class*='size-'])]:!size-3.5",
83
- "hover:bg-surface/80 hover:text-fg-primary",
82
+ "absolute z-20 !size-6 glass text-fg-primary [&_svg:not([class*='size-'])]:!size-3.5",
83
+ "hover:brightness-105 hover:text-fg-primary",
84
84
  "disabled:pointer-events-none disabled:opacity-0",
85
85
  motion.colors,
86
86
  )
package/src/modal.tsx CHANGED
@@ -52,7 +52,7 @@ const TRACKPAD_LABEL =
52
52
  "Swipe, use the arrow keys, or use the controls to navigate"
53
53
 
54
54
  const modalControlClassName =
55
- "glass [--glass-tint:var(--surface-inverted)] [--glass-opacity:60%] text-fg-inverted shadow-md hover:[--glass-opacity:80%] hover:text-fg-inverted outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-surface-inverted focus-visible:ring-ring/20"
55
+ "glass glass-dark dark:glass-light text-fg-inverted hover:text-fg-inverted outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-offset-1 focus-visible:ring-offset-surface-inverted focus-visible:ring-ring/20"
56
56
 
57
57
  export const modalContentVariants = cva(
58
58
  "h-dvh max-h-dvh w-screen max-w-none gap-0 overflow-hidden rounded-none border-0 bg-transparent p-0 shadow-none max-sm:max-w-none",
@@ -38,8 +38,19 @@ const formatTime = (seconds: number) => {
38
38
  // light regardless of the theme — semantic foreground tokens would invert and
39
39
  // disappear against the video. Buttons follow Linear’s glass chrome: circular,
40
40
  // muted until hover, no filled chip behind the icon at rest.
41
+ /** One control, one piece of glass. Sized to 36 because a standalone floating
42
+ * object needs to be tappable in its own right — inside the old bar these
43
+ * could lean on the bar for presence and sat at 28.
44
+ *
45
+ * No hover background: the material *is* the background, and a translucent
46
+ * white wash over it fights the fill and the rim. Brightness lifts the whole
47
+ * object instead, the way a lit surface actually behaves. */
41
48
  const overlayControl =
42
- "inline-flex size-7 shrink-0 cursor-pointer items-center justify-center rounded-full text-white/65 outline-none transition-[background-color,color,transform] duration-[var(--duration-sm)] ease-enter hover:bg-white/12 hover:text-white active:scale-95 focus-visible:bg-white/12 focus-visible:text-white focus-visible:ring-2 focus-visible:ring-white/50 motion-reduce:transition-none motion-reduce:active:scale-100"
49
+ "glass glass-dark [--glass-alpha:52%] inline-flex size-9 shrink-0 cursor-pointer items-center justify-center rounded-full text-white/85 outline-none transition-[filter,color,transform] duration-[var(--duration-sm)] ease-enter hover:text-white hover:brightness-110 active:scale-95 focus-visible:text-white focus-visible:ring-2 focus-visible:ring-white/50 motion-reduce:transition-none motion-reduce:active:scale-100"
50
+
51
+ /** The scrubber and its two timecodes travel together as one object. */
52
+ const overlayTrack =
53
+ "glass glass-dark [--glass-alpha:52%] flex h-9 min-w-0 flex-1 items-center gap-2 rounded-full px-3"
43
54
 
44
55
  export type VideoPlayerProps = ComponentProps<"div"> & {
45
56
  src: string
@@ -300,7 +311,7 @@ export const VideoPlayer = ({
300
311
  {failed ? (
301
312
  <div
302
313
  role="alert"
303
- className="mx-6 flex max-w-sm flex-col items-center gap-2 rounded-xl border glass [--glass-tint:var(--black)] [--glass-opacity:65%] [--glass-edge:var(--white)] [--glass-edge-opacity:15%] px-5 py-4 text-center text-white shadow-lg"
314
+ className="mx-6 flex max-w-sm flex-col items-center gap-2 rounded-xl glass glass-dark px-5 py-4 text-center text-white shadow-lg"
304
315
  >
305
316
  <IconExclamationTriangle
306
317
  size={22}
@@ -316,7 +327,7 @@ export const VideoPlayer = ({
316
327
  ) : loading || buffering ? (
317
328
  <div
318
329
  role="status"
319
- className="flex size-14 items-center justify-center rounded-full border glass [--glass-tint:var(--black)] [--glass-opacity:45%] [--glass-edge:var(--white)] [--glass-edge-opacity:15%] text-white shadow-lg"
330
+ className="flex size-14 items-center justify-center rounded-full glass glass-dark text-white shadow-lg"
320
331
  >
321
332
  <span className="size-6 animate-spin rounded-full border-2 border-white/30 border-t-white motion-reduce:animate-none" />
322
333
  <span className="sr-only">
@@ -326,7 +337,7 @@ export const VideoPlayer = ({
326
337
  ) : !playing ? (
327
338
  <div
328
339
  className={cn(
329
- "flex items-center justify-center rounded-full border glass [--glass-tint:var(--black)] [--glass-opacity:45%] [--glass-edge:var(--white)] [--glass-edge-opacity:20%] text-white shadow-lg",
340
+ "flex items-center justify-center rounded-full glass glass-dark text-white shadow-lg",
330
341
  ended ? "h-8 gap-1 px-2.5" : "size-11",
331
342
  )}
332
343
  >
@@ -344,14 +355,13 @@ export const VideoPlayer = ({
344
355
  {!failed && !loading ? (
345
356
  <div
346
357
  className={cn(
347
- // The scrim samples 0.8 0 along smootherstep
348
- // (`6t⁵ 15t⁴ + 10t³`) rather than using a three-stop gradient.
349
- // Three stops are a run of straight segments, and the eye reads
350
- // every slope change between them as a seam; flat or evenly lit
351
- // footage shows those plainly. This curve is flat at both ends
352
- // instead — no edge where the scrim starts, no corner where it
353
- // reaches full strength behind the controls.
354
- "absolute inset-x-0 bottom-0 flex translate-y-0 flex-col bg-[linear-gradient(to_top,rgba(0,0,0,0.8)_0%,rgba(0,0,0,0.79)_12.5%,rgba(0,0,0,0.72)_25%,rgba(0,0,0,0.58)_37.5%,rgba(0,0,0,0.4)_50%,rgba(0,0,0,0.22)_62.5%,rgba(0,0,0,0.08)_75%,rgba(0,0,0,0.01)_87.5%,transparent_100%)] px-2.5 pt-14 pb-2.5 transition-[opacity,transform] duration-[var(--duration-md)] ease-enter group-data-[fullscreen]:px-5 group-data-[fullscreen]:pb-5 motion-reduce:transition-none",
358
+ // A floating bar rather than a full-bleed scrim. The scrim existed
359
+ // to keep white controls legible over arbitrary footage; the glass
360
+ // material does that itself, and does it without darkening a strip
361
+ // of the picture the viewer is trying to watch. Inset from the
362
+ // edges so it reads as an object on the video rather than part of
363
+ // the frame.
364
+ "absolute inset-x-2 bottom-2 flex translate-y-0 items-center gap-2 transition-[opacity,transform] duration-[var(--duration-md)] ease-enter group-data-[fullscreen]:inset-x-5 group-data-[fullscreen]:bottom-5 motion-reduce:transition-none",
355
365
  "group-hover:translate-y-0 group-hover:opacity-100 group-focus-within:translate-y-0 group-focus-within:opacity-100",
356
366
  // Nothing hovers on a touch screen, so the chrome would never come
357
367
  // back once playback started. Keep it visible there instead.
@@ -359,12 +369,6 @@ export const VideoPlayer = ({
359
369
  playing ? "translate-y-2 opacity-0" : "opacity-100",
360
370
  )}
361
371
  >
362
- {title ? (
363
- <p className="text-sm-strong mb-2 truncate px-1 text-white">{title}</p>
364
- ) : null}
365
-
366
- <div className="flex items-center gap-1.5">
367
- <div className="flex shrink-0 items-center">
368
372
  <button
369
373
  type="button"
370
374
  className={overlayControl}
@@ -399,9 +403,8 @@ export const VideoPlayer = ({
399
403
  />
400
404
  )}
401
405
  </button>
402
- </div>
403
-
404
- <span className="text-xs min-w-9 shrink-0 tabular-nums text-white/85">
406
+ <div className={overlayTrack}>
407
+ <span className="text-xs min-w-9 shrink-0 tabular-nums text-white/85">
405
408
  {formatTime(current)}
406
409
  </span>
407
410
 
@@ -469,11 +472,11 @@ export const VideoPlayer = ({
469
472
  />
470
473
  </div>
471
474
 
472
- <span className="text-xs min-w-10 shrink-0 text-right tabular-nums text-white/85">
473
- -{formatTime(remaining)}
474
- </span>
475
+ <span className="text-xs min-w-10 shrink-0 text-right tabular-nums text-white/85">
476
+ -{formatTime(remaining)}
477
+ </span>
478
+ </div>
475
479
 
476
- <div className="flex shrink-0 items-center">
477
480
  {pipSupported ? (
478
481
  <button
479
482
  type="button"
@@ -508,8 +511,6 @@ export const VideoPlayer = ({
508
511
  aria-hidden
509
512
  />
510
513
  </button>
511
- </div>
512
- </div>
513
514
  </div>
514
515
  ) : null}
515
516
  </div>