@syscore/ui-library 1.1.10 → 1.1.12
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/client/App.tsx +47 -0
- package/client/components/icons/ConceptIcons.tsx +667 -0
- package/client/components/icons/NavAccount.tsx +31 -0
- package/client/components/icons/NavBullet.tsx +19 -0
- package/client/components/icons/NavLogo.tsx +36 -0
- package/client/components/icons/ProviderBadges.tsx +295 -0
- package/client/components/icons/ProviderSeals.tsx +319 -0
- package/client/components/icons/SealHealthSafetyRating.tsx +65 -0
- package/client/components/icons/SealIwbiMember.tsx +86 -0
- package/client/components/icons/SealWell.tsx +84 -0
- package/client/components/icons/SealWellCertification.tsx +138 -0
- package/client/components/icons/SealWellCommunity.tsx +122 -0
- package/client/components/icons/SealWellResidence.tsx +122 -0
- package/client/components/icons/SealWorksWithWell.tsx +140 -0
- package/client/components/icons/UtilityAccordion.tsx +21 -0
- package/client/components/icons/UtilityChevronDown.tsx +36 -0
- package/client/components/icons/UtilityClassification.tsx +45 -0
- package/client/components/icons/UtilityClose.tsx +41 -0
- package/client/components/icons/UtilityDrag.tsx +69 -0
- package/client/components/icons/UtilityEdit.tsx +42 -0
- package/client/components/icons/UtilityOptions.tsx +45 -0
- package/client/components/icons/UtilityPortfolio.tsx +87 -0
- package/client/components/icons/UtilityReset.tsx +41 -0
- package/client/components/icons/UtilityScoring.tsx +43 -0
- package/client/components/icons/UtilitySearch.tsx +38 -0
- package/client/components/icons/UtilitySort.tsx +52 -0
- package/client/components/icons/UtilityText.tsx +34 -0
- package/client/components/icons/WaterMarkWWWProducts.tsx +26 -0
- package/client/components/icons/WaterMarkWellProjects.tsx +30 -0
- package/client/components/icons/WatermarkMemberOrg.tsx +59 -0
- package/client/components/icons/WellSeal.tsx +79 -0
- package/client/components/icons/X.tsx +35 -0
- package/client/hooks/UseTabs.tsx +35 -0
- package/client/hooks/use-mobile.tsx +21 -0
- package/client/hooks/use-segmented-control.ts +42 -0
- package/client/hooks/use-toast.ts +188 -0
- package/client/pages/Index.tsx +88 -0
- package/client/pages/NotFound.tsx +29 -0
- package/client/ui/Accordion/Accordion.stories.tsx +74 -0
- package/client/ui/Alert/Alert.stories.tsx +82 -0
- package/client/ui/AlertDialog/AlertDialog.stories.tsx +106 -0
- package/client/ui/AspectRatio.stories.tsx +78 -0
- package/client/ui/Avatar/Avatar.stories.tsx +94 -0
- package/client/ui/Badge/Badge.stories.tsx +60 -0
- package/client/ui/Breadcrumb/Breadcrumb.stories.tsx +97 -0
- package/client/ui/Button.stories.tsx +429 -0
- package/client/ui/Calendar/Calendar.stories.tsx +99 -0
- package/client/ui/Card.stories.tsx +84 -0
- package/client/ui/Carousel/Carousel.stories.tsx +85 -0
- package/client/ui/Chart/Chart.stories.tsx +58 -0
- package/client/ui/Checkbox/Checkbox.stories.tsx +112 -0
- package/client/ui/Collapsible/Collapsible.stories.tsx +101 -0
- package/client/ui/Colors.stories.tsx +1041 -0
- package/client/ui/Command/Command.stories.tsx +97 -0
- package/client/ui/ContextMenu/ContextMenu.stories.tsx +74 -0
- package/client/ui/Dialog.stories.tsx +69 -0
- package/client/ui/Drawer/Drawer.stories.tsx +87 -0
- package/client/ui/DropdownMenu/DropdownMenu.stories.tsx +139 -0
- package/client/ui/Form/Form.stories.tsx +74 -0
- package/client/ui/HoverCard/HoverCard.stories.tsx +94 -0
- package/client/ui/Icons.stories.tsx +328 -0
- package/client/ui/Input/Input.stories.tsx +69 -0
- package/client/ui/InputOTP/InputOTP.stories.tsx +85 -0
- package/client/ui/Label.stories.tsx +66 -0
- package/client/ui/Menubar/Menubar.stories.tsx +88 -0
- package/client/ui/Navigation.stories.tsx +57 -0
- package/client/ui/NavigationMenu/NavigationMenu.stories.tsx +106 -0
- package/client/ui/Pagination/Pagination.stories.tsx +115 -0
- package/client/ui/Popover/Popover.stories.tsx +99 -0
- package/client/ui/Progress/Progress.stories.tsx +63 -0
- package/client/ui/RadioGroup/RadioGroup.stories.tsx +110 -0
- package/client/ui/Resizable/Resizable.stories.tsx +88 -0
- package/client/ui/ScrollArea/ScrollArea.stories.tsx +64 -0
- package/client/ui/SearchField.stories.tsx +63 -0
- package/client/ui/Select/Select.stories.tsx +111 -0
- package/client/ui/Separator/Separator.stories.tsx +67 -0
- package/client/ui/Sheet/Sheet.stories.tsx +138 -0
- package/client/ui/Sidebar/Sidebar.stories.tsx +92 -0
- package/client/ui/Skeleton/Skeleton.stories.tsx +65 -0
- package/client/ui/Slider/Slider.stories.tsx +101 -0
- package/client/ui/Sonner/Sonner.stories.tsx +48 -0
- package/client/ui/StrategyTable.stories.tsx +138 -0
- package/client/ui/Switch/Switch.stories.tsx +96 -0
- package/client/ui/Table/Table.stories.tsx +135 -0
- package/client/ui/Tabs.stories.tsx +33 -0
- package/client/ui/Tag.stories.tsx +190 -0
- package/client/ui/Textarea/Textarea.stories.tsx +56 -0
- package/client/ui/Toast/Toast.stories.tsx +76 -0
- package/client/ui/Toaster/Toaster.stories.tsx +52 -0
- package/client/ui/Toggle.stories.tsx +248 -0
- package/client/ui/ToggleGroup/ToggleGroup.stories.tsx +88 -0
- package/client/ui/Tooltip.stories.tsx +72 -0
- package/client/ui/Typography.stories.tsx +421 -0
- package/client/ui/WELLDashboard/WELLDashboard.stories.tsx +115 -0
- package/client/ui/WELLDashboard/index.tsx +317 -0
- package/client/vite-env.d.ts +1 -0
- package/dist/ui/index.cjs.js +1 -1
- package/dist/ui/index.d.ts +10 -1
- package/dist/ui/index.es.js +2233 -447
- package/package.json +2 -1
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import {
|
|
3
|
+
Command,
|
|
4
|
+
CommandDialog,
|
|
5
|
+
CommandEmpty,
|
|
6
|
+
CommandGroup,
|
|
7
|
+
CommandInput,
|
|
8
|
+
CommandItem,
|
|
9
|
+
CommandList,
|
|
10
|
+
CommandSeparator,
|
|
11
|
+
} from "../../components/ui/command";
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
import { Search, FileText, Settings, Users } from "lucide-react";
|
|
14
|
+
|
|
15
|
+
const meta = {
|
|
16
|
+
title: "UI/Command",
|
|
17
|
+
component: Command,
|
|
18
|
+
tags: ["autodocs"],
|
|
19
|
+
parameters: {
|
|
20
|
+
layout: "padded",
|
|
21
|
+
},
|
|
22
|
+
} satisfies Meta<typeof Command>;
|
|
23
|
+
|
|
24
|
+
export default meta;
|
|
25
|
+
|
|
26
|
+
type Story = StoryObj<typeof meta>;
|
|
27
|
+
|
|
28
|
+
export const Default: Story = {
|
|
29
|
+
render: () => (
|
|
30
|
+
<Command className="rounded-lg border w-full max-w-sm">
|
|
31
|
+
<CommandInput placeholder="Type a command or search..." />
|
|
32
|
+
<CommandList>
|
|
33
|
+
<CommandEmpty>No results found.</CommandEmpty>
|
|
34
|
+
<CommandGroup heading="Suggestions">
|
|
35
|
+
<CommandItem>
|
|
36
|
+
<Search className="mr-2 h-4 w-4" />
|
|
37
|
+
<span>Search</span>
|
|
38
|
+
</CommandItem>
|
|
39
|
+
<CommandItem>
|
|
40
|
+
<FileText className="mr-2 h-4 w-4" />
|
|
41
|
+
<span>Create New</span>
|
|
42
|
+
</CommandItem>
|
|
43
|
+
</CommandGroup>
|
|
44
|
+
<CommandSeparator />
|
|
45
|
+
<CommandGroup heading="Settings">
|
|
46
|
+
<CommandItem>
|
|
47
|
+
<Settings className="mr-2 h-4 w-4" />
|
|
48
|
+
<span>Preferences</span>
|
|
49
|
+
</CommandItem>
|
|
50
|
+
<CommandItem>
|
|
51
|
+
<Users className="mr-2 h-4 w-4" />
|
|
52
|
+
<span>Team</span>
|
|
53
|
+
</CommandItem>
|
|
54
|
+
</CommandGroup>
|
|
55
|
+
</CommandList>
|
|
56
|
+
</Command>
|
|
57
|
+
),
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const Dialog: Story = {
|
|
61
|
+
render: () => {
|
|
62
|
+
const [open, setOpen] = useState(false);
|
|
63
|
+
return (
|
|
64
|
+
<>
|
|
65
|
+
<button
|
|
66
|
+
onClick={() => setOpen(true)}
|
|
67
|
+
className="inline-flex items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium ring-offset-background transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
|
|
68
|
+
>
|
|
69
|
+
Open Command Menu
|
|
70
|
+
</button>
|
|
71
|
+
<CommandDialog open={open} onOpenChange={setOpen}>
|
|
72
|
+
<CommandInput placeholder="Type a command or search..." />
|
|
73
|
+
<CommandList>
|
|
74
|
+
<CommandEmpty>No results found.</CommandEmpty>
|
|
75
|
+
<CommandGroup heading="Actions">
|
|
76
|
+
<CommandItem>
|
|
77
|
+
<Search className="mr-2 h-4 w-4" />
|
|
78
|
+
<span>Search</span>
|
|
79
|
+
</CommandItem>
|
|
80
|
+
<CommandItem>
|
|
81
|
+
<FileText className="mr-2 h-4 w-4" />
|
|
82
|
+
<span>Create Document</span>
|
|
83
|
+
</CommandItem>
|
|
84
|
+
</CommandGroup>
|
|
85
|
+
<CommandSeparator />
|
|
86
|
+
<CommandGroup heading="Settings">
|
|
87
|
+
<CommandItem>
|
|
88
|
+
<Settings className="mr-2 h-4 w-4" />
|
|
89
|
+
<span>Settings</span>
|
|
90
|
+
</CommandItem>
|
|
91
|
+
</CommandGroup>
|
|
92
|
+
</CommandList>
|
|
93
|
+
</CommandDialog>
|
|
94
|
+
</>
|
|
95
|
+
);
|
|
96
|
+
},
|
|
97
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import {
|
|
3
|
+
ContextMenu,
|
|
4
|
+
ContextMenuTrigger,
|
|
5
|
+
ContextMenuContent,
|
|
6
|
+
ContextMenuItem,
|
|
7
|
+
ContextMenuSeparator,
|
|
8
|
+
ContextMenuCheckboxItem,
|
|
9
|
+
} from "../../components/ui/context-menu";
|
|
10
|
+
import { useState } from "react";
|
|
11
|
+
|
|
12
|
+
type Story = StoryObj;
|
|
13
|
+
|
|
14
|
+
const meta = {
|
|
15
|
+
title: "UI/ContextMenu",
|
|
16
|
+
tags: ["autodocs"],
|
|
17
|
+
parameters: {
|
|
18
|
+
layout: "padded",
|
|
19
|
+
},
|
|
20
|
+
} satisfies Meta;
|
|
21
|
+
|
|
22
|
+
export default meta;
|
|
23
|
+
|
|
24
|
+
export const Default: Story = {
|
|
25
|
+
render: () => (
|
|
26
|
+
<ContextMenu>
|
|
27
|
+
<ContextMenuTrigger className="flex h-40 w-40 items-center justify-center rounded-md border border-dashed text-sm text-gray-600">
|
|
28
|
+
Right click here
|
|
29
|
+
</ContextMenuTrigger>
|
|
30
|
+
<ContextMenuContent>
|
|
31
|
+
<ContextMenuItem>Back</ContextMenuItem>
|
|
32
|
+
<ContextMenuItem>Forward</ContextMenuItem>
|
|
33
|
+
<ContextMenuSeparator />
|
|
34
|
+
<ContextMenuItem>Reload</ContextMenuItem>
|
|
35
|
+
<ContextMenuSeparator />
|
|
36
|
+
<ContextMenuItem>View Page Source</ContextMenuItem>
|
|
37
|
+
</ContextMenuContent>
|
|
38
|
+
</ContextMenu>
|
|
39
|
+
),
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const WithCheckboxes: Story = {
|
|
43
|
+
render: () => {
|
|
44
|
+
const [items, setItems] = useState({
|
|
45
|
+
showImages: true,
|
|
46
|
+
enableJavaScript: true,
|
|
47
|
+
});
|
|
48
|
+
return (
|
|
49
|
+
<ContextMenu>
|
|
50
|
+
<ContextMenuTrigger className="flex h-40 w-40 items-center justify-center rounded-md border border-dashed text-sm text-gray-600">
|
|
51
|
+
Right click here
|
|
52
|
+
</ContextMenuTrigger>
|
|
53
|
+
<ContextMenuContent>
|
|
54
|
+
<ContextMenuCheckboxItem
|
|
55
|
+
checked={items.showImages}
|
|
56
|
+
onCheckedChange={(checked) =>
|
|
57
|
+
setItems({ ...items, showImages: checked })
|
|
58
|
+
}
|
|
59
|
+
>
|
|
60
|
+
Show Images
|
|
61
|
+
</ContextMenuCheckboxItem>
|
|
62
|
+
<ContextMenuCheckboxItem
|
|
63
|
+
checked={items.enableJavaScript}
|
|
64
|
+
onCheckedChange={(checked) =>
|
|
65
|
+
setItems({ ...items, enableJavaScript: checked })
|
|
66
|
+
}
|
|
67
|
+
>
|
|
68
|
+
Enable JavaScript
|
|
69
|
+
</ContextMenuCheckboxItem>
|
|
70
|
+
</ContextMenuContent>
|
|
71
|
+
</ContextMenu>
|
|
72
|
+
);
|
|
73
|
+
},
|
|
74
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Button } from "@/components/ui/Button";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import {
|
|
5
|
+
Dialog,
|
|
6
|
+
DialogContent,
|
|
7
|
+
DialogDescription,
|
|
8
|
+
DialogHeader,
|
|
9
|
+
DialogTitle,
|
|
10
|
+
DialogTrigger,
|
|
11
|
+
} from "@/components/ui/dialog";
|
|
12
|
+
import { cn } from "@/lib/utils";
|
|
13
|
+
|
|
14
|
+
const meta = {
|
|
15
|
+
title: "Review/Dialog",
|
|
16
|
+
component: Dialog,
|
|
17
|
+
tags: ["autodocs"],
|
|
18
|
+
parameters: {
|
|
19
|
+
layout: "centered",
|
|
20
|
+
},
|
|
21
|
+
} satisfies Meta<typeof Dialog>;
|
|
22
|
+
|
|
23
|
+
export default meta;
|
|
24
|
+
|
|
25
|
+
type Story = StoryObj<typeof meta>;
|
|
26
|
+
|
|
27
|
+
export const Default: Story = {
|
|
28
|
+
render: () => {
|
|
29
|
+
const [open, setOpen] = useState(false);
|
|
30
|
+
return (
|
|
31
|
+
<>
|
|
32
|
+
<Dialog open={open}>
|
|
33
|
+
<DialogTrigger asChild>
|
|
34
|
+
<Button
|
|
35
|
+
size="large"
|
|
36
|
+
variant="general-primary"
|
|
37
|
+
onClick={() => setOpen(true)}
|
|
38
|
+
>
|
|
39
|
+
Open Dialog
|
|
40
|
+
</Button>
|
|
41
|
+
</DialogTrigger>
|
|
42
|
+
<DialogContent className="sm:min-w-[297px]" showCloseButton={false}>
|
|
43
|
+
<DialogHeader>
|
|
44
|
+
<DialogTitle className="text-gray-800 text-center mb-8 h-8 justify-center items-center flex">
|
|
45
|
+
Are you sure?
|
|
46
|
+
</DialogTitle>
|
|
47
|
+
</DialogHeader>
|
|
48
|
+
<div className="flex gap-4 justify-center items-center">
|
|
49
|
+
<Button
|
|
50
|
+
size="utility"
|
|
51
|
+
variant="general-secondary"
|
|
52
|
+
onClick={() => setOpen(false)}
|
|
53
|
+
>
|
|
54
|
+
Nevermind
|
|
55
|
+
</Button>
|
|
56
|
+
<Button
|
|
57
|
+
size="utility"
|
|
58
|
+
variant="general-primary"
|
|
59
|
+
onClick={() => setOpen(false)}
|
|
60
|
+
>
|
|
61
|
+
Yes
|
|
62
|
+
</Button>
|
|
63
|
+
</div>
|
|
64
|
+
</DialogContent>
|
|
65
|
+
</Dialog>
|
|
66
|
+
</>
|
|
67
|
+
);
|
|
68
|
+
},
|
|
69
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import {
|
|
3
|
+
Drawer,
|
|
4
|
+
DrawerTrigger,
|
|
5
|
+
DrawerContent,
|
|
6
|
+
DrawerHeader,
|
|
7
|
+
DrawerTitle,
|
|
8
|
+
DrawerDescription,
|
|
9
|
+
DrawerFooter,
|
|
10
|
+
DrawerClose,
|
|
11
|
+
} from "../../components/ui/drawer";
|
|
12
|
+
import { Button } from "../../components/ui/button";
|
|
13
|
+
import { useState } from "react";
|
|
14
|
+
|
|
15
|
+
const meta = {
|
|
16
|
+
title: "UI/Drawer",
|
|
17
|
+
component: Drawer,
|
|
18
|
+
tags: ["autodocs"],
|
|
19
|
+
parameters: {
|
|
20
|
+
layout: "centered",
|
|
21
|
+
},
|
|
22
|
+
} satisfies Meta<typeof Drawer>;
|
|
23
|
+
|
|
24
|
+
export default meta;
|
|
25
|
+
|
|
26
|
+
type Story = StoryObj<typeof meta>;
|
|
27
|
+
|
|
28
|
+
export const Default: Story = {
|
|
29
|
+
render: () => {
|
|
30
|
+
const [open, setOpen] = useState(false);
|
|
31
|
+
return (
|
|
32
|
+
<Drawer open={open} onOpenChange={setOpen}>
|
|
33
|
+
<DrawerTrigger asChild>
|
|
34
|
+
<Button>Open Drawer</Button>
|
|
35
|
+
</DrawerTrigger>
|
|
36
|
+
<DrawerContent>
|
|
37
|
+
<DrawerHeader>
|
|
38
|
+
<DrawerTitle>Drawer Title</DrawerTitle>
|
|
39
|
+
<DrawerDescription>This is a drawer component.</DrawerDescription>
|
|
40
|
+
</DrawerHeader>
|
|
41
|
+
<div className="p-4">
|
|
42
|
+
<p className="text-sm">Drawer content goes here.</p>
|
|
43
|
+
</div>
|
|
44
|
+
<DrawerFooter>
|
|
45
|
+
<Button onClick={() => setOpen(false)}>Close</Button>
|
|
46
|
+
</DrawerFooter>
|
|
47
|
+
</DrawerContent>
|
|
48
|
+
</Drawer>
|
|
49
|
+
);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const Bottom: Story = {
|
|
54
|
+
render: () => {
|
|
55
|
+
const [open, setOpen] = useState(false);
|
|
56
|
+
return (
|
|
57
|
+
<Drawer open={open} onOpenChange={setOpen}>
|
|
58
|
+
<DrawerTrigger asChild>
|
|
59
|
+
<Button>Open Bottom Drawer</Button>
|
|
60
|
+
</DrawerTrigger>
|
|
61
|
+
<DrawerContent>
|
|
62
|
+
<div className="mx-auto w-full max-w-sm">
|
|
63
|
+
<DrawerHeader>
|
|
64
|
+
<DrawerTitle>Share</DrawerTitle>
|
|
65
|
+
</DrawerHeader>
|
|
66
|
+
<div className="p-4 space-y-2">
|
|
67
|
+
<button className="w-full px-4 py-2 text-left text-sm hover:bg-gray-100 rounded">
|
|
68
|
+
Copy Link
|
|
69
|
+
</button>
|
|
70
|
+
<button className="w-full px-4 py-2 text-left text-sm hover:bg-gray-100 rounded">
|
|
71
|
+
Share to Twitter
|
|
72
|
+
</button>
|
|
73
|
+
<button className="w-full px-4 py-2 text-left text-sm hover:bg-gray-100 rounded">
|
|
74
|
+
Share to Facebook
|
|
75
|
+
</button>
|
|
76
|
+
</div>
|
|
77
|
+
<DrawerFooter>
|
|
78
|
+
<DrawerClose asChild>
|
|
79
|
+
<Button variant="outline">Cancel</Button>
|
|
80
|
+
</DrawerClose>
|
|
81
|
+
</DrawerFooter>
|
|
82
|
+
</div>
|
|
83
|
+
</DrawerContent>
|
|
84
|
+
</Drawer>
|
|
85
|
+
);
|
|
86
|
+
},
|
|
87
|
+
};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import {
|
|
3
|
+
DropdownMenu,
|
|
4
|
+
DropdownMenuTrigger,
|
|
5
|
+
DropdownMenuContent,
|
|
6
|
+
DropdownMenuItem,
|
|
7
|
+
DropdownMenuSeparator,
|
|
8
|
+
DropdownMenuCheckboxItem,
|
|
9
|
+
DropdownMenuRadioGroup,
|
|
10
|
+
DropdownMenuRadioItem,
|
|
11
|
+
} from "../../components/ui/dropdown-menu";
|
|
12
|
+
import { Button } from "../../components/ui/button";
|
|
13
|
+
import { ChevronDown } from "lucide-react";
|
|
14
|
+
import { useState } from "react";
|
|
15
|
+
|
|
16
|
+
const meta = {
|
|
17
|
+
title: "UI/DropdownMenu",
|
|
18
|
+
component: DropdownMenu,
|
|
19
|
+
tags: ["autodocs"],
|
|
20
|
+
parameters: {
|
|
21
|
+
layout: "padded",
|
|
22
|
+
},
|
|
23
|
+
} satisfies Meta<typeof DropdownMenu>;
|
|
24
|
+
|
|
25
|
+
export default meta;
|
|
26
|
+
|
|
27
|
+
type Story = StoryObj<typeof meta>;
|
|
28
|
+
|
|
29
|
+
export const Default: Story = {
|
|
30
|
+
render: () => (
|
|
31
|
+
<DropdownMenu>
|
|
32
|
+
<DropdownMenuTrigger asChild>
|
|
33
|
+
<Button variant="outline">
|
|
34
|
+
Open Menu
|
|
35
|
+
<ChevronDown className="ml-2 h-4 w-4" />
|
|
36
|
+
</Button>
|
|
37
|
+
</DropdownMenuTrigger>
|
|
38
|
+
<DropdownMenuContent align="end" className="w-56">
|
|
39
|
+
<DropdownMenuItem>Profile</DropdownMenuItem>
|
|
40
|
+
<DropdownMenuItem>Settings</DropdownMenuItem>
|
|
41
|
+
<DropdownMenuSeparator />
|
|
42
|
+
<DropdownMenuItem>Sign Out</DropdownMenuItem>
|
|
43
|
+
</DropdownMenuContent>
|
|
44
|
+
</DropdownMenu>
|
|
45
|
+
),
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const WithCheckboxes: Story = {
|
|
49
|
+
render: () => {
|
|
50
|
+
const [items, setItems] = useState({
|
|
51
|
+
bold: false,
|
|
52
|
+
italic: false,
|
|
53
|
+
underline: false,
|
|
54
|
+
});
|
|
55
|
+
return (
|
|
56
|
+
<DropdownMenu>
|
|
57
|
+
<DropdownMenuTrigger asChild>
|
|
58
|
+
<Button variant="outline">Text Options</Button>
|
|
59
|
+
</DropdownMenuTrigger>
|
|
60
|
+
<DropdownMenuContent className="w-56">
|
|
61
|
+
<DropdownMenuCheckboxItem
|
|
62
|
+
checked={items.bold}
|
|
63
|
+
onCheckedChange={(checked) => setItems({ ...items, bold: checked })}
|
|
64
|
+
>
|
|
65
|
+
Bold
|
|
66
|
+
</DropdownMenuCheckboxItem>
|
|
67
|
+
<DropdownMenuCheckboxItem
|
|
68
|
+
checked={items.italic}
|
|
69
|
+
onCheckedChange={(checked) =>
|
|
70
|
+
setItems({ ...items, italic: checked })
|
|
71
|
+
}
|
|
72
|
+
>
|
|
73
|
+
Italic
|
|
74
|
+
</DropdownMenuCheckboxItem>
|
|
75
|
+
<DropdownMenuCheckboxItem
|
|
76
|
+
checked={items.underline}
|
|
77
|
+
onCheckedChange={(checked) =>
|
|
78
|
+
setItems({ ...items, underline: checked })
|
|
79
|
+
}
|
|
80
|
+
>
|
|
81
|
+
Underline
|
|
82
|
+
</DropdownMenuCheckboxItem>
|
|
83
|
+
</DropdownMenuContent>
|
|
84
|
+
</DropdownMenu>
|
|
85
|
+
);
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const WithRadio: Story = {
|
|
90
|
+
render: () => {
|
|
91
|
+
const [theme, setTheme] = useState("light");
|
|
92
|
+
return (
|
|
93
|
+
<DropdownMenu>
|
|
94
|
+
<DropdownMenuTrigger asChild>
|
|
95
|
+
<Button variant="outline">Theme</Button>
|
|
96
|
+
</DropdownMenuTrigger>
|
|
97
|
+
<DropdownMenuContent className="w-56">
|
|
98
|
+
<DropdownMenuRadioGroup value={theme} onValueChange={setTheme}>
|
|
99
|
+
<DropdownMenuRadioItem value="light">Light</DropdownMenuRadioItem>
|
|
100
|
+
<DropdownMenuRadioItem value="dark">Dark</DropdownMenuRadioItem>
|
|
101
|
+
<DropdownMenuRadioItem value="system">System</DropdownMenuRadioItem>
|
|
102
|
+
</DropdownMenuRadioGroup>
|
|
103
|
+
</DropdownMenuContent>
|
|
104
|
+
</DropdownMenu>
|
|
105
|
+
);
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export const Complex: Story = {
|
|
110
|
+
render: () => {
|
|
111
|
+
const [showNotifications, setShowNotifications] = useState(true);
|
|
112
|
+
const [theme, setTheme] = useState("light");
|
|
113
|
+
return (
|
|
114
|
+
<DropdownMenu>
|
|
115
|
+
<DropdownMenuTrigger asChild>
|
|
116
|
+
<Button variant="outline">Menu</Button>
|
|
117
|
+
</DropdownMenuTrigger>
|
|
118
|
+
<DropdownMenuContent className="w-56">
|
|
119
|
+
<DropdownMenuItem>Profile</DropdownMenuItem>
|
|
120
|
+
<DropdownMenuItem>Settings</DropdownMenuItem>
|
|
121
|
+
<DropdownMenuSeparator />
|
|
122
|
+
<DropdownMenuCheckboxItem
|
|
123
|
+
checked={showNotifications}
|
|
124
|
+
onCheckedChange={setShowNotifications}
|
|
125
|
+
>
|
|
126
|
+
Show Notifications
|
|
127
|
+
</DropdownMenuCheckboxItem>
|
|
128
|
+
<DropdownMenuSeparator />
|
|
129
|
+
<DropdownMenuRadioGroup value={theme} onValueChange={setTheme}>
|
|
130
|
+
<DropdownMenuRadioItem value="light">Light</DropdownMenuRadioItem>
|
|
131
|
+
<DropdownMenuRadioItem value="dark">Dark</DropdownMenuRadioItem>
|
|
132
|
+
</DropdownMenuRadioGroup>
|
|
133
|
+
<DropdownMenuSeparator />
|
|
134
|
+
<DropdownMenuItem className="text-red-600">Sign Out</DropdownMenuItem>
|
|
135
|
+
</DropdownMenuContent>
|
|
136
|
+
</DropdownMenu>
|
|
137
|
+
);
|
|
138
|
+
},
|
|
139
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
|
|
3
|
+
type Story = StoryObj;
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: "UI/Form",
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: "padded",
|
|
10
|
+
},
|
|
11
|
+
} satisfies Meta;
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
|
|
15
|
+
export const Default: Story = {
|
|
16
|
+
render: () => (
|
|
17
|
+
<form className="w-full max-w-md space-y-6">
|
|
18
|
+
<div className="space-y-2">
|
|
19
|
+
<label className="text-sm font-medium">Name</label>
|
|
20
|
+
<input
|
|
21
|
+
type="text"
|
|
22
|
+
placeholder="Enter your name"
|
|
23
|
+
className="w-full px-3 py-2 border rounded-md text-sm focus:outline-hidden focus:ring-2 focus:ring-blue-500"
|
|
24
|
+
/>
|
|
25
|
+
</div>
|
|
26
|
+
<div className="space-y-2">
|
|
27
|
+
<label className="text-sm font-medium">Email</label>
|
|
28
|
+
<input
|
|
29
|
+
type="email"
|
|
30
|
+
placeholder="Enter your email"
|
|
31
|
+
className="w-full px-3 py-2 border rounded-md text-sm focus:outline-hidden focus:ring-2 focus:ring-blue-500"
|
|
32
|
+
/>
|
|
33
|
+
</div>
|
|
34
|
+
<div className="space-y-2">
|
|
35
|
+
<label className="text-sm font-medium">Message</label>
|
|
36
|
+
<textarea
|
|
37
|
+
placeholder="Enter your message"
|
|
38
|
+
className="w-full px-3 py-2 border rounded-md text-sm focus:outline-hidden focus:ring-2 focus:ring-blue-500"
|
|
39
|
+
/>
|
|
40
|
+
</div>
|
|
41
|
+
<button className="w-full bg-blue-600 text-white py-2 rounded-md text-sm font-medium hover:bg-blue-700">
|
|
42
|
+
Submit
|
|
43
|
+
</button>
|
|
44
|
+
</form>
|
|
45
|
+
),
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const WithValidation: Story = {
|
|
49
|
+
render: () => (
|
|
50
|
+
<form className="w-full max-w-md space-y-6">
|
|
51
|
+
<div className="space-y-2">
|
|
52
|
+
<label className="text-sm font-medium">Username *</label>
|
|
53
|
+
<input
|
|
54
|
+
type="text"
|
|
55
|
+
placeholder="Choose a username"
|
|
56
|
+
className="w-full px-3 py-2 border border-red-500 rounded-md text-sm focus:outline-hidden focus:ring-2 focus:ring-red-500"
|
|
57
|
+
/>
|
|
58
|
+
<p className="text-sm text-red-600">Username is required</p>
|
|
59
|
+
</div>
|
|
60
|
+
<div className="space-y-2">
|
|
61
|
+
<label className="text-sm font-medium">Email *</label>
|
|
62
|
+
<input
|
|
63
|
+
type="email"
|
|
64
|
+
placeholder="Enter a valid email"
|
|
65
|
+
className="w-full px-3 py-2 border border-green-500 rounded-md text-sm focus:outline-hidden focus:ring-2 focus:ring-green-500"
|
|
66
|
+
/>
|
|
67
|
+
<p className="text-sm text-green-600">✓ Email looks good</p>
|
|
68
|
+
</div>
|
|
69
|
+
<button className="w-full bg-blue-600 text-white py-2 rounded-md text-sm font-medium hover:bg-blue-700">
|
|
70
|
+
Create Account
|
|
71
|
+
</button>
|
|
72
|
+
</form>
|
|
73
|
+
),
|
|
74
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import {
|
|
3
|
+
HoverCard,
|
|
4
|
+
HoverCardTrigger,
|
|
5
|
+
HoverCardContent,
|
|
6
|
+
} from "../../components/ui/hover-card";
|
|
7
|
+
|
|
8
|
+
const meta = {
|
|
9
|
+
title: "UI/HoverCard",
|
|
10
|
+
component: HoverCard,
|
|
11
|
+
tags: ["autodocs"],
|
|
12
|
+
parameters: {
|
|
13
|
+
layout: "padded",
|
|
14
|
+
},
|
|
15
|
+
} satisfies Meta<typeof HoverCard>;
|
|
16
|
+
|
|
17
|
+
export default meta;
|
|
18
|
+
|
|
19
|
+
type Story = StoryObj<typeof meta>;
|
|
20
|
+
|
|
21
|
+
export const Default: Story = {
|
|
22
|
+
render: () => (
|
|
23
|
+
<HoverCard>
|
|
24
|
+
<HoverCardTrigger>Hover here</HoverCardTrigger>
|
|
25
|
+
<HoverCardContent>
|
|
26
|
+
<div className="space-y-2">
|
|
27
|
+
<h4 className="font-semibold">Hover Card</h4>
|
|
28
|
+
<p className="text-sm">This content appears when you hover.</p>
|
|
29
|
+
</div>
|
|
30
|
+
</HoverCardContent>
|
|
31
|
+
</HoverCard>
|
|
32
|
+
),
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const Profile: Story = {
|
|
36
|
+
render: () => (
|
|
37
|
+
<HoverCard>
|
|
38
|
+
<HoverCardTrigger className="cursor-pointer underline">
|
|
39
|
+
@username
|
|
40
|
+
</HoverCardTrigger>
|
|
41
|
+
<HoverCardContent className="w-80">
|
|
42
|
+
<div className="space-y-4">
|
|
43
|
+
<div className="flex items-start gap-4">
|
|
44
|
+
<div className="w-12 h-12 rounded-full bg-gray-200"></div>
|
|
45
|
+
<div>
|
|
46
|
+
<h4 className="font-semibold">John Doe</h4>
|
|
47
|
+
<p className="text-sm text-gray-600">@username</p>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
<p className="text-sm text-gray-600">
|
|
51
|
+
A passionate developer building amazing things.
|
|
52
|
+
</p>
|
|
53
|
+
<div className="flex gap-4 text-sm">
|
|
54
|
+
<span>Following: 500</span>
|
|
55
|
+
<span>Followers: 1.2K</span>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</HoverCardContent>
|
|
59
|
+
</HoverCard>
|
|
60
|
+
),
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const Multiple: Story = {
|
|
64
|
+
render: () => (
|
|
65
|
+
<div className="flex gap-8">
|
|
66
|
+
<HoverCard>
|
|
67
|
+
<HoverCardTrigger className="cursor-pointer underline">
|
|
68
|
+
Feature 1
|
|
69
|
+
</HoverCardTrigger>
|
|
70
|
+
<HoverCardContent>
|
|
71
|
+
<p className="text-sm">Details about feature 1</p>
|
|
72
|
+
</HoverCardContent>
|
|
73
|
+
</HoverCard>
|
|
74
|
+
|
|
75
|
+
<HoverCard>
|
|
76
|
+
<HoverCardTrigger className="cursor-pointer underline">
|
|
77
|
+
Feature 2
|
|
78
|
+
</HoverCardTrigger>
|
|
79
|
+
<HoverCardContent>
|
|
80
|
+
<p className="text-sm">Details about feature 2</p>
|
|
81
|
+
</HoverCardContent>
|
|
82
|
+
</HoverCard>
|
|
83
|
+
|
|
84
|
+
<HoverCard>
|
|
85
|
+
<HoverCardTrigger className="cursor-pointer underline">
|
|
86
|
+
Feature 3
|
|
87
|
+
</HoverCardTrigger>
|
|
88
|
+
<HoverCardContent>
|
|
89
|
+
<p className="text-sm">Details about feature 3</p>
|
|
90
|
+
</HoverCardContent>
|
|
91
|
+
</HoverCard>
|
|
92
|
+
</div>
|
|
93
|
+
),
|
|
94
|
+
};
|