@catalystsoftware/ui 1.0.2 → 1.0.5
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/data/tailwind.config.js +261 -3821
- package/dist/components/catalyst-ui/buttons/burger.tsx +207 -0
- package/dist/components/catalyst-ui/core/data-display/timeline.tsx +210 -0
- package/dist/components/catalyst-ui/core/feedback/alert.tsx +491 -0
- package/dist/components/catalyst-ui/core/feedback/spinner-1.tsx +65 -0
- package/dist/components/catalyst-ui/core/feedback/toast.tsx +1857 -0
- package/dist/components/catalyst-ui/core/navigation/menu.tsx +164 -0
- package/dist/components/catalyst-ui/forms/toggle-class.tsx +176 -0
- package/dist/components/catalyst-ui/hooks/use-copy-to-clipboard.tsx +419 -0
- package/dist/components/catalyst-ui/hooks/use-counter.tsx +13 -0
- package/dist/components/catalyst-ui/hooks/use-event-listener.tsx +23 -0
- package/dist/components/catalyst-ui/hooks/use-export-markdown.tsx +47 -0
- package/dist/components/catalyst-ui/hooks/use-focus.tsx +17 -0
- package/dist/components/catalyst-ui/hooks/use-interval.tsx +23 -0
- package/dist/components/catalyst-ui/hooks/use-is-client.tsx +16 -0
- package/dist/components/catalyst-ui/hooks/use-media-query.tsx +19 -0
- package/dist/components/catalyst-ui/hooks/use-mobile.tsx +19 -0
- package/dist/components/catalyst-ui/hooks/use-resize-observer.tsx +81 -0
- package/dist/components/catalyst-ui/hooks/use-timeout.tsx +21 -0
- package/dist/components/catalyst-ui/hooks/use-timer.tsx +209 -0
- package/dist/components/catalyst-ui/hooks/use-toggle.tsx +12 -0
- package/dist/components/catalyst-ui/media/image.tsx +13 -0
- package/dist/components/catalyst-ui/overlays/dual-sidebar.tsx +4142 -0
- package/dist/components/catalyst-ui/overlays/sidebar-original.tsx +726 -0
- package/dist/components/catalyst-ui/primitives/accordion.tsx +250 -0
- package/dist/components/catalyst-ui/primitives/alert-dialog.tsx +126 -0
- package/dist/components/catalyst-ui/primitives/aspect-ratio.tsx +9 -0
- package/dist/components/catalyst-ui/primitives/avatar.tsx +296 -0
- package/dist/components/catalyst-ui/primitives/badge.tsx +57 -0
- package/dist/components/catalyst-ui/primitives/breadcrumb.tsx +101 -0
- package/dist/components/catalyst-ui/primitives/button.tsx +265 -0
- package/dist/components/catalyst-ui/primitives/calendar-v4.tsx +208 -0
- package/dist/components/catalyst-ui/primitives/calendar.tsx +295 -0
- package/dist/components/catalyst-ui/primitives/card.tsx +618 -0
- package/dist/components/catalyst-ui/primitives/carousel.tsx +238 -0
- package/dist/components/catalyst-ui/primitives/chart.tsx +347 -0
- package/dist/components/catalyst-ui/primitives/checkbox.tsx +225 -0
- package/dist/components/catalyst-ui/primitives/collapsible.tsx +212 -0
- package/dist/components/catalyst-ui/primitives/command.tsx +393 -0
- package/dist/components/catalyst-ui/primitives/context-menu.tsx +236 -0
- package/dist/components/catalyst-ui/primitives/dialog.tsx +471 -0
- package/dist/components/catalyst-ui/primitives/drawer.tsx +761 -0
- package/dist/components/catalyst-ui/primitives/dropdown-menu.tsx +290 -0
- package/dist/components/catalyst-ui/primitives/empty.tsx +104 -0
- package/dist/components/catalyst-ui/primitives/field.tsx +244 -0
- package/dist/components/catalyst-ui/primitives/hover-card.tsx +124 -0
- package/dist/components/catalyst-ui/primitives/input-otp.tsx +76 -0
- package/dist/components/catalyst-ui/primitives/input.tsx +64 -0
- package/dist/components/catalyst-ui/primitives/item.tsx +196 -0
- package/dist/components/catalyst-ui/primitives/kbd.tsx +75 -0
- package/dist/components/catalyst-ui/primitives/label.tsx +24 -0
- package/dist/components/catalyst-ui/primitives/navigation-menu.tsx +150 -0
- package/dist/components/catalyst-ui/primitives/pagination.tsx +198 -0
- package/dist/components/catalyst-ui/primitives/popover.tsx +232 -0
- package/dist/components/catalyst-ui/primitives/progress.tsx +34 -0
- package/dist/components/catalyst-ui/primitives/radio-group.tsx +43 -0
- package/dist/components/catalyst-ui/primitives/resizable.tsx +56 -0
- package/dist/components/catalyst-ui/primitives/select.tsx +155 -0
- package/dist/components/catalyst-ui/primitives/separator.tsx +74 -0
- package/dist/components/catalyst-ui/primitives/sheet.tsx +126 -0
- package/dist/components/catalyst-ui/primitives/skeleton.tsx +15 -0
- package/dist/components/catalyst-ui/primitives/slider.tsx +27 -0
- package/dist/components/catalyst-ui/primitives/switch.tsx +187 -0
- package/dist/components/catalyst-ui/primitives/tabs.tsx +335 -0
- package/dist/components/catalyst-ui/primitives/textarea.tsx +24 -0
- package/dist/components/catalyst-ui/primitives/toggle-group.tsx +55 -0
- package/dist/components/catalyst-ui/primitives/toggle.tsx +42 -0
- package/dist/components/catalyst-ui/primitives/tooltip.tsx +116 -0
- package/dist/components/catalyst-ui/utils/basic-auth.tsx +40 -0
- package/dist/components/catalyst-ui/utils/context-storage.tsx +19 -0
- package/dist/components/catalyst-ui/utils/cors-middleware.tsx +71 -0
- package/dist/components/catalyst-ui/utils/deferred-content.tsx +595 -0
- package/dist/components/catalyst-ui/utils/honeypot-middleware.tsx +38 -0
- package/dist/components/catalyst-ui/utils/incId.tsx +75 -0
- package/dist/components/catalyst-ui/utils/jwk-auth.tsx +36 -0
- package/dist/components/catalyst-ui/utils/request-id.tsx +14 -0
- package/dist/components/catalyst-ui/utils/secure-headers.tsx +37 -0
- package/dist/components/catalyst-ui/utils/server-timing.tsx +23 -0
- package/dist/components/catalyst-ui/utils/utils.ts +43 -0
- package/dist/components/catalyst-ui/utils/with-cookie.tsx +43 -0
- package/dist/components/catalyst-ui/x/accordian-x.tsx +428 -0
- package/dist/components/catalyst-ui/x/alert-x.tsx +413 -0
- package/dist/components/catalyst-ui/x/animated-text-x.tsx +2242 -0
- package/dist/components/catalyst-ui/x/avatar-x.tsx +515 -0
- package/dist/components/catalyst-ui/x/badge-x.tsx +670 -0
- package/dist/components/catalyst-ui/x/button-X.tsx +2857 -0
- package/dist/components/catalyst-ui/x/button-group-x.tsx +847 -0
- package/dist/components/catalyst-ui/x/calendar-x.tsx +1910 -0
- package/dist/components/catalyst-ui/x/card-x.tsx +2597 -0
- package/dist/components/catalyst-ui/x/checkbox-x.tsx +656 -0
- package/dist/components/catalyst-ui/x/collapsible-x.tsx +1360 -0
- package/dist/components/catalyst-ui/x/combobox-x.tsx +911 -0
- package/dist/components/catalyst-ui/x/data-table-x.tsx +1753 -0
- package/dist/components/catalyst-ui/x/date-picker-x.tsx +648 -0
- package/dist/components/catalyst-ui/x/dialog-x.tsx +659 -0
- package/dist/components/catalyst-ui/x/dropdown-menu-x.tsx +612 -0
- package/dist/components/catalyst-ui/x/hover-card-x.tsx +375 -0
- package/dist/components/catalyst-ui/x/icon-x.tsx +840 -0
- package/dist/components/catalyst-ui/x/input-mask-x.tsx +981 -0
- package/dist/components/catalyst-ui/x/input-otp-x.tsx +659 -0
- package/dist/components/catalyst-ui/x/loader-x.tsx +1757 -0
- package/dist/components/catalyst-ui/x/pagination-x.tsx +622 -0
- package/dist/components/catalyst-ui/x/popover-x.tsx +744 -0
- package/dist/components/catalyst-ui/x/radio-group-x.tsx +499 -0
- package/dist/components/catalyst-ui/x/select-x.tsx +1127 -0
- package/dist/components/catalyst-ui/x/sheet-x.tsx +668 -0
- package/dist/components/catalyst-ui/x/switch-x.tsx +681 -0
- package/dist/components/catalyst-ui/x/table-x.tsx +574 -0
- package/dist/components/catalyst-ui/x/tabs-x.tsx +839 -0
- package/dist/components/catalyst-ui/x/textarea-x.tsx +1263 -0
- package/dist/components/catalyst-ui/x/tooltip-x.tsx +396 -0
- package/dist/components/catalyst-ui/x/tracker-x.tsx +560 -0
- package/dist/data/bg-data.tsx +901 -0
- package/dist/data/buttons-data.tsx +2327 -0
- package/dist/data/charts-data.tsx +102 -0
- package/dist/data/chat-data.tsx +83 -0
- package/dist/data/code-data.tsx +1040 -0
- package/dist/data/comboboxes-data.tsx +1843 -0
- package/dist/data/command-data.tsx +1381 -0
- package/dist/data/core-data.tsx +15953 -0
- package/dist/data/crm-data.tsx +47 -0
- package/dist/data/data.tsx +159 -0
- package/dist/data/date-and-time-data.tsx +554 -0
- package/dist/data/dependencies.tsx +7 -0
- package/dist/data/ecommerce-data.tsx +1387 -0
- package/dist/data/forms-data.tsx +7890 -0
- package/dist/data/hooks-data.tsx +5487 -0
- package/dist/data/index.ts +34 -0
- package/dist/data/inputs-data.tsx +557 -0
- package/dist/data/interactive-data.tsx +5394 -0
- package/dist/data/lofi-data.tsx +18295 -0
- package/dist/data/marketing-data.tsx +2546 -0
- package/dist/data/media-data.tsx +1510 -0
- package/dist/data/motion-data.tsx +5801 -0
- package/dist/data/overlay-data.tsx +4136 -0
- package/dist/data/pdf-data.tsx +124 -0
- package/dist/data/pos-data.tsx +213 -0
- package/dist/data/postcss.config.js +6 -0
- package/dist/data/primitive-data.tsx +5170 -0
- package/dist/data/prompt-data.tsx +1226 -0
- package/dist/data/requiredLibs.ts +4 -0
- package/dist/data/sandbox-data.tsx +1 -0
- package/dist/data/sidebars-data.tsx +5421 -0
- package/dist/data/stacks-data.tsx +32 -0
- package/dist/data/table-data.tsx +706 -0
- package/dist/data/tailwind.config.js +270 -0
- package/dist/data/tailwind.config.ngin.js +3830 -0
- package/dist/data/tailwind.css +431 -0
- package/dist/data/tools-data.tsx +6910 -0
- package/dist/data/typography-data.tsx +2050 -0
- package/dist/data/utils-data.tsx +6500 -0
- package/dist/data/x-data.tsx +1171 -0
- package/dist/data.tsx +159 -0
- package/package.json +1 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -362
|
@@ -0,0 +1,847 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import { cva, type VariantProps } from 'class-variance-authority'
|
|
3
|
+
import { cn } from '~/components/catalyst-ui'
|
|
4
|
+
import {
|
|
5
|
+
ButtonGroup,
|
|
6
|
+
ButtonGroupText,
|
|
7
|
+
ButtonGroupSeparator
|
|
8
|
+
} from '~/components/catalyst-ui'
|
|
9
|
+
import { Button } from '~/components/catalyst-ui'
|
|
10
|
+
import {
|
|
11
|
+
Tooltip,
|
|
12
|
+
TooltipTrigger,
|
|
13
|
+
TooltipContent
|
|
14
|
+
} from '~/components/catalyst-ui'
|
|
15
|
+
import {
|
|
16
|
+
DropdownMenu,
|
|
17
|
+
DropdownMenuTrigger,
|
|
18
|
+
DropdownMenuContent,
|
|
19
|
+
DropdownMenuRadioGroup,
|
|
20
|
+
DropdownMenuRadioItem
|
|
21
|
+
} from '~/components/catalyst-ui'
|
|
22
|
+
import {
|
|
23
|
+
DownloadIcon,
|
|
24
|
+
HeartIcon,
|
|
25
|
+
MousePointerIcon,
|
|
26
|
+
SquareIcon,
|
|
27
|
+
CropIcon,
|
|
28
|
+
CopyIcon,
|
|
29
|
+
EllipsisVerticalIcon,
|
|
30
|
+
SkipBackIcon,
|
|
31
|
+
PlayIcon,
|
|
32
|
+
PauseIcon,
|
|
33
|
+
SkipForwardIcon,
|
|
34
|
+
ZoomOutIcon,
|
|
35
|
+
ZoomInIcon,
|
|
36
|
+
MinusIcon,
|
|
37
|
+
PlusIcon,
|
|
38
|
+
ExternalLinkIcon,
|
|
39
|
+
SquarePenIcon,
|
|
40
|
+
Trash2Icon,
|
|
41
|
+
FlipHorizontalIcon,
|
|
42
|
+
FlipVerticalIcon,
|
|
43
|
+
ChevronDownIcon,
|
|
44
|
+
SettingsIcon,
|
|
45
|
+
BoxIcon,
|
|
46
|
+
ChartBarBigIcon,
|
|
47
|
+
InboxIcon,
|
|
48
|
+
ArchiveIcon,
|
|
49
|
+
SendHorizonalIcon,
|
|
50
|
+
ThumbsUpIcon,
|
|
51
|
+
ThumbsDownIcon,
|
|
52
|
+
ChevronLeftIcon,
|
|
53
|
+
ChevronRightIcon
|
|
54
|
+
} from 'lucide-react'
|
|
55
|
+
import type { LucideIcon } from 'lucide-react'
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* ★ ━━━━ ☆ ━━━━ ButtonGroupX ━━━━ ☆ ━━━━ ★
|
|
59
|
+
* type ButtonGroupXType =
|
|
60
|
+
* | 'download' | 'like' | 'tooltip' | 'rounded' | 'social' | 'zoom' // Interactive Groups
|
|
61
|
+
* | 'number' | 'preview' | 'actions' | 'basic' | 'dropdown' // Functional Groups
|
|
62
|
+
* | 'ghost' | 'reveal' | 'shine' // Visual Styles
|
|
63
|
+
*
|
|
64
|
+
* ★ ━━━━ ☆ ━━━━ USAGE ━━━━ ☆ ━━━━ ★
|
|
65
|
+
*
|
|
66
|
+
* ★ ━━━━━━━━━ Download Button Group ━━━━━━━━━ ★
|
|
67
|
+
* ```jsx
|
|
68
|
+
* <ButtonGroupX buttonGroup="download">
|
|
69
|
+
* <ButtonGroupXWrapper count="15k" />
|
|
70
|
+
* </ButtonGroupX>
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* ★ ━━━━━━━━━ Like Button Group ━━━━━━━━━ ★
|
|
74
|
+
* ```jsx
|
|
75
|
+
* <ButtonGroupX buttonGroup="like">
|
|
76
|
+
* <ButtonGroupXWrapper
|
|
77
|
+
* isLiked={true}
|
|
78
|
+
* likedCount={46}
|
|
79
|
+
* unlikedCount={45}
|
|
80
|
+
* onLikeChange={(liked) => console.log('Liked:', liked)}
|
|
81
|
+
* />
|
|
82
|
+
* </ButtonGroupX>
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* ★ ━━━━━━━━━ Tooltip Button Group ━━━━━━━━━ ★
|
|
86
|
+
* ```jsx
|
|
87
|
+
* <ButtonGroupX buttonGroup="tooltip">
|
|
88
|
+
* <ButtonGroupXWrapper />
|
|
89
|
+
* </ButtonGroupX>
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* ★ ━━━━━━━━━ Rounded Button Group ━━━━━━━━━ ★
|
|
93
|
+
* ```jsx
|
|
94
|
+
* <ButtonGroupX buttonGroup="rounded">
|
|
95
|
+
* <ButtonGroupXWrapper />
|
|
96
|
+
* </ButtonGroupX>
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* ★ ━━━━━━━━━ Social Media Button Group ━━━━━━━━━ ★
|
|
100
|
+
* ```jsx
|
|
101
|
+
* <ButtonGroupX buttonGroup="social">
|
|
102
|
+
* <ButtonGroupXWrapper />
|
|
103
|
+
* </ButtonGroupX>
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* ★ ━━━━━━━━━ Zoom Button Group ━━━━━━━━━ ★
|
|
107
|
+
* ```jsx
|
|
108
|
+
* <ButtonGroupX buttonGroup="zoom">
|
|
109
|
+
* <ButtonGroupXWrapper
|
|
110
|
+
* zoom={95}
|
|
111
|
+
* onZoomChange={(zoom) => console.log('Zoom:', zoom)}
|
|
112
|
+
* />
|
|
113
|
+
* </ButtonGroupX>
|
|
114
|
+
* ```
|
|
115
|
+
*
|
|
116
|
+
* ★ ━━━━━━━━━ Number Button Group ━━━━━━━━━ ★
|
|
117
|
+
* ```jsx
|
|
118
|
+
* <ButtonGroupX buttonGroup="number">
|
|
119
|
+
* <ButtonGroupXWrapper
|
|
120
|
+
* value={216}
|
|
121
|
+
* unit="px"
|
|
122
|
+
* onValueChange={(val) => console.log('Value:', val)}
|
|
123
|
+
* />
|
|
124
|
+
* </ButtonGroupX>
|
|
125
|
+
* ```
|
|
126
|
+
*
|
|
127
|
+
* ★ ━━━━━━━━━ Preview Button Group ━━━━━━━━━ ★
|
|
128
|
+
* ```jsx
|
|
129
|
+
* <ButtonGroupX buttonGroup="preview">
|
|
130
|
+
* <ButtonGroupXWrapper />
|
|
131
|
+
* </ButtonGroupX>
|
|
132
|
+
* ```
|
|
133
|
+
*
|
|
134
|
+
* ★ ━━━━━━━━━ Actions Button Group ━━━━━━━━━ ★
|
|
135
|
+
* ```jsx
|
|
136
|
+
* <ButtonGroupX buttonGroup="actions">
|
|
137
|
+
* <ButtonGroupXWrapper />
|
|
138
|
+
* </ButtonGroupX>
|
|
139
|
+
* ```
|
|
140
|
+
*
|
|
141
|
+
* ★ ━━━━━━━━━ Basic Button Group ━━━━━━━━━ ★
|
|
142
|
+
* ```jsx
|
|
143
|
+
* <ButtonGroupX buttonGroup="basic">
|
|
144
|
+
* <ButtonGroupXWrapper />
|
|
145
|
+
* </ButtonGroupX>
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* ★ ━━━━━━━━━ Dropdown Button Group ━━━━━━━━━ ★
|
|
149
|
+
* ```jsx
|
|
150
|
+
* <ButtonGroupX buttonGroup="dropdown">
|
|
151
|
+
* <ButtonGroupXWrapper
|
|
152
|
+
* options={[
|
|
153
|
+
* { label: 'Merge Pull Request', description: 'All commits will be added to the base branch' },
|
|
154
|
+
* { label: 'Squash and Merge', description: 'The commits will be combined into one commit' },
|
|
155
|
+
* { label: 'Rebase and Merge', description: 'The commits will be rebased and added' },
|
|
156
|
+
* ]}
|
|
157
|
+
* selectedIndex="0"
|
|
158
|
+
* onOptionChange={(index) => console.log('Selected:', index)}
|
|
159
|
+
* />
|
|
160
|
+
* </ButtonGroupX>
|
|
161
|
+
* ```
|
|
162
|
+
*
|
|
163
|
+
* ★ ━━━━━━━━━ Ghost Button Group ━━━━━━━━━ ★
|
|
164
|
+
* ```jsx
|
|
165
|
+
* <ButtonGroupX buttonGroup="ghost">
|
|
166
|
+
* <ButtonGroupXWrapper />
|
|
167
|
+
* </ButtonGroupX>
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* ★ ━━━━━━━━━ Reveal Button Group ━━━━━━━━━ ★
|
|
171
|
+
* ```jsx
|
|
172
|
+
* <ButtonGroupX buttonGroup="reveal">
|
|
173
|
+
* <ButtonGroupXWrapper />
|
|
174
|
+
* </ButtonGroupX>
|
|
175
|
+
* ```
|
|
176
|
+
*
|
|
177
|
+
* ★ ━━━━━━━━━ Shine Button Group ━━━━━━━━━ ★
|
|
178
|
+
* ```jsx
|
|
179
|
+
* <ButtonGroupX buttonGroup="shine">
|
|
180
|
+
* <ButtonGroupXWrapper shineButtons={['Upload', 'Download', 'Share']} />
|
|
181
|
+
* </ButtonGroupX>
|
|
182
|
+
* ```
|
|
183
|
+
*
|
|
184
|
+
* ★ ━━━━━━━━━ Props ━━━━━━━━━ ★
|
|
185
|
+
*
|
|
186
|
+
* ButtonGroupX Props:
|
|
187
|
+
* - `buttonGroup`: ButtonGroupXType - Specifies which variant to use
|
|
188
|
+
* - `className`: string - Additional CSS classes
|
|
189
|
+
* - `children`: ReactNode - Must contain a ButtonGroupXWrapper component
|
|
190
|
+
*
|
|
191
|
+
* ButtonGroupXWrapper Props:
|
|
192
|
+
* - `count`: string - Display count (for download group)
|
|
193
|
+
* - `isLiked`: boolean - Initial like state (for like group)
|
|
194
|
+
* - `likedCount`: number - Number of likes (for like group)
|
|
195
|
+
* - `unlikedCount`: number - Number of unlikes (for like group)
|
|
196
|
+
* - `onLikeChange`: (liked: boolean) => void - Like state change callback
|
|
197
|
+
* - `zoom`: number - Current zoom percentage (for zoom group)
|
|
198
|
+
* - `onZoomChange`: (zoom: number) => void - Zoom change callback
|
|
199
|
+
* - `value`: number - Current value (for number group)
|
|
200
|
+
* - `unit`: string - Unit to display (e.g., 'px', '%') (for number group)
|
|
201
|
+
* - `onValueChange`: (value: number) => void - Value change callback
|
|
202
|
+
* - `options`: Array<{ label: string, description: string }> - Dropdown options
|
|
203
|
+
* - `selectedIndex`: string - Initially selected option index
|
|
204
|
+
* - `onOptionChange`: (index: string) => void - Option selection callback
|
|
205
|
+
* - `shineButtons`: string[] - Button labels for shine group
|
|
206
|
+
*
|
|
207
|
+
* ★ ━━━━━━━━━ Component Structure ━━━━━━━━━ ★
|
|
208
|
+
* ```jsx
|
|
209
|
+
* // All ButtonGroupX components follow this pattern:
|
|
210
|
+
* <ButtonGroupX buttonGroup="variantName">
|
|
211
|
+
* <ButtonGroupXWrapper
|
|
212
|
+
* // variant-specific props
|
|
213
|
+
* />
|
|
214
|
+
* </ButtonGroupX>
|
|
215
|
+
* ```
|
|
216
|
+
*
|
|
217
|
+
* ★ ━━━━━━━━━ Basic Usage ━━━━━━━━━ ★
|
|
218
|
+
* ```javascript
|
|
219
|
+
* import { ButtonGroupX, ButtonGroupXWrapper } from "./ButtonGroupX";
|
|
220
|
+
*
|
|
221
|
+
* // Basic usage pattern
|
|
222
|
+
* <ButtonGroupX buttonGroup="download">
|
|
223
|
+
* <ButtonGroupXWrapper />
|
|
224
|
+
* </ButtonGroupX>
|
|
225
|
+
*
|
|
226
|
+
* // With props for interactive variants
|
|
227
|
+
* <ButtonGroupX buttonGroup="like">
|
|
228
|
+
* <ButtonGroupXWrapper
|
|
229
|
+
* isLiked={false}
|
|
230
|
+
* likedCount={0}
|
|
231
|
+
* onLikeChange={handleLike}
|
|
232
|
+
* />
|
|
233
|
+
* </ButtonGroupX>
|
|
234
|
+
* ```
|
|
235
|
+
*
|
|
236
|
+
*/
|
|
237
|
+
|
|
238
|
+
const TwitchIcon = ({ className }: { className?: string }) => (
|
|
239
|
+
<svg className={className} width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
|
240
|
+
<path d="M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7" />
|
|
241
|
+
</svg>
|
|
242
|
+
)
|
|
243
|
+
const DribbbleIcon = ({ className }: { className?: string }) => (
|
|
244
|
+
<svg className={className} width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
|
245
|
+
<circle cx="12" cy="12" r="10" />
|
|
246
|
+
<path d="M19.13 5.09C15.22 9.14 10 10.44 2.25 10.94m17.5 2.12C15.89 13.53 10.83 14 7 14.5" />
|
|
247
|
+
</svg>
|
|
248
|
+
)
|
|
249
|
+
const InstagramIcon = ({ className }: { className?: string }) => (
|
|
250
|
+
<svg className={className} width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
|
251
|
+
<rect x="2" y="2" width="20" height="20" rx="5" ry="5" />
|
|
252
|
+
<path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z" />
|
|
253
|
+
<line x1="17.5" y1="6.5" x2="17.51" y2="6.5" />
|
|
254
|
+
</svg>
|
|
255
|
+
)
|
|
256
|
+
const FacebookIcon = ({ className }: { className?: string }) => (
|
|
257
|
+
<svg className={className} width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
|
258
|
+
<path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z" />
|
|
259
|
+
</svg>
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
type ButtonGroupType =
|
|
263
|
+
| 'default'
|
|
264
|
+
| 'download'
|
|
265
|
+
| 'like'
|
|
266
|
+
| 'tooltip'
|
|
267
|
+
| 'rounded'
|
|
268
|
+
| 'social'
|
|
269
|
+
| 'zoom'
|
|
270
|
+
| 'number'
|
|
271
|
+
| 'preview'
|
|
272
|
+
| 'actions'
|
|
273
|
+
| 'basic'
|
|
274
|
+
| 'dropdown'
|
|
275
|
+
| 'ghost'
|
|
276
|
+
| 'reveal'
|
|
277
|
+
| 'shine'
|
|
278
|
+
|
|
279
|
+
const ButtonGroupXContext = React.createContext<ButtonGroupType>('default')
|
|
280
|
+
|
|
281
|
+
export function ButtonGroupX({ buttonGroup = 'default', children, ...props }: any) {
|
|
282
|
+
return (
|
|
283
|
+
<ButtonGroupXContext.Provider value={buttonGroup}>
|
|
284
|
+
{children}
|
|
285
|
+
</ButtonGroupXContext.Provider>
|
|
286
|
+
)
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function ButtonGroupXWrapper({ ...props }: any) {
|
|
290
|
+
const buttonGroupType = React.useContext(ButtonGroupXContext)
|
|
291
|
+
|
|
292
|
+
// State for interactive demos
|
|
293
|
+
const [isLiked, setIsLiked] = useState(props.isLiked ?? true)
|
|
294
|
+
const [zoom, setZoom] = useState(props.zoom ?? 95)
|
|
295
|
+
const [value, setValue] = useState(props.value ?? 216)
|
|
296
|
+
const [selectedIndex, setSelectedIndex] = useState(props.selectedIndex ?? '0')
|
|
297
|
+
|
|
298
|
+
const handleZoomIn = () => {
|
|
299
|
+
if (zoom < 100) {
|
|
300
|
+
setZoom(zoom + 5)
|
|
301
|
+
props.onZoomChange?.(zoom + 5)
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const handleZoomOut = () => {
|
|
306
|
+
if (zoom > 0) {
|
|
307
|
+
setZoom(zoom - 5)
|
|
308
|
+
props.onZoomChange?.(zoom - 5)
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const options = props.options || [
|
|
313
|
+
{ label: 'Option 1', description: 'First option' },
|
|
314
|
+
{ label: 'Option 2', description: 'Second option' },
|
|
315
|
+
{ label: 'Option 3', description: 'Third option' },
|
|
316
|
+
]
|
|
317
|
+
|
|
318
|
+
const tooltipButtons = props.tooltipButtons || [
|
|
319
|
+
{ icon: MousePointerIcon, label: 'Select' },
|
|
320
|
+
{ icon: SquareIcon, label: 'Shapes' },
|
|
321
|
+
{ icon: CropIcon, label: 'Crop' },
|
|
322
|
+
{ icon: CopyIcon, label: 'Duplicate' },
|
|
323
|
+
{ icon: EllipsisVerticalIcon, label: 'More' },
|
|
324
|
+
]
|
|
325
|
+
|
|
326
|
+
const roundedButtons = props.roundedButtons || [
|
|
327
|
+
{ icon: SkipBackIcon, label: 'Skip Back' },
|
|
328
|
+
{ icon: PlayIcon, label: 'Play' },
|
|
329
|
+
{ icon: PauseIcon, label: 'Pause' },
|
|
330
|
+
{ icon: SkipForwardIcon, label: 'Skip Forward' },
|
|
331
|
+
]
|
|
332
|
+
|
|
333
|
+
const socialButtons = props.socialButtons || [
|
|
334
|
+
{ icon: TwitchIcon, label: 'Twitch', color: '#9146ff' },
|
|
335
|
+
{ icon: DribbbleIcon, label: 'Dribbble', color: '#EA4C89' },
|
|
336
|
+
{ icon: InstagramIcon, label: 'Instagram', color: '#fb169a' },
|
|
337
|
+
{ icon: FacebookIcon, label: 'Facebook', color: '#0866ff' },
|
|
338
|
+
]
|
|
339
|
+
|
|
340
|
+
const actionButtons = props.actionButtons || [
|
|
341
|
+
{ icon: SquarePenIcon, label: 'Edit' },
|
|
342
|
+
{ icon: CopyIcon, label: 'Duplicate' },
|
|
343
|
+
{ icon: Trash2Icon, label: 'Delete' },
|
|
344
|
+
]
|
|
345
|
+
|
|
346
|
+
const ghostButtons = props.ghostButtons || [
|
|
347
|
+
{ icon: SettingsIcon, label: 'Settings' },
|
|
348
|
+
{ icon: BoxIcon, label: 'Dashboard' },
|
|
349
|
+
{ icon: ChartBarBigIcon, label: 'Analytics' },
|
|
350
|
+
]
|
|
351
|
+
|
|
352
|
+
const shineButtons = props.shineButtons || ['Upload', 'Download', 'Share']
|
|
353
|
+
|
|
354
|
+
switch (buttonGroupType) {
|
|
355
|
+
case 'download':
|
|
356
|
+
return (
|
|
357
|
+
<div className='inline-flex w-fit -space-x-px rounded-md shadow-xs rtl:space-x-reverse'>
|
|
358
|
+
<Button variant='outline' className='rounded-none rounded-l-md shadow-none focus-visible:z-10'>
|
|
359
|
+
<DownloadIcon />
|
|
360
|
+
Download
|
|
361
|
+
</Button>
|
|
362
|
+
<span className='bg-background dark:border-input dark:bg-input/30 flex items-center rounded-r-md border px-3 text-sm font-medium'>
|
|
363
|
+
{props.count || '15k'}
|
|
364
|
+
</span>
|
|
365
|
+
</div>
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
case 'like':
|
|
369
|
+
return (
|
|
370
|
+
<div className='inline-flex w-fit -space-x-px rounded-md shadow-xs rtl:space-x-reverse'>
|
|
371
|
+
<Button
|
|
372
|
+
variant='outline'
|
|
373
|
+
className='rounded-none rounded-l-md shadow-none focus-visible:z-10'
|
|
374
|
+
onClick={() => {
|
|
375
|
+
setIsLiked(!isLiked)
|
|
376
|
+
props.onLikeChange?.(!isLiked)
|
|
377
|
+
}}
|
|
378
|
+
>
|
|
379
|
+
<HeartIcon className={cn({ 'fill-destructive stroke-destructive': isLiked })} />
|
|
380
|
+
Like
|
|
381
|
+
</Button>
|
|
382
|
+
<span className='bg-background dark:border-input dark:bg-input/30 flex items-center rounded-r-md border px-3 text-sm font-medium'>
|
|
383
|
+
{isLiked ? (props.likedCount || 46) : (props.unlikedCount || 45)}
|
|
384
|
+
</span>
|
|
385
|
+
</div>
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
case 'tooltip':
|
|
389
|
+
return (
|
|
390
|
+
<div className='inline-flex w-fit -space-x-px rounded-md shadow-xs rtl:space-x-reverse'>
|
|
391
|
+
{tooltipButtons.map((btn: any, index: number) => {
|
|
392
|
+
const Icon = btn.icon
|
|
393
|
+
const isFirst = index === 0
|
|
394
|
+
const isLast = index === tooltipButtons.length - 1
|
|
395
|
+
|
|
396
|
+
return (
|
|
397
|
+
<Tooltip key={index}>
|
|
398
|
+
<TooltipTrigger asChild>
|
|
399
|
+
<Button
|
|
400
|
+
className={cn(
|
|
401
|
+
'rounded-none shadow-none focus-visible:z-10',
|
|
402
|
+
isFirst && 'rounded-l-md',
|
|
403
|
+
isLast && 'rounded-r-md'
|
|
404
|
+
)}
|
|
405
|
+
variant='outline'
|
|
406
|
+
>
|
|
407
|
+
<Icon />
|
|
408
|
+
<span className='sr-only'>{btn.label}</span>
|
|
409
|
+
</Button>
|
|
410
|
+
</TooltipTrigger>
|
|
411
|
+
<TooltipContent className='px-2 py-1 text-xs'>{btn.label}</TooltipContent>
|
|
412
|
+
</Tooltip>
|
|
413
|
+
)
|
|
414
|
+
})}
|
|
415
|
+
</div>
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
case 'rounded':
|
|
419
|
+
return (
|
|
420
|
+
<div className='divide-primary-foreground/30 inline-flex w-fit divide-x rounded-full shadow-xs'>
|
|
421
|
+
{roundedButtons.map((btn: any, index: number) => {
|
|
422
|
+
const Icon = btn.icon
|
|
423
|
+
const isFirst = index === 0
|
|
424
|
+
const isLast = index === roundedButtons.length - 1
|
|
425
|
+
|
|
426
|
+
return (
|
|
427
|
+
<Tooltip key={index}>
|
|
428
|
+
<TooltipTrigger asChild>
|
|
429
|
+
<Button
|
|
430
|
+
className={cn(
|
|
431
|
+
'rounded-none focus-visible:z-10',
|
|
432
|
+
isFirst && 'rounded-l-full',
|
|
433
|
+
isLast && 'rounded-r-full'
|
|
434
|
+
)}
|
|
435
|
+
>
|
|
436
|
+
<Icon />
|
|
437
|
+
<span className='sr-only'>{btn.label}</span>
|
|
438
|
+
</Button>
|
|
439
|
+
</TooltipTrigger>
|
|
440
|
+
<TooltipContent className='px-2 py-1 text-xs'>{btn.label}</TooltipContent>
|
|
441
|
+
</Tooltip>
|
|
442
|
+
)
|
|
443
|
+
})}
|
|
444
|
+
</div>
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
case 'social':
|
|
448
|
+
return (
|
|
449
|
+
<div className='inline-flex w-fit -space-x-px rounded-md shadow-xs rtl:space-x-reverse'>
|
|
450
|
+
{socialButtons.map((btn: any, index: number) => {
|
|
451
|
+
const Icon = btn.icon
|
|
452
|
+
const isFirst = index === 0
|
|
453
|
+
const isLast = index === socialButtons.length - 1
|
|
454
|
+
|
|
455
|
+
return (
|
|
456
|
+
<Button
|
|
457
|
+
key={index}
|
|
458
|
+
variant='outline'
|
|
459
|
+
className={cn(
|
|
460
|
+
'rounded-none shadow-none focus-visible:z-10',
|
|
461
|
+
isFirst && 'rounded-l-md',
|
|
462
|
+
isLast && 'rounded-r-md'
|
|
463
|
+
)}
|
|
464
|
+
style={{
|
|
465
|
+
['--hover-bg' as any]: `${btn.color}1a`,
|
|
466
|
+
}}
|
|
467
|
+
onMouseEnter={(e) => {
|
|
468
|
+
e.currentTarget.style.backgroundColor = `${btn.color}1a`
|
|
469
|
+
}}
|
|
470
|
+
onMouseLeave={(e) => {
|
|
471
|
+
e.currentTarget.style.backgroundColor = ''
|
|
472
|
+
}}
|
|
473
|
+
asChild
|
|
474
|
+
>
|
|
475
|
+
<a href='#' target='_blank' rel='noopener noreferrer'>
|
|
476
|
+
<Icon className={`stroke-[${btn.color}]`} style={{ stroke: btn.color }} />
|
|
477
|
+
<span className='sr-only'>{btn.label}</span>
|
|
478
|
+
</a>
|
|
479
|
+
</Button>
|
|
480
|
+
)
|
|
481
|
+
})}
|
|
482
|
+
</div>
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
case 'zoom':
|
|
486
|
+
return (
|
|
487
|
+
<div className='inline-flex w-fit -space-x-px rounded-md shadow-xs rtl:space-x-reverse'>
|
|
488
|
+
<Button
|
|
489
|
+
variant='outline'
|
|
490
|
+
size='icon'
|
|
491
|
+
className='rounded-none rounded-l-md shadow-none focus-visible:z-10'
|
|
492
|
+
onClick={handleZoomOut}
|
|
493
|
+
disabled={zoom === 0}
|
|
494
|
+
>
|
|
495
|
+
<ZoomOutIcon />
|
|
496
|
+
<span className='sr-only'>Zoom out</span>
|
|
497
|
+
</Button>
|
|
498
|
+
<span className='bg-background dark:border-input dark:bg-input/30 flex items-center border px-3 text-sm font-medium'>
|
|
499
|
+
{`${zoom}%`}
|
|
500
|
+
</span>
|
|
501
|
+
<Button
|
|
502
|
+
variant='outline'
|
|
503
|
+
size='icon'
|
|
504
|
+
className='rounded-none rounded-r-md shadow-none focus-visible:z-10'
|
|
505
|
+
onClick={handleZoomIn}
|
|
506
|
+
disabled={zoom === 100}
|
|
507
|
+
>
|
|
508
|
+
<ZoomInIcon />
|
|
509
|
+
<span className='sr-only'>Zoom in</span>
|
|
510
|
+
</Button>
|
|
511
|
+
</div>
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
case 'number':
|
|
515
|
+
return (
|
|
516
|
+
<div className='divide-primary-foreground/30 inline-flex w-fit divide-x rounded-md shadow-xs'>
|
|
517
|
+
<Button
|
|
518
|
+
size='icon'
|
|
519
|
+
className='rounded-none rounded-l-full focus-visible:z-10'
|
|
520
|
+
onClick={() => {
|
|
521
|
+
setValue(value - 1)
|
|
522
|
+
props.onValueChange?.(value - 1)
|
|
523
|
+
}}
|
|
524
|
+
>
|
|
525
|
+
<MinusIcon />
|
|
526
|
+
<span className='sr-only'>Minus</span>
|
|
527
|
+
</Button>
|
|
528
|
+
<span className='bg-primary text-primary-foreground inline-flex items-center px-3 py-2 text-sm font-medium'>
|
|
529
|
+
{`${value}${props.unit || 'px'}`}
|
|
530
|
+
</span>
|
|
531
|
+
<Button
|
|
532
|
+
size='icon'
|
|
533
|
+
className='rounded-none rounded-r-full focus-visible:z-10'
|
|
534
|
+
onClick={() => {
|
|
535
|
+
setValue(value + 1)
|
|
536
|
+
props.onValueChange?.(value + 1)
|
|
537
|
+
}}
|
|
538
|
+
>
|
|
539
|
+
<PlusIcon />
|
|
540
|
+
<span className='sr-only'>Plus</span>
|
|
541
|
+
</Button>
|
|
542
|
+
</div>
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
case 'preview':
|
|
546
|
+
return (
|
|
547
|
+
<div className='inline-flex w-fit -space-x-px rounded-md shadow-xs rtl:space-x-reverse'>
|
|
548
|
+
<Button variant='outline' className='rounded-none rounded-l-md shadow-none focus-visible:z-10' asChild>
|
|
549
|
+
<a href='#'>Live preview</a>
|
|
550
|
+
</Button>
|
|
551
|
+
<Button
|
|
552
|
+
variant='outline'
|
|
553
|
+
size='icon'
|
|
554
|
+
className='rounded-none rounded-r-md shadow-none focus-visible:z-10'
|
|
555
|
+
asChild
|
|
556
|
+
>
|
|
557
|
+
<a href='#' target='_blank' rel='noopener noreferrer'>
|
|
558
|
+
<ExternalLinkIcon />
|
|
559
|
+
<span className='sr-only'>External link</span>
|
|
560
|
+
</a>
|
|
561
|
+
</Button>
|
|
562
|
+
</div>
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
case 'actions':
|
|
566
|
+
return (
|
|
567
|
+
<div className='inline-flex w-fit -space-x-px rounded-md shadow-xs rtl:space-x-reverse'>
|
|
568
|
+
{actionButtons.map((btn: any, index: number) => {
|
|
569
|
+
const Icon = btn.icon
|
|
570
|
+
const isFirst = index === 0
|
|
571
|
+
const isLast = index === actionButtons.length - 1
|
|
572
|
+
|
|
573
|
+
return (
|
|
574
|
+
<Button
|
|
575
|
+
key={index}
|
|
576
|
+
variant='outline'
|
|
577
|
+
className={cn(
|
|
578
|
+
'rounded-none shadow-none focus-visible:z-10',
|
|
579
|
+
isFirst && 'rounded-l-md',
|
|
580
|
+
isLast && 'rounded-r-md'
|
|
581
|
+
)}
|
|
582
|
+
>
|
|
583
|
+
<Icon />
|
|
584
|
+
{btn.label}
|
|
585
|
+
</Button>
|
|
586
|
+
)
|
|
587
|
+
})}
|
|
588
|
+
</div>
|
|
589
|
+
)
|
|
590
|
+
|
|
591
|
+
case 'basic':
|
|
592
|
+
return (
|
|
593
|
+
<div className='divide-primary-foreground/30 inline-flex w-fit divide-x rounded-md shadow-xs'>
|
|
594
|
+
<Button size='icon' className='rounded-none rounded-l-md focus-visible:z-10'>
|
|
595
|
+
<FlipHorizontalIcon />
|
|
596
|
+
<span className='sr-only'>Flip Horizontal</span>
|
|
597
|
+
</Button>
|
|
598
|
+
<Button size='icon' className='rounded-none rounded-r-md focus-visible:z-10'>
|
|
599
|
+
<FlipVerticalIcon />
|
|
600
|
+
<span className='sr-only'>Flip Vertical</span>
|
|
601
|
+
</Button>
|
|
602
|
+
</div>
|
|
603
|
+
)
|
|
604
|
+
|
|
605
|
+
case 'dropdown':
|
|
606
|
+
return (
|
|
607
|
+
<div className='divide-primary-foreground/30 inline-flex w-fit divide-x rounded-md shadow-xs'>
|
|
608
|
+
<Button className='rounded-none rounded-l-md focus-visible:z-10'>
|
|
609
|
+
{options[Number(selectedIndex)].label}
|
|
610
|
+
</Button>
|
|
611
|
+
<DropdownMenu>
|
|
612
|
+
<DropdownMenuTrigger asChild>
|
|
613
|
+
<Button size='icon' className='rounded-none rounded-r-md focus-visible:z-10'>
|
|
614
|
+
<ChevronDownIcon />
|
|
615
|
+
<span className='sr-only'>Select option</span>
|
|
616
|
+
</Button>
|
|
617
|
+
</DropdownMenuTrigger>
|
|
618
|
+
<DropdownMenuContent side='bottom' sideOffset={4} align='end' className='max-w-64 md:max-w-xs!'>
|
|
619
|
+
<DropdownMenuRadioGroup value={selectedIndex} onValueChange={(v) => {
|
|
620
|
+
setSelectedIndex(v)
|
|
621
|
+
props.onOptionChange?.(v)
|
|
622
|
+
}}>
|
|
623
|
+
{options.map((option: any, index: number) => (
|
|
624
|
+
<DropdownMenuRadioItem
|
|
625
|
+
key={option.label}
|
|
626
|
+
value={String(index)}
|
|
627
|
+
className='items-start [&>span]:pt-1.5'
|
|
628
|
+
>
|
|
629
|
+
<div className='flex flex-col gap-1'>
|
|
630
|
+
<span className='text-sm font-medium'>{option.label}</span>
|
|
631
|
+
<span className='text-muted-foreground text-xs'>{option.description}</span>
|
|
632
|
+
</div>
|
|
633
|
+
</DropdownMenuRadioItem>
|
|
634
|
+
))}
|
|
635
|
+
</DropdownMenuRadioGroup>
|
|
636
|
+
</DropdownMenuContent>
|
|
637
|
+
</DropdownMenu>
|
|
638
|
+
</div>
|
|
639
|
+
)
|
|
640
|
+
|
|
641
|
+
case 'ghost':
|
|
642
|
+
return (
|
|
643
|
+
<div className='inline-flex w-fit rounded-md rtl:space-x-reverse'>
|
|
644
|
+
{ghostButtons.map((btn: any, index: number) => {
|
|
645
|
+
const Icon = btn.icon
|
|
646
|
+
const isFirst = index === 0
|
|
647
|
+
const isLast = index === ghostButtons.length - 1
|
|
648
|
+
|
|
649
|
+
return (
|
|
650
|
+
<Button
|
|
651
|
+
key={index}
|
|
652
|
+
variant='ghost'
|
|
653
|
+
className={cn(
|
|
654
|
+
'rounded-none focus-visible:z-10',
|
|
655
|
+
isFirst && 'rounded-l-md',
|
|
656
|
+
isLast && 'rounded-r-md'
|
|
657
|
+
)}
|
|
658
|
+
>
|
|
659
|
+
<Icon />
|
|
660
|
+
{btn.label}
|
|
661
|
+
</Button>
|
|
662
|
+
)
|
|
663
|
+
})}
|
|
664
|
+
</div>
|
|
665
|
+
)
|
|
666
|
+
|
|
667
|
+
case 'reveal':
|
|
668
|
+
return (
|
|
669
|
+
<div className='inline-flex w-fit -space-x-px rounded-md shadow-xs rtl:space-x-reverse'>
|
|
670
|
+
<Button
|
|
671
|
+
variant='outline'
|
|
672
|
+
className='group w-20 justify-start gap-3 overflow-hidden rounded-none rounded-l-md shadow-none transition-all duration-200 not-hover:w-10 hover:bg-sky-500/10 hover:text-sky-500 focus-visible:z-10 dark:hover:bg-sky-400/10 dark:hover:text-sky-400'
|
|
673
|
+
>
|
|
674
|
+
<ThumbsUpIcon />
|
|
675
|
+
Like
|
|
676
|
+
</Button>
|
|
677
|
+
<Button
|
|
678
|
+
variant='outline'
|
|
679
|
+
className='hover:bg-destructive/10! group hover:text-destructive w-24.5 justify-end gap-3 overflow-hidden rounded-none rounded-r-md shadow-none transition-all duration-200 not-hover:w-10 focus-visible:z-10'
|
|
680
|
+
>
|
|
681
|
+
Dislike
|
|
682
|
+
<ThumbsDownIcon />
|
|
683
|
+
</Button>
|
|
684
|
+
</div>
|
|
685
|
+
)
|
|
686
|
+
|
|
687
|
+
case 'shine':
|
|
688
|
+
return (
|
|
689
|
+
<div className='divide-primary-foreground/30 inline-flex w-fit divide-x rounded-md shadow-xs'>
|
|
690
|
+
{shineButtons.map((label: string, index: number) => {
|
|
691
|
+
const isFirst = index === 0
|
|
692
|
+
const isLast = index === shineButtons.length - 1
|
|
693
|
+
|
|
694
|
+
return (
|
|
695
|
+
<Button
|
|
696
|
+
key={index}
|
|
697
|
+
className={cn(
|
|
698
|
+
'relative overflow-hidden rounded-none focus-visible:z-10',
|
|
699
|
+
'before:absolute before:inset-0 before:rounded-[inherit]',
|
|
700
|
+
'before:bg-[linear-gradient(45deg,transparent_25%,rgba(255,255,255,0.35)_50%,transparent_75%,transparent_100%)]',
|
|
701
|
+
'before:bg-[length:250%_250%,100%_100%] before:bg-[position:200%_0,0_0]',
|
|
702
|
+
'before:bg-no-repeat before:transition-[background-position_0s_ease] before:duration-1000',
|
|
703
|
+
'hover:before:bg-[position:-100%_0,0_0]',
|
|
704
|
+
'dark:before:bg-[linear-gradient(45deg,transparent_25%,rgba(0,0,0,0.2)_50%,transparent_75%,transparent_100%)]',
|
|
705
|
+
isFirst && 'rounded-l-md',
|
|
706
|
+
isLast && 'rounded-r-md'
|
|
707
|
+
)}
|
|
708
|
+
>
|
|
709
|
+
{label}
|
|
710
|
+
</Button>
|
|
711
|
+
)
|
|
712
|
+
})}
|
|
713
|
+
</div>
|
|
714
|
+
)
|
|
715
|
+
|
|
716
|
+
default:
|
|
717
|
+
return (
|
|
718
|
+
<ButtonGroup {...props}>
|
|
719
|
+
{props.children}
|
|
720
|
+
</ButtonGroup>
|
|
721
|
+
)
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
export function ButtonGroupXDemo() {
|
|
726
|
+
return (
|
|
727
|
+
<div className="space-y-12 p-6 max-w-4xl mx-auto">
|
|
728
|
+
<div>
|
|
729
|
+
<h3 className="text-lg font-semibold mb-4">Download Button Group</h3>
|
|
730
|
+
<ButtonGroupX buttonGroup="download">
|
|
731
|
+
<ButtonGroupXWrapper count="15k" />
|
|
732
|
+
</ButtonGroupX>
|
|
733
|
+
</div>
|
|
734
|
+
|
|
735
|
+
<div>
|
|
736
|
+
<h3 className="text-lg font-semibold mb-4">Like Button Group</h3>
|
|
737
|
+
<ButtonGroupX buttonGroup="like">
|
|
738
|
+
<ButtonGroupXWrapper
|
|
739
|
+
isLiked={true}
|
|
740
|
+
likedCount={46}
|
|
741
|
+
unlikedCount={45}
|
|
742
|
+
onLikeChange={(liked) => console.log('Liked:', liked)}
|
|
743
|
+
/>
|
|
744
|
+
</ButtonGroupX>
|
|
745
|
+
</div>
|
|
746
|
+
|
|
747
|
+
<div>
|
|
748
|
+
<h3 className="text-lg font-semibold mb-4">Tooltip Button Group</h3>
|
|
749
|
+
<ButtonGroupX buttonGroup="tooltip">
|
|
750
|
+
<ButtonGroupXWrapper />
|
|
751
|
+
</ButtonGroupX>
|
|
752
|
+
</div>
|
|
753
|
+
|
|
754
|
+
<div>
|
|
755
|
+
<h3 className="text-lg font-semibold mb-4">Rounded Button Group</h3>
|
|
756
|
+
<ButtonGroupX buttonGroup="rounded">
|
|
757
|
+
<ButtonGroupXWrapper />
|
|
758
|
+
</ButtonGroupX>
|
|
759
|
+
</div>
|
|
760
|
+
|
|
761
|
+
<div>
|
|
762
|
+
<h3 className="text-lg font-semibold mb-4">Social Media Button Group</h3>
|
|
763
|
+
<ButtonGroupX buttonGroup="social">
|
|
764
|
+
<ButtonGroupXWrapper />
|
|
765
|
+
</ButtonGroupX>
|
|
766
|
+
</div>
|
|
767
|
+
|
|
768
|
+
<div>
|
|
769
|
+
<h3 className="text-lg font-semibold mb-4">Zoom Button Group</h3>
|
|
770
|
+
<ButtonGroupX buttonGroup="zoom">
|
|
771
|
+
<ButtonGroupXWrapper
|
|
772
|
+
zoom={95}
|
|
773
|
+
onZoomChange={(zoom) => console.log('Zoom:', zoom)}
|
|
774
|
+
/>
|
|
775
|
+
</ButtonGroupX>
|
|
776
|
+
</div>
|
|
777
|
+
|
|
778
|
+
<div>
|
|
779
|
+
<h3 className="text-lg font-semibold mb-4">Number Button Group</h3>
|
|
780
|
+
<ButtonGroupX buttonGroup="number">
|
|
781
|
+
<ButtonGroupXWrapper
|
|
782
|
+
value={216}
|
|
783
|
+
unit="px"
|
|
784
|
+
onValueChange={(val) => console.log('Value:', val)}
|
|
785
|
+
/>
|
|
786
|
+
</ButtonGroupX>
|
|
787
|
+
</div>
|
|
788
|
+
|
|
789
|
+
<div>
|
|
790
|
+
<h3 className="text-lg font-semibold mb-4">Preview Button Group</h3>
|
|
791
|
+
<ButtonGroupX buttonGroup="preview">
|
|
792
|
+
<ButtonGroupXWrapper />
|
|
793
|
+
</ButtonGroupX>
|
|
794
|
+
</div>
|
|
795
|
+
|
|
796
|
+
<div>
|
|
797
|
+
<h3 className="text-lg font-semibold mb-4">Actions Button Group</h3>
|
|
798
|
+
<ButtonGroupX buttonGroup="actions">
|
|
799
|
+
<ButtonGroupXWrapper />
|
|
800
|
+
</ButtonGroupX>
|
|
801
|
+
</div>
|
|
802
|
+
|
|
803
|
+
<div>
|
|
804
|
+
<h3 className="text-lg font-semibold mb-4">Basic Button Group</h3>
|
|
805
|
+
<ButtonGroupX buttonGroup="basic">
|
|
806
|
+
<ButtonGroupXWrapper />
|
|
807
|
+
</ButtonGroupX>
|
|
808
|
+
</div>
|
|
809
|
+
|
|
810
|
+
<div>
|
|
811
|
+
<h3 className="text-lg font-semibold mb-4">Dropdown Button Group</h3>
|
|
812
|
+
<ButtonGroupX buttonGroup="dropdown">
|
|
813
|
+
<ButtonGroupXWrapper
|
|
814
|
+
options={[
|
|
815
|
+
{ label: 'Merge Pull Request', description: 'All commits will be added to the base branch' },
|
|
816
|
+
{ label: 'Squash and Merge', description: 'The commits will be combined into one commit' },
|
|
817
|
+
{ label: 'Rebase and Merge', description: 'The commits will be rebased and added' },
|
|
818
|
+
]}
|
|
819
|
+
selectedIndex="0"
|
|
820
|
+
onOptionChange={(index) => console.log('Selected:', index)}
|
|
821
|
+
/>
|
|
822
|
+
</ButtonGroupX>
|
|
823
|
+
</div>
|
|
824
|
+
|
|
825
|
+
<div>
|
|
826
|
+
<h3 className="text-lg font-semibold mb-4">Ghost Button Group</h3>
|
|
827
|
+
<ButtonGroupX buttonGroup="ghost">
|
|
828
|
+
<ButtonGroupXWrapper />
|
|
829
|
+
</ButtonGroupX>
|
|
830
|
+
</div>
|
|
831
|
+
|
|
832
|
+
<div>
|
|
833
|
+
<h3 className="text-lg font-semibold mb-4">Reveal Button Group</h3>
|
|
834
|
+
<ButtonGroupX buttonGroup="reveal">
|
|
835
|
+
<ButtonGroupXWrapper />
|
|
836
|
+
</ButtonGroupX>
|
|
837
|
+
</div>
|
|
838
|
+
|
|
839
|
+
<div>
|
|
840
|
+
<h3 className="text-lg font-semibold mb-4">Shine Button Group</h3>
|
|
841
|
+
<ButtonGroupX buttonGroup="shine">
|
|
842
|
+
<ButtonGroupXWrapper shineButtons={['Upload', 'Download', 'Share']} />
|
|
843
|
+
</ButtonGroupX>
|
|
844
|
+
</div>
|
|
845
|
+
</div>
|
|
846
|
+
)
|
|
847
|
+
}
|