@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.
Files changed (100) hide show
  1. package/client/App.tsx +47 -0
  2. package/client/components/icons/ConceptIcons.tsx +667 -0
  3. package/client/components/icons/NavAccount.tsx +31 -0
  4. package/client/components/icons/NavBullet.tsx +19 -0
  5. package/client/components/icons/NavLogo.tsx +36 -0
  6. package/client/components/icons/ProviderBadges.tsx +295 -0
  7. package/client/components/icons/ProviderSeals.tsx +319 -0
  8. package/client/components/icons/SealHealthSafetyRating.tsx +65 -0
  9. package/client/components/icons/SealIwbiMember.tsx +86 -0
  10. package/client/components/icons/SealWell.tsx +84 -0
  11. package/client/components/icons/SealWellCertification.tsx +138 -0
  12. package/client/components/icons/SealWellCommunity.tsx +122 -0
  13. package/client/components/icons/SealWellResidence.tsx +122 -0
  14. package/client/components/icons/SealWorksWithWell.tsx +140 -0
  15. package/client/components/icons/UtilityAccordion.tsx +21 -0
  16. package/client/components/icons/UtilityChevronDown.tsx +36 -0
  17. package/client/components/icons/UtilityClassification.tsx +45 -0
  18. package/client/components/icons/UtilityClose.tsx +41 -0
  19. package/client/components/icons/UtilityDrag.tsx +69 -0
  20. package/client/components/icons/UtilityEdit.tsx +42 -0
  21. package/client/components/icons/UtilityOptions.tsx +45 -0
  22. package/client/components/icons/UtilityPortfolio.tsx +87 -0
  23. package/client/components/icons/UtilityReset.tsx +41 -0
  24. package/client/components/icons/UtilityScoring.tsx +43 -0
  25. package/client/components/icons/UtilitySearch.tsx +38 -0
  26. package/client/components/icons/UtilitySort.tsx +52 -0
  27. package/client/components/icons/UtilityText.tsx +34 -0
  28. package/client/components/icons/WaterMarkWWWProducts.tsx +26 -0
  29. package/client/components/icons/WaterMarkWellProjects.tsx +30 -0
  30. package/client/components/icons/WatermarkMemberOrg.tsx +59 -0
  31. package/client/components/icons/WellSeal.tsx +79 -0
  32. package/client/components/icons/X.tsx +35 -0
  33. package/client/hooks/UseTabs.tsx +35 -0
  34. package/client/hooks/use-mobile.tsx +21 -0
  35. package/client/hooks/use-segmented-control.ts +42 -0
  36. package/client/hooks/use-toast.ts +188 -0
  37. package/client/pages/Index.tsx +88 -0
  38. package/client/pages/NotFound.tsx +29 -0
  39. package/client/ui/Accordion/Accordion.stories.tsx +74 -0
  40. package/client/ui/Alert/Alert.stories.tsx +82 -0
  41. package/client/ui/AlertDialog/AlertDialog.stories.tsx +106 -0
  42. package/client/ui/AspectRatio.stories.tsx +78 -0
  43. package/client/ui/Avatar/Avatar.stories.tsx +94 -0
  44. package/client/ui/Badge/Badge.stories.tsx +60 -0
  45. package/client/ui/Breadcrumb/Breadcrumb.stories.tsx +97 -0
  46. package/client/ui/Button.stories.tsx +429 -0
  47. package/client/ui/Calendar/Calendar.stories.tsx +99 -0
  48. package/client/ui/Card.stories.tsx +84 -0
  49. package/client/ui/Carousel/Carousel.stories.tsx +85 -0
  50. package/client/ui/Chart/Chart.stories.tsx +58 -0
  51. package/client/ui/Checkbox/Checkbox.stories.tsx +112 -0
  52. package/client/ui/Collapsible/Collapsible.stories.tsx +101 -0
  53. package/client/ui/Colors.stories.tsx +1041 -0
  54. package/client/ui/Command/Command.stories.tsx +97 -0
  55. package/client/ui/ContextMenu/ContextMenu.stories.tsx +74 -0
  56. package/client/ui/Dialog.stories.tsx +69 -0
  57. package/client/ui/Drawer/Drawer.stories.tsx +87 -0
  58. package/client/ui/DropdownMenu/DropdownMenu.stories.tsx +139 -0
  59. package/client/ui/Form/Form.stories.tsx +74 -0
  60. package/client/ui/HoverCard/HoverCard.stories.tsx +94 -0
  61. package/client/ui/Icons.stories.tsx +328 -0
  62. package/client/ui/Input/Input.stories.tsx +69 -0
  63. package/client/ui/InputOTP/InputOTP.stories.tsx +85 -0
  64. package/client/ui/Label.stories.tsx +66 -0
  65. package/client/ui/Menubar/Menubar.stories.tsx +88 -0
  66. package/client/ui/Navigation.stories.tsx +57 -0
  67. package/client/ui/NavigationMenu/NavigationMenu.stories.tsx +106 -0
  68. package/client/ui/Pagination/Pagination.stories.tsx +115 -0
  69. package/client/ui/Popover/Popover.stories.tsx +99 -0
  70. package/client/ui/Progress/Progress.stories.tsx +63 -0
  71. package/client/ui/RadioGroup/RadioGroup.stories.tsx +110 -0
  72. package/client/ui/Resizable/Resizable.stories.tsx +88 -0
  73. package/client/ui/ScrollArea/ScrollArea.stories.tsx +64 -0
  74. package/client/ui/SearchField.stories.tsx +63 -0
  75. package/client/ui/Select/Select.stories.tsx +111 -0
  76. package/client/ui/Separator/Separator.stories.tsx +67 -0
  77. package/client/ui/Sheet/Sheet.stories.tsx +138 -0
  78. package/client/ui/Sidebar/Sidebar.stories.tsx +92 -0
  79. package/client/ui/Skeleton/Skeleton.stories.tsx +65 -0
  80. package/client/ui/Slider/Slider.stories.tsx +101 -0
  81. package/client/ui/Sonner/Sonner.stories.tsx +48 -0
  82. package/client/ui/StrategyTable.stories.tsx +138 -0
  83. package/client/ui/Switch/Switch.stories.tsx +96 -0
  84. package/client/ui/Table/Table.stories.tsx +135 -0
  85. package/client/ui/Tabs.stories.tsx +33 -0
  86. package/client/ui/Tag.stories.tsx +190 -0
  87. package/client/ui/Textarea/Textarea.stories.tsx +56 -0
  88. package/client/ui/Toast/Toast.stories.tsx +76 -0
  89. package/client/ui/Toaster/Toaster.stories.tsx +52 -0
  90. package/client/ui/Toggle.stories.tsx +248 -0
  91. package/client/ui/ToggleGroup/ToggleGroup.stories.tsx +88 -0
  92. package/client/ui/Tooltip.stories.tsx +72 -0
  93. package/client/ui/Typography.stories.tsx +421 -0
  94. package/client/ui/WELLDashboard/WELLDashboard.stories.tsx +115 -0
  95. package/client/ui/WELLDashboard/index.tsx +317 -0
  96. package/client/vite-env.d.ts +1 -0
  97. package/dist/ui/index.cjs.js +1 -1
  98. package/dist/ui/index.d.ts +10 -1
  99. package/dist/ui/index.es.js +2233 -447
  100. package/package.json +2 -1
@@ -0,0 +1,190 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Tag } from "@/components/ui/Tag";
3
+
4
+ const meta = {
5
+ title: "Review/Tag",
6
+ component: Tag,
7
+ tags: ["autodocs"],
8
+ parameters: {
9
+ layout: "padded",
10
+ },
11
+ } satisfies Meta<typeof Tag>;
12
+
13
+ export default meta;
14
+
15
+ type Story = StoryObj<typeof meta>;
16
+
17
+ export const DualStateInactive: Story = {
18
+ args: {
19
+ active: false,
20
+ children: "Tag",
21
+ },
22
+ render: () => (
23
+ <div className="space-y-4">
24
+ <div>
25
+ <p className="text-sm text-gray-600 mb-2">General purpose, inactive</p>
26
+ <Tag active={false}>Tag</Tag>
27
+ </div>
28
+ </div>
29
+ ),
30
+ };
31
+
32
+ export const DualStateActive: Story = {
33
+ args: {
34
+ active: true,
35
+ children: "Tag",
36
+ },
37
+ render: () => (
38
+ <div className="space-y-4">
39
+ <div>
40
+ <p className="text-sm text-gray-600 mb-2">General purpose, active</p>
41
+ <Tag active={true}>Tag</Tag>
42
+ </div>
43
+ </div>
44
+ ),
45
+ };
46
+
47
+ export const StatusTagsLight: Story = {
48
+ args: {
49
+ status: "todo",
50
+ variant: "light",
51
+ children: "Todo",
52
+ },
53
+ render: () => (
54
+ <div className="space-y-6">
55
+ <div>
56
+ <p className="text-sm font-semibold text-gray-600 mb-4">
57
+ Status, light
58
+ </p>
59
+ <div className="flex flex-col justify-center items-center gap-6">
60
+ <Tag status="todo" variant="light">
61
+ Todo
62
+ </Tag>
63
+ <Tag status="low" variant="light">
64
+ Low
65
+ </Tag>
66
+ <Tag status="medium" variant="light">
67
+ Medium
68
+ </Tag>
69
+ <Tag status="high" variant="light">
70
+ High
71
+ </Tag>
72
+ <Tag status="done" variant="light">
73
+ Done
74
+ </Tag>
75
+ </div>
76
+ </div>
77
+ </div>
78
+ ),
79
+ };
80
+
81
+ export const StatusTagsDark: Story = {
82
+ args: {
83
+ status: "todo",
84
+ variant: "dark",
85
+ children: "Todo",
86
+ },
87
+ render: () => (
88
+ <div className="space-y-6 bg-gray-900 p-8 rounded-lg">
89
+ <div>
90
+ <p className="text-sm font-semibold text-gray-300 mb-4">Status, dark</p>
91
+ <div className="flex flex-col justify-center items-center gap-6">
92
+ <Tag status="todo" variant="dark">
93
+ Todo
94
+ </Tag>
95
+ <Tag status="low" variant="dark">
96
+ Low
97
+ </Tag>
98
+ <Tag status="medium" variant="dark">
99
+ Medium
100
+ </Tag>
101
+ <Tag status="high" variant="dark">
102
+ High
103
+ </Tag>
104
+ <Tag status="done" variant="dark">
105
+ Done
106
+ </Tag>
107
+ </div>
108
+ </div>
109
+ </div>
110
+ ),
111
+ };
112
+
113
+ export const AllVariants: Story = {
114
+ args: {
115
+ active: false,
116
+ variant: "light",
117
+ children: "Tag",
118
+ },
119
+ render: (args) => (
120
+ <div className="space-y-12">
121
+ <div className="space-y-6">
122
+ <h3 className="text-base font-semibold text-gray-700">
123
+ Dual-state tags
124
+ </h3>
125
+ <div className="flex flex-col justify-center items-center gap-6">
126
+ <div>
127
+ <p className="text-sm text-gray-600 mb-2">
128
+ General purpose, inactive
129
+ </p>
130
+ <Tag {...args}>Tag</Tag>
131
+ </div>
132
+ <div>
133
+ <p className="text-sm text-gray-600 mb-2">
134
+ General purpose, active
135
+ </p>
136
+ <Tag {...args} active>
137
+ Tag
138
+ </Tag>
139
+ </div>
140
+ </div>
141
+ </div>
142
+
143
+ <div className="space-y-6">
144
+ <h3 className="text-base font-semibold text-gray-700">Status tags</h3>
145
+ <div className="grid grid-cols-2 gap-12">
146
+ <div>
147
+ <p className="text-sm text-gray-600 mb-4">Status, light</p>
148
+ <div className="flex flex-col justify-center items-center gap-6">
149
+ <Tag {...args} variant="light" status="todo">
150
+ Todo
151
+ </Tag>
152
+ <Tag {...args} variant="light" status="low">
153
+ Low
154
+ </Tag>
155
+ <Tag {...args} variant="light" status="medium">
156
+ Medium
157
+ </Tag>
158
+ <Tag {...args} variant="light" status="high">
159
+ High
160
+ </Tag>
161
+ <Tag {...args} variant="light" status="done">
162
+ Done
163
+ </Tag>
164
+ </div>
165
+ </div>
166
+ <div className="bg-gray-900 p-6 rounded-lg">
167
+ <p className="text-sm text-gray-300 mb-4">Status, dark</p>
168
+ <div className="flex flex-col justify-center items-center gap-6">
169
+ <Tag {...args} variant="dark" status="todo">
170
+ Todo
171
+ </Tag>
172
+ <Tag {...args} variant="dark" status="low">
173
+ Low
174
+ </Tag>
175
+ <Tag {...args} variant="dark" status="medium">
176
+ Medium
177
+ </Tag>
178
+ <Tag {...args} variant="dark" status="high">
179
+ High
180
+ </Tag>
181
+ <Tag {...args} variant="dark" status="done">
182
+ Done
183
+ </Tag>
184
+ </div>
185
+ </div>
186
+ </div>
187
+ </div>
188
+ </div>
189
+ ),
190
+ };
@@ -0,0 +1,56 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Textarea } from "../../components/ui/textarea";
3
+
4
+ const meta = {
5
+ title: "UI/Textarea",
6
+ component: Textarea,
7
+ tags: ["autodocs"],
8
+ parameters: {
9
+ layout: "centered",
10
+ },
11
+ } satisfies Meta<typeof Textarea>;
12
+
13
+ export default meta;
14
+
15
+ type Story = StoryObj<typeof meta>;
16
+
17
+ export const Default: Story = {
18
+ args: {
19
+ placeholder: "Enter your message here...",
20
+ },
21
+ };
22
+
23
+ export const WithValue: Story = {
24
+ args: {
25
+ placeholder: "Enter your message here...",
26
+ value: "This is some pre-filled text.",
27
+ },
28
+ };
29
+
30
+ export const Disabled: Story = {
31
+ args: {
32
+ placeholder: "This textarea is disabled",
33
+ disabled: true,
34
+ },
35
+ };
36
+
37
+ export const Rows: Story = {
38
+ render: () => (
39
+ <div className="space-y-4 w-full max-w-md">
40
+ <div>
41
+ <label className="text-sm font-medium mb-2 block">Small (3 rows)</label>
42
+ <Textarea placeholder="Type here..." rows={3} />
43
+ </div>
44
+ <div>
45
+ <label className="text-sm font-medium mb-2 block">
46
+ Medium (5 rows)
47
+ </label>
48
+ <Textarea placeholder="Type here..." rows={5} />
49
+ </div>
50
+ <div>
51
+ <label className="text-sm font-medium mb-2 block">Large (8 rows)</label>
52
+ <Textarea placeholder="Type here..." rows={8} />
53
+ </div>
54
+ </div>
55
+ ),
56
+ };
@@ -0,0 +1,76 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { useToast } from "../../hooks/use-toast";
3
+ import { Button } from "../../components/ui/button";
4
+ import { Toast, ToastAction } from "../../components/ui/toast";
5
+
6
+ const meta = {
7
+ title: "UI/Toast",
8
+ tags: ["autodocs"],
9
+ parameters: {
10
+ layout: "centered",
11
+ },
12
+ };
13
+
14
+ export default meta;
15
+
16
+ type Story = StoryObj;
17
+
18
+ export const Default: Story = {
19
+ render: () => {
20
+ const { toast } = useToast();
21
+
22
+ return (
23
+ <Button
24
+ onClick={() =>
25
+ toast({
26
+ title: "Success",
27
+ description: "Your action was successful.",
28
+ })
29
+ }
30
+ >
31
+ Show Toast
32
+ </Button>
33
+ );
34
+ },
35
+ };
36
+
37
+ export const WithAction: Story = {
38
+ render: () => {
39
+ const { toast } = useToast();
40
+
41
+ return (
42
+ <Button
43
+ onClick={() =>
44
+ toast({
45
+ title: "Undo Action",
46
+ description: "You can undo this action.",
47
+ action: <ToastAction altText="Undo">Undo</ToastAction>,
48
+ })
49
+ }
50
+ >
51
+ Show Toast with Action
52
+ </Button>
53
+ );
54
+ },
55
+ };
56
+
57
+ export const Destructive: Story = {
58
+ render: () => {
59
+ const { toast } = useToast();
60
+
61
+ return (
62
+ <Button
63
+ variant="destructive"
64
+ onClick={() =>
65
+ toast({
66
+ title: "Error",
67
+ description: "Something went wrong.",
68
+ variant: "destructive",
69
+ })
70
+ }
71
+ >
72
+ Show Error Toast
73
+ </Button>
74
+ );
75
+ },
76
+ };
@@ -0,0 +1,52 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Toaster } from "../../components/ui/toaster";
3
+ import { useToast } from "../../hooks/use-toast";
4
+ import { Button } from "../../components/ui/button";
5
+
6
+ const meta = {
7
+ title: "UI/Toaster",
8
+ tags: ["autodocs"],
9
+ parameters: {
10
+ layout: "centered",
11
+ },
12
+ };
13
+
14
+ export default meta;
15
+
16
+ type Story = StoryObj;
17
+
18
+ export const Default: Story = {
19
+ render: () => {
20
+ const { toast } = useToast();
21
+
22
+ return (
23
+ <div className="space-y-4">
24
+ <Toaster />
25
+ <div className="space-y-2">
26
+ <Button
27
+ onClick={() =>
28
+ toast({
29
+ title: "Success",
30
+ description: "Your changes have been saved.",
31
+ })
32
+ }
33
+ >
34
+ Show Success Toast
35
+ </Button>
36
+ <Button
37
+ variant="destructive"
38
+ onClick={() =>
39
+ toast({
40
+ title: "Error",
41
+ description: "Something went wrong.",
42
+ variant: "destructive",
43
+ })
44
+ }
45
+ >
46
+ Show Error Toast
47
+ </Button>
48
+ </div>
49
+ </div>
50
+ );
51
+ },
52
+ };
@@ -0,0 +1,248 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { SegmentedControl } from "../components/ui/Toggle";
3
+ import { useState } from "react";
4
+ import { cn } from "../lib/utils";
5
+ import { UtilityAccordion } from "@/components/icons/UtilityAccordion";
6
+ import { UtilityText } from "@/components/icons/UtilityText";
7
+
8
+ const meta = {
9
+ title: "Review/Toggle",
10
+ component: SegmentedControl,
11
+ tags: ["autodocs"],
12
+ parameters: {
13
+ layout: "centered",
14
+ },
15
+ } satisfies Meta<typeof SegmentedControl>;
16
+
17
+ export default meta;
18
+
19
+ type Story = StoryObj<typeof meta>;
20
+
21
+ // Complete Design System Overview
22
+ export const AllToggleVariants: Story = {
23
+ args: {
24
+ options: [{ label: "Placeholder", value: "placeholder" }],
25
+ },
26
+ render: () => {
27
+ const [segmentedValue, setSegmentedValue] = useState("active");
28
+ const [viewValue, setViewValue] = useState<"grid" | "list">("grid");
29
+
30
+ return (
31
+ <div className="bg-[#FAFAFA] p-16 space-y-20">
32
+ {/* Utility Toggles Section */}
33
+ <div className="space-y-12">
34
+ <div>
35
+ <h3 className="text-lg font-semibold text-[#4E4F57] mb-8">
36
+ Utility toggles
37
+ </h3>
38
+ <div className="space-y-6">
39
+ <div className="space-y-4">
40
+ <p className="text-[#4E4F57]">Modal pagination</p>
41
+ <div className="inline-flex items-center overflow-hidden border border-gray-100 bg-white rounded-full transition-all h-8 gap-0">
42
+ <button
43
+ className={cn(
44
+ "inline-flex items-center justify-center w-12 h-8 rounded-full text-gray-500 hover:bg-gray-50 disabled:opacity-50 transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring bg-gray-100",
45
+ )}
46
+ onClick={() => console.log("Previous")}
47
+ type="button"
48
+ aria-label="Previous page"
49
+ >
50
+ <svg
51
+ xmlns="http://www.w3.org/2000/svg"
52
+ width="10"
53
+ height="2"
54
+ viewBox="0 0 10 2"
55
+ fill="none"
56
+ >
57
+ <path
58
+ d="M0.75 0.75L8.75 0.75"
59
+ stroke="#71747D"
60
+ strokeWidth="1.5"
61
+ strokeLinecap="round"
62
+ strokeLinejoin="round"
63
+ />
64
+ </svg>
65
+ </button>
66
+ <button
67
+ className={cn(
68
+ "inline-flex items-center justify-center w-12 h-8 rounded-full text-gray-500 hover:bg-gray-50 disabled:opacity-50 transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring bg-white",
69
+ )}
70
+ onClick={() => console.log("Next")}
71
+ type="button"
72
+ aria-label="Next page"
73
+ >
74
+ <svg
75
+ xmlns="http://www.w3.org/2000/svg"
76
+ width="16"
77
+ height="10"
78
+ viewBox="0 0 16 10"
79
+ fill="none"
80
+ >
81
+ <path
82
+ d="M10.75 0.75L14.75 4.75L10.75 8.75"
83
+ stroke="#71747D"
84
+ strokeWidth="1.5"
85
+ strokeLinecap="round"
86
+ strokeLinejoin="round"
87
+ />
88
+ <path
89
+ d="M14.75 4.75H0.75"
90
+ stroke="#71747D"
91
+ strokeWidth="1.5"
92
+ strokeLinecap="round"
93
+ strokeLinejoin="round"
94
+ />
95
+ </svg>
96
+ </button>
97
+ </div>
98
+ </div>
99
+ </div>
100
+ </div>
101
+ </div>
102
+
103
+ {/* State Controls Section */}
104
+ <div className="space-y-12">
105
+ <div>
106
+ <h3 className="text-lg font-semibold text-[#4E4F57] mb-8">
107
+ State controls
108
+ </h3>
109
+ <div className="space-y-8">
110
+ <div className="space-y-4">
111
+ <p className="text-[#4E4F57]">Segmented control</p>
112
+ <SegmentedControl
113
+ className="inline-flex items-center overflow-hidden border border-gray-100 bg-white rounded-full transition-all h-8 p-0 [&>button]:flex-1"
114
+ options={[
115
+ { label: "Active", value: "active" },
116
+ { label: "Inactive", value: "inactive" },
117
+ ]}
118
+ value={segmentedValue}
119
+ onValueChange={setSegmentedValue}
120
+ />
121
+ </div>
122
+ <div className="space-y-4">
123
+ <p className="text-[#4E4F57]">View control</p>
124
+ <SegmentedControl<"grid" | "list">
125
+ className="inline-flex items-center overflow-hidden border border-gray-100 bg-white rounded-full transition-all h-8 p-0 [&>button]:w-12 [&>button]:px-0 [&>button]:text-gray-500 [&>button[data-active='true']]:bg-cyan-700 [&>button[data-active='true']]:text-white"
126
+ options={[
127
+ {
128
+ label: <UtilityAccordion />,
129
+ value: "grid",
130
+ },
131
+ {
132
+ label: <UtilityText />,
133
+ value: "list",
134
+ },
135
+ ]}
136
+ value={viewValue}
137
+ defaultValue="grid"
138
+ onValueChange={setViewValue}
139
+ />
140
+ </div>
141
+ </div>
142
+ </div>
143
+ </div>
144
+ </div>
145
+ );
146
+ },
147
+ };
148
+
149
+ // Segmented Control Stories
150
+ export const SegmentedControlExample: Story = {
151
+ render: (args) => {
152
+ const [value, setValue] = useState("active");
153
+ return (
154
+ <SegmentedControl
155
+ {...args}
156
+ className="inline-flex items-center overflow-hidden border border-gray-100 bg-white rounded-full transition-all h-8 p-0 [&>button]:flex-1"
157
+ value={value}
158
+ onValueChange={setValue}
159
+ />
160
+ );
161
+ },
162
+ args: {
163
+ options: [
164
+ { label: "Active", value: "active" },
165
+ { label: "Inactive", value: "inactive" },
166
+ ],
167
+ },
168
+ };
169
+
170
+ // Pagination Control Stories
171
+ export const PaginationControlExample: Story = {
172
+ args: {
173
+ options: [{ label: "Placeholder", value: "placeholder" }],
174
+ },
175
+ render: () => {
176
+ const [currentPage, setCurrentPage] = useState(1);
177
+ const totalPages = 5;
178
+
179
+ return (
180
+ <div className="flex items-center gap-4">
181
+ <div className="inline-flex items-center overflow-hidden border border-gray-100 bg-white rounded-full transition-all h-8 gap-0">
182
+ <button
183
+ className={cn(
184
+ "inline-flex items-center justify-center w-12 h-8 rounded-full text-gray-500 hover:bg-gray-50 disabled:opacity-50 transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring bg-gray-100",
185
+ )}
186
+ onClick={() => setCurrentPage(Math.max(1, currentPage - 1))}
187
+ disabled={currentPage === 1}
188
+ type="button"
189
+ aria-label="Previous page"
190
+ >
191
+ <svg
192
+ xmlns="http://www.w3.org/2000/svg"
193
+ width="10"
194
+ height="2"
195
+ viewBox="0 0 10 2"
196
+ fill="none"
197
+ >
198
+ <path
199
+ d="M0.75 0.75L8.75 0.75"
200
+ stroke="#71747D"
201
+ strokeWidth="1.5"
202
+ strokeLinecap="round"
203
+ strokeLinejoin="round"
204
+ />
205
+ </svg>
206
+ </button>
207
+ <button
208
+ className={cn(
209
+ "inline-flex items-center justify-center w-12 h-8 rounded-full text-gray-500 hover:bg-gray-50 disabled:opacity-50 transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring bg-white",
210
+ )}
211
+ onClick={() =>
212
+ setCurrentPage(Math.min(totalPages, currentPage + 1))
213
+ }
214
+ disabled={currentPage === totalPages}
215
+ type="button"
216
+ aria-label="Next page"
217
+ >
218
+ <svg
219
+ xmlns="http://www.w3.org/2000/svg"
220
+ width="16"
221
+ height="10"
222
+ viewBox="0 0 16 10"
223
+ fill="none"
224
+ >
225
+ <path
226
+ d="M10.75 0.75L14.75 4.75L10.75 8.75"
227
+ stroke="#71747D"
228
+ strokeWidth="1.5"
229
+ strokeLinecap="round"
230
+ strokeLinejoin="round"
231
+ />
232
+ <path
233
+ d="M14.75 4.75H0.75"
234
+ stroke="#71747D"
235
+ strokeWidth="1.5"
236
+ strokeLinecap="round"
237
+ strokeLinejoin="round"
238
+ />
239
+ </svg>
240
+ </button>
241
+ </div>
242
+ <span className="text-sm text-gray-600">
243
+ Page {currentPage} of {totalPages}
244
+ </span>
245
+ </div>
246
+ );
247
+ },
248
+ };