@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.
- package/dist/components/Badge/Badge.d.ts +10 -2
- package/dist/components/Badge/Badge.d.ts.map +1 -1
- package/dist/components/Badge/Badge.js +6 -4
- package/dist/components/Badge/Badge.js.map +1 -1
- package/dist/components/Button/Button.d.ts +25 -2
- package/dist/components/Button/Button.d.ts.map +1 -1
- package/dist/components/Button/Button.js +13 -4
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/DataTable/DataTable.d.ts +89 -0
- package/dist/components/DataTable/DataTable.d.ts.map +1 -0
- package/dist/components/DataTable/DataTable.js +107 -0
- package/dist/components/DataTable/DataTable.js.map +1 -0
- package/dist/components/DataTable/index.d.ts +2 -0
- package/dist/components/DataTable/index.d.ts.map +1 -0
- package/dist/components/DataTable/index.js +2 -0
- package/dist/components/DataTable/index.js.map +1 -0
- package/dist/components/DatePicker/DatePicker.d.ts.map +1 -1
- package/dist/components/DatePicker/DatePicker.js +2 -1
- package/dist/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.d.ts.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.js +2 -1
- package/dist/components/DateTimePicker/DateTimePicker.js.map +1 -1
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.d.ts.map +1 -1
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js +2 -1
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js.map +1 -1
- package/dist/components/FileDropzone/FileDropzone.d.ts +87 -0
- package/dist/components/FileDropzone/FileDropzone.d.ts.map +1 -0
- package/dist/components/FileDropzone/FileDropzone.js +146 -0
- package/dist/components/FileDropzone/FileDropzone.js.map +1 -0
- package/dist/components/FileDropzone/index.d.ts +2 -0
- package/dist/components/FileDropzone/index.d.ts.map +1 -0
- package/dist/components/FileDropzone/index.js +2 -0
- package/dist/components/FileDropzone/index.js.map +1 -0
- package/dist/components/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/components/HoverCard/HoverCard.js +3 -0
- package/dist/components/HoverCard/HoverCard.js.map +1 -1
- package/dist/components/HoverCard/components/HoverCardContent.d.ts +16 -2
- package/dist/components/HoverCard/components/HoverCardContent.d.ts.map +1 -1
- package/dist/components/HoverCard/components/HoverCardContent.js +3 -3
- package/dist/components/HoverCard/components/HoverCardContent.js.map +1 -1
- package/dist/components/HoverCard/components/HoverCardContext.d.ts +2 -0
- package/dist/components/HoverCard/components/HoverCardContext.d.ts.map +1 -1
- package/dist/components/HoverCard/components/HoverCardContext.js.map +1 -1
- package/dist/components/ImageGallery/ImageGallery.d.ts +93 -0
- package/dist/components/ImageGallery/ImageGallery.d.ts.map +1 -0
- package/dist/components/ImageGallery/ImageGallery.js +121 -0
- package/dist/components/ImageGallery/ImageGallery.js.map +1 -0
- package/dist/components/ImageGallery/index.d.ts +2 -0
- package/dist/components/ImageGallery/index.d.ts.map +1 -0
- package/dist/components/ImageGallery/index.js +2 -0
- package/dist/components/ImageGallery/index.js.map +1 -0
- package/dist/components/Message/Message.d.ts +4 -0
- package/dist/components/Message/Message.d.ts.map +1 -1
- package/dist/components/Message/Message.js +2 -2
- package/dist/components/Message/Message.js.map +1 -1
- package/dist/components/Modal/Modal.d.ts +12 -0
- package/dist/components/Modal/Modal.d.ts.map +1 -1
- package/dist/components/Modal/Modal.js +5 -2
- package/dist/components/Modal/Modal.js.map +1 -1
- package/dist/components/NumberStepper/NumberStepper.d.ts +78 -0
- package/dist/components/NumberStepper/NumberStepper.d.ts.map +1 -0
- package/dist/components/NumberStepper/NumberStepper.js +129 -0
- package/dist/components/NumberStepper/NumberStepper.js.map +1 -0
- package/dist/components/NumberStepper/index.d.ts +2 -0
- package/dist/components/NumberStepper/index.d.ts.map +1 -0
- package/dist/components/NumberStepper/index.js +2 -0
- package/dist/components/NumberStepper/index.js.map +1 -0
- package/dist/components/Popover/Popover.d.ts +3 -1
- package/dist/components/Popover/Popover.d.ts.map +1 -1
- package/dist/components/Popover/Popover.js +3 -0
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Popover/components/PopoverBody.d.ts +16 -2
- package/dist/components/Popover/components/PopoverBody.d.ts.map +1 -1
- package/dist/components/Popover/components/PopoverBody.js +3 -3
- package/dist/components/Popover/components/PopoverBody.js.map +1 -1
- package/dist/components/Popover/components/PopoverContext.d.ts +2 -0
- package/dist/components/Popover/components/PopoverContext.d.ts.map +1 -1
- package/dist/components/Popover/components/PopoverContext.js.map +1 -1
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/Select.js +3 -2
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Select/SelectDropdown.d.ts +3 -1
- package/dist/components/Select/SelectDropdown.d.ts.map +1 -1
- package/dist/components/Select/SelectDropdown.js +2 -2
- package/dist/components/Select/SelectDropdown.js.map +1 -1
- package/dist/components/Sheet/Sheet.d.ts +12 -0
- package/dist/components/Sheet/Sheet.d.ts.map +1 -1
- package/dist/components/Sheet/Sheet.js +4 -2
- package/dist/components/Sheet/Sheet.js.map +1 -1
- package/dist/components/Steps/Steps.d.ts +65 -0
- package/dist/components/Steps/Steps.d.ts.map +1 -0
- package/dist/components/Steps/Steps.js +62 -0
- package/dist/components/Steps/Steps.js.map +1 -0
- package/dist/components/Steps/index.d.ts +2 -0
- package/dist/components/Steps/index.d.ts.map +1 -0
- package/dist/components/Steps/index.js +2 -0
- package/dist/components/Steps/index.js.map +1 -0
- package/dist/components/TimePicker/TimePicker.d.ts.map +1 -1
- package/dist/components/TimePicker/TimePicker.js +2 -1
- package/dist/components/TimePicker/TimePicker.js.map +1 -1
- package/dist/components/Toast/Toast.d.ts.map +1 -1
- package/dist/components/Toast/Toast.js +2 -2
- package/dist/components/Toast/Toast.js.map +1 -1
- package/dist/components/Toggle/Toggle.d.ts +4 -0
- package/dist/components/Toggle/Toggle.d.ts.map +1 -1
- package/dist/components/Toggle/Toggle.js +2 -2
- package/dist/components/Toggle/Toggle.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupMultiple.d.ts +1 -0
- package/dist/components/ToggleGroup/ToggleGroupMultiple.d.ts.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupMultiple.js +2 -2
- package/dist/components/ToggleGroup/ToggleGroupMultiple.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupSingle.d.ts +1 -0
- package/dist/components/ToggleGroup/ToggleGroupSingle.d.ts.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupSingle.js +2 -2
- package/dist/components/ToggleGroup/ToggleGroupSingle.js.map +1 -1
- package/dist/components/ToggleGroup/toggleGroup.types.d.ts +6 -0
- package/dist/components/ToggleGroup/toggleGroup.types.d.ts.map +1 -1
- package/dist/components/Tooltip/Tooltip.d.ts +3 -1
- package/dist/components/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/components/Tooltip/Tooltip.js +3 -0
- package/dist/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/components/Tooltip/components/TooltipBody.d.ts +16 -2
- package/dist/components/Tooltip/components/TooltipBody.d.ts.map +1 -1
- package/dist/components/Tooltip/components/TooltipBody.js +3 -3
- package/dist/components/Tooltip/components/TooltipBody.js.map +1 -1
- package/dist/components/Tooltip/components/TooltipContext.d.ts +2 -0
- package/dist/components/Tooltip/components/TooltipContext.d.ts.map +1 -1
- package/dist/components/Tooltip/components/TooltipContext.js.map +1 -1
- package/dist/internal/brandScope.d.ts +25 -0
- package/dist/internal/brandScope.d.ts.map +1 -0
- package/dist/internal/brandScope.js +37 -0
- package/dist/internal/brandScope.js.map +1 -0
- package/package.json +21 -1
- package/src/components/Badge/Badge.tsx +10 -4
- package/src/components/Button/Button.tsx +24 -4
- package/src/components/DataTable/DataTable.tsx +261 -0
- package/src/components/DataTable/data-table.recipe.css +28 -0
- package/src/components/DataTable/index.ts +10 -0
- package/src/components/DatePicker/DatePicker.tsx +3 -0
- package/src/components/DateTimePicker/DateTimePicker.tsx +3 -0
- package/src/components/DateTimeRangePicker/DateTimeRangePicker.tsx +3 -0
- package/src/components/FileDropzone/FileDropzone.tsx +239 -0
- package/src/components/FileDropzone/file-dropzone.recipe.css +38 -0
- package/src/components/FileDropzone/index.ts +1 -0
- package/src/components/HoverCard/HoverCard.tsx +3 -0
- package/src/components/HoverCard/components/HoverCardContent.tsx +11 -3
- package/src/components/HoverCard/components/HoverCardContext.tsx +2 -0
- package/src/components/ImageGallery/ImageGallery.tsx +285 -0
- package/src/components/ImageGallery/image-gallery.recipe.css +50 -0
- package/src/components/ImageGallery/index.ts +7 -0
- package/src/components/Message/Message.tsx +26 -22
- package/src/components/Modal/Modal.tsx +11 -0
- package/src/components/NumberStepper/NumberStepper.tsx +227 -0
- package/src/components/NumberStepper/index.ts +1 -0
- package/src/components/NumberStepper/number-stepper.recipe.css +31 -0
- package/src/components/Popover/Popover.tsx +3 -0
- package/src/components/Popover/components/PopoverBody.tsx +11 -3
- package/src/components/Popover/components/PopoverContext.tsx +2 -0
- package/src/components/Select/Select.tsx +3 -1
- package/src/components/Select/SelectDropdown.tsx +4 -0
- package/src/components/Sheet/Sheet.tsx +10 -0
- package/src/components/Steps/Steps.tsx +149 -0
- package/src/components/Steps/index.ts +1 -0
- package/src/components/Steps/steps.recipe.css +51 -0
- package/src/components/TimePicker/TimePicker.tsx +3 -0
- package/src/components/Toast/Toast.tsx +5 -1
- package/src/components/Toggle/Toggle.tsx +17 -2
- package/src/components/ToggleGroup/ToggleGroupMultiple.tsx +2 -1
- package/src/components/ToggleGroup/ToggleGroupSingle.tsx +2 -0
- package/src/components/ToggleGroup/toggleGroup.types.ts +6 -0
- package/src/components/Tooltip/Tooltip.tsx +3 -0
- package/src/components/Tooltip/components/TooltipBody.tsx +11 -3
- package/src/components/Tooltip/components/TooltipContext.tsx +2 -0
- package/src/internal/brandScope.ts +39 -0
- 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
|
-
{
|
|
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
|
+
}
|
package/src/theming/tailwind.css
CHANGED
|
@@ -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
|