@tinybigui/react 0.10.0 → 0.11.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 CHANGED
@@ -12,7 +12,7 @@ A modern, accessible React component library implementing Google's Material Desi
12
12
 
13
13
  ## ✅ Status
14
14
 
15
- > **Latest Release: v0.10.0** (2026-06-09)
15
+ > **Latest Release: v0.11.0** (2026-06-09)
16
16
  >
17
17
  > **29 MD3 components** published to npm with full TypeScript support and WCAG 2.1 AA accessibility.
18
18
  >
@@ -159,14 +159,14 @@ See [THEMING.md](./THEMING.md) for the full customization guide.
159
159
 
160
160
  ### Phase 3: Feedback ✅
161
161
 
162
- | Component | Status | Description |
163
- | ------------- | ------ | --------------------------------------- |
164
- | `Dialog` | ✅ | Basic and fullscreen modal dialogs |
165
- | `Snackbar` | ✅ | Provider, stacking, imperative API |
166
- | `Menu` | ✅ | Dropdown, context menu, submenus |
167
- | `Progress` | ✅ | Linear and circular indicators |
168
- | `BottomSheet` | ✅ | Standard and modal with snap points |
169
- | `Tooltip` | ✅ | Plain and rich tooltip with positioning |
162
+ | Component | Status | Description |
163
+ | ------------- | ------ | ---------------------------------------------------------------- |
164
+ | `Dialog` | ✅ | Basic and fullscreen modal dialogs |
165
+ | `Snackbar` | ✅ | Provider, stacking, imperative API |
166
+ | `Menu` | ✅ | Dropdown, context menu, submenus |
167
+ | `Progress` | ✅ | Linear and circular indicators |
168
+ | `BottomSheet` | ✅ | MD3 expressive handle, variants-vs-states architecture (v0.11.0) |
169
+ | `Tooltip` | ✅ | Plain and rich tooltip with positioning |
170
170
 
171
171
  ### Phase 4: Data Display ✅
172
172
 
package/dist/index.cjs CHANGED
@@ -11160,7 +11160,7 @@ var BottomSheetModalPanel = ({
11160
11160
  "aria-modal": "true",
11161
11161
  className: cn(className, getAnimationClassName?.(animationState)),
11162
11162
  "data-animation-state": animationState,
11163
- "data-dragging": isDragging || void 0,
11163
+ "data-dragging": isDragging ? "" : void 0,
11164
11164
  style: panelStyle,
11165
11165
  onTransitionEnd,
11166
11166
  children
@@ -11297,7 +11297,7 @@ var BottomSheetHeadless = React.forwardRef(
11297
11297
  ref,
11298
11298
  className: cn(className, getAnimationClassName?.(animationState)),
11299
11299
  "data-animation-state": animationState,
11300
- "data-dragging": isDragging || void 0,
11300
+ "data-dragging": isDragging ? "" : void 0,
11301
11301
  style: panelStyle,
11302
11302
  onTransitionEnd: handleTransitionEnd,
11303
11303
  children
@@ -11312,7 +11312,6 @@ var bottomSheetAnimationVariants = classVarianceAuthority.cva("", {
11312
11312
  variants: {
11313
11313
  animationState: {
11314
11314
  // entering: initial mount frame — sheet starts below viewport (translateY(100%))
11315
- // The CSS is handled inside animate-md-slide-in-bottom keyframes
11316
11315
  entering: ["opacity-0"],
11317
11316
  // visible: entry animation active — animate-md-slide-in-bottom runs once
11318
11317
  visible: ["animate-md-slide-in-bottom"],
@@ -11329,52 +11328,38 @@ var bottomSheetAnimationVariants = classVarianceAuthority.cva("", {
11329
11328
  var bottomSheetVariants = classVarianceAuthority.cva(
11330
11329
  [
11331
11330
  // Position: fixed to bottom edge, full width
11332
- "fixed",
11333
- "bottom-0",
11334
- "left-0",
11335
- "right-0",
11331
+ "fixed bottom-0 left-0 right-0",
11336
11332
  // Surface token
11337
11333
  "bg-surface-container-low",
11338
11334
  // Elevation level 1 per MD3 spec
11339
11335
  "shadow-elevation-1",
11340
- // Shape: extra-large top corners (28dp), bottom corners are 0 (attached to screen edge)
11336
+ // Shape: extra-large top corners (28dp), square bottom (screen-attached)
11337
+ // NOTE: measurement-derived value from MD3 spec; permitted exception per component-variants rule
11341
11338
  "rounded-t-xl",
11342
11339
  // Layout
11343
- "flex",
11344
- "flex-col",
11345
- // Max width constraint (full width up to 640dp)
11340
+ "flex flex-col",
11341
+ // Width constraint (full width up to 640dp)
11346
11342
  "mx-auto",
11347
11343
  // NOTE: measurement-derived value from MD3 spec; permitted exception
11348
11344
  "w-[640px] max-w-full",
11349
- // Clip content during height transitions (sheet shrinks/grows from bottom edge)
11345
+ // Clip content during height transitions
11350
11346
  "overflow-hidden",
11351
- // Transition: height for snap spring (MD3 spec sheet "resizes" between heights)
11352
- // Standard personality, default speed tier, spatial: no overshoot.
11353
- // During drag, data-[dragging=true]:transition-none suppresses this so the
11354
- // sheet height follows the pointer 1:1 without transition lag.
11355
- // After drag release, the spring transition animates height to the new snap position.
11347
+ // Snap spring: spatial property (height), standard personality, default tier
11356
11348
  "transition-[height]",
11357
11349
  "duration-spring-standard-default-spatial",
11358
11350
  "ease-spring-standard-default-spatial",
11359
- "data-[dragging=true]:transition-none",
11351
+ // Suppress spring while dragging so the sheet follows the pointer 1:1
11352
+ "data-[dragging]:transition-none",
11360
11353
  "will-change-[height]",
11361
- // Responsive layout: when viewport > 640dp, apply wider top margin per MD3 spec.
11362
- // The sheet remains bottom-anchored at all sizes. Side centering is handled by
11363
- // mx-auto + max-w-[640px] — at 752dp viewport this naturally produces 56dp side
11364
- // margins on each side (exactly matching MD3 measurements).
11365
- // Top margin is expressed as max-height so the sheet cannot overlap the top edge:
11366
- // - Default: 72dp top margin (max-h-[calc(100vh-72px)])
11367
- // - Wide viewport (> 640dp): 56dp top margin (sm:max-h-[calc(100vh-56px)])
11354
+ // Responsive layout: top margin expressed as max-height
11368
11355
  // NOTE: measurement-derived values from MD3 spec; permitted exception
11369
11356
  "max-h-[calc(100vh-72px)]",
11370
- "sm:max-h-[calc(100vh-56px)]",
11371
- // Top corners rounded at wide layout (sheet floats away from screen edge)
11372
- "rounded-t-xl"
11357
+ "sm:max-h-[calc(100vh-56px)]"
11373
11358
  ],
11374
11359
  {
11375
11360
  variants: {
11376
11361
  variant: {
11377
- // Modal: above scrim (z-50)
11362
+ // Modal: rendered above the scrim (z-50)
11378
11363
  modal: "z-50",
11379
11364
  // Standard: sits above normal content but below overlays
11380
11365
  standard: "z-10"
@@ -11386,62 +11371,96 @@ var bottomSheetVariants = classVarianceAuthority.cva(
11386
11371
  }
11387
11372
  );
11388
11373
  var bottomSheetScrimVariants = classVarianceAuthority.cva([
11389
- "fixed",
11390
- "inset-0",
11391
- "z-40",
11392
- "bg-scrim",
11393
- "opacity-32",
11394
- "transition-opacity",
11395
- "duration-short4",
11396
- "ease-standard"
11374
+ "fixed inset-0 z-40",
11375
+ "bg-scrim opacity-32",
11376
+ // Screen-level effects transition (scrim enters/exits the screen, not an on-screen state change)
11377
+ "transition-opacity duration-short4 ease-standard"
11397
11378
  ]);
11398
11379
  var bottomSheetHandleWrapperVariants = classVarianceAuthority.cva([
11399
- // Center the handle pill horizontally
11400
- "flex",
11401
- "items-center",
11402
- "justify-center",
11403
- // Top/bottom padding creates the 48dp touch target area
11404
- // 22dp top + 4dp handle + 22dp bottom ≈ 48dp interaction zone (per MD3 measurements)
11380
+ // Center the pill horizontally; provide positioning context for overlays
11381
+ "relative flex items-center justify-center w-full",
11382
+ // 48dp touch target (22dp top + 4dp pill + 22dp bottom)
11405
11383
  // NOTE: measurement-derived value from MD3 spec; permitted exception
11406
11384
  "py-[22px]",
11407
- // Full width so the touch target spans the sheet
11408
- "w-full",
11409
- // Focus ring styling for keyboard/switch navigation
11410
- // MD3 spec: focus indicator color = secondary, thickness = 3dp, offset = 2dp
11385
+ // Suppress browser default focus outline — the focus-ring overlay slot handles it
11411
11386
  "focus-visible:outline-none",
11412
- "focus-visible:ring-3",
11413
- "focus-visible:ring-secondary",
11414
- "focus-visible:ring-offset-2",
11415
- "focus-visible:rounded-sm",
11416
- // Cursor affordance
11387
+ // Cursor affordance for drag interaction
11417
11388
  "cursor-ns-resize"
11418
11389
  ]);
11390
+ var bottomSheetHandleStateLayerVariants = classVarianceAuthority.cva([
11391
+ // Overlay positioned centrally — sits behind the pill
11392
+ "absolute pointer-events-none",
11393
+ // Pill-shaped to complement the handle's form
11394
+ "rounded-full",
11395
+ // Sized wider than the pill to provide a visible state layer halo
11396
+ // 48dp wide × 16dp tall — centred by the flex wrapper
11397
+ "w-12 h-4",
11398
+ // State-layer color (same role as the pill)
11399
+ "bg-on-surface-variant",
11400
+ // Effects transition — opacity must NOT overshoot
11401
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
11402
+ // Opacity at rest
11403
+ "opacity-0",
11404
+ // Hover: 8%
11405
+ "group-data-[hovered]/handle:opacity-8",
11406
+ // Focus-visible: 10%
11407
+ "group-data-[focus-visible]/handle:opacity-10",
11408
+ // Pressed: 10% (doubled selector wins over hover at same cascade position)
11409
+ "group-data-[pressed]/handle:group-data-[pressed]/handle:opacity-10",
11410
+ // Dragging: 16% (MD3 dragged state — highest on-screen opacity)
11411
+ // Doubled selector wins over hover + pressed
11412
+ "group-data-[dragging]/handle:group-data-[dragging]/handle:opacity-16"
11413
+ ]);
11414
+ var bottomSheetHandleFocusRingVariants = classVarianceAuthority.cva([
11415
+ "absolute pointer-events-none",
11416
+ "rounded-full",
11417
+ // Sized to sit around the state layer halo
11418
+ "w-14 h-5",
11419
+ // MD3 focus indicator: secondary color, 2dp weight
11420
+ "outline outline-2 outline-offset-0 outline-secondary",
11421
+ // Effects transition — opacity change must NOT overshoot
11422
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
11423
+ // Hidden at rest; shown on keyboard/programmatic focus
11424
+ "opacity-0",
11425
+ "group-data-[focus-visible]/handle:opacity-100"
11426
+ ]);
11419
11427
  var bottomSheetHandlePillVariants = classVarianceAuthority.cva([
11428
+ "relative z-10 pointer-events-none",
11420
11429
  "bg-on-surface-variant",
11421
- "opacity-40",
11422
11430
  "rounded-full",
11423
11431
  // Dimensions: 32dp × 4dp per MD3 spec (measurement-derived; permitted exception)
11424
11432
  "w-8",
11425
- // 32dp = 2rem = w-8
11426
- "h-1",
11427
- // 4dp = 0.25rem = h-1
11428
- // Pill itself is decorative; the wrapper handles interaction
11429
- "pointer-events-none"
11433
+ // 32dp = 2rem
11434
+ "h-1"
11435
+ // 4dp = 0.25rem
11430
11436
  ]);
11431
11437
  function BottomSheetHandle({
11432
11438
  className,
11433
11439
  "aria-label": ariaLabelOverride
11434
11440
  }) {
11435
11441
  const { handleProps, isDragging } = useBottomSheetContext();
11436
- return /* @__PURE__ */ jsxRuntime.jsx(
11442
+ const { isHovered, hoverProps } = reactAria.useHover({});
11443
+ const { isFocusVisible, focusProps } = reactAria.useFocusRing();
11444
+ const mergedHandleProps = reactAria.mergeProps(handleProps, hoverProps, focusProps);
11445
+ return /* @__PURE__ */ jsxRuntime.jsxs(
11437
11446
  "div",
11438
11447
  {
11439
- ...handleProps,
11448
+ ...mergedHandleProps,
11440
11449
  ...ariaLabelOverride !== void 0 ? { "aria-label": ariaLabelOverride } : {},
11441
- className: cn(bottomSheetHandleWrapperVariants(), className),
11450
+ className: cn(bottomSheetHandleWrapperVariants(), "group/handle", className),
11442
11451
  "data-testid": "bottom-sheet-handle",
11443
- "data-dragging": isDragging || void 0,
11444
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: bottomSheetHandlePillVariants(), "aria-hidden": "true" })
11452
+ ...getInteractionDataAttributes({
11453
+ isHovered,
11454
+ isFocusVisible,
11455
+ // Treat active drag as pressed — drives the state layer to 10% opacity
11456
+ isPressed: isDragging
11457
+ }),
11458
+ "data-dragging": isDragging ? "" : void 0,
11459
+ children: [
11460
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(bottomSheetHandleStateLayerVariants()), "aria-hidden": "true" }),
11461
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(bottomSheetHandleFocusRingVariants()), "aria-hidden": "true" }),
11462
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(bottomSheetHandlePillVariants()), "aria-hidden": "true" })
11463
+ ]
11445
11464
  }
11446
11465
  );
11447
11466
  }