@tinybigui/react 0.21.1 → 0.23.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/dist/index.d.cts CHANGED
@@ -756,12 +756,21 @@ declare const AppBarHeadless: React$1.ForwardRefExoticComponent<AppBarHeadlessPr
756
756
  * - Content flags (data-with-icon, data-loading) are set explicitly by the component.
757
757
  *
758
758
  * Slot responsibilities:
759
- * buttonVariants — root <button>; shape, color, elevation
759
+ * buttonVariants — root <button>; shape, text color, elevation (shadow)
760
+ * buttonContainerVariants — absolute inset child; background color + disabled bg override
760
761
  * buttonStateLayerVariants — hover/focus/press opacity ring (absolute inset overlay)
761
762
  * buttonFocusRingVariants — keyboard focus outline, MUST NOT be inside overflow-hidden
762
763
  * buttonIconVariants — leading/trailing icon wrapper
763
764
  * buttonLabelVariants — label text slot
764
765
  *
766
+ * Why background lives on a child slot (buttonContainerVariants) rather than the root:
767
+ * Tailwind `group-data-[x]/button:` generates a descendant combinator selector —
768
+ * `.group\/button[data-x] .target`. The root <button> IS the group host and cannot
769
+ * be its own descendant, so group selectors cannot target it directly. Moving the
770
+ * background to an absolutely-positioned child span lets us use the proven
771
+ * `group-data-[disabled]/button:bg-on-surface/12` pattern (same as Switch track)
772
+ * to override the container background on disabled, guaranteeing correct specificity.
773
+ *
765
774
  * MD3 Spec:
766
775
  * Shape: rounded-full (corner-full)
767
776
  * Height: 32dp small | 40dp medium | 56dp large
@@ -780,12 +789,19 @@ declare const AppBarHeadless: React$1.ForwardRefExoticComponent<AppBarHeadlessPr
780
789
  /**
781
790
  * Root <button> element.
782
791
  *
792
+ * Owns: shape, text color, elevation (box-shadow), cursor, layout.
793
+ * Does NOT own background-color — that lives on buttonContainerVariants so
794
+ * the group-data disabled override can reach it via descendant selector.
795
+ *
783
796
  * IMPORTANT — overflow is intentionally NOT on the root.
784
797
  * Overflow clipping is delegated to the ripple container and state layer
785
798
  * via `overflow-hidden rounded-[inherit]` on those children. This lets the
786
799
  * focus ring span (`inset-[-3px]`) extend outside the button boundary and
787
800
  * remain fully visible — if overflow-hidden were on the root it would be
788
801
  * clipped to zero width.
802
+ *
803
+ * Elevation state classes use self-targeting `data-[x]:` (not group-data)
804
+ * because the root is the group host and cannot be its own descendant.
789
805
  */
790
806
  declare const buttonVariants: (props?: ({
791
807
  variant?: "text" | "filled" | "outlined" | "tonal" | "elevated" | null | undefined;
@@ -5331,10 +5347,17 @@ declare namespace MenuTrigger {
5331
5347
  /**
5332
5348
  * MD3 styled MenuItem component (Layer 3).
5333
5349
  *
5334
- * All MD3 styles (selection colors, typography, density height) are applied
5335
- * directly to the `<li role="menuitem">` element via RAC's render-prop className,
5336
- * ensuring tests and assistive technologies see the correct classes on the
5337
- * semantically meaningful element.
5350
+ * Slot architecture (mirrors Button/Switch):
5351
+ * root (group/menuitem) — layout, cursor, color, density height
5352
+ * highlight (z-0) — selected/active background fill
5353
+ * stateLayer (z-[1]) — hover/press opacity overlay
5354
+ * focusRing (z-[2]) — keyboard focus outline (inset, not on state-layer)
5355
+ * ripple (z-[3]) — press ripple feedback
5356
+ * content (z-10) — icon, label, trailing text/icon, description
5357
+ *
5358
+ * All interaction/selection styles are driven by data-* attributes that RAC
5359
+ * MenuItem emits natively (data-hovered, data-pressed, data-focus-visible,
5360
+ * data-selected, data-disabled, data-open) consumed via group-data selectors.
5338
5361
  *
5339
5362
  * @example
5340
5363
  * ```tsx
@@ -5351,6 +5374,10 @@ declare const MenuItem: React$1.ForwardRefExoticComponent<MenuItemProps & React$
5351
5374
  * Groups related `MenuItem` elements with an optional section header and an
5352
5375
  * optional top divider.
5353
5376
  *
5377
+ * The section header color adapts to the `colorScheme` from `MenuContext`:
5378
+ * standard → text-on-surface-variant
5379
+ * vibrant → text-on-tertiary-container
5380
+ *
5354
5381
  * **Implementation note**: The divider is rendered as a SIBLING BEFORE the
5355
5382
  * `RACMenuSection`, NOT inside it. RAC's `Section`/`MenuSection` only accepts
5356
5383
  * `Header` and `MenuItem` children — placing a `Separator` inside the section
@@ -5435,17 +5462,20 @@ declare function HeadlessMenuDivider({ className, ...props }: SeparatorProps & {
5435
5462
  /**
5436
5463
  * Material Design 3 Menu container variants (CVA).
5437
5464
  *
5438
- * Elevation: `shadow-elevation-2` (both styles)
5439
- * Width: min 112dp / max 280dp per MD3 spec
5465
+ * Architecture: Variants vs States
5466
+ * - CVA holds design-time structure only (menuStyle, colorScheme).
5467
+ * - Animation (enter/exit motion) lives on `menuPopoverVariants` which is
5468
+ * applied to the RAC Popover element — the element where RAC actually emits
5469
+ * data-entering, data-exiting, and data-placement.
5440
5470
  *
5441
5471
  * Shape per menuStyle:
5442
- * - baseline: `rounded-xs` (4dp extra-small)
5443
- * - vertical: `rounded-lg` (16dp large)
5472
+ * baseline: `rounded-xs` (4dp extra-small)
5473
+ * vertical: `rounded-lg` (16dp large, MD3 Expressive)
5444
5474
  *
5445
- * Background per colorScheme + menuStyle:
5446
- * - baseline + standard: `bg-surface-container`
5447
- * - vertical + standard: `bg-surface-container-low`
5448
- * - vertical + vibrant: `bg-tertiary-container`
5475
+ * Background per menuStyle:
5476
+ * baseline: bg-surface-container (solid, houses all items)
5477
+ * vertical: bg-transparent (items paint their own segment cards; gap reveals
5478
+ * the page background between segments — acting as the divider)
5449
5479
  *
5450
5480
  * @see https://m3.material.io/components/menus/specs
5451
5481
  */
@@ -6249,12 +6279,13 @@ type ChipVariants = VariantProps<typeof chipVariants>;
6249
6279
  * Structural variant of the MD3 Dialog.
6250
6280
  *
6251
6281
  * - `basic` — Floating dialog with headline, body, and action buttons.
6252
- * Supports scale + fade entry animation. Closes on scrim click or Escape.
6253
- * Max width 560dp per MD3 spec.
6282
+ * Supports scale + fade entry animation (MD3 Expressive, `animate-md-scale-in`).
6283
+ * Closes on scrim click or Escape. Max width 560dp per MD3 spec.
6254
6284
  *
6255
6285
  * - `fullscreen` — Full viewport overlay suited for mobile and complex forms.
6256
6286
  * Replaces headline with a top app bar row (close icon + confirm action).
6257
- * Slide-up entry animation. Does NOT close on scrim click per MD3 spec.
6287
+ * Slide-up entry animation (`animate-md-slide-in-bottom`). Does NOT close on
6288
+ * scrim click per MD3 spec.
6258
6289
  *
6259
6290
  * @default 'basic'
6260
6291
  */
@@ -6262,10 +6293,12 @@ type DialogVariant = "basic" | "fullscreen";
6262
6293
  /**
6263
6294
  * Internal animation state machine for the Dialog.
6264
6295
  *
6265
- * - `entering` — initial mount state before transition fires
6266
- * - `visible` — fully shown, entry animation complete
6267
- * - `exiting` — exit animation in progress
6268
- * - `exited` — removed from DOM
6296
+ * - `entering` — initial mount state; dialog starts invisible before animation fires
6297
+ * - `visible` — entry animation active (`animate-md-scale-in` / `animate-md-slide-in-bottom`)
6298
+ * - `exiting` — exit animation active (`animate-md-scale-out` / `animate-md-slide-out-bottom`)
6299
+ * - `exited` — animation complete; portal removes element from DOM
6300
+ *
6301
+ * The scrim receives the same state for its own fade-in/out animation.
6269
6302
  */
6270
6303
  type DialogAnimationState = "entering" | "visible" | "exiting" | "exited";
6271
6304
  /**
@@ -6302,7 +6335,7 @@ interface DialogContextValue {
6302
6335
  * onOpenChange={setOpen}
6303
6336
  * aria-label="Confirm action"
6304
6337
  * className="bg-surface-container-high rounded-xl shadow-elevation-3"
6305
- * scrimClassName="fixed inset-0 z-40 bg-scrim opacity-32"
6338
+ * scrimClassName="fixed inset-0 z-40 bg-scrim/32"
6306
6339
  * >
6307
6340
  * <DialogHeadline>Confirm deletion?</DialogHeadline>
6308
6341
  * <DialogContent>This action cannot be undone.</DialogContent>
@@ -6337,6 +6370,21 @@ interface DialogHeadlessProps {
6337
6370
  * When `DialogHeadline` is present, `aria-labelledby` is preferred automatically.
6338
6371
  */
6339
6372
  "aria-label"?: string;
6373
+ /**
6374
+ * Optional hero icon rendered centered above the headline per MD3 spec.
6375
+ * When present, sets `data-with-icon` on the panel root so headline and
6376
+ * supporting text center-align via `group-data-[with-icon]/dialog:` selectors.
6377
+ *
6378
+ * Only rendered in the `basic` variant.
6379
+ *
6380
+ * @example
6381
+ * ```tsx
6382
+ * <Dialog icon={<BookmarkIcon />}>
6383
+ * <DialogHeadline>Save bookmark?</DialogHeadline>
6384
+ * </Dialog>
6385
+ * ```
6386
+ */
6387
+ icon?: ReactNode;
6340
6388
  /**
6341
6389
  * Dialog slot content — typically `DialogHeadline`, `DialogContent`, `DialogActions`.
6342
6390
  */
@@ -6346,13 +6394,28 @@ interface DialogHeadlessProps {
6346
6394
  */
6347
6395
  className?: string;
6348
6396
  /**
6349
- * Additional CSS classes applied to the scrim overlay element.
6397
+ * Additional CSS classes applied to the centering/positioning wrapper element.
6398
+ * Consumed from `dialogWrapperVariants` by the styled `Dialog` layer.
6350
6399
  */
6351
- scrimClassName?: string;
6400
+ wrapperClassName?: string;
6401
+ /**
6402
+ * Returns CSS classes for the scrim based on the current animation state.
6403
+ * Called at render time to apply the correct fade-in/out animation.
6404
+ * When `undefined`, falls back to a static base scrim class.
6405
+ *
6406
+ * @example
6407
+ * ```tsx
6408
+ * getScrimClassName={(state) => dialogScrimVariants({ animationState: state })}
6409
+ * ```
6410
+ */
6411
+ getScrimClassName?: (state: DialogAnimationState) => string;
6352
6412
  /**
6353
6413
  * Additional CSS classes injected based on the current animation state.
6354
6414
  * Called at render time to merge CVA animation classes onto the panel.
6355
6415
  *
6416
+ * Returns empty string when `prefers-reduced-motion: reduce` is active
6417
+ * (handled by the styled `Dialog` layer via `useReducedMotion`).
6418
+ *
6356
6419
  * @example
6357
6420
  * ```tsx
6358
6421
  * getAnimationClassName={(state) => dialogAnimationVariants({ animationState: state, variant })}
@@ -6382,6 +6445,16 @@ interface DialogHeadlessProps {
6382
6445
  * </DialogActions>
6383
6446
  * </Dialog>
6384
6447
  *
6448
+ * // With hero icon
6449
+ * <Dialog icon={<BookmarkIcon />} open={open} onOpenChange={setOpen}>
6450
+ * <DialogHeadline>Save bookmark?</DialogHeadline>
6451
+ * <DialogContent>The page will be saved to your bookmarks.</DialogContent>
6452
+ * <DialogActions>
6453
+ * <Button variant="text" onPress={() => setOpen(false)}>Cancel</Button>
6454
+ * <Button variant="filled" onPress={handleSave}>Save</Button>
6455
+ * </DialogActions>
6456
+ * </Dialog>
6457
+ *
6385
6458
  * // Full-screen dialog (controlled)
6386
6459
  * <Dialog variant="fullscreen" open={open} onOpenChange={setOpen}>
6387
6460
  * <DialogHeadline
@@ -6419,6 +6492,19 @@ interface DialogProps {
6419
6492
  * Accessible label for the dialog when no `DialogHeadline` is present.
6420
6493
  */
6421
6494
  "aria-label"?: string;
6495
+ /**
6496
+ * Optional hero icon rendered centered above the headline per MD3 spec.
6497
+ * When present, headline and supporting text center-align automatically.
6498
+ * Only rendered in the `basic` variant.
6499
+ *
6500
+ * @example
6501
+ * ```tsx
6502
+ * <Dialog icon={<BookmarkIcon />}>
6503
+ * <DialogHeadline>Save bookmark?</DialogHeadline>
6504
+ * </Dialog>
6505
+ * ```
6506
+ */
6507
+ icon?: ReactNode;
6422
6508
  /**
6423
6509
  * Dialog slot content — `DialogHeadline`, `DialogContent`, `DialogActions`.
6424
6510
  */
@@ -6477,6 +6563,10 @@ interface DialogHeadlineProps {
6477
6563
  * Renders as a scrollable `<div>` and provides its `id` to `DialogContext`
6478
6564
  * so the parent dialog panel can reference it via `aria-describedby`.
6479
6565
  *
6566
+ * Shows MD3 scroll dividers (`border-outline-variant`) at the top and/or bottom
6567
+ * of the scroll container when content overflows. Dividers are toggled via
6568
+ * `data-scroll-divider-top` and `data-scroll-divider-bottom` attributes.
6569
+ *
6480
6570
  * @example
6481
6571
  * ```tsx
6482
6572
  * <DialogContent>
@@ -6531,17 +6621,24 @@ interface DialogActionsProps {
6531
6621
  * **Basic** (default):
6532
6622
  * - Floating card: `bg-surface-container-high`, `rounded-xl`, `shadow-elevation-3`
6533
6623
  * - Centered in viewport (min 280dp, max 560dp width)
6534
- * - Scale + fade entry animation (`duration-medium4 / ease-emphasized-decelerate`)
6535
- * - Fade exit animation (`duration-short2 / ease-emphasized-accelerate`)
6624
+ * - Scale + fade entry animation (`animate-md-scale-in`, expressive-fast-spatial 350ms)
6625
+ * - Scale + fade exit animation (`animate-md-scale-out`, emphasized-accelerate 200ms)
6626
+ * - Scrim fades in/out (`animate-md-fade-in` / `animate-md-fade-out`)
6536
6627
  * - Closes on scrim click or Escape key
6628
+ * - Optional hero icon above headline (`icon` prop) — centers headline + content text
6537
6629
  *
6538
6630
  * **Full-screen**:
6539
6631
  * - Full viewport coverage — suited for mobile and complex forms
6540
6632
  * - No rounded corners, no elevation shadow
6541
- * - Slide-up entry / slide-down exit animation
6633
+ * - Slide-up entry / slide-down exit animation (`animate-md-slide-in-bottom` / out)
6542
6634
  * - Does NOT close on scrim click per MD3 spec (only via Escape or close button)
6543
6635
  * - Headline replaced by top app bar row (close icon + confirm action)
6544
6636
  *
6637
+ * **Reduced motion**:
6638
+ * - When `prefers-reduced-motion: reduce` is active, all keyframe animations are
6639
+ * suppressed (no animate-md-* class applied). Dialog appears/disappears instantly.
6640
+ * - `transition-none` is appended so any inherited transitions are also disabled.
6641
+ *
6545
6642
  * Both variants:
6546
6643
  * - `role="dialog"` + `aria-modal="true"` (React Aria `useDialog`)
6547
6644
  * - `aria-labelledby` pointing to `DialogHeadline` id
@@ -6576,6 +6673,16 @@ interface DialogActionsProps {
6576
6673
  * );
6577
6674
  * }
6578
6675
  *
6676
+ * // With hero icon
6677
+ * <Dialog icon={<BookmarkIcon />} open={open} onOpenChange={setOpen}>
6678
+ * <DialogHeadline>Save bookmark?</DialogHeadline>
6679
+ * <DialogContent>The page will be saved to your bookmarks.</DialogContent>
6680
+ * <DialogActions>
6681
+ * <Button variant="text" onPress={() => setOpen(false)}>Cancel</Button>
6682
+ * <Button variant="filled" onPress={handleSave}>Save</Button>
6683
+ * </DialogActions>
6684
+ * </Dialog>
6685
+ *
6579
6686
  * // Full-screen dialog — mobile form flow
6580
6687
  * function NewEventDialog() {
6581
6688
  * const [open, setOpen] = useState(false);
@@ -6617,9 +6724,15 @@ declare const Dialog: React$1.ForwardRefExoticComponent<DialogProps & React$1.Re
6617
6724
  * Renders as an `<h2>` element and registers its `id` with the parent
6618
6725
  * `DialogContext` so the dialog panel can wire `aria-labelledby` correctly.
6619
6726
  *
6727
+ * When the parent dialog has a hero `icon` prop, the panel root carries
6728
+ * `data-with-icon` and `group/dialog`, so the `group-data-[with-icon]/dialog:text-center`
6729
+ * selector in `dialogHeadlineVariants` automatically centers the headline text —
6730
+ * no additional props needed here.
6731
+ *
6620
6732
  * For the `fullscreen` variant, the headline renders as a top app bar row
6621
6733
  * containing optional `closeButton` (leading icon button) and `confirmButton`
6622
- * (trailing text action) per MD3 Full-screen Dialog spec.
6734
+ * (trailing text action) per MD3 Full-screen Dialog spec. The fullscreen app bar
6735
+ * always shows a `border-b border-outline-variant` divider below it.
6623
6736
  *
6624
6737
  * Must be rendered inside a `<Dialog>` or `<DialogHeadless>` component.
6625
6738
  *
@@ -6660,6 +6773,13 @@ declare const DialogHeadline: React$1.ForwardRefExoticComponent<DialogHeadlinePr
6660
6773
  * Styled with `text-body-medium` and `text-on-surface-variant` per MD3 spec.
6661
6774
  * Overflows vertically when content exceeds the available height.
6662
6775
  *
6776
+ * **Scroll dividers**: Shows `border-outline-variant` dividers at the top and/or
6777
+ * bottom edge when content overflows and is not scrolled to the respective edge.
6778
+ * Dividers are toggled by setting `data-scroll-divider-top` / `data-scroll-divider-bottom`
6779
+ * presence attributes on the element. The CVA base class uses
6780
+ * `data-[scroll-divider-top]:border-t` and `data-[scroll-divider-bottom]:border-b`
6781
+ * to apply the borders — no style props needed.
6782
+ *
6663
6783
  * Must be rendered inside a `<Dialog>` or `<DialogHeadless>` component.
6664
6784
  *
6665
6785
  * @example
@@ -6739,7 +6859,12 @@ declare function useDialogContext(): DialogContextValue;
6739
6859
  * Basic variant is dismissable (Escape + outside click);
6740
6860
  * Full-screen variant is Escape-dismissable only (no scrim click) per MD3 spec.
6741
6861
  * - **Animation state machine**: `entering → visible → exiting → exited`
6742
- * mirrors the Snackbar animation pattern.
6862
+ * Exit advances on `onAnimationEnd` with `e.target === e.currentTarget` guard
6863
+ * (prevents child animation events from advancing the state machine), plus a
6864
+ * 250ms fallback timer in case the animation event doesn't fire.
6865
+ * - **Scrim animation**: state-driven via `getScrimClassName(animationState)`.
6866
+ * - **Hero icon**: optional `icon` prop renders centered above headline;
6867
+ * sets `data-with-icon` on panel root for group-data centering of headline/content.
6743
6868
  * - **ARIA wiring**: `DialogContext` provides stable IDs for `aria-labelledby`
6744
6869
  * and `aria-describedby`, consumed by slot sub-components.
6745
6870
  *
@@ -6757,8 +6882,9 @@ declare function useDialogContext(): DialogContextValue;
6757
6882
  * variant="basic"
6758
6883
  * open={open}
6759
6884
  * onOpenChange={setOpen}
6760
- * className={cn(dialogWrapperVariants({ variant: 'basic' }), dialogPanelVariants({ variant: 'basic' }))}
6761
- * scrimClassName={dialogScrimVariants()}
6885
+ * className={cn(dialogPanelVariants({ variant: 'basic' }))}
6886
+ * wrapperClassName={dialogWrapperVariants({ variant: 'basic' })}
6887
+ * getScrimClassName={(state) => dialogScrimVariants({ animationState: state })}
6762
6888
  * getAnimationClassName={(state) =>
6763
6889
  * dialogAnimationVariants({ animationState: state, variant: 'basic' })
6764
6890
  * }