@sixthshift/design-system 0.6.0 → 0.8.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.
Files changed (175) hide show
  1. package/dist/components/Badge/Badge.d.ts +10 -2
  2. package/dist/components/Badge/Badge.d.ts.map +1 -1
  3. package/dist/components/Badge/Badge.js +6 -4
  4. package/dist/components/Badge/Badge.js.map +1 -1
  5. package/dist/components/Button/Button.d.ts +25 -2
  6. package/dist/components/Button/Button.d.ts.map +1 -1
  7. package/dist/components/Button/Button.js +13 -4
  8. package/dist/components/Button/Button.js.map +1 -1
  9. package/dist/components/DataTable/DataTable.d.ts +89 -0
  10. package/dist/components/DataTable/DataTable.d.ts.map +1 -0
  11. package/dist/components/DataTable/DataTable.js +107 -0
  12. package/dist/components/DataTable/DataTable.js.map +1 -0
  13. package/dist/components/DataTable/index.d.ts +2 -0
  14. package/dist/components/DataTable/index.d.ts.map +1 -0
  15. package/dist/components/DataTable/index.js +2 -0
  16. package/dist/components/DataTable/index.js.map +1 -0
  17. package/dist/components/DatePicker/DatePicker.d.ts.map +1 -1
  18. package/dist/components/DatePicker/DatePicker.js +2 -1
  19. package/dist/components/DatePicker/DatePicker.js.map +1 -1
  20. package/dist/components/DateTimePicker/DateTimePicker.d.ts.map +1 -1
  21. package/dist/components/DateTimePicker/DateTimePicker.js +2 -1
  22. package/dist/components/DateTimePicker/DateTimePicker.js.map +1 -1
  23. package/dist/components/DateTimeRangePicker/DateTimeRangePicker.d.ts.map +1 -1
  24. package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js +2 -1
  25. package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js.map +1 -1
  26. package/dist/components/FileDropzone/FileDropzone.d.ts +87 -0
  27. package/dist/components/FileDropzone/FileDropzone.d.ts.map +1 -0
  28. package/dist/components/FileDropzone/FileDropzone.js +146 -0
  29. package/dist/components/FileDropzone/FileDropzone.js.map +1 -0
  30. package/dist/components/FileDropzone/index.d.ts +2 -0
  31. package/dist/components/FileDropzone/index.d.ts.map +1 -0
  32. package/dist/components/FileDropzone/index.js +2 -0
  33. package/dist/components/FileDropzone/index.js.map +1 -0
  34. package/dist/components/HoverCard/HoverCard.d.ts.map +1 -1
  35. package/dist/components/HoverCard/HoverCard.js +3 -0
  36. package/dist/components/HoverCard/HoverCard.js.map +1 -1
  37. package/dist/components/HoverCard/components/HoverCardContent.d.ts +16 -2
  38. package/dist/components/HoverCard/components/HoverCardContent.d.ts.map +1 -1
  39. package/dist/components/HoverCard/components/HoverCardContent.js +3 -3
  40. package/dist/components/HoverCard/components/HoverCardContent.js.map +1 -1
  41. package/dist/components/HoverCard/components/HoverCardContext.d.ts +2 -0
  42. package/dist/components/HoverCard/components/HoverCardContext.d.ts.map +1 -1
  43. package/dist/components/HoverCard/components/HoverCardContext.js.map +1 -1
  44. package/dist/components/ImageGallery/ImageGallery.d.ts +93 -0
  45. package/dist/components/ImageGallery/ImageGallery.d.ts.map +1 -0
  46. package/dist/components/ImageGallery/ImageGallery.js +121 -0
  47. package/dist/components/ImageGallery/ImageGallery.js.map +1 -0
  48. package/dist/components/ImageGallery/index.d.ts +2 -0
  49. package/dist/components/ImageGallery/index.d.ts.map +1 -0
  50. package/dist/components/ImageGallery/index.js +2 -0
  51. package/dist/components/ImageGallery/index.js.map +1 -0
  52. package/dist/components/Message/Message.d.ts +4 -0
  53. package/dist/components/Message/Message.d.ts.map +1 -1
  54. package/dist/components/Message/Message.js +2 -2
  55. package/dist/components/Message/Message.js.map +1 -1
  56. package/dist/components/Modal/Modal.d.ts +12 -0
  57. package/dist/components/Modal/Modal.d.ts.map +1 -1
  58. package/dist/components/Modal/Modal.js +5 -2
  59. package/dist/components/Modal/Modal.js.map +1 -1
  60. package/dist/components/NumberStepper/NumberStepper.d.ts +78 -0
  61. package/dist/components/NumberStepper/NumberStepper.d.ts.map +1 -0
  62. package/dist/components/NumberStepper/NumberStepper.js +129 -0
  63. package/dist/components/NumberStepper/NumberStepper.js.map +1 -0
  64. package/dist/components/NumberStepper/index.d.ts +2 -0
  65. package/dist/components/NumberStepper/index.d.ts.map +1 -0
  66. package/dist/components/NumberStepper/index.js +2 -0
  67. package/dist/components/NumberStepper/index.js.map +1 -0
  68. package/dist/components/Popover/Popover.d.ts +3 -1
  69. package/dist/components/Popover/Popover.d.ts.map +1 -1
  70. package/dist/components/Popover/Popover.js +3 -0
  71. package/dist/components/Popover/Popover.js.map +1 -1
  72. package/dist/components/Popover/components/PopoverBody.d.ts +16 -2
  73. package/dist/components/Popover/components/PopoverBody.d.ts.map +1 -1
  74. package/dist/components/Popover/components/PopoverBody.js +3 -3
  75. package/dist/components/Popover/components/PopoverBody.js.map +1 -1
  76. package/dist/components/Popover/components/PopoverContext.d.ts +2 -0
  77. package/dist/components/Popover/components/PopoverContext.d.ts.map +1 -1
  78. package/dist/components/Popover/components/PopoverContext.js.map +1 -1
  79. package/dist/components/Select/Select.d.ts.map +1 -1
  80. package/dist/components/Select/Select.js +3 -2
  81. package/dist/components/Select/Select.js.map +1 -1
  82. package/dist/components/Select/SelectDropdown.d.ts +3 -1
  83. package/dist/components/Select/SelectDropdown.d.ts.map +1 -1
  84. package/dist/components/Select/SelectDropdown.js +2 -2
  85. package/dist/components/Select/SelectDropdown.js.map +1 -1
  86. package/dist/components/Sheet/Sheet.d.ts +12 -0
  87. package/dist/components/Sheet/Sheet.d.ts.map +1 -1
  88. package/dist/components/Sheet/Sheet.js +4 -2
  89. package/dist/components/Sheet/Sheet.js.map +1 -1
  90. package/dist/components/Steps/Steps.d.ts +65 -0
  91. package/dist/components/Steps/Steps.d.ts.map +1 -0
  92. package/dist/components/Steps/Steps.js +62 -0
  93. package/dist/components/Steps/Steps.js.map +1 -0
  94. package/dist/components/Steps/index.d.ts +2 -0
  95. package/dist/components/Steps/index.d.ts.map +1 -0
  96. package/dist/components/Steps/index.js +2 -0
  97. package/dist/components/Steps/index.js.map +1 -0
  98. package/dist/components/TimePicker/TimePicker.d.ts.map +1 -1
  99. package/dist/components/TimePicker/TimePicker.js +2 -1
  100. package/dist/components/TimePicker/TimePicker.js.map +1 -1
  101. package/dist/components/Toast/Toast.d.ts.map +1 -1
  102. package/dist/components/Toast/Toast.js +2 -2
  103. package/dist/components/Toast/Toast.js.map +1 -1
  104. package/dist/components/Toggle/Toggle.d.ts +4 -0
  105. package/dist/components/Toggle/Toggle.d.ts.map +1 -1
  106. package/dist/components/Toggle/Toggle.js +2 -2
  107. package/dist/components/Toggle/Toggle.js.map +1 -1
  108. package/dist/components/ToggleGroup/ToggleGroupMultiple.d.ts +1 -0
  109. package/dist/components/ToggleGroup/ToggleGroupMultiple.d.ts.map +1 -1
  110. package/dist/components/ToggleGroup/ToggleGroupMultiple.js +2 -2
  111. package/dist/components/ToggleGroup/ToggleGroupMultiple.js.map +1 -1
  112. package/dist/components/ToggleGroup/ToggleGroupSingle.d.ts +1 -0
  113. package/dist/components/ToggleGroup/ToggleGroupSingle.d.ts.map +1 -1
  114. package/dist/components/ToggleGroup/ToggleGroupSingle.js +2 -2
  115. package/dist/components/ToggleGroup/ToggleGroupSingle.js.map +1 -1
  116. package/dist/components/ToggleGroup/toggleGroup.types.d.ts +6 -0
  117. package/dist/components/ToggleGroup/toggleGroup.types.d.ts.map +1 -1
  118. package/dist/components/Tooltip/Tooltip.d.ts +3 -1
  119. package/dist/components/Tooltip/Tooltip.d.ts.map +1 -1
  120. package/dist/components/Tooltip/Tooltip.js +3 -0
  121. package/dist/components/Tooltip/Tooltip.js.map +1 -1
  122. package/dist/components/Tooltip/components/TooltipBody.d.ts +16 -2
  123. package/dist/components/Tooltip/components/TooltipBody.d.ts.map +1 -1
  124. package/dist/components/Tooltip/components/TooltipBody.js +3 -3
  125. package/dist/components/Tooltip/components/TooltipBody.js.map +1 -1
  126. package/dist/components/Tooltip/components/TooltipContext.d.ts +2 -0
  127. package/dist/components/Tooltip/components/TooltipContext.d.ts.map +1 -1
  128. package/dist/components/Tooltip/components/TooltipContext.js.map +1 -1
  129. package/dist/internal/brandScope.d.ts +25 -0
  130. package/dist/internal/brandScope.d.ts.map +1 -0
  131. package/dist/internal/brandScope.js +37 -0
  132. package/dist/internal/brandScope.js.map +1 -0
  133. package/package.json +21 -1
  134. package/src/components/Badge/Badge.tsx +10 -4
  135. package/src/components/Button/Button.tsx +24 -4
  136. package/src/components/DataTable/DataTable.tsx +261 -0
  137. package/src/components/DataTable/data-table.recipe.css +28 -0
  138. package/src/components/DataTable/index.ts +10 -0
  139. package/src/components/DatePicker/DatePicker.tsx +3 -0
  140. package/src/components/DateTimePicker/DateTimePicker.tsx +3 -0
  141. package/src/components/DateTimeRangePicker/DateTimeRangePicker.tsx +3 -0
  142. package/src/components/FileDropzone/FileDropzone.tsx +239 -0
  143. package/src/components/FileDropzone/file-dropzone.recipe.css +38 -0
  144. package/src/components/FileDropzone/index.ts +1 -0
  145. package/src/components/HoverCard/HoverCard.tsx +3 -0
  146. package/src/components/HoverCard/components/HoverCardContent.tsx +11 -3
  147. package/src/components/HoverCard/components/HoverCardContext.tsx +2 -0
  148. package/src/components/ImageGallery/ImageGallery.tsx +285 -0
  149. package/src/components/ImageGallery/image-gallery.recipe.css +50 -0
  150. package/src/components/ImageGallery/index.ts +7 -0
  151. package/src/components/Message/Message.tsx +26 -22
  152. package/src/components/Modal/Modal.tsx +11 -0
  153. package/src/components/NumberStepper/NumberStepper.tsx +227 -0
  154. package/src/components/NumberStepper/index.ts +1 -0
  155. package/src/components/NumberStepper/number-stepper.recipe.css +31 -0
  156. package/src/components/Popover/Popover.tsx +3 -0
  157. package/src/components/Popover/components/PopoverBody.tsx +11 -3
  158. package/src/components/Popover/components/PopoverContext.tsx +2 -0
  159. package/src/components/Select/Select.tsx +3 -1
  160. package/src/components/Select/SelectDropdown.tsx +4 -0
  161. package/src/components/Sheet/Sheet.tsx +10 -0
  162. package/src/components/Steps/Steps.tsx +149 -0
  163. package/src/components/Steps/index.ts +1 -0
  164. package/src/components/Steps/steps.recipe.css +51 -0
  165. package/src/components/TimePicker/TimePicker.tsx +3 -0
  166. package/src/components/Toast/Toast.tsx +5 -1
  167. package/src/components/Toggle/Toggle.tsx +17 -2
  168. package/src/components/ToggleGroup/ToggleGroupMultiple.tsx +2 -1
  169. package/src/components/ToggleGroup/ToggleGroupSingle.tsx +2 -0
  170. package/src/components/ToggleGroup/toggleGroup.types.ts +6 -0
  171. package/src/components/Tooltip/Tooltip.tsx +3 -0
  172. package/src/components/Tooltip/components/TooltipBody.tsx +11 -3
  173. package/src/components/Tooltip/components/TooltipContext.tsx +2 -0
  174. package/src/internal/brandScope.ts +39 -0
  175. package/src/theming/tailwind.css +5 -0
@@ -0,0 +1 @@
1
+ export { type StepItem, type StepState, Steps, type StepsOrientation, type StepsProps, stepsVariants } from "./Steps";
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Steps recipe — the component-token layer for Steps.
3
+ *
4
+ * One axis, and it is not `intent`: a step's colour says where it sits in the
5
+ * sequence, which the component renders as `data-state` on each item
6
+ * (`complete`, `current`, `upcoming`). Same shape as tabs.css keying its
7
+ * selected cell on `data-selected` rather than a variant.
8
+ *
9
+ * The grammar is `--steps-[{part}-]{context}[-{state}]`. Parts are the
10
+ * `indicator` (the numbered circle), the `connector` (the rule to the next
11
+ * step), and the `label`/`description` text. `-hovered` on the indicator only
12
+ * ever applies to a completed step with `onStepClick`, the one clickable case.
13
+ *
14
+ * The connector belongs to the step it leaves, so a completed step's
15
+ * connector takes the brand colour: the line fills up to the current step.
16
+ *
17
+ * `@layer components` is load-bearing, not tidiness — see button.css.
18
+ */
19
+
20
+ @layer components {
21
+ /* The floor, and also the upcoming look: an outlined, quiet step. An item
22
+ with a state a consumer added but did not style renders like this. */
23
+ .steps-item {
24
+ --steps-indicator-bg: var(--bg-normal);
25
+ --steps-indicator-bg-hovered: var(--steps-indicator-bg);
26
+ --steps-indicator-fg: var(--fg-subtle);
27
+ --steps-indicator-border: var(--border-normal);
28
+ --steps-connector-bg: var(--border-normal);
29
+ --steps-label-fg: var(--fg-subtle);
30
+ --steps-description-fg: var(--fg-subtle);
31
+ --steps-ring: var(--focus-ring);
32
+ }
33
+
34
+ /* current — outlined in brand, the label at full strength. */
35
+ .steps-item[data-state="current"] {
36
+ --steps-indicator-bg: var(--bg-brand-subtle);
37
+ --steps-indicator-fg: var(--fg-on-brand-subtle);
38
+ --steps-indicator-border: var(--border-brand);
39
+ --steps-label-fg: var(--fg-normal);
40
+ }
41
+
42
+ /* complete — a filled brand disc with the check reversed out. */
43
+ .steps-item[data-state="complete"] {
44
+ --steps-indicator-bg: var(--bg-brand);
45
+ --steps-indicator-bg-hovered: var(--bg-brand-hovered);
46
+ --steps-indicator-fg: var(--fg-on-brand);
47
+ --steps-indicator-border: var(--steps-indicator-bg);
48
+ --steps-connector-bg: var(--border-brand);
49
+ --steps-label-fg: var(--fg-normal);
50
+ }
51
+ }
@@ -8,6 +8,7 @@ import * as React from "react";
8
8
  import { useCallback, useId, useMemo, useState } from "react";
9
9
  import { fromISOTime, fromISOTimeOrUndefined, type Temporal, toISOTimeOrUndefined } from "../../date-time";
10
10
  import { PickerField } from "../../internal";
11
+ import { closestBrand } from "../../internal/brandScope";
11
12
  import { useEscapeLayer } from "../../internal/escapeLayers";
12
13
  import { Button } from "../Button";
13
14
  import { Separator } from "../Separator";
@@ -354,6 +355,8 @@ export const TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>((pro
354
355
  role="dialog"
355
356
  aria-label="Choose time"
356
357
  style={floatingStyles}
358
+ // Portalled out of the trigger's brand scope, so carry it across.
359
+ data-brand={closestBrand(context.elements.domReference)}
357
360
  className="z-popover rounded-xl border border-border-normal bg-bg-normal p-4 shadow-lg"
358
361
  {...getFloatingProps()}
359
362
  >
@@ -68,7 +68,7 @@ export type ToastProps = Omit<MessageProps, "size"> & {
68
68
  * a dialog.
69
69
  */
70
70
  export const Toast = React.forwardRef<HTMLDivElement, ToastProps>(
71
- ({ className, intent = "neutral", title, icon, action, onAction, onClose, root, open = true, standalone = true, children, ...props }, ref) => {
71
+ ({ className, intent = "neutral", brand, title, icon, action, onAction, onClose, root, open = true, standalone = true, children, ...props }, ref) => {
72
72
  const { ref: presenceRef, state, isMounted, show, hide } = usePresence();
73
73
 
74
74
  // `open` drives presence: enter on mount, exit when it flips false. The
@@ -118,6 +118,10 @@ export const Toast = React.forwardRef<HTMLDivElement, ToastProps>(
118
118
  isExiting && "animate-fade-out",
119
119
  className
120
120
  )}
121
+ // On the wrapper rather than the Message, so the dismiss and action
122
+ // buttons are in the same scope. A toast has no trigger to inherit
123
+ // from: it is opened from code, often long after the click.
124
+ data-brand={brand}
121
125
  {...props}
122
126
  >
123
127
  <Message intent={intent}>
@@ -15,6 +15,8 @@ export type ToggleProps = Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "o
15
15
  VariantProps<typeof buttonVariants> & {
16
16
  variant?: ButtonVariant | undefined;
17
17
  intent?: ButtonIntent | undefined;
18
+ /** Name of a brand the theme defines, rendered as `data-brand`. Omitted, the toggle follows the nearest `data-brand` ancestor. */
19
+ brand?: string | undefined;
18
20
  /** Square the toggle at its current size, for an icon with no label. */
19
21
  iconOnly?: boolean;
20
22
  /** Controlled pressed state */
@@ -43,7 +45,20 @@ export type ToggleProps = Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "o
43
45
  */
44
46
  const Toggle = React.forwardRef<HTMLButtonElement, ToggleProps>(
45
47
  (
46
- { className, variant, intent, size, iconOnly = false, pressed: controlledPressed, defaultPressed = false, onPressedChange, disabled, children, ...props },
48
+ {
49
+ className,
50
+ variant,
51
+ intent,
52
+ brand,
53
+ size,
54
+ iconOnly = false,
55
+ pressed: controlledPressed,
56
+ defaultPressed = false,
57
+ onPressedChange,
58
+ disabled,
59
+ children,
60
+ ...props
61
+ },
47
62
  ref
48
63
  ) => {
49
64
  const [pressed, setPressed] = useControllableState({
@@ -52,7 +67,7 @@ const Toggle = React.forwardRef<HTMLButtonElement, ToggleProps>(
52
67
  onChange: onPressedChange,
53
68
  });
54
69
 
55
- const recipe = buttonRecipe({ variant, intent, size, iconOnly });
70
+ const recipe = buttonRecipe({ variant, intent, brand, size, iconOnly });
56
71
 
57
72
  return (
58
73
  <button
@@ -17,6 +17,7 @@ const ToggleGroupMultiple = React.forwardRef<HTMLDivElement, ToggleGroupMultiple
17
17
  orientation = "horizontal",
18
18
  variant = "solid",
19
19
  intent = "neutral",
20
+ brand,
20
21
  size = "md",
21
22
  iconOnly = false,
22
23
  disabled,
@@ -39,7 +40,7 @@ const ToggleGroupMultiple = React.forwardRef<HTMLDivElement, ToggleGroupMultiple
39
40
  };
40
41
 
41
42
  return (
42
- <ToggleGroupContainer ref={ref} role="group" appearance={appearance} orientation={orientation} className={className} {...props}>
43
+ <ToggleGroupContainer ref={ref} role="group" data-brand={brand} appearance={appearance} orientation={orientation} className={className} {...props}>
43
44
  {options.map((option, index) => (
44
45
  <ToggleGroupItem
45
46
  key={option.value}
@@ -19,6 +19,7 @@ const ToggleGroupSingle = React.forwardRef<HTMLDivElement, ToggleGroupSingleProp
19
19
  orientation = "horizontal",
20
20
  variant = "solid",
21
21
  intent = "neutral",
22
+ brand,
22
23
  size = "md",
23
24
  iconOnly = false,
24
25
  disabled,
@@ -76,6 +77,7 @@ const ToggleGroupSingle = React.forwardRef<HTMLDivElement, ToggleGroupSingleProp
76
77
  <ToggleGroupContainer
77
78
  ref={mergedRef}
78
79
  role="radiogroup"
80
+ data-brand={brand}
79
81
  onKeyDown={handleKeyDown}
80
82
  appearance={appearance}
81
83
  orientation={orientation}
@@ -33,6 +33,12 @@ export type ToggleGroupBaseProps = Omit<React.HTMLAttributes<HTMLDivElement>, "o
33
33
  variant?: Exclude<ButtonVariantName, "link">;
34
34
  /** Color intent */
35
35
  intent?: ButtonIntentName;
36
+ /**
37
+ * Name of a brand the theme defines. Rendered once, as `data-brand` on the
38
+ * group element, so every item inherits it. Omitted, the group follows the
39
+ * nearest `data-brand` ancestor.
40
+ */
41
+ brand?: string | undefined;
36
42
  /** Button size (xl excluded — too large for grouped toggles) */
37
43
  size?: Exclude<ToggleProp<"size">, "xl">;
38
44
  /** Square every item at the current size, for icon-only options */
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { autoUpdate, flip, offset, type Placement, shift, useDismiss, useFloating, useFocus, useHover, useInteractions, useRole } from "@floating-ui/react";
4
4
  import { useControllableState } from "@sixthshift/design-system/hooks";
5
+ import { closestBrand } from "../../internal/brandScope";
5
6
  import { TooltipBody } from "./components/TooltipBody";
6
7
  import { TooltipContext } from "./components/TooltipContext";
7
8
  import { TooltipTrigger } from "./components/TooltipTrigger";
@@ -55,6 +56,8 @@ const TooltipRoot = ({ open: controlledOpen, onOpenChange, placement = "top", de
55
56
  setFloating: refs.setFloating,
56
57
  },
57
58
  floatingStyles,
59
+ // Read at render: `domReference` is state, so this updates once the trigger mounts.
60
+ inheritedBrand: closestBrand(context.elements.domReference),
58
61
  getReferenceProps,
59
62
  getFloatingProps,
60
63
  };
@@ -5,10 +5,17 @@ import { cn } from "@sixthshift/design-system/utils";
5
5
  import * as React from "react";
6
6
  import { useTooltipContext } from "./TooltipContext";
7
7
 
8
- export type TooltipBodyProps = React.HTMLAttributes<HTMLDivElement>;
8
+ export type TooltipBodyProps = React.HTMLAttributes<HTMLDivElement> & {
9
+ /**
10
+ * Name of a brand the theme defines, rendered as `data-brand`. Omitted, the
11
+ * body copies the brand scope of its trigger, which the portal would
12
+ * otherwise leave behind.
13
+ */
14
+ brand?: string | undefined;
15
+ };
9
16
 
10
- export const TooltipBody = React.forwardRef<HTMLDivElement, TooltipBodyProps>(({ className, children, ...props }, forwardedRef) => {
11
- const { open, refs, floatingStyles, getFloatingProps } = useTooltipContext();
17
+ export const TooltipBody = React.forwardRef<HTMLDivElement, TooltipBodyProps>(({ className, brand, children, ...props }, forwardedRef) => {
18
+ const { open, refs, floatingStyles, inheritedBrand, getFloatingProps } = useTooltipContext();
12
19
 
13
20
  if (!open) return null;
14
21
 
@@ -21,6 +28,7 @@ export const TooltipBody = React.forwardRef<HTMLDivElement, TooltipBodyProps>(({
21
28
  else if (forwardedRef) forwardedRef.current = node;
22
29
  }}
23
30
  style={floatingStyles}
31
+ data-brand={brand ?? inheritedBrand}
24
32
  className={cn("z-popover rounded-lg border border-border-normal bg-bg-normal px-2.5 py-1.5 text-fg-normal text-xs shadow-lg", className)}
25
33
  {...getFloatingProps(props)}
26
34
  >
@@ -9,6 +9,8 @@ export type TooltipContextValue = {
9
9
  setFloating: (node: HTMLElement | null) => void;
10
10
  };
11
11
  floatingStyles: React.CSSProperties;
12
+ /** The trigger's brand scope, re-stamped on the portalled body. */
13
+ inheritedBrand: string | undefined;
12
14
  getReferenceProps: (props?: React.HTMLProps<HTMLElement>) => Record<string, unknown>;
13
15
  getFloatingProps: (props?: React.HTMLProps<HTMLElement>) => Record<string, unknown>;
14
16
  };
@@ -0,0 +1,39 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+
5
+ /**
6
+ * The brand an element sits in: the `data-brand` of it or its nearest
7
+ * ancestor, or `undefined` outside any scope.
8
+ *
9
+ * Overlays need this because a portal moves their content out from under the
10
+ * element that set `data-brand`, so CSS inheritance no longer carries it. The
11
+ * overlay reads the brand off its trigger and re-stamps it on its own element.
12
+ * The value is copied verbatim, unknown names included: the theme only gives
13
+ * listed names meaning, so an unknown one resolves exactly as it would have in
14
+ * place.
15
+ */
16
+ export function closestBrand(element: Element | null | undefined): string | undefined {
17
+ return element?.closest?.("[data-brand]")?.getAttribute("data-brand") ?? undefined;
18
+ }
19
+
20
+ const focusedBrand = () => (typeof document === "undefined" ? undefined : closestBrand(document.activeElement));
21
+
22
+ /**
23
+ * The brand of whatever held focus when the calling overlay opened.
24
+ *
25
+ * For Modal and Sheet, which have no reference element: the thing that opened
26
+ * them is almost always the focused control, and it still holds focus during
27
+ * the render that opens them, before the focus manager moves it. Captured on
28
+ * each closed → open transition and kept through the close, so neither focus
29
+ * moving into the dialog nor the exit animation changes it. When nothing useful
30
+ * was focused (Safari does not focus a clicked button) this is `undefined`, and
31
+ * the overlay inherits from wherever its portal landed.
32
+ */
33
+ export function useOpenerBrand(open: boolean): string | undefined {
34
+ const [captured, setCaptured] = useState(() => ({ open, brand: open ? focusedBrand() : undefined }));
35
+ // Adjusting state during render, React's pattern for deriving from a prop
36
+ // change: an effect would run after the focus manager has already moved focus.
37
+ if (captured.open !== open) setCaptured({ open, brand: open ? focusedBrand() : captured.brand });
38
+ return captured.brand;
39
+ }
@@ -41,6 +41,11 @@
41
41
  @import "../components/Sheet/sheet.recipe.css";
42
42
  @import "../components/Select/select.recipe.css";
43
43
  @import "../components/TagChip/tag-chip.recipe.css";
44
+ @import "../components/NumberStepper/number-stepper.recipe.css";
45
+ @import "../components/Steps/steps.recipe.css";
46
+ @import "../components/ImageGallery/image-gallery.recipe.css";
47
+ @import "../components/DataTable/data-table.recipe.css";
48
+ @import "../components/FileDropzone/file-dropzone.recipe.css";
44
49
 
45
50
  /* =============================================================================
46
51
  3. TAILWIND THEME