@tinybigui/react 0.22.0 → 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.cjs CHANGED
@@ -472,6 +472,10 @@ var buttonVariants = classVarianceAuthority.cva(
472
472
  * Filled/Tonal hover→level-1, focus/pressed→level-0
473
473
  * Elevated base→level-1, hover→level-2, focus/pressed→level-1
474
474
  * Outlined/Text no elevation
475
+ *
476
+ * Self-targeting `data-[x]:` is used for elevation because these classes
477
+ * sit on the root element (the group host) — group-data descendant
478
+ * selectors cannot match an element against itself.
475
479
  */
476
480
  variant: {
477
481
  /**
@@ -480,17 +484,17 @@ var buttonVariants = classVarianceAuthority.cva(
480
484
  * Elevation: 0 base → 1 hover → 0 focus → 0 pressed
481
485
  */
482
486
  filled: [
483
- "bg-primary text-on-primary shadow-none",
487
+ "text-on-primary shadow-none",
484
488
  // Hover: gains level-1 elevation
485
- "group-data-[hovered]/button:shadow-elevation-1",
489
+ "data-[hovered]:shadow-elevation-1",
486
490
  // Focus/pressed: shadow must explicitly return to level-0
487
491
  // (doubled attribute selector → higher specificity than hover)
488
- "group-data-[focus-visible]/button:shadow-none",
489
- "group-data-[pressed]/button:group-data-[pressed]/button:shadow-none",
490
- // Disabled overrides
491
- "group-data-[disabled]/button:bg-on-surface/12",
492
- "group-data-[disabled]/button:text-on-surface/38",
493
- "group-data-[disabled]/button:shadow-none"
492
+ "data-[focus-visible]:data-[focus-visible]:shadow-none",
493
+ "data-[pressed]:data-[pressed]:data-[pressed]:shadow-none",
494
+ // Disabled overrides — root owns text color + shadow only;
495
+ // disabled bg override lives on buttonContainerVariants (filled variant)
496
+ "data-[disabled]:text-on-surface/38",
497
+ "data-[disabled]:shadow-none"
494
498
  ],
495
499
  /**
496
500
  * Outlined — medium emphasis. Transparent with border.
@@ -498,10 +502,10 @@ var buttonVariants = classVarianceAuthority.cva(
498
502
  * Elevation: always 0
499
503
  */
500
504
  outlined: [
501
- "bg-transparent border border-outline text-primary",
505
+ "border border-outline text-primary",
502
506
  // Disabled overrides
503
- "group-data-[disabled]/button:border-on-surface/12",
504
- "group-data-[disabled]/button:text-on-surface/38"
507
+ "data-[disabled]:border-on-surface/12",
508
+ "data-[disabled]:text-on-surface/38"
505
509
  ],
506
510
  /**
507
511
  * Tonal — secondary emphasis.
@@ -509,16 +513,15 @@ var buttonVariants = classVarianceAuthority.cva(
509
513
  * Elevation: 0 base → 1 hover → 0 focus → 0 pressed
510
514
  */
511
515
  tonal: [
512
- "bg-secondary-container text-on-secondary-container shadow-none",
516
+ "text-on-secondary-container shadow-none",
513
517
  // Hover: gains level-1 elevation (same as filled)
514
- "group-data-[hovered]/button:shadow-elevation-1",
518
+ "data-[hovered]:shadow-elevation-1",
515
519
  // Focus/pressed: return to level-0
516
- "group-data-[focus-visible]/button:shadow-none",
517
- "group-data-[pressed]/button:group-data-[pressed]/button:shadow-none",
520
+ "data-[focus-visible]:data-[focus-visible]:shadow-none",
521
+ "data-[pressed]:data-[pressed]:data-[pressed]:shadow-none",
518
522
  // Disabled overrides
519
- "group-data-[disabled]/button:bg-on-surface/12",
520
- "group-data-[disabled]/button:text-on-surface/38",
521
- "group-data-[disabled]/button:shadow-none"
523
+ "data-[disabled]:text-on-surface/38",
524
+ "data-[disabled]:shadow-none"
522
525
  ],
523
526
  /**
524
527
  * Elevated — separation via shadow.
@@ -526,17 +529,16 @@ var buttonVariants = classVarianceAuthority.cva(
526
529
  * Elevation: 1 base → 2 hover → 1 focus → 1 pressed
527
530
  */
528
531
  elevated: [
529
- "bg-surface-container-low text-primary shadow-elevation-1",
532
+ "text-primary shadow-elevation-1",
530
533
  // Hover: gains extra elevation
531
- "group-data-[hovered]/button:shadow-elevation-2",
534
+ "data-[hovered]:shadow-elevation-2",
532
535
  // Focus/pressed: return to base level-1
533
536
  // (doubled selector wins over single hover selector at same cascade position)
534
- "group-data-[focus-visible]/button:shadow-elevation-1",
535
- "group-data-[pressed]/button:group-data-[pressed]/button:shadow-elevation-1",
537
+ "data-[focus-visible]:data-[focus-visible]:shadow-elevation-1",
538
+ "data-[pressed]:data-[pressed]:data-[pressed]:shadow-elevation-1",
536
539
  // Disabled overrides
537
- "group-data-[disabled]/button:bg-on-surface/12",
538
- "group-data-[disabled]/button:text-on-surface/38",
539
- "group-data-[disabled]/button:shadow-none"
540
+ "data-[disabled]:text-on-surface/38",
541
+ "data-[disabled]:shadow-none"
540
542
  ],
541
543
  /**
542
544
  * Text — lowest emphasis.
@@ -544,9 +546,9 @@ var buttonVariants = classVarianceAuthority.cva(
544
546
  * Elevation: always 0
545
547
  */
546
548
  text: [
547
- "bg-transparent text-primary",
549
+ "text-primary",
548
550
  // Disabled overrides
549
- "group-data-[disabled]/button:text-on-surface/38"
551
+ "data-[disabled]:text-on-surface/38"
550
552
  ]
551
553
  },
552
554
  /**
@@ -584,6 +586,29 @@ var buttonVariants = classVarianceAuthority.cva(
584
586
  }
585
587
  }
586
588
  );
589
+ var buttonContainerVariants = classVarianceAuthority.cva(
590
+ [
591
+ "absolute inset-0 rounded-[inherit] pointer-events-none",
592
+ // Effects transition for background-color — no overshoot
593
+ "transition-[background-color] duration-spring-standard-fast-effects ease-spring-standard-fast-effects"
594
+ ],
595
+ {
596
+ variants: {
597
+ variant: {
598
+ // MD3 disabled: filled containers replace bg with on-surface/12.
599
+ // group-data descendant selector targets this child span (not the root host).
600
+ filled: "bg-primary group-data-[disabled]/button:bg-on-surface/12",
601
+ // outlined/text: container stays transparent when disabled — only border + label fade.
602
+ outlined: "bg-transparent",
603
+ // MD3 disabled: tonal and elevated containers also replace bg with on-surface/12.
604
+ tonal: "bg-secondary-container group-data-[disabled]/button:bg-on-surface/12",
605
+ elevated: "bg-surface-container-low group-data-[disabled]/button:bg-on-surface/12",
606
+ text: "bg-transparent"
607
+ }
608
+ },
609
+ defaultVariants: { variant: "filled" }
610
+ }
611
+ );
587
612
  var buttonStateLayerVariants = classVarianceAuthority.cva(
588
613
  [
589
614
  "absolute inset-0 rounded-[inherit] overflow-hidden pointer-events-none opacity-0",
@@ -886,6 +911,7 @@ var Button = React.forwardRef(
886
911
  className
887
912
  ),
888
913
  children: [
914
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(buttonContainerVariants({ variant })), "aria-hidden": "true" }),
889
915
  ripples,
890
916
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(buttonStateLayerVariants({ variant })), "aria-hidden": "true" }),
891
917
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(buttonFocusRingVariants()), "aria-hidden": "true" }),
@@ -5952,6 +5978,416 @@ var CardActions = React.forwardRef(function CardActions2({ children, className }
5952
5978
  return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex items-center justify-end gap-2 p-4 pt-0", className), children });
5953
5979
  });
5954
5980
  CardActions.displayName = "CardActions";
5981
+ var menuContainerVariants = classVarianceAuthority.cva(
5982
+ [
5983
+ // Width constraints: 112dp min / 280dp max per MD3 spec
5984
+ "min-w-28 max-w-70",
5985
+ "flex flex-col",
5986
+ // Scroll behaviour
5987
+ "max-h-[calc(var(--visual-viewport-height,100vh)-2rem)]",
5988
+ // Stacking
5989
+ "z-50",
5990
+ "gap-0.5",
5991
+ // Focus outline delegated to React Aria
5992
+ "outline-none"
5993
+ ],
5994
+ {
5995
+ variants: {
5996
+ /**
5997
+ * Color scheme — drives item/segment background and content colors.
5998
+ * standard: surface-container-low item background.
5999
+ * vibrant: tertiary-container item background.
6000
+ */
6001
+ colorScheme: {
6002
+ standard: [],
6003
+ vibrant: []
6004
+ },
6005
+ /**
6006
+ * Visual style — drives corner radius and container background.
6007
+ *
6008
+ * baseline: solid surface-container, 4dp corners, 8dp vertical padding.
6009
+ * vertical: transparent container, 16dp corners, no container padding —
6010
+ * items own their segment surface, gaps reveal the page background.
6011
+ */
6012
+ menuStyle: {
6013
+ baseline: ["rounded-xs", "bg-surface-container", "py-2"],
6014
+ vertical: ["bg-transparent"]
6015
+ }
6016
+ },
6017
+ defaultVariants: {
6018
+ colorScheme: "standard",
6019
+ menuStyle: "baseline"
6020
+ }
6021
+ }
6022
+ );
6023
+ var menuPopoverVariants = classVarianceAuthority.cva([
6024
+ "will-change-[transform,opacity]",
6025
+ "data-[entering]:pointer-events-none data-[exiting]:pointer-events-none",
6026
+ "data-[entering]:animate-md-scale-in",
6027
+ "data-[exiting]:animate-md-scale-out",
6028
+ "origin-top",
6029
+ "data-[placement=top]:origin-bottom",
6030
+ "data-[placement=left]:origin-right",
6031
+ "data-[placement=right]:origin-left",
6032
+ "motion-reduce:data-[entering]:animate-none motion-reduce:data-[exiting]:animate-none"
6033
+ ]);
6034
+ var menuItemVariants = classVarianceAuthority.cva(
6035
+ [
6036
+ // Layout — height set by density context in MenuItem component
6037
+ // gap is style-specific: baseline = 12dp (gap-3), vertical = 8dp (gap-2)
6038
+ "relative flex w-full items-center",
6039
+ // Typography: Label Large per MD3 menu spec
6040
+ "text-label-large",
6041
+ // Interaction
6042
+ "cursor-pointer select-none outline-none",
6043
+ // Color transition (effects — no overshoot)
6044
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
6045
+ // Disabled — self-targeting data-[x]: selectors (RAC emits data-disabled)
6046
+ "data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed"
6047
+ ],
6048
+ {
6049
+ variants: {
6050
+ /**
6051
+ * Color scheme — drives item bg, default text/icon color, and selection colors.
6052
+ *
6053
+ * standard: surface-container-low bg, on-surface text, on-surface-variant icons.
6054
+ * Selected/open: tertiary-container bg highlight, on-tertiary-container content.
6055
+ * vibrant: tertiary-container bg, on-tertiary-container text AND icons.
6056
+ * Selected/open: tertiary bg highlight, on-tertiary content.
6057
+ */
6058
+ colorScheme: {
6059
+ standard: ["text-on-surface"],
6060
+ vibrant: ["text-on-tertiary-container"]
6061
+ },
6062
+ /**
6063
+ * Visual style — drives padding, gap, segment surface, and corner rounding.
6064
+ *
6065
+ * baseline: 12dp h-padding, 12dp icon-to-label gap, no item background (container provides it).
6066
+ * vertical: 12dp h-padding, 8dp icon-to-label gap, item owns segment surface, segmented rounding
6067
+ * via first/last + adjacent-sibling gap selectors.
6068
+ */
6069
+ menuStyle: {
6070
+ baseline: ["px-3", "gap-3"],
6071
+ vertical: [
6072
+ "px-3",
6073
+ "gap-2",
6074
+ // Default: inner item (4dp all corners)
6075
+ "rounded-md"
6076
+ // Last item in the whole menu → 16dp bottom corners
6077
+ ]
6078
+ }
6079
+ },
6080
+ compoundVariants: [
6081
+ // vertical + standard: selected/open text → on-tertiary-container
6082
+ {
6083
+ menuStyle: "vertical",
6084
+ colorScheme: "standard",
6085
+ class: [
6086
+ "data-[selected]:text-on-tertiary-container",
6087
+ "data-[open]:text-on-tertiary-container"
6088
+ ]
6089
+ },
6090
+ // vertical + vibrant: selected/open text → on-tertiary
6091
+ {
6092
+ menuStyle: "vertical",
6093
+ colorScheme: "vibrant",
6094
+ class: ["data-[selected]:text-on-tertiary", "data-[open]:text-on-tertiary"]
6095
+ }
6096
+ ],
6097
+ defaultVariants: {
6098
+ colorScheme: "standard",
6099
+ menuStyle: "baseline"
6100
+ }
6101
+ }
6102
+ );
6103
+ var menuItemHighlightVariants = classVarianceAuthority.cva(
6104
+ [
6105
+ "absolute inset-0 pointer-events-none",
6106
+ // Inherit the item's own corner radius (inner 4dp or outer 16dp)
6107
+ "rounded-[inherit]",
6108
+ // Effects transition for background-color — no overshoot
6109
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
6110
+ // z-0: below state layer (z-[1]) and content (z-10)
6111
+ "z-0"
6112
+ ],
6113
+ {
6114
+ variants: {
6115
+ menuStyle: {
6116
+ baseline: [],
6117
+ vertical: []
6118
+ },
6119
+ colorScheme: {
6120
+ standard: [
6121
+ // baseline selected bg
6122
+ "group-data-[selected]/menuitem:bg-surface-container-highest"
6123
+ ],
6124
+ vibrant: [
6125
+ // baseline + vibrant: use surface-container-highest as fallback
6126
+ "group-data-[selected]/menuitem:bg-surface-container-highest"
6127
+ ]
6128
+ }
6129
+ },
6130
+ compoundVariants: [
6131
+ // vertical + standard: selected/open highlight → tertiary-container
6132
+ {
6133
+ menuStyle: "vertical",
6134
+ colorScheme: "standard",
6135
+ class: [
6136
+ "group-data-[selected]/menuitem:bg-tertiary-container",
6137
+ "group-data-[open]/menuitem:bg-tertiary-container"
6138
+ ]
6139
+ },
6140
+ // vertical + vibrant: selected/open highlight → tertiary
6141
+ {
6142
+ menuStyle: "vertical",
6143
+ colorScheme: "vibrant",
6144
+ class: [
6145
+ "group-data-[selected]/menuitem:bg-tertiary",
6146
+ "group-data-[open]/menuitem:bg-tertiary"
6147
+ ]
6148
+ }
6149
+ ],
6150
+ defaultVariants: {
6151
+ menuStyle: "baseline",
6152
+ colorScheme: "standard"
6153
+ }
6154
+ }
6155
+ );
6156
+ var menuItemStateLayerVariants = classVarianceAuthority.cva(
6157
+ [
6158
+ "absolute inset-0 rounded-[inherit] overflow-hidden pointer-events-none opacity-0",
6159
+ // Effects transition — opacity must NOT overshoot
6160
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
6161
+ // Hover: 8%
6162
+ "group-data-[hovered]/menuitem:opacity-8",
6163
+ // Pressed: 10%, doubled selector wins over hover at same cascade position
6164
+ "group-data-[pressed]/menuitem:group-data-[pressed]/menuitem:opacity-10",
6165
+ // No state layer when disabled
6166
+ "group-data-[disabled]/menuitem:hidden",
6167
+ // z-[1]: above highlight layer (z-0), below content (z-10)
6168
+ "z-[1]"
6169
+ ],
6170
+ {
6171
+ variants: {
6172
+ colorScheme: {
6173
+ standard: ["bg-on-surface"],
6174
+ vibrant: ["bg-on-tertiary-container"]
6175
+ },
6176
+ menuStyle: {
6177
+ baseline: [],
6178
+ vertical: []
6179
+ }
6180
+ },
6181
+ compoundVariants: [
6182
+ // vertical + standard: selected/open state layer → on-tertiary-container
6183
+ {
6184
+ menuStyle: "vertical",
6185
+ colorScheme: "standard",
6186
+ class: [
6187
+ "group-data-[selected]/menuitem:bg-on-tertiary-container",
6188
+ "group-data-[open]/menuitem:bg-on-tertiary-container"
6189
+ ]
6190
+ },
6191
+ // vertical + vibrant: selected/open state layer → on-tertiary
6192
+ {
6193
+ menuStyle: "vertical",
6194
+ colorScheme: "vibrant",
6195
+ class: [
6196
+ "group-data-[selected]/menuitem:bg-on-tertiary",
6197
+ "group-data-[open]/menuitem:bg-on-tertiary"
6198
+ ]
6199
+ }
6200
+ ],
6201
+ defaultVariants: {
6202
+ colorScheme: "standard",
6203
+ menuStyle: "baseline"
6204
+ }
6205
+ }
6206
+ );
6207
+ var menuItemFocusRingVariants = classVarianceAuthority.cva([
6208
+ "pointer-events-none absolute inset-0 rounded-[inherit]",
6209
+ "outline outline-2 -outline-offset-2 outline-secondary",
6210
+ // Effects transition — opacity must not overshoot
6211
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
6212
+ "opacity-0",
6213
+ "group-data-[focus-visible]/menuitem:opacity-100",
6214
+ // z-[2]: above state layer (z-[1]) and highlight (z-0), below content (z-10)
6215
+ "z-[2]"
6216
+ ]);
6217
+ var menuItemIconVariants = classVarianceAuthority.cva(
6218
+ [
6219
+ "relative z-10 shrink-0 flex items-center justify-center",
6220
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
6221
+ // Disabled: 38% opacity on icon color
6222
+ "group-data-[disabled]/menuitem:text-on-surface/38"
6223
+ ],
6224
+ {
6225
+ variants: {
6226
+ colorScheme: {
6227
+ standard: ["text-on-surface-variant"],
6228
+ vibrant: ["text-on-tertiary-container"]
6229
+ },
6230
+ menuStyle: {
6231
+ baseline: ["h-6 w-6"],
6232
+ vertical: ["h-5 w-5"]
6233
+ }
6234
+ },
6235
+ compoundVariants: [
6236
+ // vertical + standard: selected/open icon → on-tertiary-container
6237
+ {
6238
+ menuStyle: "vertical",
6239
+ colorScheme: "standard",
6240
+ class: [
6241
+ "group-data-[selected]/menuitem:text-on-tertiary-container",
6242
+ "group-data-[open]/menuitem:text-on-tertiary-container"
6243
+ ]
6244
+ },
6245
+ // vertical + vibrant: selected/open icon → on-tertiary
6246
+ {
6247
+ menuStyle: "vertical",
6248
+ colorScheme: "vibrant",
6249
+ class: [
6250
+ "group-data-[selected]/menuitem:text-on-tertiary",
6251
+ "group-data-[open]/menuitem:text-on-tertiary"
6252
+ ]
6253
+ }
6254
+ ],
6255
+ defaultVariants: {
6256
+ colorScheme: "standard",
6257
+ menuStyle: "baseline"
6258
+ }
6259
+ }
6260
+ );
6261
+ var menuSectionVariants = classVarianceAuthority.cva(["flex flex-col w-full"]);
6262
+ var menuSectionHeaderVariants = classVarianceAuthority.cva(
6263
+ [
6264
+ // 32dp tall region, content vertically centred, 12dp leading padding aligned with items
6265
+ "px-3 h-8 flex items-center",
6266
+ "text-title-small",
6267
+ "select-none"
6268
+ ],
6269
+ {
6270
+ variants: {
6271
+ colorScheme: {
6272
+ standard: ["text-on-surface-variant"],
6273
+ vibrant: ["text-on-tertiary-container"]
6274
+ }
6275
+ },
6276
+ defaultVariants: {
6277
+ colorScheme: "standard"
6278
+ }
6279
+ }
6280
+ );
6281
+ var menuDividerVariants = classVarianceAuthority.cva(["border-t border-outline-variant", "my-0.5 mx-3"]);
6282
+ classVarianceAuthority.cva(["h-0.5 w-full"]);
6283
+ var menuItemTrailingTextVariants = classVarianceAuthority.cva(
6284
+ [
6285
+ "ml-auto shrink-0 text-label-large",
6286
+ "select-none",
6287
+ "group-data-[disabled]/menuitem:text-on-surface/38"
6288
+ ],
6289
+ {
6290
+ variants: {
6291
+ colorScheme: {
6292
+ standard: ["text-on-surface-variant"],
6293
+ vibrant: ["text-on-tertiary-container"]
6294
+ },
6295
+ menuStyle: {
6296
+ baseline: [],
6297
+ vertical: [
6298
+ "group-data-[selected]/menuitem:text-on-tertiary-container",
6299
+ "group-data-[open]/menuitem:text-on-tertiary-container"
6300
+ ]
6301
+ }
6302
+ },
6303
+ compoundVariants: [
6304
+ // vertical + vibrant: selected/open trailing text → on-tertiary
6305
+ {
6306
+ menuStyle: "vertical",
6307
+ colorScheme: "vibrant",
6308
+ class: [
6309
+ "group-data-[selected]/menuitem:text-on-tertiary",
6310
+ "group-data-[open]/menuitem:text-on-tertiary"
6311
+ ]
6312
+ }
6313
+ ],
6314
+ defaultVariants: {
6315
+ colorScheme: "standard",
6316
+ menuStyle: "baseline"
6317
+ }
6318
+ }
6319
+ );
6320
+ var menuItemDescriptionVariants = classVarianceAuthority.cva(
6321
+ ["text-body-medium", "select-none", "group-data-[disabled]/menuitem:text-on-surface/38"],
6322
+ {
6323
+ variants: {
6324
+ colorScheme: {
6325
+ standard: ["text-on-surface-variant"],
6326
+ vibrant: ["text-on-tertiary-container"]
6327
+ },
6328
+ menuStyle: {
6329
+ baseline: [],
6330
+ vertical: [
6331
+ "group-data-[selected]/menuitem:text-on-tertiary-container",
6332
+ "group-data-[open]/menuitem:text-on-tertiary-container"
6333
+ ]
6334
+ }
6335
+ },
6336
+ compoundVariants: [
6337
+ // vertical + vibrant: selected/open description → on-tertiary
6338
+ {
6339
+ menuStyle: "vertical",
6340
+ colorScheme: "vibrant",
6341
+ class: [
6342
+ "group-data-[selected]/menuitem:text-on-tertiary",
6343
+ "group-data-[open]/menuitem:text-on-tertiary"
6344
+ ]
6345
+ }
6346
+ ],
6347
+ defaultVariants: {
6348
+ colorScheme: "standard",
6349
+ menuStyle: "baseline"
6350
+ }
6351
+ }
6352
+ );
6353
+ classVarianceAuthority.cva(
6354
+ [
6355
+ "flex flex-col w-full",
6356
+ "px-1 py-0.5 gap-0.5",
6357
+ "rounded-lg first:rounded-b-sm last:rounded-t-sm",
6358
+ "shadow-elevation-1"
6359
+ ],
6360
+ {
6361
+ variants: {
6362
+ menuStyle: {
6363
+ vertical: ["bg-surface-container-low"],
6364
+ baseline: []
6365
+ },
6366
+ colorScheme: {
6367
+ standard: ["bg-surface-container-low"],
6368
+ vibrant: ["bg-tertiary-container"]
6369
+ }
6370
+ },
6371
+ compoundVariants: [
6372
+ // vertical + standard: item background = surface-container-low
6373
+ {
6374
+ menuStyle: "vertical",
6375
+ colorScheme: "standard",
6376
+ class: ["bg-surface-container-low"]
6377
+ },
6378
+ // vertical + vibrant: item background = tertiary-container
6379
+ {
6380
+ menuStyle: "vertical",
6381
+ colorScheme: "vibrant",
6382
+ class: ["bg-tertiary-container"]
6383
+ }
6384
+ ],
6385
+ defaultVariants: {
6386
+ menuStyle: "vertical",
6387
+ colorScheme: "standard"
6388
+ }
6389
+ }
6390
+ );
5955
6391
  var MenuContext = React.createContext(null);
5956
6392
  function useMenuContext() {
5957
6393
  return React.useContext(MenuContext);
@@ -5989,7 +6425,16 @@ function HeadlessMenuTrigger({
5989
6425
  const [triggerChild, menuChild] = childrenArray;
5990
6426
  return /* @__PURE__ */ jsxRuntime.jsxs(reactAriaComponents.MenuTrigger, { ...rest, children: [
5991
6427
  /* @__PURE__ */ jsxRuntime.jsx(TriggerBridge, { children: triggerChild }),
5992
- /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Popover, { placement, shouldFlip, offset: 4, children: menuChild })
6428
+ /* @__PURE__ */ jsxRuntime.jsx(
6429
+ reactAriaComponents.Popover,
6430
+ {
6431
+ placement,
6432
+ shouldFlip,
6433
+ offset: 4,
6434
+ className: menuPopoverVariants(),
6435
+ children: menuChild
6436
+ }
6437
+ )
5993
6438
  ] });
5994
6439
  }
5995
6440
  function HeadlessMenu({
@@ -6041,192 +6486,6 @@ function HeadlessMenuDivider({
6041
6486
  }) {
6042
6487
  return /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Separator, { ...props, className: className ?? "" });
6043
6488
  }
6044
- var menuContainerVariants = classVarianceAuthority.cva(
6045
- [
6046
- // Elevation
6047
- "shadow-elevation-2",
6048
- // Width constraints per MD3 spec (112dp min / 280dp max)
6049
- "min-w-28 max-w-70",
6050
- // Layout
6051
- "py-2",
6052
- // Scroll: show scrollbar when content overflows; max height avoids clipping
6053
- "overflow-y-auto",
6054
- "max-h-[calc(var(--visual-viewport-height,100vh)-2rem)]",
6055
- // Stacking
6056
- "z-50",
6057
- // Focus outline handled by React Aria
6058
- "outline-none",
6059
- // GPU compositing — promotes menu to its own compositor layer so
6060
- // scale + opacity animations run without triggering layout reflow.
6061
- "will-change-[transform,opacity]",
6062
- // Pointer events blocked during animation to prevent accidental clicks
6063
- // on menu items while the panel is still animating in or out.
6064
- "data-[entering]:pointer-events-none data-[exiting]:pointer-events-none",
6065
- // ── Enter animation ────────────────────────────────────────────────────
6066
- // @keyframes menu-enter (defined in styles.css): scale(0.8)+opacity:0 →
6067
- // scale(1)+opacity:1 in 120ms with cubic-bezier(0,0,0.2,1) (standard
6068
- // decelerate — matches Angular Material's _mat-menu-enter keyframe).
6069
- "data-[entering]:animate-[menu-enter_120ms_cubic-bezier(0,0,0.2,1)_both]",
6070
- // ── Exit animation ─────────────────────────────────────────────────────
6071
- // @keyframes menu-exit (defined in styles.css): opacity:1 → opacity:0
6072
- // in 100ms after 25ms delay, linear — matches Angular Material's
6073
- // _mat-menu-exit keyframe (fade-only, no reverse scale).
6074
- "data-[exiting]:animate-[menu-exit_100ms_25ms_linear_both]",
6075
- // ── Transform origin (placement-aware) ────────────────────────────────
6076
- // RAC sets data-placement="bottom|top|left|right" on the Popover element.
6077
- // Default (bottom): origin at top edge (menu expands downward).
6078
- "origin-top",
6079
- // top: origin at bottom edge (menu expands upward)
6080
- "data-[placement=top]:origin-bottom",
6081
- // left: origin at right edge
6082
- "data-[placement=left]:origin-right",
6083
- // right: origin at left edge
6084
- "data-[placement=right]:origin-left",
6085
- // ── Reduced motion ────────────────────────────────────────────────────
6086
- // Skip both animations entirely for users who prefer reduced motion.
6087
- "motion-reduce:data-[entering]:animate-none motion-reduce:data-[exiting]:animate-none"
6088
- ],
6089
- {
6090
- variants: {
6091
- /**
6092
- * Color scheme — drives the container background.
6093
- * baseline+standard uses a separate compound variant.
6094
- */
6095
- colorScheme: {
6096
- standard: [],
6097
- vibrant: []
6098
- },
6099
- /**
6100
- * Visual style — drives corner radius and baseline vs vertical background.
6101
- */
6102
- menuStyle: {
6103
- baseline: ["rounded-xs", "bg-surface-container"],
6104
- vertical: ["rounded-lg", "bg-surface-container-low"]
6105
- }
6106
- },
6107
- compoundVariants: [
6108
- // Vertical + vibrant: tertiary container background
6109
- {
6110
- menuStyle: "vertical",
6111
- colorScheme: "vibrant",
6112
- class: ["bg-tertiary-container"]
6113
- }
6114
- ],
6115
- defaultVariants: {
6116
- colorScheme: "standard",
6117
- menuStyle: "baseline"
6118
- }
6119
- }
6120
- );
6121
- var menuItemVariants = classVarianceAuthority.cva(
6122
- [
6123
- // Layout — height set by density context in MenuItem component
6124
- "relative flex w-full items-center",
6125
- "px-3 gap-3",
6126
- // Typography: Body Large per MD3 baseline spec
6127
- "text-body-large",
6128
- // Interaction
6129
- "cursor-pointer select-none outline-none",
6130
- // State layer pseudo-element
6131
- "before:absolute before:inset-0 before:rounded-[inherit]",
6132
- "before:transition-opacity before:duration-short2 before:ease-standard",
6133
- "before:opacity-0",
6134
- // Hover state layer
6135
- "hover:before:opacity-8",
6136
- // Focus visible state layer
6137
- "focus-visible:before:opacity-12",
6138
- // Active pressed state layer
6139
- "active:before:opacity-12",
6140
- // Color transition for selection
6141
- "transition-colors duration-short2 ease-standard"
6142
- ],
6143
- {
6144
- variants: {
6145
- /**
6146
- * Disabled state: reduces opacity and blocks interaction.
6147
- */
6148
- isDisabled: {
6149
- true: ["opacity-38 cursor-not-allowed pointer-events-none"],
6150
- false: []
6151
- },
6152
- /**
6153
- * Selected state: background and text color driven by compound variants.
6154
- */
6155
- isSelected: {
6156
- true: [],
6157
- false: []
6158
- },
6159
- /**
6160
- * Color scheme: drives default text and state layer colors.
6161
- * - standard: on-surface text, on-surface state layer
6162
- * - vibrant (vertical only): on-tertiary-container text + state layer
6163
- */
6164
- colorScheme: {
6165
- standard: ["text-on-surface", "before:bg-on-surface"],
6166
- vibrant: ["text-on-tertiary-container", "before:bg-on-tertiary-container"]
6167
- },
6168
- /**
6169
- * Visual style: drives corner radius on items (vertical uses rounded-lg
6170
- * inherited from container, items stay flat inside).
6171
- */
6172
- menuStyle: {
6173
- baseline: [],
6174
- vertical: []
6175
- }
6176
- },
6177
- compoundVariants: [
6178
- // ── Baseline selection (both colorSchemes) ──────────────────────────
6179
- {
6180
- isSelected: true,
6181
- menuStyle: "baseline",
6182
- class: [
6183
- "bg-surface-container-highest"
6184
- // text-on-surface already applied by standard colorScheme variant
6185
- ]
6186
- },
6187
- // ── Vertical + Standard selection ───────────────────────────────────
6188
- {
6189
- isSelected: true,
6190
- menuStyle: "vertical",
6191
- colorScheme: "standard",
6192
- class: [
6193
- "bg-tertiary-container",
6194
- "text-on-tertiary-container",
6195
- "before:bg-on-tertiary-container"
6196
- ]
6197
- },
6198
- // ── Vertical + Vibrant selection ─────────────────────────────────────
6199
- {
6200
- isSelected: true,
6201
- menuStyle: "vertical",
6202
- colorScheme: "vibrant",
6203
- class: ["bg-tertiary", "text-on-tertiary", "before:bg-on-tertiary"]
6204
- }
6205
- ],
6206
- defaultVariants: {
6207
- isDisabled: false,
6208
- isSelected: false,
6209
- colorScheme: "standard",
6210
- menuStyle: "baseline"
6211
- }
6212
- }
6213
- );
6214
- var menuSectionVariants = classVarianceAuthority.cva(["flex flex-col w-full"]);
6215
- var menuSectionHeaderVariants = classVarianceAuthority.cva([
6216
- "px-3 pt-2 pb-1",
6217
- "text-title-small text-on-surface-variant",
6218
- "select-none"
6219
- ]);
6220
- var menuDividerVariants = classVarianceAuthority.cva(["border-t border-outline-variant", "my-2 mx-0"]);
6221
- classVarianceAuthority.cva(["h-2 w-full"]);
6222
- var menuItemTrailingTextVariants = classVarianceAuthority.cva([
6223
- "ml-auto shrink-0 text-label-large text-on-surface-variant",
6224
- "select-none"
6225
- ]);
6226
- var menuItemDescriptionVariants = classVarianceAuthority.cva([
6227
- "text-body-medium text-on-surface-variant",
6228
- "select-none"
6229
- ]);
6230
6489
  var Menu = React.forwardRef(function Menu2({
6231
6490
  children,
6232
6491
  className,
@@ -6286,7 +6545,13 @@ function CheckIcon() {
6286
6545
  }
6287
6546
  );
6288
6547
  }
6289
- var DENSITY_HEIGHT = {
6548
+ var BASELINE_DENSITY_HEIGHT = {
6549
+ 0: "h-12",
6550
+ [-1]: "h-11",
6551
+ [-2]: "h-10",
6552
+ [-3]: "h-9"
6553
+ };
6554
+ var VERTICAL_DENSITY_HEIGHT = {
6290
6555
  0: "h-12",
6291
6556
  [-1]: "h-11",
6292
6557
  [-2]: "h-10",
@@ -6309,19 +6574,18 @@ var MenuItem = React.forwardRef(function MenuItem2({
6309
6574
  const menuStyle = ctx?.menuStyle ?? "baseline";
6310
6575
  const density = ctx?.density ?? 0;
6311
6576
  const selectionMode = ctx?.selectionMode;
6312
- const heightClass = DENSITY_HEIGHT[density];
6577
+ const heightClass = menuStyle === "vertical" ? VERTICAL_DENSITY_HEIGHT[density] : BASELINE_DENSITY_HEIGHT[density];
6313
6578
  const isSelectionMenu = selectionMode != null;
6314
6579
  const { ripples, onMouseDown } = useRipple({ disabled: disableRipple });
6315
- const computeClassName = ({ isDisabled, isSelected }) => cn(
6316
- menuItemVariants({
6317
- isDisabled,
6318
- isSelected: isSelected ?? false,
6319
- colorScheme,
6320
- menuStyle
6321
- }),
6580
+ const computeClassName = ({ isSelected }) => cn(
6581
+ menuItemVariants({ colorScheme, menuStyle }),
6582
+ // group/menuitem scope: all slot children read state via group-data-[x]/menuitem
6583
+ "group/menuitem",
6322
6584
  // Height: auto when description is present (multi-line), otherwise density
6323
6585
  description ? "min-h-12 py-2 h-auto items-start" : heightClass,
6324
- className
6586
+ className,
6587
+ // Silence the isSelected lint — value consumed in render-prop below
6588
+ isSelected ? "" : ""
6325
6589
  );
6326
6590
  return /* @__PURE__ */ jsxRuntime.jsx(
6327
6591
  HeadlessMenuItem,
@@ -6331,24 +6595,48 @@ var MenuItem = React.forwardRef(function MenuItem2({
6331
6595
  className: computeClassName,
6332
6596
  onMouseDown,
6333
6597
  children: ({ isSelected }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6334
- !disableRipple && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none absolute inset-0 z-0 overflow-hidden rounded-[inherit]", children: ripples }),
6335
- (leadingIcon != null || isSelectionMenu) && /* @__PURE__ */ jsxRuntime.jsx(
6598
+ /* @__PURE__ */ jsxRuntime.jsx(
6599
+ "span",
6600
+ {
6601
+ "aria-hidden": "true",
6602
+ "data-testid": "menuitem-highlight",
6603
+ className: menuItemHighlightVariants({ colorScheme, menuStyle })
6604
+ }
6605
+ ),
6606
+ /* @__PURE__ */ jsxRuntime.jsx(
6607
+ "span",
6608
+ {
6609
+ "aria-hidden": "true",
6610
+ className: menuItemStateLayerVariants({ colorScheme, menuStyle })
6611
+ }
6612
+ ),
6613
+ /* @__PURE__ */ jsxRuntime.jsx(
6336
6614
  "span",
6337
6615
  {
6338
- className: "text-on-surface-variant relative z-10 flex h-6 w-6 shrink-0 items-center justify-center",
6339
6616
  "aria-hidden": "true",
6340
- children: isSelectionMenu && leadingIcon == null ? isSelected ? /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, {}) : null : leadingIcon
6617
+ "data-testid": "menuitem-focus-ring",
6618
+ className: menuItemFocusRingVariants()
6341
6619
  }
6342
6620
  ),
6621
+ !disableRipple && /* @__PURE__ */ jsxRuntime.jsx(
6622
+ "span",
6623
+ {
6624
+ className: cn(
6625
+ "pointer-events-none absolute inset-0 z-[3] overflow-hidden rounded-[inherit]"
6626
+ ),
6627
+ children: ripples
6628
+ }
6629
+ ),
6630
+ (leadingIcon != null || isSelectionMenu) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: menuItemIconVariants({ colorScheme, menuStyle }), "aria-hidden": "true", children: isSelectionMenu && leadingIcon == null ? isSelected ? /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, {}) : null : leadingIcon }),
6343
6631
  description != null ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative z-10 flex min-w-0 flex-1 flex-col", children: [
6344
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-body-large", children }),
6345
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: menuItemDescriptionVariants(), children: description })
6346
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-body-large relative z-10 min-w-0 flex-1", children }),
6632
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-label-large group-data-[disabled]/menuitem:text-on-surface/38", children }),
6633
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: menuItemDescriptionVariants({ colorScheme, menuStyle }), children: description })
6634
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-label-large group-data-[disabled]/menuitem:text-on-surface/38 relative z-10 min-w-0 flex-1", children }),
6347
6635
  badge != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative z-10 shrink-0", children: badge }),
6348
6636
  trailingIcon != null && trailingText == null && /* @__PURE__ */ jsxRuntime.jsx(
6349
6637
  "span",
6350
6638
  {
6351
- className: "text-on-surface-variant relative z-10 ml-auto flex h-6 w-6 shrink-0 items-center justify-center",
6639
+ className: cn(menuItemIconVariants({ colorScheme, menuStyle }), "ml-auto"),
6352
6640
  "aria-hidden": "true",
6353
6641
  children: trailingIcon
6354
6642
  }
@@ -6356,7 +6644,10 @@ var MenuItem = React.forwardRef(function MenuItem2({
6356
6644
  trailingText != null && trailingIcon == null && /* @__PURE__ */ jsxRuntime.jsx(
6357
6645
  "span",
6358
6646
  {
6359
- className: cn(menuItemTrailingTextVariants(), "relative z-10"),
6647
+ className: cn(
6648
+ menuItemTrailingTextVariants({ colorScheme, menuStyle }),
6649
+ "relative z-10"
6650
+ ),
6360
6651
  "aria-keyshortcuts": trailingText,
6361
6652
  children: trailingText
6362
6653
  }
@@ -6372,6 +6663,8 @@ function MenuSection({
6372
6663
  className,
6373
6664
  "aria-label": ariaLabel
6374
6665
  }) {
6666
+ const ctx = useMenuContext();
6667
+ const colorScheme = ctx?.colorScheme ?? "standard";
6375
6668
  const sectionAriaLabel = ariaLabel ?? header;
6376
6669
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6377
6670
  showDivider && /* @__PURE__ */ jsxRuntime.jsx(HeadlessMenuDivider, { className: menuDividerVariants() }),
@@ -6381,7 +6674,7 @@ function MenuSection({
6381
6674
  "aria-label": sectionAriaLabel,
6382
6675
  className: cn(menuSectionVariants(), className),
6383
6676
  children: [
6384
- header && /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Header, { className: menuSectionHeaderVariants(), "aria-hidden": "true", children: header }),
6677
+ header && /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Header, { className: menuSectionHeaderVariants({ colorScheme }), "aria-hidden": "true", children: header }),
6385
6678
  children
6386
6679
  ]
6387
6680
  }