@tangle-network/ui 11.17.0 → 11.20.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/CHANGELOG.md +23 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.js +10 -1
- package/dist/primitives/alert-dialog.d.ts +34 -0
- package/dist/primitives/alert-dialog.js +68 -0
- package/dist/primitives/checkbox.d.ts +12 -0
- package/dist/primitives/checkbox.js +34 -0
- package/dist/primitives/collapsible.d.ts +12 -0
- package/dist/primitives/collapsible.js +13 -0
- package/dist/primitives/context-menu.d.ts +36 -0
- package/dist/primitives/context-menu.js +86 -0
- package/dist/primitives/icon-tile.d.ts +6 -1
- package/dist/primitives/icon-tile.js +3 -1
- package/dist/primitives/popover.d.ts +15 -0
- package/dist/primitives/popover.js +25 -0
- package/dist/primitives/separator.d.ts +11 -0
- package/dist/primitives/separator.js +21 -0
- package/dist/primitives/sheet.d.ts +28 -0
- package/dist/primitives/sheet.js +70 -0
- package/dist/primitives/slider.d.ts +14 -0
- package/dist/primitives/slider.js +37 -0
- package/dist/primitives/theme-toggle.js +8 -0
- package/dist/primitives/tooltip.d.ts +16 -0
- package/dist/primitives/tooltip.js +32 -0
- package/dist/primitives.d.ts +10 -1
- package/dist/primitives.js +10 -1
- package/package.json +9 -2
- package/src/primitives/alert-dialog.tsx +139 -0
- package/src/primitives/checkbox-separator-sheet-tooltip.stories.tsx +92 -0
- package/src/primitives/checkbox-separator-sheet-tooltip.test.tsx +107 -0
- package/src/primitives/checkbox.tsx +42 -0
- package/src/primitives/collapsible.tsx +16 -0
- package/src/primitives/context-menu.tsx +168 -0
- package/src/primitives/icon-tile.stories.tsx +2 -2
- package/src/primitives/icon-tile.test.tsx +39 -0
- package/src/primitives/icon-tile.tsx +8 -1
- package/src/primitives/index.ts +57 -0
- package/src/primitives/popover-collapsible-alert-dialog-context-menu-slider.stories.tsx +124 -0
- package/src/primitives/popover-collapsible-alert-dialog-context-menu-slider.test.tsx +165 -0
- package/src/primitives/popover.tsx +45 -0
- package/src/primitives/separator.tsx +30 -0
- package/src/primitives/sheet.tsx +134 -0
- package/src/primitives/slider.tsx +71 -0
- package/src/primitives/theme-toggle.test.tsx +2 -1
- package/src/primitives/theme-toggle.tsx +2 -0
- package/src/primitives/tooltip.tsx +54 -0
- package/src/stories/theme-showcase.stories.tsx +2 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { focusRing } from "../lib/focus.js";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
import { cva } from "class-variance-authority";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import * as SheetPrimitive from "@radix-ui/react-dialog";
|
|
8
|
+
import { X } from "lucide-react";
|
|
9
|
+
//#region src/primitives/sheet.tsx
|
|
10
|
+
/** A dialog that slides in from an edge: a mobile nav drawer or a side panel. */
|
|
11
|
+
const Sheet = SheetPrimitive.Root;
|
|
12
|
+
const SheetTrigger = SheetPrimitive.Trigger;
|
|
13
|
+
const SheetClose = SheetPrimitive.Close;
|
|
14
|
+
const SheetPortal = SheetPrimitive.Portal;
|
|
15
|
+
const SheetOverlay = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Overlay, {
|
|
16
|
+
ref,
|
|
17
|
+
className: cn("fixed inset-0 z-50 bg-black/40", "data-[state=closed]:animate-out data-[state=open]:animate-in", "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", className),
|
|
18
|
+
...props
|
|
19
|
+
}));
|
|
20
|
+
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
|
21
|
+
const sheetVariants = cva([
|
|
22
|
+
"fixed z-50 flex flex-col gap-4 border-border bg-card shadow-lg",
|
|
23
|
+
"data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
24
|
+
"data-[state=closed]:duration-200 data-[state=open]:duration-300 ease-out motion-reduce:animate-none"
|
|
25
|
+
], {
|
|
26
|
+
variants: { side: {
|
|
27
|
+
right: "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
|
|
28
|
+
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
|
|
29
|
+
top: "inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
|
|
30
|
+
bottom: "inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom"
|
|
31
|
+
} },
|
|
32
|
+
defaultVariants: { side: "right" }
|
|
33
|
+
});
|
|
34
|
+
const SheetContent = React.forwardRef(({ className, children, side = "right", hideCloseButton = false, ...props }, ref) => /* @__PURE__ */ jsxs(SheetPortal, { children: [/* @__PURE__ */ jsx(SheetOverlay, {}), /* @__PURE__ */ jsxs(SheetPrimitive.Content, {
|
|
35
|
+
ref,
|
|
36
|
+
className: cn(sheetVariants({ side }), className),
|
|
37
|
+
...props,
|
|
38
|
+
children: [children, !hideCloseButton && /* @__PURE__ */ jsxs(SheetPrimitive.Close, {
|
|
39
|
+
className: cn("absolute top-4 right-4 rounded-sm text-muted-foreground opacity-70 transition-[opacity,box-shadow] hover:opacity-100 focus-visible:opacity-100 disabled:pointer-events-none", focusRing),
|
|
40
|
+
children: [/* @__PURE__ */ jsx(X, { className: "size-4" }), /* @__PURE__ */ jsx("span", {
|
|
41
|
+
className: "sr-only",
|
|
42
|
+
children: "Close"
|
|
43
|
+
})]
|
|
44
|
+
})]
|
|
45
|
+
})] }));
|
|
46
|
+
SheetContent.displayName = SheetPrimitive.Content.displayName;
|
|
47
|
+
const SheetHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
48
|
+
className: cn("flex flex-col gap-1.5 p-4 pr-10", className),
|
|
49
|
+
...props
|
|
50
|
+
});
|
|
51
|
+
SheetHeader.displayName = "SheetHeader";
|
|
52
|
+
const SheetFooter = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
53
|
+
className: cn("mt-auto flex flex-col gap-2 p-4", className),
|
|
54
|
+
...props
|
|
55
|
+
});
|
|
56
|
+
SheetFooter.displayName = "SheetFooter";
|
|
57
|
+
const SheetTitle = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Title, {
|
|
58
|
+
ref,
|
|
59
|
+
className: cn("font-semibold text-base text-foreground leading-tight", className),
|
|
60
|
+
...props
|
|
61
|
+
}));
|
|
62
|
+
SheetTitle.displayName = SheetPrimitive.Title.displayName;
|
|
63
|
+
const SheetDescription = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Description, {
|
|
64
|
+
ref,
|
|
65
|
+
className: cn("text-muted-foreground text-sm", className),
|
|
66
|
+
...props
|
|
67
|
+
}));
|
|
68
|
+
SheetDescription.displayName = SheetPrimitive.Description.displayName;
|
|
69
|
+
//#endregion
|
|
70
|
+
export { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as SliderPrimitive from "@radix-ui/react-slider";
|
|
3
|
+
//#region src/primitives/slider.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Range input with one thumb per value. A single value renders one thumb; an
|
|
6
|
+
* array of two renders a range. The thumbs are what assistive technology
|
|
7
|
+
* focuses, so the names go on them: `aria-label` / `aria-labelledby` name a
|
|
8
|
+
* single thumb, and `thumbLabels` names each thumb of a range.
|
|
9
|
+
*/
|
|
10
|
+
declare const Slider: React.ForwardRefExoticComponent<Omit<SliderPrimitive.SliderProps & React.RefAttributes<HTMLSpanElement>, "ref"> & {
|
|
11
|
+
thumbLabels?: string[];
|
|
12
|
+
} & React.RefAttributes<HTMLSpanElement>>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { Slider };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { focusRing } from "../lib/focus.js";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import * as SliderPrimitive from "@radix-ui/react-slider";
|
|
7
|
+
//#region src/primitives/slider.tsx
|
|
8
|
+
/**
|
|
9
|
+
* Range input with one thumb per value. A single value renders one thumb; an
|
|
10
|
+
* array of two renders a range. The thumbs are what assistive technology
|
|
11
|
+
* focuses, so the names go on them: `aria-label` / `aria-labelledby` name a
|
|
12
|
+
* single thumb, and `thumbLabels` names each thumb of a range.
|
|
13
|
+
*/
|
|
14
|
+
const Slider = React.forwardRef(({ className, defaultValue, value, min = 0, max = 100, thumbLabels, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }, ref) => {
|
|
15
|
+
const values = Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min];
|
|
16
|
+
const single = values.length === 1;
|
|
17
|
+
return /* @__PURE__ */ jsxs(SliderPrimitive.Root, {
|
|
18
|
+
ref,
|
|
19
|
+
defaultValue,
|
|
20
|
+
value,
|
|
21
|
+
min,
|
|
22
|
+
max,
|
|
23
|
+
className: cn("relative flex w-full touch-none select-none items-center data-[disabled]:opacity-50", "data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col", className),
|
|
24
|
+
...props,
|
|
25
|
+
children: [/* @__PURE__ */ jsx(SliderPrimitive.Track, {
|
|
26
|
+
className: "relative grow overflow-hidden rounded-full bg-muted data-[orientation=horizontal]:h-1.5 data-[orientation=vertical]:h-full data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-1.5",
|
|
27
|
+
children: /* @__PURE__ */ jsx(SliderPrimitive.Range, { className: "absolute bg-primary data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full" })
|
|
28
|
+
}), values.map((_, index) => /* @__PURE__ */ jsx(SliderPrimitive.Thumb, {
|
|
29
|
+
"aria-label": thumbLabels?.[index] ?? (single ? ariaLabel : void 0),
|
|
30
|
+
"aria-labelledby": single && !thumbLabels?.[index] ? ariaLabelledBy : void 0,
|
|
31
|
+
className: cn("block size-4 shrink-0 rounded-full border border-primary bg-background shadow-sm transition-[box-shadow] disabled:pointer-events-none", focusRing)
|
|
32
|
+
}, index))]
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
Slider.displayName = SliderPrimitive.Root.displayName;
|
|
36
|
+
//#endregion
|
|
37
|
+
export { Slider };
|
|
@@ -12,9 +12,17 @@ const namedModes = [
|
|
|
12
12
|
dark: "arena",
|
|
13
13
|
light: "arena-light"
|
|
14
14
|
},
|
|
15
|
+
{
|
|
16
|
+
dark: "super",
|
|
17
|
+
light: "super-light"
|
|
18
|
+
},
|
|
15
19
|
{
|
|
16
20
|
dark: "tangle-dark",
|
|
17
21
|
light: "tangle-light"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
dark: "agents",
|
|
25
|
+
light: "agents-light"
|
|
18
26
|
}
|
|
19
27
|
];
|
|
20
28
|
let preference;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
3
|
+
//#region src/primitives/tooltip.d.ts
|
|
4
|
+
declare function TooltipProvider({ delayDuration, skipDelayDuration, ...props }: React.ComponentProps<typeof TooltipPrimitive.Provider>): React.JSX.Element;
|
|
5
|
+
declare namespace TooltipProvider {
|
|
6
|
+
var displayName: string;
|
|
7
|
+
}
|
|
8
|
+
declare const Tooltip: React.FC<TooltipPrimitive.TooltipProps>;
|
|
9
|
+
declare const TooltipTrigger: React.ForwardRefExoticComponent<TooltipPrimitive.TooltipTriggerProps & React.RefAttributes<HTMLButtonElement>>;
|
|
10
|
+
/**
|
|
11
|
+
* Inverse-surface label for a control whose name is otherwise only an icon.
|
|
12
|
+
* It is supplementary: the trigger still needs its own accessible name.
|
|
13
|
+
*/
|
|
14
|
+
declare const TooltipContent: React.ForwardRefExoticComponent<Omit<TooltipPrimitive.TooltipContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
6
|
+
//#region src/primitives/tooltip.tsx
|
|
7
|
+
/**
|
|
8
|
+
* Wrap an app (or a toolbar) once. The open delay applies to the first tooltip;
|
|
9
|
+
* moving between triggers inside `skipDelayDuration` opens the next one at
|
|
10
|
+
* once, which keeps an icon rail fast to scan.
|
|
11
|
+
*/
|
|
12
|
+
const TooltipProvider = ({ delayDuration = 400, skipDelayDuration = 300, ...props }) => /* @__PURE__ */ jsx(TooltipPrimitive.Provider, {
|
|
13
|
+
delayDuration,
|
|
14
|
+
skipDelayDuration,
|
|
15
|
+
...props
|
|
16
|
+
});
|
|
17
|
+
TooltipProvider.displayName = "TooltipProvider";
|
|
18
|
+
const Tooltip = TooltipPrimitive.Root;
|
|
19
|
+
const TooltipTrigger = TooltipPrimitive.Trigger;
|
|
20
|
+
/**
|
|
21
|
+
* Inverse-surface label for a control whose name is otherwise only an icon.
|
|
22
|
+
* It is supplementary: the trigger still needs its own accessible name.
|
|
23
|
+
*/
|
|
24
|
+
const TooltipContent = React.forwardRef(({ className, sideOffset = 6, ...props }, ref) => /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(TooltipPrimitive.Content, {
|
|
25
|
+
ref,
|
|
26
|
+
sideOffset,
|
|
27
|
+
className: cn("z-50 max-w-xs origin-(--radix-tooltip-content-transform-origin) rounded-md bg-foreground px-2.5 py-1.5 text-background text-xs leading-snug shadow-md", "data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95", "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", "duration-150 ease-out motion-reduce:animate-none", className),
|
|
28
|
+
...props
|
|
29
|
+
}) }));
|
|
30
|
+
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
|
package/dist/primitives.d.ts
CHANGED
|
@@ -2,6 +2,11 @@ import { Button, ButtonProps, buttonVariants } from "./primitives/button.js";
|
|
|
2
2
|
import { ArtifactPane, ArtifactPaneProps } from "./primitives/artifact-pane.js";
|
|
3
3
|
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CardTitleProps } from "./primitives/card.js";
|
|
4
4
|
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from "./primitives/dialog.js";
|
|
5
|
+
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger } from "./primitives/alert-dialog.js";
|
|
6
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./primitives/collapsible.js";
|
|
7
|
+
import { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger } from "./primitives/context-menu.js";
|
|
8
|
+
import { Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger } from "./primitives/popover.js";
|
|
9
|
+
import { Slider } from "./primitives/slider.js";
|
|
5
10
|
import { Input, InputProps, Textarea, TextareaProps } from "./primitives/input.js";
|
|
6
11
|
import { Badge, BadgeProps, badgeVariants } from "./primitives/badge.js";
|
|
7
12
|
import { Avatar, AvatarFallback, AvatarImage } from "./primitives/avatar.js";
|
|
@@ -12,6 +17,10 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "./primitives/tabs.js";
|
|
|
12
17
|
import { SegmentedControl, SegmentedControlOption, SegmentedControlProps } from "./primitives/segmented-control.js";
|
|
13
18
|
import { Progress } from "./primitives/progress.js";
|
|
14
19
|
import { Switch } from "./primitives/switch.js";
|
|
20
|
+
import { Checkbox } from "./primitives/checkbox.js";
|
|
21
|
+
import { Separator } from "./primitives/separator.js";
|
|
22
|
+
import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger } from "./primitives/sheet.js";
|
|
23
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./primitives/tooltip.js";
|
|
15
24
|
import { Skeleton, SkeletonCard, SkeletonTable } from "./primitives/skeleton.js";
|
|
16
25
|
import { TextShimmer, TextShimmerProps } from "./primitives/text-shimmer.js";
|
|
17
26
|
import { Toast, ToastContainer, ToastProvider, useToast } from "./primitives/toast.js";
|
|
@@ -36,4 +45,4 @@ import { IconTile, IconTileProps, initialsOf } from "./primitives/icon-tile.js";
|
|
|
36
45
|
import { Metric, MetricProps, MetricStrip, MetricStripProps } from "./primitives/metric-strip.js";
|
|
37
46
|
import { FilterField, FilterFieldProps, Toolbar, ToolbarProps } from "./primitives/toolbar.js";
|
|
38
47
|
import { Logo, LogoProps, TangleKnot } from "@tangle-network/brand";
|
|
39
|
-
export { ArtifactPane, type ArtifactPaneProps, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, Button, type ButtonProps, CATEGORY_TONES, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, type CardTitleProps, type CategoryTone, Chip, type ChipProps, CodeBlock, type CodeBlockProps, CopyButton, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropZone, type DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, FilterField, type FilterFieldProps, Heading, type HeadingProps, type HeadingVariant, IconTile, type IconTileProps, InlineCode, type InlineCodeProps, Input, type InputProps, Label, Logo, type LogoProps, Metric, type MetricProps, MetricStrip, type MetricStripProps, PageHeader, type PageHeaderProps, PageShell, type PageShellProps, Progress, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SidebarDropZone, type SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, StatCard, type StatCardProps, StatusPill, type StatusPillProps, type StatusTone, Switch, TONE_CLASSES, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, type TableProps, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, type TagProps, TangleKnot, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, TextShimmer, type TextShimmerProps, Textarea, type TextareaProps, ThemeToggle, type Toast, ToastContainer, ToastProvider, type Tone, type ToneClasses, Toolbar, type ToolbarProps, type UploadFile, UploadProgress, type UploadProgressProps, badgeVariants, buttonVariants, initialsOf, toneFor, useTheme, useToast };
|
|
48
|
+
export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, ArtifactPane, type ArtifactPaneProps, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, Button, type ButtonProps, CATEGORY_TONES, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, type CardTitleProps, type CategoryTone, Checkbox, Chip, type ChipProps, CodeBlock, type CodeBlockProps, Collapsible, CollapsibleContent, CollapsibleTrigger, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropZone, type DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, FilterField, type FilterFieldProps, Heading, type HeadingProps, type HeadingVariant, IconTile, type IconTileProps, InlineCode, type InlineCodeProps, Input, type InputProps, Label, Logo, type LogoProps, Metric, type MetricProps, MetricStrip, type MetricStripProps, PageHeader, type PageHeaderProps, PageShell, type PageShellProps, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarDropZone, type SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, Slider, StatCard, type StatCardProps, StatusPill, type StatusPillProps, type StatusTone, Switch, TONE_CLASSES, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, type TableProps, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, type TagProps, TangleKnot, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, TextShimmer, type TextShimmerProps, Textarea, type TextareaProps, ThemeToggle, type Toast, ToastContainer, ToastProvider, type Tone, type ToneClasses, Toolbar, type ToolbarProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UploadFile, UploadProgress, type UploadProgressProps, badgeVariants, buttonVariants, initialsOf, toneFor, useTheme, useToast };
|
package/dist/primitives.js
CHANGED
|
@@ -2,6 +2,11 @@ import { Button, buttonVariants } from "./primitives/button.js";
|
|
|
2
2
|
import { Heading } from "./primitives/heading.js";
|
|
3
3
|
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "./primitives/card.js";
|
|
4
4
|
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from "./primitives/dialog.js";
|
|
5
|
+
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger } from "./primitives/alert-dialog.js";
|
|
6
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./primitives/collapsible.js";
|
|
7
|
+
import { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger } from "./primitives/context-menu.js";
|
|
8
|
+
import { Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger } from "./primitives/popover.js";
|
|
9
|
+
import { Slider } from "./primitives/slider.js";
|
|
5
10
|
import { Label } from "./primitives/label.js";
|
|
6
11
|
import { Input, Textarea } from "./primitives/input.js";
|
|
7
12
|
import { Badge, badgeVariants } from "./primitives/badge.js";
|
|
@@ -13,6 +18,10 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "./primitives/tabs.js";
|
|
|
13
18
|
import { SegmentedControl } from "./primitives/segmented-control.js";
|
|
14
19
|
import { Progress } from "./primitives/progress.js";
|
|
15
20
|
import { Switch } from "./primitives/switch.js";
|
|
21
|
+
import { Checkbox } from "./primitives/checkbox.js";
|
|
22
|
+
import { Separator } from "./primitives/separator.js";
|
|
23
|
+
import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger } from "./primitives/sheet.js";
|
|
24
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./primitives/tooltip.js";
|
|
16
25
|
import { Skeleton, SkeletonCard, SkeletonTable } from "./primitives/skeleton.js";
|
|
17
26
|
import { TextShimmer } from "./primitives/text-shimmer.js";
|
|
18
27
|
import { ToastContainer, ToastProvider, useToast } from "./primitives/toast.js";
|
|
@@ -36,4 +45,4 @@ import { IconTile, initialsOf } from "./primitives/icon-tile.js";
|
|
|
36
45
|
import { Metric, MetricStrip } from "./primitives/metric-strip.js";
|
|
37
46
|
import { FilterField, Toolbar } from "./primitives/toolbar.js";
|
|
38
47
|
import { Logo, TangleKnot } from "@tangle-network/brand";
|
|
39
|
-
export { ArtifactPane, Avatar, AvatarFallback, AvatarImage, Badge, Button, CATEGORY_TONES, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Chip, CodeBlock, CopyButton, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropZone, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, FilterField, Heading, IconTile, InlineCode, Input, Label, Logo, Metric, MetricStrip, PageHeader, PageShell, Progress, SegmentedControl, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SidebarDropZone, Skeleton, SkeletonCard, SkeletonTable, StatCard, StatusPill, Switch, TONE_CLASSES, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, TangleKnot, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, TextShimmer, Textarea, ThemeToggle, ToastContainer, ToastProvider, Toolbar, UploadProgress, badgeVariants, buttonVariants, initialsOf, toneFor, useTheme, useToast };
|
|
48
|
+
export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, ArtifactPane, Avatar, AvatarFallback, AvatarImage, Badge, Button, CATEGORY_TONES, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Chip, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropZone, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, FilterField, Heading, IconTile, InlineCode, Input, Label, Logo, Metric, MetricStrip, PageHeader, PageShell, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, SegmentedControl, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarDropZone, Skeleton, SkeletonCard, SkeletonTable, Slider, StatCard, StatusPill, Switch, TONE_CLASSES, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tag, TangleKnot, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, TextShimmer, Textarea, ThemeToggle, ToastContainer, ToastProvider, Toolbar, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UploadProgress, badgeVariants, buttonVariants, initialsOf, toneFor, useTheme, useToast };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/ui",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.20.0",
|
|
4
4
|
"description": "Generic React UI components for Tangle products — primitives, chat, run, files, editor, markdown.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -116,16 +116,23 @@
|
|
|
116
116
|
"dependencies": {
|
|
117
117
|
"@pierre/theme": "1.1.0",
|
|
118
118
|
"@pierre/trees": "1.0.0-beta.6",
|
|
119
|
+
"@radix-ui/react-alert-dialog": "^1.1.23",
|
|
119
120
|
"@radix-ui/react-avatar": "^1.2.6",
|
|
121
|
+
"@radix-ui/react-checkbox": "^1.3.11",
|
|
120
122
|
"@radix-ui/react-collapsible": "^1.1.20",
|
|
123
|
+
"@radix-ui/react-context-menu": "^2.3.7",
|
|
121
124
|
"@radix-ui/react-dialog": "^1.1.23",
|
|
122
125
|
"@radix-ui/react-dropdown-menu": "^2.1.24",
|
|
123
126
|
"@radix-ui/react-label": "^2.1.15",
|
|
127
|
+
"@radix-ui/react-popover": "^1.1.23",
|
|
124
128
|
"@radix-ui/react-progress": "^1.1.16",
|
|
125
129
|
"@radix-ui/react-select": "^2.3.7",
|
|
130
|
+
"@radix-ui/react-separator": "^1.1.15",
|
|
131
|
+
"@radix-ui/react-slider": "^1.4.7",
|
|
126
132
|
"@radix-ui/react-slot": "^1.3.3",
|
|
127
133
|
"@radix-ui/react-switch": "^1.3.7",
|
|
128
134
|
"@radix-ui/react-tabs": "^1.1.21",
|
|
135
|
+
"@radix-ui/react-tooltip": "^1.2.16",
|
|
129
136
|
"class-variance-authority": "^0.7.1",
|
|
130
137
|
"clsx": "^2.1.1",
|
|
131
138
|
"github-slugger": "^2.0.0",
|
|
@@ -142,7 +149,7 @@
|
|
|
142
149
|
"peerDependencies": {
|
|
143
150
|
"@hocuspocus/provider": ">=2.15.0 <5.0.0",
|
|
144
151
|
"@nanostores/react": ">=0.8.4 <3.0.0",
|
|
145
|
-
"@tangle-network/brand": "^1.
|
|
152
|
+
"@tangle-network/brand": "^1.15.1",
|
|
146
153
|
"@tiptap/core": ">=3.20.4 <4.0.0",
|
|
147
154
|
"@tiptap/extension-collaboration": ">=3.20.4 <4.0.0",
|
|
148
155
|
"@tiptap/extension-collaboration-caret": ">=3.7.0 <4.0.0",
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { cn } from "../lib/utils";
|
|
6
|
+
import { buttonVariants } from "./button";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A dialog that interrupts for a decision. Unlike `Dialog` it has no close
|
|
10
|
+
* button and ignores outside clicks; Escape and `AlertDialogCancel` dismiss it.
|
|
11
|
+
* Radix focuses `AlertDialogCancel` on open, so a destructive action is never
|
|
12
|
+
* under the Enter key when the dialog appears.
|
|
13
|
+
*/
|
|
14
|
+
const AlertDialog = AlertDialogPrimitive.Root;
|
|
15
|
+
|
|
16
|
+
const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
|
|
17
|
+
|
|
18
|
+
const AlertDialogPortal = AlertDialogPrimitive.Portal;
|
|
19
|
+
|
|
20
|
+
const AlertDialogOverlay = React.forwardRef<
|
|
21
|
+
React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
|
|
22
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
|
|
23
|
+
>(({ className, ...props }, ref) => (
|
|
24
|
+
<AlertDialogPrimitive.Overlay
|
|
25
|
+
ref={ref}
|
|
26
|
+
className={cn(
|
|
27
|
+
"fixed inset-0 z-50 bg-black/40",
|
|
28
|
+
"data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
29
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
30
|
+
className,
|
|
31
|
+
)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
));
|
|
35
|
+
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
|
|
36
|
+
|
|
37
|
+
const AlertDialogContent = React.forwardRef<
|
|
38
|
+
React.ElementRef<typeof AlertDialogPrimitive.Content>,
|
|
39
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
|
|
40
|
+
>(({ className, ...props }, ref) => (
|
|
41
|
+
<AlertDialogPortal>
|
|
42
|
+
<AlertDialogOverlay />
|
|
43
|
+
<AlertDialogPrimitive.Content
|
|
44
|
+
ref={ref}
|
|
45
|
+
className={cn(
|
|
46
|
+
"fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] sm:max-w-lg",
|
|
47
|
+
"gap-4 rounded-lg border border-border bg-card p-6 text-foreground shadow-lg duration-200 outline-hidden",
|
|
48
|
+
"data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
49
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
50
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
51
|
+
"motion-reduce:animate-none",
|
|
52
|
+
className,
|
|
53
|
+
)}
|
|
54
|
+
{...props}
|
|
55
|
+
/>
|
|
56
|
+
</AlertDialogPortal>
|
|
57
|
+
));
|
|
58
|
+
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
|
|
59
|
+
|
|
60
|
+
const AlertDialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
|
61
|
+
<div className={cn("flex flex-col gap-2 text-center sm:text-left", className)} {...props} />
|
|
62
|
+
);
|
|
63
|
+
AlertDialogHeader.displayName = "AlertDialogHeader";
|
|
64
|
+
|
|
65
|
+
const AlertDialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
|
66
|
+
<div
|
|
67
|
+
className={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
|
|
68
|
+
{...props}
|
|
69
|
+
/>
|
|
70
|
+
);
|
|
71
|
+
AlertDialogFooter.displayName = "AlertDialogFooter";
|
|
72
|
+
|
|
73
|
+
const AlertDialogTitle = React.forwardRef<
|
|
74
|
+
React.ElementRef<typeof AlertDialogPrimitive.Title>,
|
|
75
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
|
|
76
|
+
>(({ className, ...props }, ref) => (
|
|
77
|
+
<AlertDialogPrimitive.Title
|
|
78
|
+
ref={ref}
|
|
79
|
+
className={cn("font-semibold text-lg leading-snug [overflow-wrap:anywhere]", className)}
|
|
80
|
+
{...props}
|
|
81
|
+
/>
|
|
82
|
+
));
|
|
83
|
+
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
|
|
84
|
+
|
|
85
|
+
const AlertDialogDescription = React.forwardRef<
|
|
86
|
+
React.ElementRef<typeof AlertDialogPrimitive.Description>,
|
|
87
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
|
|
88
|
+
>(({ className, ...props }, ref) => (
|
|
89
|
+
<AlertDialogPrimitive.Description
|
|
90
|
+
ref={ref}
|
|
91
|
+
className={cn("text-muted-foreground text-sm [overflow-wrap:anywhere]", className)}
|
|
92
|
+
{...props}
|
|
93
|
+
/>
|
|
94
|
+
));
|
|
95
|
+
AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* The confirming action. `tone="destructive"` paints it with the danger fill;
|
|
99
|
+
* the default is the primary button.
|
|
100
|
+
*/
|
|
101
|
+
const AlertDialogAction = React.forwardRef<
|
|
102
|
+
React.ElementRef<typeof AlertDialogPrimitive.Action>,
|
|
103
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action> & {
|
|
104
|
+
tone?: "default" | "destructive";
|
|
105
|
+
}
|
|
106
|
+
>(({ className, tone = "default", ...props }, ref) => (
|
|
107
|
+
<AlertDialogPrimitive.Action
|
|
108
|
+
ref={ref}
|
|
109
|
+
className={cn(buttonVariants({ variant: tone === "destructive" ? "destructive" : "default" }), className)}
|
|
110
|
+
{...props}
|
|
111
|
+
/>
|
|
112
|
+
));
|
|
113
|
+
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
|
|
114
|
+
|
|
115
|
+
const AlertDialogCancel = React.forwardRef<
|
|
116
|
+
React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
|
|
117
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
|
|
118
|
+
>(({ className, ...props }, ref) => (
|
|
119
|
+
<AlertDialogPrimitive.Cancel
|
|
120
|
+
ref={ref}
|
|
121
|
+
className={cn(buttonVariants({ variant: "outline" }), className)}
|
|
122
|
+
{...props}
|
|
123
|
+
/>
|
|
124
|
+
));
|
|
125
|
+
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
|
|
126
|
+
|
|
127
|
+
export {
|
|
128
|
+
AlertDialog,
|
|
129
|
+
AlertDialogAction,
|
|
130
|
+
AlertDialogCancel,
|
|
131
|
+
AlertDialogContent,
|
|
132
|
+
AlertDialogDescription,
|
|
133
|
+
AlertDialogFooter,
|
|
134
|
+
AlertDialogHeader,
|
|
135
|
+
AlertDialogOverlay,
|
|
136
|
+
AlertDialogPortal,
|
|
137
|
+
AlertDialogTitle,
|
|
138
|
+
AlertDialogTrigger,
|
|
139
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { Info } from 'lucide-react'
|
|
3
|
+
import { Button } from './button'
|
|
4
|
+
import { Checkbox } from './checkbox'
|
|
5
|
+
import { Label } from './label'
|
|
6
|
+
import { Separator } from './separator'
|
|
7
|
+
import { Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from './sheet'
|
|
8
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './tooltip'
|
|
9
|
+
|
|
10
|
+
const meta: Meta = {
|
|
11
|
+
title: 'Primitives/Checkbox, Separator, Sheet, Tooltip',
|
|
12
|
+
parameters: { layout: 'centered' },
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default meta
|
|
16
|
+
type Story = StoryObj
|
|
17
|
+
|
|
18
|
+
export const Checkboxes: Story = {
|
|
19
|
+
render: () => (
|
|
20
|
+
<div className="flex flex-col gap-3">
|
|
21
|
+
{[
|
|
22
|
+
{ id: 'a', label: 'Record a video of every run', checked: true },
|
|
23
|
+
{ id: 'b', label: 'Retry failed steps once', checked: false },
|
|
24
|
+
{ id: 'c', label: 'Select every suite in this workspace', checked: 'indeterminate' as const },
|
|
25
|
+
{ id: 'd', label: 'Disabled until billing is set up', checked: false, disabled: true },
|
|
26
|
+
].map((row) => (
|
|
27
|
+
<div key={row.id} className="flex items-center gap-2">
|
|
28
|
+
<Checkbox id={row.id} defaultChecked={row.checked} disabled={row.disabled} />
|
|
29
|
+
<Label htmlFor={row.id}>{row.label}</Label>
|
|
30
|
+
</div>
|
|
31
|
+
))}
|
|
32
|
+
</div>
|
|
33
|
+
),
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const Separators: Story = {
|
|
37
|
+
render: () => (
|
|
38
|
+
<div className="w-72 text-sm">
|
|
39
|
+
<p>Account</p>
|
|
40
|
+
<Separator className="my-3" />
|
|
41
|
+
<div className="flex h-5 items-center gap-3">
|
|
42
|
+
<span>Runs</span>
|
|
43
|
+
<Separator orientation="vertical" />
|
|
44
|
+
<span>Suites</span>
|
|
45
|
+
<Separator orientation="vertical" />
|
|
46
|
+
<span>Settings</span>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
),
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const Sheets: Story = {
|
|
53
|
+
render: () => (
|
|
54
|
+
<div className="flex gap-2">
|
|
55
|
+
{(['left', 'right', 'bottom'] as const).map((side) => (
|
|
56
|
+
<Sheet key={side}>
|
|
57
|
+
<SheetTrigger asChild>
|
|
58
|
+
<Button variant="outline">Open {side}</Button>
|
|
59
|
+
</SheetTrigger>
|
|
60
|
+
<SheetContent side={side}>
|
|
61
|
+
<SheetHeader>
|
|
62
|
+
<SheetTitle>Run assistant</SheetTitle>
|
|
63
|
+
<SheetDescription>Ask why a step failed or what to test next.</SheetDescription>
|
|
64
|
+
</SheetHeader>
|
|
65
|
+
<SheetFooter>
|
|
66
|
+
<Button>Send</Button>
|
|
67
|
+
</SheetFooter>
|
|
68
|
+
</SheetContent>
|
|
69
|
+
</Sheet>
|
|
70
|
+
))}
|
|
71
|
+
</div>
|
|
72
|
+
),
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const Tooltips: Story = {
|
|
76
|
+
render: () => (
|
|
77
|
+
<TooltipProvider>
|
|
78
|
+
<div className="flex gap-2">
|
|
79
|
+
{['Runs', 'Test suites', 'A much longer label that wraps at the maximum tooltip width'].map((label) => (
|
|
80
|
+
<Tooltip key={label}>
|
|
81
|
+
<TooltipTrigger asChild>
|
|
82
|
+
<Button size="icon" variant="ghost" aria-label={label}>
|
|
83
|
+
<Info className="size-4" />
|
|
84
|
+
</Button>
|
|
85
|
+
</TooltipTrigger>
|
|
86
|
+
<TooltipContent>{label}</TooltipContent>
|
|
87
|
+
</Tooltip>
|
|
88
|
+
))}
|
|
89
|
+
</div>
|
|
90
|
+
</TooltipProvider>
|
|
91
|
+
),
|
|
92
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
2
|
+
import userEvent from "@testing-library/user-event";
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
|
+
import { Checkbox } from "./checkbox";
|
|
5
|
+
import { Label } from "./label";
|
|
6
|
+
import { Separator } from "./separator";
|
|
7
|
+
import { Sheet, SheetContent, SheetDescription, SheetTitle, SheetTrigger } from "./sheet";
|
|
8
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./tooltip";
|
|
9
|
+
|
|
10
|
+
describe("Checkbox", () => {
|
|
11
|
+
it("toggles from its label and exposes checkbox state", () => {
|
|
12
|
+
render(
|
|
13
|
+
<>
|
|
14
|
+
<Checkbox id="notify" />
|
|
15
|
+
<Label htmlFor="notify">Email me</Label>
|
|
16
|
+
</>,
|
|
17
|
+
);
|
|
18
|
+
const box = screen.getByRole("checkbox", { name: "Email me" });
|
|
19
|
+
expect(box).toHaveAttribute("aria-checked", "false");
|
|
20
|
+
fireEvent.click(screen.getByText("Email me"));
|
|
21
|
+
expect(box).toHaveAttribute("aria-checked", "true");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("reports the indeterminate state as mixed", () => {
|
|
25
|
+
render(<Checkbox aria-label="Select all" checked="indeterminate" />);
|
|
26
|
+
expect(screen.getByRole("checkbox", { name: "Select all" })).toHaveAttribute(
|
|
27
|
+
"aria-checked",
|
|
28
|
+
"mixed",
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("draws the dash for an uncontrolled indeterminate box too", () => {
|
|
33
|
+
const { container } = render(<Checkbox aria-label="Some" defaultChecked="indeterminate" />);
|
|
34
|
+
expect(screen.getByRole("checkbox")).toHaveAttribute("aria-checked", "mixed");
|
|
35
|
+
const dash = container.querySelector("svg.lucide-minus");
|
|
36
|
+
const tick = container.querySelector("svg.lucide-check");
|
|
37
|
+
expect(dash?.getAttribute("class")).toContain("group-data-[state=indeterminate]/checkbox:block");
|
|
38
|
+
expect(tick?.getAttribute("class")).toContain("group-data-[state=indeterminate]/checkbox:hidden");
|
|
39
|
+
expect(screen.getByRole("checkbox")).toHaveAttribute("data-state", "indeterminate");
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("paints with tokens, never palette utilities", () => {
|
|
43
|
+
render(<Checkbox aria-label="Agree" defaultChecked />);
|
|
44
|
+
const cls = screen.getByRole("checkbox").className;
|
|
45
|
+
expect(cls).toContain("data-[state=checked]:bg-primary");
|
|
46
|
+
expect(cls).not.toMatch(/\b(?:bg|text|border)-(?:slate|zinc|gray|neutral|blue|green|red|amber|emerald)-\d/);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe("Separator", () => {
|
|
51
|
+
it("is hidden from assistive technology unless it is semantic", () => {
|
|
52
|
+
const { container, rerender } = render(<Separator />);
|
|
53
|
+
expect(container.firstElementChild).toHaveAttribute("role", "none");
|
|
54
|
+
rerender(<Separator decorative={false} orientation="vertical" />);
|
|
55
|
+
const rule = screen.getByRole("separator");
|
|
56
|
+
expect(rule).toHaveAttribute("aria-orientation", "vertical");
|
|
57
|
+
expect(rule.className).toContain("w-px");
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("Sheet", () => {
|
|
62
|
+
it("opens as a labelled dialog and closes from its close button", async () => {
|
|
63
|
+
render(
|
|
64
|
+
<Sheet>
|
|
65
|
+
<SheetTrigger>Open chat</SheetTrigger>
|
|
66
|
+
<SheetContent side="left">
|
|
67
|
+
<SheetTitle>Assistant</SheetTitle>
|
|
68
|
+
<SheetDescription>Ask about this run.</SheetDescription>
|
|
69
|
+
</SheetContent>
|
|
70
|
+
</Sheet>,
|
|
71
|
+
);
|
|
72
|
+
fireEvent.click(screen.getByText("Open chat"));
|
|
73
|
+
const dialog = await screen.findByRole("dialog", { name: "Assistant" });
|
|
74
|
+
expect(dialog.className).toContain("slide-in-from-left");
|
|
75
|
+
fireEvent.click(screen.getByRole("button", { name: "Close" }));
|
|
76
|
+
await waitFor(() => expect(screen.queryByRole("dialog")).not.toBeInTheDocument());
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("can hide its close button", async () => {
|
|
80
|
+
render(
|
|
81
|
+
<Sheet defaultOpen>
|
|
82
|
+
<SheetContent hideCloseButton>
|
|
83
|
+
<SheetTitle>Filters</SheetTitle>
|
|
84
|
+
<SheetDescription>Narrow the list.</SheetDescription>
|
|
85
|
+
</SheetContent>
|
|
86
|
+
</Sheet>,
|
|
87
|
+
);
|
|
88
|
+
await screen.findByRole("dialog", { name: "Filters" });
|
|
89
|
+
expect(screen.queryByRole("button", { name: "Close" })).not.toBeInTheDocument();
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe("Tooltip", () => {
|
|
94
|
+
it("shows its label when the trigger receives keyboard focus", async () => {
|
|
95
|
+
const user = userEvent.setup();
|
|
96
|
+
render(
|
|
97
|
+
<TooltipProvider delayDuration={0}>
|
|
98
|
+
<Tooltip>
|
|
99
|
+
<TooltipTrigger aria-label="Runs">R</TooltipTrigger>
|
|
100
|
+
<TooltipContent>Runs</TooltipContent>
|
|
101
|
+
</Tooltip>
|
|
102
|
+
</TooltipProvider>,
|
|
103
|
+
);
|
|
104
|
+
await user.tab();
|
|
105
|
+
expect(await screen.findByRole("tooltip")).toHaveTextContent("Runs");
|
|
106
|
+
});
|
|
107
|
+
});
|