@fanvue/ui 1.10.0 → 1.10.2
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/cjs/components/Chip/Chip.cjs +1 -1
- package/dist/cjs/components/Chip/Chip.cjs.map +1 -1
- package/dist/cjs/components/Select/Select.cjs +4 -3
- package/dist/cjs/components/Select/Select.cjs.map +1 -1
- package/dist/cjs/components/Tooltip/Tooltip.cjs +3 -1
- package/dist/cjs/components/Tooltip/Tooltip.cjs.map +1 -1
- package/dist/components/Chip/Chip.mjs +1 -1
- package/dist/components/Chip/Chip.mjs.map +1 -1
- package/dist/components/Select/Select.mjs +4 -3
- package/dist/components/Select/Select.mjs.map +1 -1
- package/dist/components/Tooltip/Tooltip.mjs +3 -1
- package/dist/components/Tooltip/Tooltip.mjs.map +1 -1
- package/dist/styles/theme.css +5 -0
- package/package.json +5 -4
|
@@ -59,7 +59,7 @@ const Chip = React__namespace.forwardRef(
|
|
|
59
59
|
!isDark && !selected && "bg-neutral-100 text-neutral-400",
|
|
60
60
|
// Hover
|
|
61
61
|
isInteractive && !disabled && !isDark && selected && "hover:bg-brand-green-500 hover:text-body-black-solid-constant active:bg-brand-green-500 active:text-body-black-solid-constant",
|
|
62
|
-
isInteractive && !disabled && !isDark && !selected && "hover:bg-hover-
|
|
62
|
+
isInteractive && !disabled && !isDark && !selected && "hover:bg-hover-300 active:bg-hover-300",
|
|
63
63
|
// Focus
|
|
64
64
|
"focus-visible:shadow-focus-ring focus-visible:outline-none",
|
|
65
65
|
// Disabled
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chip.cjs","sources":["../../../../src/components/Chip/Chip.tsx"],"sourcesContent":["import { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Visual variant of the chip. */\nexport type ChipVariant = \"rounded\" | \"square\" | \"dark\";\n/** Height of the chip in pixels. */\nexport type ChipSize = \"32\" | \"40\";\n\nexport interface ChipProps extends React.HTMLAttributes<HTMLElement> {\n /** Visual variant of the chip. @default \"rounded\" */\n variant?: ChipVariant;\n /** Height of the chip in pixels. @default \"32\" */\n size?: ChipSize;\n /** Whether the chip is in a selected (pressed) state. @default false */\n selected?: boolean;\n /** Whether the chip is disabled. @default false */\n disabled?: boolean;\n /** Whether to show a coloured status dot at the leading edge. @default false */\n leftDot?: boolean;\n /** Icon element displayed before the label. */\n leftIcon?: React.ReactNode;\n /** Icon element displayed after the label. */\n rightIcon?: React.ReactNode;\n /** Notification badge content (e.g. `\"99+\"`). Passed as a string for i18n support. */\n notificationLabel?: string;\n /** Click handler — when provided, the chip renders as a `<button>` for accessibility. */\n onClick?: React.MouseEventHandler<HTMLElement>;\n /** Merge props onto a child element instead of rendering a wrapper. @default false */\n asChild?: boolean;\n}\n\n/**\n * A compact element for filters, tags, or toggleable actions. When an `onClick`\n * handler is provided, the chip renders as an interactive `<button>` with\n * `aria-pressed` support.\n *\n * @example\n * ```tsx\n * <Chip selected onClick={toggle}>Music</Chip>\n * ```\n */\nexport const Chip = React.forwardRef<HTMLButtonElement, ChipProps>(\n (\n {\n className,\n variant = \"rounded\",\n size = \"32\",\n selected = false,\n disabled = false,\n leftDot = false,\n leftIcon,\n rightIcon,\n notificationLabel,\n onClick,\n asChild = false,\n children,\n ...props\n },\n ref,\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Variant-heavy UI component\n ) => {\n const isInteractive = !!onClick && !asChild;\n const Comp = asChild ? Slot : isInteractive ? \"button\" : \"span\";\n const isDark = variant === \"dark\";\n\n return (\n <Comp\n ref={ref}\n data-testid=\"chip\"\n className={cn(\n \"typography-caption-semibold relative inline-flex items-center justify-center gap-2 whitespace-nowrap px-3 motion-safe:transition-colors motion-safe:duration-150\",\n // Shape\n variant === \"square\" ? \"rounded-lg\" : \"rounded-full\",\n // Size\n size === \"32\" && \"h-8 py-1\",\n size === \"40\" && \"h-10 py-2.5\",\n // Variant colors\n isDark && \"bg-background-800 text-body-white-solid-constant\",\n !isDark && selected && \"bg-brand-green-50 text-neutral-400\",\n !isDark && !selected && \"bg-neutral-100 text-neutral-400\",\n // Hover\n isInteractive &&\n !disabled &&\n !isDark &&\n selected &&\n \"hover:bg-brand-green-500 hover:text-body-black-solid-constant active:bg-brand-green-500 active:text-body-black-solid-constant\",\n isInteractive &&\n !disabled &&\n !isDark &&\n !selected &&\n \"hover:bg-hover-
|
|
1
|
+
{"version":3,"file":"Chip.cjs","sources":["../../../../src/components/Chip/Chip.tsx"],"sourcesContent":["import { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Visual variant of the chip. */\nexport type ChipVariant = \"rounded\" | \"square\" | \"dark\";\n/** Height of the chip in pixels. */\nexport type ChipSize = \"32\" | \"40\";\n\nexport interface ChipProps extends React.HTMLAttributes<HTMLElement> {\n /** Visual variant of the chip. @default \"rounded\" */\n variant?: ChipVariant;\n /** Height of the chip in pixels. @default \"32\" */\n size?: ChipSize;\n /** Whether the chip is in a selected (pressed) state. @default false */\n selected?: boolean;\n /** Whether the chip is disabled. @default false */\n disabled?: boolean;\n /** Whether to show a coloured status dot at the leading edge. @default false */\n leftDot?: boolean;\n /** Icon element displayed before the label. */\n leftIcon?: React.ReactNode;\n /** Icon element displayed after the label. */\n rightIcon?: React.ReactNode;\n /** Notification badge content (e.g. `\"99+\"`). Passed as a string for i18n support. */\n notificationLabel?: string;\n /** Click handler — when provided, the chip renders as a `<button>` for accessibility. */\n onClick?: React.MouseEventHandler<HTMLElement>;\n /** Merge props onto a child element instead of rendering a wrapper. @default false */\n asChild?: boolean;\n}\n\n/**\n * A compact element for filters, tags, or toggleable actions. When an `onClick`\n * handler is provided, the chip renders as an interactive `<button>` with\n * `aria-pressed` support.\n *\n * @example\n * ```tsx\n * <Chip selected onClick={toggle}>Music</Chip>\n * ```\n */\nexport const Chip = React.forwardRef<HTMLButtonElement, ChipProps>(\n (\n {\n className,\n variant = \"rounded\",\n size = \"32\",\n selected = false,\n disabled = false,\n leftDot = false,\n leftIcon,\n rightIcon,\n notificationLabel,\n onClick,\n asChild = false,\n children,\n ...props\n },\n ref,\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Variant-heavy UI component\n ) => {\n const isInteractive = !!onClick && !asChild;\n const Comp = asChild ? Slot : isInteractive ? \"button\" : \"span\";\n const isDark = variant === \"dark\";\n\n return (\n <Comp\n ref={ref}\n data-testid=\"chip\"\n className={cn(\n \"typography-caption-semibold relative inline-flex items-center justify-center gap-2 whitespace-nowrap px-3 motion-safe:transition-colors motion-safe:duration-150\",\n // Shape\n variant === \"square\" ? \"rounded-lg\" : \"rounded-full\",\n // Size\n size === \"32\" && \"h-8 py-1\",\n size === \"40\" && \"h-10 py-2.5\",\n // Variant colors\n isDark && \"bg-background-800 text-body-white-solid-constant\",\n !isDark && selected && \"bg-brand-green-50 text-neutral-400\",\n !isDark && !selected && \"bg-neutral-100 text-neutral-400\",\n // Hover\n isInteractive &&\n !disabled &&\n !isDark &&\n selected &&\n \"hover:bg-brand-green-500 hover:text-body-black-solid-constant active:bg-brand-green-500 active:text-body-black-solid-constant\",\n isInteractive &&\n !disabled &&\n !isDark &&\n !selected &&\n \"hover:bg-hover-300 active:bg-hover-300\",\n // Focus\n \"focus-visible:shadow-focus-ring focus-visible:outline-none\",\n // Disabled\n disabled && isDark && \"pointer-events-none opacity-50\",\n disabled && !isDark && \"pointer-events-none text-neutral-300\",\n className,\n )}\n {...(isInteractive && {\n type: \"button\" as const,\n disabled,\n \"aria-pressed\": selected,\n onClick,\n })}\n {...(!isInteractive && disabled && { \"aria-disabled\": true })}\n {...(selected && { \"data-selected\": \"\" })}\n {...props}\n >\n {leftDot && <span className=\"size-2 shrink-0 rounded-full bg-current\" aria-hidden=\"true\" />}\n {leftIcon && (\n <span className=\"flex size-5 shrink-0 items-center justify-center\" aria-hidden=\"true\">\n {leftIcon}\n </span>\n )}\n <Slottable>{children}</Slottable>\n {rightIcon && (\n <span className=\"flex size-5 shrink-0 items-center justify-center\" aria-hidden=\"true\">\n {rightIcon}\n </span>\n )}\n {notificationLabel && (\n <span className=\"typography-caption-semibold absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-body-100 px-1 text-body-300\">\n {notificationLabel}\n </span>\n )}\n </Comp>\n );\n },\n);\n\nChip.displayName = \"Chip\";\n"],"names":["React","Slot","jsxs","cn","jsx","Slottable"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA0CO,MAAM,OAAOA,iBAAM;AAAA,EACxB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV,OAAO;AAAA,IACP,WAAW;AAAA,IACX,WAAW;AAAA,IACX,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QAEG;AACH,UAAM,gBAAgB,CAAC,CAAC,WAAW,CAAC;AACpC,UAAM,OAAO,UAAUC,UAAAA,OAAO,gBAAgB,WAAW;AACzD,UAAM,SAAS,YAAY;AAE3B,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,eAAY;AAAA,QACZ,WAAWC,GAAAA;AAAAA,UACT;AAAA;AAAA,UAEA,YAAY,WAAW,eAAe;AAAA;AAAA,UAEtC,SAAS,QAAQ;AAAA,UACjB,SAAS,QAAQ;AAAA;AAAA,UAEjB,UAAU;AAAA,UACV,CAAC,UAAU,YAAY;AAAA,UACvB,CAAC,UAAU,CAAC,YAAY;AAAA;AAAA,UAExB,iBACE,CAAC,YACD,CAAC,UACD,YACA;AAAA,UACF,iBACE,CAAC,YACD,CAAC,UACD,CAAC,YACD;AAAA;AAAA,UAEF;AAAA;AAAA,UAEA,YAAY,UAAU;AAAA,UACtB,YAAY,CAAC,UAAU;AAAA,UACvB;AAAA,QAAA;AAAA,QAED,GAAI,iBAAiB;AAAA,UACpB,MAAM;AAAA,UACN;AAAA,UACA,gBAAgB;AAAA,UAChB;AAAA,QAAA;AAAA,QAED,GAAI,CAAC,iBAAiB,YAAY,EAAE,iBAAiB,KAAA;AAAA,QACrD,GAAI,YAAY,EAAE,iBAAiB,GAAA;AAAA,QACnC,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,WAAWC,2BAAAA,IAAC,QAAA,EAAK,WAAU,2CAA0C,eAAY,QAAO;AAAA,UACxF,YACCA,2BAAAA,IAAC,QAAA,EAAK,WAAU,oDAAmD,eAAY,QAC5E,UAAA,UACH;AAAA,UAEFA,+BAACC,UAAAA,aAAW,UAAS;AAAA,UACpB,aACCD,2BAAAA,IAAC,QAAA,EAAK,WAAU,oDAAmD,eAAY,QAC5E,UAAA,WACH;AAAA,UAED,qBACCA,2BAAAA,IAAC,QAAA,EAAK,WAAU,iJACb,UAAA,kBAAA,CACH;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,KAAK,cAAc;;"}
|
|
@@ -147,14 +147,15 @@ const Select = React__namespace.forwardRef(
|
|
|
147
147
|
}
|
|
148
148
|
);
|
|
149
149
|
Select.displayName = "Select";
|
|
150
|
-
const SelectContent = React__namespace.forwardRef(({ className, children, position = "popper", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
150
|
+
const SelectContent = React__namespace.forwardRef(({ className, children, position = "popper", sideOffset = 4, style, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
151
151
|
SelectPrimitive__namespace.Content,
|
|
152
152
|
{
|
|
153
153
|
ref,
|
|
154
154
|
position,
|
|
155
155
|
sideOffset,
|
|
156
|
+
style: { zIndex: "var(--fanvue-ui-portal-z-index, 50)", ...style },
|
|
156
157
|
className: cn.cn(
|
|
157
|
-
"relative
|
|
158
|
+
"relative min-w-(--radix-select-trigger-width) overflow-hidden rounded-xl border border-neutral-200 bg-background-inverse-solid text-body-100 shadow-[0_4px_16px_rgba(0,0,0,0.10)]",
|
|
158
159
|
"data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
159
160
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
160
161
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
@@ -162,7 +163,7 @@ const SelectContent = React__namespace.forwardRef(({ className, children, positi
|
|
|
162
163
|
className
|
|
163
164
|
),
|
|
164
165
|
...props,
|
|
165
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Viewport, { className: "p-1", children })
|
|
166
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Viewport, { className: "max-h-[var(--radix-select-content-available-height)] overflow-y-auto p-1", children })
|
|
166
167
|
}
|
|
167
168
|
) }));
|
|
168
169
|
SelectContent.displayName = "SelectContent";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.cjs","sources":["../../../../src/components/Select/Select.tsx"],"sourcesContent":["import * as SelectPrimitive from \"@radix-ui/react-select\";\nimport * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { CheckIcon } from \"../Icons/CheckIcon\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\n\n/** Select field height in pixels. */\nexport type SelectSize = \"48\" | \"40\" | \"32\";\n\ntype SelectContextValue = {\n size: SelectSize;\n error: boolean;\n disabled?: boolean;\n};\n\nconst SelectContext = React.createContext<SelectContextValue>({\n size: \"48\",\n error: false,\n});\n\nconst TRIGGER_HEIGHT: Record<SelectSize, string> = {\n \"48\": \"h-12\",\n \"40\": \"h-10\",\n \"32\": \"h-8\",\n};\n\nconst TRIGGER_PADDING_X: Record<SelectSize, string> = {\n \"48\": \"px-4\",\n \"40\": \"px-4\",\n \"32\": \"px-3\",\n};\n\nconst TRIGGER_GAP: Record<SelectSize, string> = {\n \"48\": \"gap-3\",\n \"40\": \"gap-3\",\n \"32\": \"gap-2\",\n};\n\nconst TRIGGER_TYPOGRAPHY: Record<SelectSize, string> = {\n \"48\": \"typography-body-1-regular\",\n \"40\": \"typography-body-1-regular\",\n \"32\": \"typography-body-2-regular\",\n};\n\nexport interface SelectProps extends Omit<SelectPrimitive.SelectProps, \"dir\"> {\n /** Label text displayed above the trigger. Also used as the accessible name. */\n label?: string;\n /** Accessible name applied directly to the trigger button when no visible `label` is provided. */\n \"aria-label\"?: string;\n /** ID of an external element that labels the trigger button. */\n \"aria-labelledby\"?: string;\n /** Helper text displayed below the trigger. Replaced by `errorMessage` when `error` is `true`. */\n helperText?: string;\n /** Height of the select field in pixels. @default \"48\" */\n size?: SelectSize;\n /** Whether the field is in an error state. @default false */\n error?: boolean;\n /** Error message displayed below the trigger. Shown instead of `helperText` when `error` is `true`. */\n errorMessage?: string;\n /** Placeholder shown when no value is selected. */\n placeholder?: string;\n /** Icon element displayed at the left side of the trigger. */\n leftIcon?: React.ReactNode;\n /** Whether the field stretches to fill its container width. @default false */\n fullWidth?: boolean;\n /** Wraps the `className` of the outermost container div. */\n className?: string;\n /** HTML `id` applied to the trigger button. Auto-generated if omitted. */\n id?: string;\n}\n\n/**\n * A select field with optional label, helper/error text, and an icon slot,\n * built on Radix UI Select for full accessibility and keyboard navigation.\n *\n * Pair with {@link SelectContent} and {@link SelectItem} to provide options.\n *\n * @example\n * ```tsx\n * <Select label=\"Country\" placeholder=\"Select a country\">\n * <SelectContent>\n * <SelectItem value=\"us\">United States</SelectItem>\n * <SelectItem value=\"uk\">United Kingdom</SelectItem>\n * </SelectContent>\n * </Select>\n * ```\n */\nexport const Select = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Trigger>,\n SelectProps\n>(\n (\n {\n label,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n placeholder,\n leftIcon,\n fullWidth = false,\n className,\n id,\n disabled,\n children,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n ...props\n },\n ref,\n ) => {\n const generatedId = React.useId();\n const triggerId = id ?? generatedId;\n const helperTextId = `${triggerId}-helper`;\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n return (\n <SelectContext.Provider value={{ size, error, disabled }}>\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={triggerId}\n className=\"typography-caption-semibold px-1 pt-1 pb-2 text-body-100\"\n >\n {label}\n </label>\n )}\n\n <SelectPrimitive.Root disabled={disabled} {...props}>\n <SelectPrimitive.Trigger\n ref={ref}\n id={triggerId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n aria-describedby={bottomText ? helperTextId : undefined}\n aria-invalid={error || undefined}\n className={cn(\n \"flex w-full cursor-pointer items-center justify-between rounded-xl border bg-neutral-100 outline-none motion-safe:transition-colors\",\n TRIGGER_HEIGHT[size],\n TRIGGER_PADDING_X[size],\n TRIGGER_GAP[size],\n TRIGGER_TYPOGRAPHY[size],\n error ? \"border-error-500\" : \"border-transparent\",\n !disabled &&\n !error &&\n \"hover:border-neutral-400 data-[state=open]:border-neutral-400\",\n disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n <div className=\"flex items-center gap-2\">\n {leftIcon && (\n <span\n className=\"flex size-5 shrink-0 items-center justify-center text-body-200\"\n data-testid=\"left-icon\"\n >\n {leftIcon}\n </span>\n )}\n <SelectPrimitive.Value\n placeholder={placeholder}\n className=\"min-w-0 flex-1 truncate text-left text-body-100 data-placeholder:text-body-200 data-placeholder:opacity-40\"\n />\n </div>\n\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n\n {children}\n </SelectPrimitive.Root>\n\n {bottomText && (\n <p\n id={helperTextId}\n className={cn(\n \"typography-caption-regular px-2 pt-1 pb-0.5\",\n error ? \"text-error-500\" : \"text-body-200\",\n )}\n >\n {bottomText}\n </p>\n )}\n </div>\n </SelectContext.Provider>\n );\n },\n);\n\nSelect.displayName = \"Select\";\n\nexport interface SelectContentProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> {}\n\n/**\n * The dropdown panel rendered inside a portal. Place {@link SelectItem} elements\n * (and optionally {@link SelectGroup} / {@link SelectLabel}) as children.\n */\nexport const SelectContent = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Content>,\n SelectContentProps\n>(({ className, children, position = \"popper\", sideOffset = 4, ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n position={position}\n sideOffset={sideOffset}\n className={cn(\n \"relative z-50 min-w-(--radix-select-trigger-width) overflow-hidden rounded-xl border border-neutral-200 bg-background-inverse-solid text-body-100 shadow-[0_4px_16px_rgba(0,0,0,0.10)]\",\n \"data-[state=closed]:animate-out data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n \"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.Viewport className=\"p-1\">{children}</SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n));\n\nSelectContent.displayName = \"SelectContent\";\n\nexport interface SelectItemProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> {}\n\n/**\n * An individual option inside {@link SelectContent}.\n */\nexport const SelectItem = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Item>,\n SelectItemProps\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n \"typography-body-1-regular relative flex w-full cursor-pointer select-none items-center gap-2 rounded-lg py-2 pr-2 pl-3 text-body-100 outline-none\",\n \"focus:bg-neutral-100 data-disabled:pointer-events-none data-disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator className=\"ml-auto flex size-4 shrink-0 items-center justify-center\">\n <CheckIcon className=\"size-4 text-body-100\" />\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n));\n\nSelectItem.displayName = \"SelectItem\";\n\n/** Props for {@link SelectGroup}. */\nexport type SelectGroupProps = React.ComponentPropsWithoutRef<typeof SelectPrimitive.Group>;\n\n/**\n * Groups related {@link SelectItem} elements under a {@link SelectLabel}.\n */\nexport const SelectGroup = SelectPrimitive.Group;\nSelectGroup.displayName = \"SelectGroup\";\n\nexport interface SelectLabelProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label> {}\n\n/**\n * A non-interactive label shown above a {@link SelectGroup}.\n */\nexport const SelectLabel = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Label>,\n SelectLabelProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\"typography-caption-semibold px-3 py-1.5 text-body-200\", className)}\n {...props}\n />\n));\n\nSelectLabel.displayName = \"SelectLabel\";\n\nexport interface SelectSeparatorProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator> {}\n\n/** A horizontal rule that visually separates groups in {@link SelectContent}. */\nexport const SelectSeparator = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Separator>,\n SelectSeparatorProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-neutral-200\", className)}\n {...props}\n />\n));\n\nSelectSeparator.displayName = \"SelectSeparator\";\n"],"names":["React","jsx","jsxs","cn","SelectPrimitive","ChevronDownIcon","CheckIcon"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Select.cjs","sources":["../../../../src/components/Select/Select.tsx"],"sourcesContent":["import * as SelectPrimitive from \"@radix-ui/react-select\";\nimport * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { CheckIcon } from \"../Icons/CheckIcon\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\n\n/** Select field height in pixels. */\nexport type SelectSize = \"48\" | \"40\" | \"32\";\n\ntype SelectContextValue = {\n size: SelectSize;\n error: boolean;\n disabled?: boolean;\n};\n\nconst SelectContext = React.createContext<SelectContextValue>({\n size: \"48\",\n error: false,\n});\n\nconst TRIGGER_HEIGHT: Record<SelectSize, string> = {\n \"48\": \"h-12\",\n \"40\": \"h-10\",\n \"32\": \"h-8\",\n};\n\nconst TRIGGER_PADDING_X: Record<SelectSize, string> = {\n \"48\": \"px-4\",\n \"40\": \"px-4\",\n \"32\": \"px-3\",\n};\n\nconst TRIGGER_GAP: Record<SelectSize, string> = {\n \"48\": \"gap-3\",\n \"40\": \"gap-3\",\n \"32\": \"gap-2\",\n};\n\nconst TRIGGER_TYPOGRAPHY: Record<SelectSize, string> = {\n \"48\": \"typography-body-1-regular\",\n \"40\": \"typography-body-1-regular\",\n \"32\": \"typography-body-2-regular\",\n};\n\nexport interface SelectProps extends Omit<SelectPrimitive.SelectProps, \"dir\"> {\n /** Label text displayed above the trigger. Also used as the accessible name. */\n label?: string;\n /** Accessible name applied directly to the trigger button when no visible `label` is provided. */\n \"aria-label\"?: string;\n /** ID of an external element that labels the trigger button. */\n \"aria-labelledby\"?: string;\n /** Helper text displayed below the trigger. Replaced by `errorMessage` when `error` is `true`. */\n helperText?: string;\n /** Height of the select field in pixels. @default \"48\" */\n size?: SelectSize;\n /** Whether the field is in an error state. @default false */\n error?: boolean;\n /** Error message displayed below the trigger. Shown instead of `helperText` when `error` is `true`. */\n errorMessage?: string;\n /** Placeholder shown when no value is selected. */\n placeholder?: string;\n /** Icon element displayed at the left side of the trigger. */\n leftIcon?: React.ReactNode;\n /** Whether the field stretches to fill its container width. @default false */\n fullWidth?: boolean;\n /** Wraps the `className` of the outermost container div. */\n className?: string;\n /** HTML `id` applied to the trigger button. Auto-generated if omitted. */\n id?: string;\n}\n\n/**\n * A select field with optional label, helper/error text, and an icon slot,\n * built on Radix UI Select for full accessibility and keyboard navigation.\n *\n * Pair with {@link SelectContent} and {@link SelectItem} to provide options.\n *\n * @example\n * ```tsx\n * <Select label=\"Country\" placeholder=\"Select a country\">\n * <SelectContent>\n * <SelectItem value=\"us\">United States</SelectItem>\n * <SelectItem value=\"uk\">United Kingdom</SelectItem>\n * </SelectContent>\n * </Select>\n * ```\n */\nexport const Select = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Trigger>,\n SelectProps\n>(\n (\n {\n label,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n placeholder,\n leftIcon,\n fullWidth = false,\n className,\n id,\n disabled,\n children,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n ...props\n },\n ref,\n ) => {\n const generatedId = React.useId();\n const triggerId = id ?? generatedId;\n const helperTextId = `${triggerId}-helper`;\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n return (\n <SelectContext.Provider value={{ size, error, disabled }}>\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={triggerId}\n className=\"typography-caption-semibold px-1 pt-1 pb-2 text-body-100\"\n >\n {label}\n </label>\n )}\n\n <SelectPrimitive.Root disabled={disabled} {...props}>\n <SelectPrimitive.Trigger\n ref={ref}\n id={triggerId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n aria-describedby={bottomText ? helperTextId : undefined}\n aria-invalid={error || undefined}\n className={cn(\n \"flex w-full cursor-pointer items-center justify-between rounded-xl border bg-neutral-100 outline-none motion-safe:transition-colors\",\n TRIGGER_HEIGHT[size],\n TRIGGER_PADDING_X[size],\n TRIGGER_GAP[size],\n TRIGGER_TYPOGRAPHY[size],\n error ? \"border-error-500\" : \"border-transparent\",\n !disabled &&\n !error &&\n \"hover:border-neutral-400 data-[state=open]:border-neutral-400\",\n disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n <div className=\"flex items-center gap-2\">\n {leftIcon && (\n <span\n className=\"flex size-5 shrink-0 items-center justify-center text-body-200\"\n data-testid=\"left-icon\"\n >\n {leftIcon}\n </span>\n )}\n <SelectPrimitive.Value\n placeholder={placeholder}\n className=\"min-w-0 flex-1 truncate text-left text-body-100 data-placeholder:text-body-200 data-placeholder:opacity-40\"\n />\n </div>\n\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n\n {children}\n </SelectPrimitive.Root>\n\n {bottomText && (\n <p\n id={helperTextId}\n className={cn(\n \"typography-caption-regular px-2 pt-1 pb-0.5\",\n error ? \"text-error-500\" : \"text-body-200\",\n )}\n >\n {bottomText}\n </p>\n )}\n </div>\n </SelectContext.Provider>\n );\n },\n);\n\nSelect.displayName = \"Select\";\n\nexport interface SelectContentProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> {}\n\n/**\n * The dropdown panel rendered inside a portal. Place {@link SelectItem} elements\n * (and optionally {@link SelectGroup} / {@link SelectLabel}) as children.\n */\nexport const SelectContent = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Content>,\n SelectContentProps\n>(({ className, children, position = \"popper\", sideOffset = 4, style, ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n position={position}\n sideOffset={sideOffset}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"relative min-w-(--radix-select-trigger-width) overflow-hidden rounded-xl border border-neutral-200 bg-background-inverse-solid text-body-100 shadow-[0_4px_16px_rgba(0,0,0,0.10)]\",\n \"data-[state=closed]:animate-out data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n \"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.Viewport className=\"max-h-[var(--radix-select-content-available-height)] overflow-y-auto p-1\">\n {children}\n </SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n));\n\nSelectContent.displayName = \"SelectContent\";\n\nexport interface SelectItemProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> {}\n\n/**\n * An individual option inside {@link SelectContent}.\n */\nexport const SelectItem = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Item>,\n SelectItemProps\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n \"typography-body-1-regular relative flex w-full cursor-pointer select-none items-center gap-2 rounded-lg py-2 pr-2 pl-3 text-body-100 outline-none\",\n \"focus:bg-neutral-100 data-disabled:pointer-events-none data-disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator className=\"ml-auto flex size-4 shrink-0 items-center justify-center\">\n <CheckIcon className=\"size-4 text-body-100\" />\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n));\n\nSelectItem.displayName = \"SelectItem\";\n\n/** Props for {@link SelectGroup}. */\nexport type SelectGroupProps = React.ComponentPropsWithoutRef<typeof SelectPrimitive.Group>;\n\n/**\n * Groups related {@link SelectItem} elements under a {@link SelectLabel}.\n */\nexport const SelectGroup = SelectPrimitive.Group;\nSelectGroup.displayName = \"SelectGroup\";\n\nexport interface SelectLabelProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label> {}\n\n/**\n * A non-interactive label shown above a {@link SelectGroup}.\n */\nexport const SelectLabel = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Label>,\n SelectLabelProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\"typography-caption-semibold px-3 py-1.5 text-body-200\", className)}\n {...props}\n />\n));\n\nSelectLabel.displayName = \"SelectLabel\";\n\nexport interface SelectSeparatorProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator> {}\n\n/** A horizontal rule that visually separates groups in {@link SelectContent}. */\nexport const SelectSeparator = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Separator>,\n SelectSeparatorProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-neutral-200\", className)}\n {...props}\n />\n));\n\nSelectSeparator.displayName = \"SelectSeparator\";\n"],"names":["React","jsx","jsxs","cn","SelectPrimitive","ChevronDownIcon","CheckIcon"],"mappings":"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"}
|
|
@@ -40,6 +40,7 @@ const TooltipContent = React__namespace.forwardRef(
|
|
|
40
40
|
secondaryAction,
|
|
41
41
|
children,
|
|
42
42
|
side,
|
|
43
|
+
style,
|
|
43
44
|
...props
|
|
44
45
|
}, ref) => {
|
|
45
46
|
const isInfobox = variant === "infobox";
|
|
@@ -50,8 +51,9 @@ const TooltipContent = React__namespace.forwardRef(
|
|
|
50
51
|
{
|
|
51
52
|
ref,
|
|
52
53
|
sideOffset,
|
|
54
|
+
style: { zIndex: "var(--fanvue-ui-portal-z-index, 50)", ...style },
|
|
53
55
|
className: cn.cn(
|
|
54
|
-
"typography-body-2-regular
|
|
56
|
+
"typography-body-2-regular max-w-[320px] overflow-hidden rounded-3xl bg-background-solid p-4 text-background-inverse-solid shadow-[0px_2px_4px_0px_rgba(17,24,39,0.08)]",
|
|
55
57
|
isInfobox && "border border-neutral-200",
|
|
56
58
|
className
|
|
57
59
|
),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.cjs","sources":["../../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button/Button\";\n\n/** Props for the {@link TooltipProvider}. Wraps Radix `Tooltip.Provider`. */\nexport type TooltipProviderProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>;\n\n/** Provides tooltip delay and skip-delay context. Wrap your app or a subtree. */\nexport const TooltipProvider = TooltipPrimitive.Provider;\n\n/** Props for the {@link Tooltip} root component. */\nexport interface TooltipProps extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root> {\n /**\n * Controlled open state. When provided, the component is in controlled mode\n * and you must also supply `onOpenChange` to update the value.\n */\n open?: boolean;\n /** Called when the open state changes. Required when `open` is controlled. */\n onOpenChange?: (open: boolean) => void;\n /** The open state of the tooltip when it is initially rendered (uncontrolled). */\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for a single tooltip. */\nexport const Tooltip = TooltipPrimitive.Root;\n\n/** Props for the {@link TooltipTrigger} component. */\nexport type TooltipTriggerProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>;\n\n/** The element that triggers the tooltip on hover/focus. */\nexport const TooltipTrigger = TooltipPrimitive.Trigger;\n\n/**\n * Visual style variant of the tooltip content.\n *\n * - `\"tooltip\"` — simple text bubble, no border.\n * - `\"infobox\"` — richer card with a visible border, structured header, body text, and optional actions.\n */\nexport type TooltipContentVariant = \"tooltip\" | \"infobox\";\n\n/** Action button configuration for the infobox variant of {@link TooltipContent}. */\nexport interface TooltipAction {\n /** Button label. */\n label: string;\n /** Click handler. */\n onClick?: () => void;\n /**\n * Optional custom React node to be rendered for the action instead of the default button.\n * Only used in the infobox variant.\n */\n element?: React.ReactNode;\n}\n\nexport interface TooltipContentProps\n extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> {\n /**\n * Visual style variant.\n *\n * `\"tooltip\"` is a lightweight text bubble. `\"infobox\"` renders a structured card\n * with optional heading, icon, pill, body text, and action buttons.\n *\n * @default \"tooltip\"\n */\n variant?: TooltipContentVariant;\n /** Whether to show the directional arrow pointer. @default true */\n showArrow?: boolean;\n /**\n * Heading text rendered in subtitle style at the top of the infobox.\n * Infobox variant only.\n */\n heading?: React.ReactNode;\n /**\n * Icon element displayed to the left of the heading.\n * Infobox variant only.\n */\n icon?: React.ReactNode;\n /**\n * Pill or badge element displayed to the right of the heading.\n * Infobox variant only.\n */\n pill?: React.ReactNode;\n /**\n * Primary action button (brand green). Rendered below the body text.\n * Infobox variant only.\n */\n primaryAction?: TooltipAction;\n /**\n * Secondary action button (ghost). Rendered next to the primary action.\n * Infobox variant only.\n */\n secondaryAction?: TooltipAction;\n}\n\n/**\n * The popup content of the tooltip. Renders inside a portal.\n *\n * Arrow direction is controlled via the `side` and `align` props (Radix passthrough).\n *\n * @example\n * ```tsx\n * // Simple tooltip\n * <TooltipContent>Info text</TooltipContent>\n *\n * // Infobox with structured content\n * <TooltipContent\n * variant=\"infobox\"\n * heading=\"Title\"\n * icon={<InfoCircleIcon className=\"size-5\" />}\n * primaryAction={{ label: \"OK\", onClick: () => {} }}\n * secondaryAction={{ label: \"Dismiss\" }}\n * >\n * Info text\n * </TooltipContent>\n * ```\n */\nexport const TooltipContent = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Content>,\n TooltipContentProps\n>(\n (\n {\n className,\n variant = \"tooltip\",\n showArrow = true,\n sideOffset = 8,\n heading,\n icon,\n pill,\n primaryAction,\n secondaryAction,\n children,\n side,\n ...props\n },\n ref,\n ) => {\n const isInfobox = variant === \"infobox\";\n const hasHeader =\n isInfobox && (icon !== undefined || heading !== undefined || pill !== undefined);\n const hasActions = isInfobox && (primaryAction !== undefined || secondaryAction !== undefined);\n\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n \"typography-body-2-regular
|
|
1
|
+
{"version":3,"file":"Tooltip.cjs","sources":["../../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button/Button\";\n\n/** Props for the {@link TooltipProvider}. Wraps Radix `Tooltip.Provider`. */\nexport type TooltipProviderProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>;\n\n/** Provides tooltip delay and skip-delay context. Wrap your app or a subtree. */\nexport const TooltipProvider = TooltipPrimitive.Provider;\n\n/** Props for the {@link Tooltip} root component. */\nexport interface TooltipProps extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root> {\n /**\n * Controlled open state. When provided, the component is in controlled mode\n * and you must also supply `onOpenChange` to update the value.\n */\n open?: boolean;\n /** Called when the open state changes. Required when `open` is controlled. */\n onOpenChange?: (open: boolean) => void;\n /** The open state of the tooltip when it is initially rendered (uncontrolled). */\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for a single tooltip. */\nexport const Tooltip = TooltipPrimitive.Root;\n\n/** Props for the {@link TooltipTrigger} component. */\nexport type TooltipTriggerProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>;\n\n/** The element that triggers the tooltip on hover/focus. */\nexport const TooltipTrigger = TooltipPrimitive.Trigger;\n\n/**\n * Visual style variant of the tooltip content.\n *\n * - `\"tooltip\"` — simple text bubble, no border.\n * - `\"infobox\"` — richer card with a visible border, structured header, body text, and optional actions.\n */\nexport type TooltipContentVariant = \"tooltip\" | \"infobox\";\n\n/** Action button configuration for the infobox variant of {@link TooltipContent}. */\nexport interface TooltipAction {\n /** Button label. */\n label: string;\n /** Click handler. */\n onClick?: () => void;\n /**\n * Optional custom React node to be rendered for the action instead of the default button.\n * Only used in the infobox variant.\n */\n element?: React.ReactNode;\n}\n\nexport interface TooltipContentProps\n extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> {\n /**\n * Visual style variant.\n *\n * `\"tooltip\"` is a lightweight text bubble. `\"infobox\"` renders a structured card\n * with optional heading, icon, pill, body text, and action buttons.\n *\n * @default \"tooltip\"\n */\n variant?: TooltipContentVariant;\n /** Whether to show the directional arrow pointer. @default true */\n showArrow?: boolean;\n /**\n * Heading text rendered in subtitle style at the top of the infobox.\n * Infobox variant only.\n */\n heading?: React.ReactNode;\n /**\n * Icon element displayed to the left of the heading.\n * Infobox variant only.\n */\n icon?: React.ReactNode;\n /**\n * Pill or badge element displayed to the right of the heading.\n * Infobox variant only.\n */\n pill?: React.ReactNode;\n /**\n * Primary action button (brand green). Rendered below the body text.\n * Infobox variant only.\n */\n primaryAction?: TooltipAction;\n /**\n * Secondary action button (ghost). Rendered next to the primary action.\n * Infobox variant only.\n */\n secondaryAction?: TooltipAction;\n}\n\n/**\n * The popup content of the tooltip. Renders inside a portal.\n *\n * Arrow direction is controlled via the `side` and `align` props (Radix passthrough).\n *\n * @example\n * ```tsx\n * // Simple tooltip\n * <TooltipContent>Info text</TooltipContent>\n *\n * // Infobox with structured content\n * <TooltipContent\n * variant=\"infobox\"\n * heading=\"Title\"\n * icon={<InfoCircleIcon className=\"size-5\" />}\n * primaryAction={{ label: \"OK\", onClick: () => {} }}\n * secondaryAction={{ label: \"Dismiss\" }}\n * >\n * Info text\n * </TooltipContent>\n * ```\n */\nexport const TooltipContent = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Content>,\n TooltipContentProps\n>(\n (\n {\n className,\n variant = \"tooltip\",\n showArrow = true,\n sideOffset = 8,\n heading,\n icon,\n pill,\n primaryAction,\n secondaryAction,\n children,\n side,\n style,\n ...props\n },\n ref,\n ) => {\n const isInfobox = variant === \"infobox\";\n const hasHeader =\n isInfobox && (icon !== undefined || heading !== undefined || pill !== undefined);\n const hasActions = isInfobox && (primaryAction !== undefined || secondaryAction !== undefined);\n\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"typography-body-2-regular max-w-[320px] overflow-hidden rounded-3xl bg-background-solid p-4 text-background-inverse-solid shadow-[0px_2px_4px_0px_rgba(17,24,39,0.08)]\",\n isInfobox && \"border border-neutral-200\",\n className,\n )}\n align=\"center\"\n arrowPadding={12}\n side={side}\n {...props}\n >\n {isInfobox ? (\n <div className=\"flex flex-col gap-3\">\n {hasHeader && (\n <div className=\"flex items-center gap-3\">\n {icon && <div className=\"size-5 shrink-0\">{icon}</div>}\n {heading && (\n <p className=\"typography-subtitle min-w-0 flex-1 text-background-inverse-solid\">\n {heading}\n </p>\n )}\n {pill && <div className=\"shrink-0\">{pill}</div>}\n </div>\n )}\n {children && (\n <div className=\"typography-body-2-regular text-background-inverse-solid\">\n {children}\n </div>\n )}\n {hasActions && (\n <div className=\"flex items-center gap-1\">\n {primaryAction &&\n (primaryAction.element ? (\n primaryAction.element\n ) : (\n <Button variant=\"brand\" size=\"32\" onClick={primaryAction.onClick}>\n {primaryAction.label}\n </Button>\n ))}\n {secondaryAction &&\n (secondaryAction.element ? (\n secondaryAction.element\n ) : (\n <Button variant=\"tertiary\" size=\"32\" onClick={secondaryAction.onClick}>\n {secondaryAction.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n ) : (\n children\n )}\n {showArrow && (\n <TooltipPrimitive.Arrow\n className={\"-translate-y-px! fill-background-solid stroke-2 stroke-background-solid\"}\n width={12}\n height={6}\n />\n )}\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n );\n },\n);\nTooltipContent.displayName = \"TooltipContent\";\n"],"names":["TooltipPrimitive","React","jsx","jsxs","cn","Button"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AASO,MAAM,kBAAkBA,4BAAiB;AAgBzC,MAAM,UAAUA,4BAAiB;AAMjC,MAAM,iBAAiBA,4BAAiB;AAqFxC,MAAM,iBAAiBC,iBAAM;AAAA,EAIlC,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,YAAY,YAAY;AAC9B,UAAM,YACJ,cAAc,SAAS,UAAa,YAAY,UAAa,SAAS;AACxE,UAAM,aAAa,cAAc,kBAAkB,UAAa,oBAAoB;AAEpF,WACEC,2BAAAA,IAACF,4BAAiB,QAAjB,EACC,UAAAG,2BAAAA;AAAAA,MAACH,4BAAiB;AAAA,MAAjB;AAAA,QACC;AAAA,QACA;AAAA,QACA,OAAO,EAAE,QAAQ,uCAAuC,GAAG,MAAA;AAAA,QAC3D,WAAWI,GAAAA;AAAAA,UACT;AAAA,UACA,aAAa;AAAA,UACb;AAAA,QAAA;AAAA,QAEF,OAAM;AAAA,QACN,cAAc;AAAA,QACd;AAAA,QACC,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,YACCD,2BAAAA,KAAC,OAAA,EAAI,WAAU,uBACZ,UAAA;AAAA,YAAA,aACCA,2BAAAA,KAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,cAAA,QAAQD,2BAAAA,IAAC,OAAA,EAAI,WAAU,mBAAmB,UAAA,MAAK;AAAA,cAC/C,WACCA,2BAAAA,IAAC,KAAA,EAAE,WAAU,oEACV,UAAA,SACH;AAAA,cAED,QAAQA,2BAAAA,IAAC,OAAA,EAAI,WAAU,YAAY,UAAA,KAAA,CAAK;AAAA,YAAA,GAC3C;AAAA,YAED,YACCA,2BAAAA,IAAC,OAAA,EAAI,WAAU,2DACZ,UACH;AAAA,YAED,cACCC,2BAAAA,KAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,cAAA,kBACE,cAAc,UACb,cAAc,yCAEbE,OAAAA,QAAA,EAAO,SAAQ,SAAQ,MAAK,MAAK,SAAS,cAAc,SACtD,wBAAc,MAAA,CACjB;AAAA,cAEH,oBACE,gBAAgB,UACf,gBAAgB,UAEhBH,2BAAAA,IAACG,OAAAA,QAAA,EAAO,SAAQ,YAAW,MAAK,MAAK,SAAS,gBAAgB,SAC3D,0BAAgB,OACnB;AAAA,YAAA,EAAA,CAEN;AAAA,UAAA,EAAA,CAEJ,IAEA;AAAA,UAED,aACCH,2BAAAA;AAAAA,YAACF,4BAAiB;AAAA,YAAjB;AAAA,cACC,WAAW;AAAA,cACX,OAAO;AAAA,cACP,QAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,QACV;AAAA,MAAA;AAAA,IAAA,GAGN;AAAA,EAEJ;AACF;AACA,eAAe,cAAc;;;;;"}
|
|
@@ -40,7 +40,7 @@ const Chip = React.forwardRef(
|
|
|
40
40
|
!isDark && !selected && "bg-neutral-100 text-neutral-400",
|
|
41
41
|
// Hover
|
|
42
42
|
isInteractive && !disabled && !isDark && selected && "hover:bg-brand-green-500 hover:text-body-black-solid-constant active:bg-brand-green-500 active:text-body-black-solid-constant",
|
|
43
|
-
isInteractive && !disabled && !isDark && !selected && "hover:bg-hover-
|
|
43
|
+
isInteractive && !disabled && !isDark && !selected && "hover:bg-hover-300 active:bg-hover-300",
|
|
44
44
|
// Focus
|
|
45
45
|
"focus-visible:shadow-focus-ring focus-visible:outline-none",
|
|
46
46
|
// Disabled
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chip.mjs","sources":["../../../src/components/Chip/Chip.tsx"],"sourcesContent":["import { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Visual variant of the chip. */\nexport type ChipVariant = \"rounded\" | \"square\" | \"dark\";\n/** Height of the chip in pixels. */\nexport type ChipSize = \"32\" | \"40\";\n\nexport interface ChipProps extends React.HTMLAttributes<HTMLElement> {\n /** Visual variant of the chip. @default \"rounded\" */\n variant?: ChipVariant;\n /** Height of the chip in pixels. @default \"32\" */\n size?: ChipSize;\n /** Whether the chip is in a selected (pressed) state. @default false */\n selected?: boolean;\n /** Whether the chip is disabled. @default false */\n disabled?: boolean;\n /** Whether to show a coloured status dot at the leading edge. @default false */\n leftDot?: boolean;\n /** Icon element displayed before the label. */\n leftIcon?: React.ReactNode;\n /** Icon element displayed after the label. */\n rightIcon?: React.ReactNode;\n /** Notification badge content (e.g. `\"99+\"`). Passed as a string for i18n support. */\n notificationLabel?: string;\n /** Click handler — when provided, the chip renders as a `<button>` for accessibility. */\n onClick?: React.MouseEventHandler<HTMLElement>;\n /** Merge props onto a child element instead of rendering a wrapper. @default false */\n asChild?: boolean;\n}\n\n/**\n * A compact element for filters, tags, or toggleable actions. When an `onClick`\n * handler is provided, the chip renders as an interactive `<button>` with\n * `aria-pressed` support.\n *\n * @example\n * ```tsx\n * <Chip selected onClick={toggle}>Music</Chip>\n * ```\n */\nexport const Chip = React.forwardRef<HTMLButtonElement, ChipProps>(\n (\n {\n className,\n variant = \"rounded\",\n size = \"32\",\n selected = false,\n disabled = false,\n leftDot = false,\n leftIcon,\n rightIcon,\n notificationLabel,\n onClick,\n asChild = false,\n children,\n ...props\n },\n ref,\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Variant-heavy UI component\n ) => {\n const isInteractive = !!onClick && !asChild;\n const Comp = asChild ? Slot : isInteractive ? \"button\" : \"span\";\n const isDark = variant === \"dark\";\n\n return (\n <Comp\n ref={ref}\n data-testid=\"chip\"\n className={cn(\n \"typography-caption-semibold relative inline-flex items-center justify-center gap-2 whitespace-nowrap px-3 motion-safe:transition-colors motion-safe:duration-150\",\n // Shape\n variant === \"square\" ? \"rounded-lg\" : \"rounded-full\",\n // Size\n size === \"32\" && \"h-8 py-1\",\n size === \"40\" && \"h-10 py-2.5\",\n // Variant colors\n isDark && \"bg-background-800 text-body-white-solid-constant\",\n !isDark && selected && \"bg-brand-green-50 text-neutral-400\",\n !isDark && !selected && \"bg-neutral-100 text-neutral-400\",\n // Hover\n isInteractive &&\n !disabled &&\n !isDark &&\n selected &&\n \"hover:bg-brand-green-500 hover:text-body-black-solid-constant active:bg-brand-green-500 active:text-body-black-solid-constant\",\n isInteractive &&\n !disabled &&\n !isDark &&\n !selected &&\n \"hover:bg-hover-
|
|
1
|
+
{"version":3,"file":"Chip.mjs","sources":["../../../src/components/Chip/Chip.tsx"],"sourcesContent":["import { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Visual variant of the chip. */\nexport type ChipVariant = \"rounded\" | \"square\" | \"dark\";\n/** Height of the chip in pixels. */\nexport type ChipSize = \"32\" | \"40\";\n\nexport interface ChipProps extends React.HTMLAttributes<HTMLElement> {\n /** Visual variant of the chip. @default \"rounded\" */\n variant?: ChipVariant;\n /** Height of the chip in pixels. @default \"32\" */\n size?: ChipSize;\n /** Whether the chip is in a selected (pressed) state. @default false */\n selected?: boolean;\n /** Whether the chip is disabled. @default false */\n disabled?: boolean;\n /** Whether to show a coloured status dot at the leading edge. @default false */\n leftDot?: boolean;\n /** Icon element displayed before the label. */\n leftIcon?: React.ReactNode;\n /** Icon element displayed after the label. */\n rightIcon?: React.ReactNode;\n /** Notification badge content (e.g. `\"99+\"`). Passed as a string for i18n support. */\n notificationLabel?: string;\n /** Click handler — when provided, the chip renders as a `<button>` for accessibility. */\n onClick?: React.MouseEventHandler<HTMLElement>;\n /** Merge props onto a child element instead of rendering a wrapper. @default false */\n asChild?: boolean;\n}\n\n/**\n * A compact element for filters, tags, or toggleable actions. When an `onClick`\n * handler is provided, the chip renders as an interactive `<button>` with\n * `aria-pressed` support.\n *\n * @example\n * ```tsx\n * <Chip selected onClick={toggle}>Music</Chip>\n * ```\n */\nexport const Chip = React.forwardRef<HTMLButtonElement, ChipProps>(\n (\n {\n className,\n variant = \"rounded\",\n size = \"32\",\n selected = false,\n disabled = false,\n leftDot = false,\n leftIcon,\n rightIcon,\n notificationLabel,\n onClick,\n asChild = false,\n children,\n ...props\n },\n ref,\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Variant-heavy UI component\n ) => {\n const isInteractive = !!onClick && !asChild;\n const Comp = asChild ? Slot : isInteractive ? \"button\" : \"span\";\n const isDark = variant === \"dark\";\n\n return (\n <Comp\n ref={ref}\n data-testid=\"chip\"\n className={cn(\n \"typography-caption-semibold relative inline-flex items-center justify-center gap-2 whitespace-nowrap px-3 motion-safe:transition-colors motion-safe:duration-150\",\n // Shape\n variant === \"square\" ? \"rounded-lg\" : \"rounded-full\",\n // Size\n size === \"32\" && \"h-8 py-1\",\n size === \"40\" && \"h-10 py-2.5\",\n // Variant colors\n isDark && \"bg-background-800 text-body-white-solid-constant\",\n !isDark && selected && \"bg-brand-green-50 text-neutral-400\",\n !isDark && !selected && \"bg-neutral-100 text-neutral-400\",\n // Hover\n isInteractive &&\n !disabled &&\n !isDark &&\n selected &&\n \"hover:bg-brand-green-500 hover:text-body-black-solid-constant active:bg-brand-green-500 active:text-body-black-solid-constant\",\n isInteractive &&\n !disabled &&\n !isDark &&\n !selected &&\n \"hover:bg-hover-300 active:bg-hover-300\",\n // Focus\n \"focus-visible:shadow-focus-ring focus-visible:outline-none\",\n // Disabled\n disabled && isDark && \"pointer-events-none opacity-50\",\n disabled && !isDark && \"pointer-events-none text-neutral-300\",\n className,\n )}\n {...(isInteractive && {\n type: \"button\" as const,\n disabled,\n \"aria-pressed\": selected,\n onClick,\n })}\n {...(!isInteractive && disabled && { \"aria-disabled\": true })}\n {...(selected && { \"data-selected\": \"\" })}\n {...props}\n >\n {leftDot && <span className=\"size-2 shrink-0 rounded-full bg-current\" aria-hidden=\"true\" />}\n {leftIcon && (\n <span className=\"flex size-5 shrink-0 items-center justify-center\" aria-hidden=\"true\">\n {leftIcon}\n </span>\n )}\n <Slottable>{children}</Slottable>\n {rightIcon && (\n <span className=\"flex size-5 shrink-0 items-center justify-center\" aria-hidden=\"true\">\n {rightIcon}\n </span>\n )}\n {notificationLabel && (\n <span className=\"typography-caption-semibold absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-body-100 px-1 text-body-300\">\n {notificationLabel}\n </span>\n )}\n </Comp>\n );\n },\n);\n\nChip.displayName = \"Chip\";\n"],"names":[],"mappings":";;;;;AA0CO,MAAM,OAAO,MAAM;AAAA,EACxB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV,OAAO;AAAA,IACP,WAAW;AAAA,IACX,WAAW;AAAA,IACX,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QAEG;AACH,UAAM,gBAAgB,CAAC,CAAC,WAAW,CAAC;AACpC,UAAM,OAAO,UAAU,OAAO,gBAAgB,WAAW;AACzD,UAAM,SAAS,YAAY;AAE3B,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,eAAY;AAAA,QACZ,WAAW;AAAA,UACT;AAAA;AAAA,UAEA,YAAY,WAAW,eAAe;AAAA;AAAA,UAEtC,SAAS,QAAQ;AAAA,UACjB,SAAS,QAAQ;AAAA;AAAA,UAEjB,UAAU;AAAA,UACV,CAAC,UAAU,YAAY;AAAA,UACvB,CAAC,UAAU,CAAC,YAAY;AAAA;AAAA,UAExB,iBACE,CAAC,YACD,CAAC,UACD,YACA;AAAA,UACF,iBACE,CAAC,YACD,CAAC,UACD,CAAC,YACD;AAAA;AAAA,UAEF;AAAA;AAAA,UAEA,YAAY,UAAU;AAAA,UACtB,YAAY,CAAC,UAAU;AAAA,UACvB;AAAA,QAAA;AAAA,QAED,GAAI,iBAAiB;AAAA,UACpB,MAAM;AAAA,UACN;AAAA,UACA,gBAAgB;AAAA,UAChB;AAAA,QAAA;AAAA,QAED,GAAI,CAAC,iBAAiB,YAAY,EAAE,iBAAiB,KAAA;AAAA,QACrD,GAAI,YAAY,EAAE,iBAAiB,GAAA;AAAA,QACnC,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,WAAW,oBAAC,QAAA,EAAK,WAAU,2CAA0C,eAAY,QAAO;AAAA,UACxF,YACC,oBAAC,QAAA,EAAK,WAAU,oDAAmD,eAAY,QAC5E,UAAA,UACH;AAAA,UAEF,oBAAC,aAAW,UAAS;AAAA,UACpB,aACC,oBAAC,QAAA,EAAK,WAAU,oDAAmD,eAAY,QAC5E,UAAA,WACH;AAAA,UAED,qBACC,oBAAC,QAAA,EAAK,WAAU,iJACb,UAAA,kBAAA,CACH;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,KAAK,cAAc;"}
|
|
@@ -127,14 +127,15 @@ const Select = React.forwardRef(
|
|
|
127
127
|
}
|
|
128
128
|
);
|
|
129
129
|
Select.displayName = "Select";
|
|
130
|
-
const SelectContent = React.forwardRef(({ className, children, position = "popper", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
130
|
+
const SelectContent = React.forwardRef(({ className, children, position = "popper", sideOffset = 4, style, ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
131
131
|
SelectPrimitive.Content,
|
|
132
132
|
{
|
|
133
133
|
ref,
|
|
134
134
|
position,
|
|
135
135
|
sideOffset,
|
|
136
|
+
style: { zIndex: "var(--fanvue-ui-portal-z-index, 50)", ...style },
|
|
136
137
|
className: cn(
|
|
137
|
-
"relative
|
|
138
|
+
"relative min-w-(--radix-select-trigger-width) overflow-hidden rounded-xl border border-neutral-200 bg-background-inverse-solid text-body-100 shadow-[0_4px_16px_rgba(0,0,0,0.10)]",
|
|
138
139
|
"data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
139
140
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
140
141
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
@@ -142,7 +143,7 @@ const SelectContent = React.forwardRef(({ className, children, position = "poppe
|
|
|
142
143
|
className
|
|
143
144
|
),
|
|
144
145
|
...props,
|
|
145
|
-
children: /* @__PURE__ */ jsx(SelectPrimitive.Viewport, { className: "p-1", children })
|
|
146
|
+
children: /* @__PURE__ */ jsx(SelectPrimitive.Viewport, { className: "max-h-[var(--radix-select-content-available-height)] overflow-y-auto p-1", children })
|
|
146
147
|
}
|
|
147
148
|
) }));
|
|
148
149
|
SelectContent.displayName = "SelectContent";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.mjs","sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["import * as SelectPrimitive from \"@radix-ui/react-select\";\nimport * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { CheckIcon } from \"../Icons/CheckIcon\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\n\n/** Select field height in pixels. */\nexport type SelectSize = \"48\" | \"40\" | \"32\";\n\ntype SelectContextValue = {\n size: SelectSize;\n error: boolean;\n disabled?: boolean;\n};\n\nconst SelectContext = React.createContext<SelectContextValue>({\n size: \"48\",\n error: false,\n});\n\nconst TRIGGER_HEIGHT: Record<SelectSize, string> = {\n \"48\": \"h-12\",\n \"40\": \"h-10\",\n \"32\": \"h-8\",\n};\n\nconst TRIGGER_PADDING_X: Record<SelectSize, string> = {\n \"48\": \"px-4\",\n \"40\": \"px-4\",\n \"32\": \"px-3\",\n};\n\nconst TRIGGER_GAP: Record<SelectSize, string> = {\n \"48\": \"gap-3\",\n \"40\": \"gap-3\",\n \"32\": \"gap-2\",\n};\n\nconst TRIGGER_TYPOGRAPHY: Record<SelectSize, string> = {\n \"48\": \"typography-body-1-regular\",\n \"40\": \"typography-body-1-regular\",\n \"32\": \"typography-body-2-regular\",\n};\n\nexport interface SelectProps extends Omit<SelectPrimitive.SelectProps, \"dir\"> {\n /** Label text displayed above the trigger. Also used as the accessible name. */\n label?: string;\n /** Accessible name applied directly to the trigger button when no visible `label` is provided. */\n \"aria-label\"?: string;\n /** ID of an external element that labels the trigger button. */\n \"aria-labelledby\"?: string;\n /** Helper text displayed below the trigger. Replaced by `errorMessage` when `error` is `true`. */\n helperText?: string;\n /** Height of the select field in pixels. @default \"48\" */\n size?: SelectSize;\n /** Whether the field is in an error state. @default false */\n error?: boolean;\n /** Error message displayed below the trigger. Shown instead of `helperText` when `error` is `true`. */\n errorMessage?: string;\n /** Placeholder shown when no value is selected. */\n placeholder?: string;\n /** Icon element displayed at the left side of the trigger. */\n leftIcon?: React.ReactNode;\n /** Whether the field stretches to fill its container width. @default false */\n fullWidth?: boolean;\n /** Wraps the `className` of the outermost container div. */\n className?: string;\n /** HTML `id` applied to the trigger button. Auto-generated if omitted. */\n id?: string;\n}\n\n/**\n * A select field with optional label, helper/error text, and an icon slot,\n * built on Radix UI Select for full accessibility and keyboard navigation.\n *\n * Pair with {@link SelectContent} and {@link SelectItem} to provide options.\n *\n * @example\n * ```tsx\n * <Select label=\"Country\" placeholder=\"Select a country\">\n * <SelectContent>\n * <SelectItem value=\"us\">United States</SelectItem>\n * <SelectItem value=\"uk\">United Kingdom</SelectItem>\n * </SelectContent>\n * </Select>\n * ```\n */\nexport const Select = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Trigger>,\n SelectProps\n>(\n (\n {\n label,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n placeholder,\n leftIcon,\n fullWidth = false,\n className,\n id,\n disabled,\n children,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n ...props\n },\n ref,\n ) => {\n const generatedId = React.useId();\n const triggerId = id ?? generatedId;\n const helperTextId = `${triggerId}-helper`;\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n return (\n <SelectContext.Provider value={{ size, error, disabled }}>\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={triggerId}\n className=\"typography-caption-semibold px-1 pt-1 pb-2 text-body-100\"\n >\n {label}\n </label>\n )}\n\n <SelectPrimitive.Root disabled={disabled} {...props}>\n <SelectPrimitive.Trigger\n ref={ref}\n id={triggerId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n aria-describedby={bottomText ? helperTextId : undefined}\n aria-invalid={error || undefined}\n className={cn(\n \"flex w-full cursor-pointer items-center justify-between rounded-xl border bg-neutral-100 outline-none motion-safe:transition-colors\",\n TRIGGER_HEIGHT[size],\n TRIGGER_PADDING_X[size],\n TRIGGER_GAP[size],\n TRIGGER_TYPOGRAPHY[size],\n error ? \"border-error-500\" : \"border-transparent\",\n !disabled &&\n !error &&\n \"hover:border-neutral-400 data-[state=open]:border-neutral-400\",\n disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n <div className=\"flex items-center gap-2\">\n {leftIcon && (\n <span\n className=\"flex size-5 shrink-0 items-center justify-center text-body-200\"\n data-testid=\"left-icon\"\n >\n {leftIcon}\n </span>\n )}\n <SelectPrimitive.Value\n placeholder={placeholder}\n className=\"min-w-0 flex-1 truncate text-left text-body-100 data-placeholder:text-body-200 data-placeholder:opacity-40\"\n />\n </div>\n\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n\n {children}\n </SelectPrimitive.Root>\n\n {bottomText && (\n <p\n id={helperTextId}\n className={cn(\n \"typography-caption-regular px-2 pt-1 pb-0.5\",\n error ? \"text-error-500\" : \"text-body-200\",\n )}\n >\n {bottomText}\n </p>\n )}\n </div>\n </SelectContext.Provider>\n );\n },\n);\n\nSelect.displayName = \"Select\";\n\nexport interface SelectContentProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> {}\n\n/**\n * The dropdown panel rendered inside a portal. Place {@link SelectItem} elements\n * (and optionally {@link SelectGroup} / {@link SelectLabel}) as children.\n */\nexport const SelectContent = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Content>,\n SelectContentProps\n>(({ className, children, position = \"popper\", sideOffset = 4, ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n position={position}\n sideOffset={sideOffset}\n className={cn(\n \"relative z-50 min-w-(--radix-select-trigger-width) overflow-hidden rounded-xl border border-neutral-200 bg-background-inverse-solid text-body-100 shadow-[0_4px_16px_rgba(0,0,0,0.10)]\",\n \"data-[state=closed]:animate-out data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n \"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.Viewport className=\"p-1\">{children}</SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n));\n\nSelectContent.displayName = \"SelectContent\";\n\nexport interface SelectItemProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> {}\n\n/**\n * An individual option inside {@link SelectContent}.\n */\nexport const SelectItem = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Item>,\n SelectItemProps\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n \"typography-body-1-regular relative flex w-full cursor-pointer select-none items-center gap-2 rounded-lg py-2 pr-2 pl-3 text-body-100 outline-none\",\n \"focus:bg-neutral-100 data-disabled:pointer-events-none data-disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator className=\"ml-auto flex size-4 shrink-0 items-center justify-center\">\n <CheckIcon className=\"size-4 text-body-100\" />\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n));\n\nSelectItem.displayName = \"SelectItem\";\n\n/** Props for {@link SelectGroup}. */\nexport type SelectGroupProps = React.ComponentPropsWithoutRef<typeof SelectPrimitive.Group>;\n\n/**\n * Groups related {@link SelectItem} elements under a {@link SelectLabel}.\n */\nexport const SelectGroup = SelectPrimitive.Group;\nSelectGroup.displayName = \"SelectGroup\";\n\nexport interface SelectLabelProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label> {}\n\n/**\n * A non-interactive label shown above a {@link SelectGroup}.\n */\nexport const SelectLabel = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Label>,\n SelectLabelProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\"typography-caption-semibold px-3 py-1.5 text-body-200\", className)}\n {...props}\n />\n));\n\nSelectLabel.displayName = \"SelectLabel\";\n\nexport interface SelectSeparatorProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator> {}\n\n/** A horizontal rule that visually separates groups in {@link SelectContent}. */\nexport const SelectSeparator = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Separator>,\n SelectSeparatorProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-neutral-200\", className)}\n {...props}\n />\n));\n\nSelectSeparator.displayName = \"SelectSeparator\";\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Select.mjs","sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["import * as SelectPrimitive from \"@radix-ui/react-select\";\nimport * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { CheckIcon } from \"../Icons/CheckIcon\";\nimport { ChevronDownIcon } from \"../Icons/ChevronDownIcon\";\n\n/** Select field height in pixels. */\nexport type SelectSize = \"48\" | \"40\" | \"32\";\n\ntype SelectContextValue = {\n size: SelectSize;\n error: boolean;\n disabled?: boolean;\n};\n\nconst SelectContext = React.createContext<SelectContextValue>({\n size: \"48\",\n error: false,\n});\n\nconst TRIGGER_HEIGHT: Record<SelectSize, string> = {\n \"48\": \"h-12\",\n \"40\": \"h-10\",\n \"32\": \"h-8\",\n};\n\nconst TRIGGER_PADDING_X: Record<SelectSize, string> = {\n \"48\": \"px-4\",\n \"40\": \"px-4\",\n \"32\": \"px-3\",\n};\n\nconst TRIGGER_GAP: Record<SelectSize, string> = {\n \"48\": \"gap-3\",\n \"40\": \"gap-3\",\n \"32\": \"gap-2\",\n};\n\nconst TRIGGER_TYPOGRAPHY: Record<SelectSize, string> = {\n \"48\": \"typography-body-1-regular\",\n \"40\": \"typography-body-1-regular\",\n \"32\": \"typography-body-2-regular\",\n};\n\nexport interface SelectProps extends Omit<SelectPrimitive.SelectProps, \"dir\"> {\n /** Label text displayed above the trigger. Also used as the accessible name. */\n label?: string;\n /** Accessible name applied directly to the trigger button when no visible `label` is provided. */\n \"aria-label\"?: string;\n /** ID of an external element that labels the trigger button. */\n \"aria-labelledby\"?: string;\n /** Helper text displayed below the trigger. Replaced by `errorMessage` when `error` is `true`. */\n helperText?: string;\n /** Height of the select field in pixels. @default \"48\" */\n size?: SelectSize;\n /** Whether the field is in an error state. @default false */\n error?: boolean;\n /** Error message displayed below the trigger. Shown instead of `helperText` when `error` is `true`. */\n errorMessage?: string;\n /** Placeholder shown when no value is selected. */\n placeholder?: string;\n /** Icon element displayed at the left side of the trigger. */\n leftIcon?: React.ReactNode;\n /** Whether the field stretches to fill its container width. @default false */\n fullWidth?: boolean;\n /** Wraps the `className` of the outermost container div. */\n className?: string;\n /** HTML `id` applied to the trigger button. Auto-generated if omitted. */\n id?: string;\n}\n\n/**\n * A select field with optional label, helper/error text, and an icon slot,\n * built on Radix UI Select for full accessibility and keyboard navigation.\n *\n * Pair with {@link SelectContent} and {@link SelectItem} to provide options.\n *\n * @example\n * ```tsx\n * <Select label=\"Country\" placeholder=\"Select a country\">\n * <SelectContent>\n * <SelectItem value=\"us\">United States</SelectItem>\n * <SelectItem value=\"uk\">United Kingdom</SelectItem>\n * </SelectContent>\n * </Select>\n * ```\n */\nexport const Select = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Trigger>,\n SelectProps\n>(\n (\n {\n label,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n placeholder,\n leftIcon,\n fullWidth = false,\n className,\n id,\n disabled,\n children,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n ...props\n },\n ref,\n ) => {\n const generatedId = React.useId();\n const triggerId = id ?? generatedId;\n const helperTextId = `${triggerId}-helper`;\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n return (\n <SelectContext.Provider value={{ size, error, disabled }}>\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={triggerId}\n className=\"typography-caption-semibold px-1 pt-1 pb-2 text-body-100\"\n >\n {label}\n </label>\n )}\n\n <SelectPrimitive.Root disabled={disabled} {...props}>\n <SelectPrimitive.Trigger\n ref={ref}\n id={triggerId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n aria-describedby={bottomText ? helperTextId : undefined}\n aria-invalid={error || undefined}\n className={cn(\n \"flex w-full cursor-pointer items-center justify-between rounded-xl border bg-neutral-100 outline-none motion-safe:transition-colors\",\n TRIGGER_HEIGHT[size],\n TRIGGER_PADDING_X[size],\n TRIGGER_GAP[size],\n TRIGGER_TYPOGRAPHY[size],\n error ? \"border-error-500\" : \"border-transparent\",\n !disabled &&\n !error &&\n \"hover:border-neutral-400 data-[state=open]:border-neutral-400\",\n disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n <div className=\"flex items-center gap-2\">\n {leftIcon && (\n <span\n className=\"flex size-5 shrink-0 items-center justify-center text-body-200\"\n data-testid=\"left-icon\"\n >\n {leftIcon}\n </span>\n )}\n <SelectPrimitive.Value\n placeholder={placeholder}\n className=\"min-w-0 flex-1 truncate text-left text-body-100 data-placeholder:text-body-200 data-placeholder:opacity-40\"\n />\n </div>\n\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n\n {children}\n </SelectPrimitive.Root>\n\n {bottomText && (\n <p\n id={helperTextId}\n className={cn(\n \"typography-caption-regular px-2 pt-1 pb-0.5\",\n error ? \"text-error-500\" : \"text-body-200\",\n )}\n >\n {bottomText}\n </p>\n )}\n </div>\n </SelectContext.Provider>\n );\n },\n);\n\nSelect.displayName = \"Select\";\n\nexport interface SelectContentProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content> {}\n\n/**\n * The dropdown panel rendered inside a portal. Place {@link SelectItem} elements\n * (and optionally {@link SelectGroup} / {@link SelectLabel}) as children.\n */\nexport const SelectContent = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Content>,\n SelectContentProps\n>(({ className, children, position = \"popper\", sideOffset = 4, style, ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n position={position}\n sideOffset={sideOffset}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"relative min-w-(--radix-select-trigger-width) overflow-hidden rounded-xl border border-neutral-200 bg-background-inverse-solid text-body-100 shadow-[0_4px_16px_rgba(0,0,0,0.10)]\",\n \"data-[state=closed]:animate-out data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n \"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.Viewport className=\"max-h-[var(--radix-select-content-available-height)] overflow-y-auto p-1\">\n {children}\n </SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n));\n\nSelectContent.displayName = \"SelectContent\";\n\nexport interface SelectItemProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> {}\n\n/**\n * An individual option inside {@link SelectContent}.\n */\nexport const SelectItem = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Item>,\n SelectItemProps\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n \"typography-body-1-regular relative flex w-full cursor-pointer select-none items-center gap-2 rounded-lg py-2 pr-2 pl-3 text-body-100 outline-none\",\n \"focus:bg-neutral-100 data-disabled:pointer-events-none data-disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator className=\"ml-auto flex size-4 shrink-0 items-center justify-center\">\n <CheckIcon className=\"size-4 text-body-100\" />\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n));\n\nSelectItem.displayName = \"SelectItem\";\n\n/** Props for {@link SelectGroup}. */\nexport type SelectGroupProps = React.ComponentPropsWithoutRef<typeof SelectPrimitive.Group>;\n\n/**\n * Groups related {@link SelectItem} elements under a {@link SelectLabel}.\n */\nexport const SelectGroup = SelectPrimitive.Group;\nSelectGroup.displayName = \"SelectGroup\";\n\nexport interface SelectLabelProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label> {}\n\n/**\n * A non-interactive label shown above a {@link SelectGroup}.\n */\nexport const SelectLabel = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Label>,\n SelectLabelProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\"typography-caption-semibold px-3 py-1.5 text-body-200\", className)}\n {...props}\n />\n));\n\nSelectLabel.displayName = \"SelectLabel\";\n\nexport interface SelectSeparatorProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator> {}\n\n/** A horizontal rule that visually separates groups in {@link SelectContent}. */\nexport const SelectSeparator = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Separator>,\n SelectSeparatorProps\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-neutral-200\", className)}\n {...props}\n />\n));\n\nSelectSeparator.displayName = \"SelectSeparator\";\n"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,7 @@ const TooltipContent = React.forwardRef(
|
|
|
20
20
|
secondaryAction,
|
|
21
21
|
children,
|
|
22
22
|
side,
|
|
23
|
+
style,
|
|
23
24
|
...props
|
|
24
25
|
}, ref) => {
|
|
25
26
|
const isInfobox = variant === "infobox";
|
|
@@ -30,8 +31,9 @@ const TooltipContent = React.forwardRef(
|
|
|
30
31
|
{
|
|
31
32
|
ref,
|
|
32
33
|
sideOffset,
|
|
34
|
+
style: { zIndex: "var(--fanvue-ui-portal-z-index, 50)", ...style },
|
|
33
35
|
className: cn(
|
|
34
|
-
"typography-body-2-regular
|
|
36
|
+
"typography-body-2-regular max-w-[320px] overflow-hidden rounded-3xl bg-background-solid p-4 text-background-inverse-solid shadow-[0px_2px_4px_0px_rgba(17,24,39,0.08)]",
|
|
35
37
|
isInfobox && "border border-neutral-200",
|
|
36
38
|
className
|
|
37
39
|
),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.mjs","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button/Button\";\n\n/** Props for the {@link TooltipProvider}. Wraps Radix `Tooltip.Provider`. */\nexport type TooltipProviderProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>;\n\n/** Provides tooltip delay and skip-delay context. Wrap your app or a subtree. */\nexport const TooltipProvider = TooltipPrimitive.Provider;\n\n/** Props for the {@link Tooltip} root component. */\nexport interface TooltipProps extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root> {\n /**\n * Controlled open state. When provided, the component is in controlled mode\n * and you must also supply `onOpenChange` to update the value.\n */\n open?: boolean;\n /** Called when the open state changes. Required when `open` is controlled. */\n onOpenChange?: (open: boolean) => void;\n /** The open state of the tooltip when it is initially rendered (uncontrolled). */\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for a single tooltip. */\nexport const Tooltip = TooltipPrimitive.Root;\n\n/** Props for the {@link TooltipTrigger} component. */\nexport type TooltipTriggerProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>;\n\n/** The element that triggers the tooltip on hover/focus. */\nexport const TooltipTrigger = TooltipPrimitive.Trigger;\n\n/**\n * Visual style variant of the tooltip content.\n *\n * - `\"tooltip\"` — simple text bubble, no border.\n * - `\"infobox\"` — richer card with a visible border, structured header, body text, and optional actions.\n */\nexport type TooltipContentVariant = \"tooltip\" | \"infobox\";\n\n/** Action button configuration for the infobox variant of {@link TooltipContent}. */\nexport interface TooltipAction {\n /** Button label. */\n label: string;\n /** Click handler. */\n onClick?: () => void;\n /**\n * Optional custom React node to be rendered for the action instead of the default button.\n * Only used in the infobox variant.\n */\n element?: React.ReactNode;\n}\n\nexport interface TooltipContentProps\n extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> {\n /**\n * Visual style variant.\n *\n * `\"tooltip\"` is a lightweight text bubble. `\"infobox\"` renders a structured card\n * with optional heading, icon, pill, body text, and action buttons.\n *\n * @default \"tooltip\"\n */\n variant?: TooltipContentVariant;\n /** Whether to show the directional arrow pointer. @default true */\n showArrow?: boolean;\n /**\n * Heading text rendered in subtitle style at the top of the infobox.\n * Infobox variant only.\n */\n heading?: React.ReactNode;\n /**\n * Icon element displayed to the left of the heading.\n * Infobox variant only.\n */\n icon?: React.ReactNode;\n /**\n * Pill or badge element displayed to the right of the heading.\n * Infobox variant only.\n */\n pill?: React.ReactNode;\n /**\n * Primary action button (brand green). Rendered below the body text.\n * Infobox variant only.\n */\n primaryAction?: TooltipAction;\n /**\n * Secondary action button (ghost). Rendered next to the primary action.\n * Infobox variant only.\n */\n secondaryAction?: TooltipAction;\n}\n\n/**\n * The popup content of the tooltip. Renders inside a portal.\n *\n * Arrow direction is controlled via the `side` and `align` props (Radix passthrough).\n *\n * @example\n * ```tsx\n * // Simple tooltip\n * <TooltipContent>Info text</TooltipContent>\n *\n * // Infobox with structured content\n * <TooltipContent\n * variant=\"infobox\"\n * heading=\"Title\"\n * icon={<InfoCircleIcon className=\"size-5\" />}\n * primaryAction={{ label: \"OK\", onClick: () => {} }}\n * secondaryAction={{ label: \"Dismiss\" }}\n * >\n * Info text\n * </TooltipContent>\n * ```\n */\nexport const TooltipContent = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Content>,\n TooltipContentProps\n>(\n (\n {\n className,\n variant = \"tooltip\",\n showArrow = true,\n sideOffset = 8,\n heading,\n icon,\n pill,\n primaryAction,\n secondaryAction,\n children,\n side,\n ...props\n },\n ref,\n ) => {\n const isInfobox = variant === \"infobox\";\n const hasHeader =\n isInfobox && (icon !== undefined || heading !== undefined || pill !== undefined);\n const hasActions = isInfobox && (primaryAction !== undefined || secondaryAction !== undefined);\n\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n \"typography-body-2-regular
|
|
1
|
+
{"version":3,"file":"Tooltip.mjs","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button/Button\";\n\n/** Props for the {@link TooltipProvider}. Wraps Radix `Tooltip.Provider`. */\nexport type TooltipProviderProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>;\n\n/** Provides tooltip delay and skip-delay context. Wrap your app or a subtree. */\nexport const TooltipProvider = TooltipPrimitive.Provider;\n\n/** Props for the {@link Tooltip} root component. */\nexport interface TooltipProps extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root> {\n /**\n * Controlled open state. When provided, the component is in controlled mode\n * and you must also supply `onOpenChange` to update the value.\n */\n open?: boolean;\n /** Called when the open state changes. Required when `open` is controlled. */\n onOpenChange?: (open: boolean) => void;\n /** The open state of the tooltip when it is initially rendered (uncontrolled). */\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for a single tooltip. */\nexport const Tooltip = TooltipPrimitive.Root;\n\n/** Props for the {@link TooltipTrigger} component. */\nexport type TooltipTriggerProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>;\n\n/** The element that triggers the tooltip on hover/focus. */\nexport const TooltipTrigger = TooltipPrimitive.Trigger;\n\n/**\n * Visual style variant of the tooltip content.\n *\n * - `\"tooltip\"` — simple text bubble, no border.\n * - `\"infobox\"` — richer card with a visible border, structured header, body text, and optional actions.\n */\nexport type TooltipContentVariant = \"tooltip\" | \"infobox\";\n\n/** Action button configuration for the infobox variant of {@link TooltipContent}. */\nexport interface TooltipAction {\n /** Button label. */\n label: string;\n /** Click handler. */\n onClick?: () => void;\n /**\n * Optional custom React node to be rendered for the action instead of the default button.\n * Only used in the infobox variant.\n */\n element?: React.ReactNode;\n}\n\nexport interface TooltipContentProps\n extends React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> {\n /**\n * Visual style variant.\n *\n * `\"tooltip\"` is a lightweight text bubble. `\"infobox\"` renders a structured card\n * with optional heading, icon, pill, body text, and action buttons.\n *\n * @default \"tooltip\"\n */\n variant?: TooltipContentVariant;\n /** Whether to show the directional arrow pointer. @default true */\n showArrow?: boolean;\n /**\n * Heading text rendered in subtitle style at the top of the infobox.\n * Infobox variant only.\n */\n heading?: React.ReactNode;\n /**\n * Icon element displayed to the left of the heading.\n * Infobox variant only.\n */\n icon?: React.ReactNode;\n /**\n * Pill or badge element displayed to the right of the heading.\n * Infobox variant only.\n */\n pill?: React.ReactNode;\n /**\n * Primary action button (brand green). Rendered below the body text.\n * Infobox variant only.\n */\n primaryAction?: TooltipAction;\n /**\n * Secondary action button (ghost). Rendered next to the primary action.\n * Infobox variant only.\n */\n secondaryAction?: TooltipAction;\n}\n\n/**\n * The popup content of the tooltip. Renders inside a portal.\n *\n * Arrow direction is controlled via the `side` and `align` props (Radix passthrough).\n *\n * @example\n * ```tsx\n * // Simple tooltip\n * <TooltipContent>Info text</TooltipContent>\n *\n * // Infobox with structured content\n * <TooltipContent\n * variant=\"infobox\"\n * heading=\"Title\"\n * icon={<InfoCircleIcon className=\"size-5\" />}\n * primaryAction={{ label: \"OK\", onClick: () => {} }}\n * secondaryAction={{ label: \"Dismiss\" }}\n * >\n * Info text\n * </TooltipContent>\n * ```\n */\nexport const TooltipContent = React.forwardRef<\n React.ComponentRef<typeof TooltipPrimitive.Content>,\n TooltipContentProps\n>(\n (\n {\n className,\n variant = \"tooltip\",\n showArrow = true,\n sideOffset = 8,\n heading,\n icon,\n pill,\n primaryAction,\n secondaryAction,\n children,\n side,\n style,\n ...props\n },\n ref,\n ) => {\n const isInfobox = variant === \"infobox\";\n const hasHeader =\n isInfobox && (icon !== undefined || heading !== undefined || pill !== undefined);\n const hasActions = isInfobox && (primaryAction !== undefined || secondaryAction !== undefined);\n\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n \"typography-body-2-regular max-w-[320px] overflow-hidden rounded-3xl bg-background-solid p-4 text-background-inverse-solid shadow-[0px_2px_4px_0px_rgba(17,24,39,0.08)]\",\n isInfobox && \"border border-neutral-200\",\n className,\n )}\n align=\"center\"\n arrowPadding={12}\n side={side}\n {...props}\n >\n {isInfobox ? (\n <div className=\"flex flex-col gap-3\">\n {hasHeader && (\n <div className=\"flex items-center gap-3\">\n {icon && <div className=\"size-5 shrink-0\">{icon}</div>}\n {heading && (\n <p className=\"typography-subtitle min-w-0 flex-1 text-background-inverse-solid\">\n {heading}\n </p>\n )}\n {pill && <div className=\"shrink-0\">{pill}</div>}\n </div>\n )}\n {children && (\n <div className=\"typography-body-2-regular text-background-inverse-solid\">\n {children}\n </div>\n )}\n {hasActions && (\n <div className=\"flex items-center gap-1\">\n {primaryAction &&\n (primaryAction.element ? (\n primaryAction.element\n ) : (\n <Button variant=\"brand\" size=\"32\" onClick={primaryAction.onClick}>\n {primaryAction.label}\n </Button>\n ))}\n {secondaryAction &&\n (secondaryAction.element ? (\n secondaryAction.element\n ) : (\n <Button variant=\"tertiary\" size=\"32\" onClick={secondaryAction.onClick}>\n {secondaryAction.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n ) : (\n children\n )}\n {showArrow && (\n <TooltipPrimitive.Arrow\n className={\"-translate-y-px! fill-background-solid stroke-2 stroke-background-solid\"}\n width={12}\n height={6}\n />\n )}\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n );\n },\n);\nTooltipContent.displayName = \"TooltipContent\";\n"],"names":[],"mappings":";;;;;;AASO,MAAM,kBAAkB,iBAAiB;AAgBzC,MAAM,UAAU,iBAAiB;AAMjC,MAAM,iBAAiB,iBAAiB;AAqFxC,MAAM,iBAAiB,MAAM;AAAA,EAIlC,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,YAAY,YAAY;AAC9B,UAAM,YACJ,cAAc,SAAS,UAAa,YAAY,UAAa,SAAS;AACxE,UAAM,aAAa,cAAc,kBAAkB,UAAa,oBAAoB;AAEpF,WACE,oBAAC,iBAAiB,QAAjB,EACC,UAAA;AAAA,MAAC,iBAAiB;AAAA,MAAjB;AAAA,QACC;AAAA,QACA;AAAA,QACA,OAAO,EAAE,QAAQ,uCAAuC,GAAG,MAAA;AAAA,QAC3D,WAAW;AAAA,UACT;AAAA,UACA,aAAa;AAAA,UACb;AAAA,QAAA;AAAA,QAEF,OAAM;AAAA,QACN,cAAc;AAAA,QACd;AAAA,QACC,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,YACC,qBAAC,OAAA,EAAI,WAAU,uBACZ,UAAA;AAAA,YAAA,aACC,qBAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,cAAA,QAAQ,oBAAC,OAAA,EAAI,WAAU,mBAAmB,UAAA,MAAK;AAAA,cAC/C,WACC,oBAAC,KAAA,EAAE,WAAU,oEACV,UAAA,SACH;AAAA,cAED,QAAQ,oBAAC,OAAA,EAAI,WAAU,YAAY,UAAA,KAAA,CAAK;AAAA,YAAA,GAC3C;AAAA,YAED,YACC,oBAAC,OAAA,EAAI,WAAU,2DACZ,UACH;AAAA,YAED,cACC,qBAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,cAAA,kBACE,cAAc,UACb,cAAc,8BAEb,QAAA,EAAO,SAAQ,SAAQ,MAAK,MAAK,SAAS,cAAc,SACtD,wBAAc,MAAA,CACjB;AAAA,cAEH,oBACE,gBAAgB,UACf,gBAAgB,UAEhB,oBAAC,QAAA,EAAO,SAAQ,YAAW,MAAK,MAAK,SAAS,gBAAgB,SAC3D,0BAAgB,OACnB;AAAA,YAAA,EAAA,CAEN;AAAA,UAAA,EAAA,CAEJ,IAEA;AAAA,UAED,aACC;AAAA,YAAC,iBAAiB;AAAA,YAAjB;AAAA,cACC,WAAW;AAAA,cACX,OAAO;AAAA,cACP,QAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,QACV;AAAA,MAAA;AAAA,IAAA,GAGN;AAAA,EAEJ;AACF;AACA,eAAe,cAAc;"}
|
package/dist/styles/theme.css
CHANGED
|
@@ -165,6 +165,11 @@
|
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
:root {
|
|
168
|
+
/* Stacking layer for portal-rendered overlays (Select, Tooltip).
|
|
169
|
+
Override to sit above high-z containers such as MUI Dialog:
|
|
170
|
+
:root { --fanvue-ui-portal-z-index: 1400; } */
|
|
171
|
+
--fanvue-ui-portal-z-index: 50;
|
|
172
|
+
|
|
168
173
|
--color-primary-50: #1515150a;
|
|
169
174
|
--color-primary-100: #15151533;
|
|
170
175
|
--color-primary-200: #15151566;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fanvue/ui",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.2",
|
|
4
4
|
"description": "React component library built with Tailwind CSS for Fanvue ecosystem",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org",
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
"react-dom": "19.2.3",
|
|
125
125
|
"remark-gfm": "4.0.1",
|
|
126
126
|
"size-limit": "12.0.0",
|
|
127
|
-
"storybook": "10.2.
|
|
127
|
+
"storybook": "10.2.13",
|
|
128
128
|
"style-dictionary": "4.2.0",
|
|
129
129
|
"tailwindcss": "4.1.18",
|
|
130
130
|
"typescript": "5.9.3",
|
|
@@ -137,8 +137,9 @@
|
|
|
137
137
|
"overrides": {
|
|
138
138
|
"@isaacs/brace-expansion": ">=5.0.1",
|
|
139
139
|
"qs": ">=6.14.2",
|
|
140
|
-
"minimatch": ">=10.2.
|
|
141
|
-
"rollup": ">=4.59.0"
|
|
140
|
+
"minimatch": ">=10.2.3",
|
|
141
|
+
"rollup": ">=4.59.0",
|
|
142
|
+
"storybook": ">=10.2.10"
|
|
142
143
|
}
|
|
143
144
|
},
|
|
144
145
|
"size-limit": [
|