Skip to content

Commit f5f52ff

Browse files
authored
feat: button-group component (#1431)
* feat: button-group component #1430 * fix: change button-group registryDependencies
1 parent fa29558 commit f5f52ff

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1821
-13
lines changed

apps/v4/__registry__/index.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,35 @@ export const Index: Record<string, any> = {
255255
category: "",
256256
subcategory: ""
257257
},
258+
"button-group": {
259+
name: "button-group",
260+
description: "",
261+
type: "registry:ui",
262+
registryDependencies: [],
263+
files: [{
264+
path: "registry/new-york-v4/ui/button-group/ButtonGroup.vue",
265+
type: "registry:ui",
266+
target: ""
267+
},
268+
{
269+
path: "registry/new-york-v4/ui/button-group/ButtonGroupSeparator.vue",
270+
type: "registry:ui",
271+
target: ""
272+
},
273+
{
274+
path: "registry/new-york-v4/ui/button-group/ButtonGroupText.vue",
275+
type: "registry:ui",
276+
target: ""
277+
},{
278+
path: "registry/new-york-v4/ui/button-group/index.ts",
279+
type: "registry:ui",
280+
target: ""
281+
}],
282+
component: () => import("@/registry/new-york-v4/ui/button-group/ButtonGroup.vue").then((m) => m.default),
283+
source: "",
284+
category: "",
285+
subcategory: ""
286+
},
258287
"calendar": {
259288
name: "calendar",
260289
description: "",
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<script setup lang="ts">
2+
import { ArchiveIcon, ArrowLeftIcon, CalendarPlusIcon, ClockIcon, ListFilterPlusIcon, MailCheckIcon, MoreHorizontalIcon, TagIcon, Trash2Icon } from 'lucide-vue-next'
3+
import { Button } from '@/registry/new-york-v4/ui/button'
4+
import { ButtonGroup } from '@/registry/new-york-v4/ui/button-group'
5+
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from '@/registry/new-york-v4/ui/dropdown-menu'
6+
7+
const label = ref('personal')
8+
</script>
9+
10+
<template>
11+
<ButtonGroup>
12+
<ButtonGroup class="hidden sm:flex">
13+
<Button variant="outline" size="icon" aria-label="Go Back">
14+
<ArrowLeftIcon />
15+
</Button>
16+
</ButtonGroup>
17+
<ButtonGroup>
18+
<Button variant="outline">
19+
Archive
20+
</Button>
21+
<Button variant="outline">
22+
Report
23+
</Button>
24+
</ButtonGroup>
25+
<ButtonGroup>
26+
<Button variant="outline">
27+
Snooze
28+
</Button>
29+
<DropdownMenu>
30+
<DropdownMenuTrigger as-child>
31+
<Button variant="outline" size="icon" aria-label="More Options">
32+
<MoreHorizontalIcon />
33+
</Button>
34+
</DropdownMenuTrigger>
35+
<DropdownMenuContent align="end" class="w-52">
36+
<DropdownMenuGroup>
37+
<DropdownMenuItem>
38+
<MailCheckIcon />
39+
Mark as Read
40+
</DropdownMenuItem>
41+
<DropdownMenuItem>
42+
<ArchiveIcon />
43+
Archive
44+
</DropdownMenuItem>
45+
</DropdownMenuGroup>
46+
<DropdownMenuSeparator />
47+
<DropdownMenuGroup>
48+
<DropdownMenuItem>
49+
<ClockIcon />
50+
Snooze
51+
</DropdownMenuItem>
52+
<DropdownMenuItem>
53+
<CalendarPlusIcon />
54+
Add to Calendar
55+
</DropdownMenuItem>
56+
<DropdownMenuItem>
57+
<ListFilterPlusIcon />
58+
Add to List
59+
</DropdownMenuItem>
60+
<DropdownMenuSub>
61+
<DropdownMenuSubTrigger>
62+
<TagIcon class="mr-2 size-4" />
63+
Label As...
64+
</DropdownMenuSubTrigger>
65+
<DropdownMenuSubContent>
66+
<DropdownMenuRadioGroup v-model="label">
67+
<DropdownMenuRadioItem value="personal">
68+
Personal
69+
</DropdownMenuRadioItem>
70+
<DropdownMenuRadioItem value="work">
71+
Work
72+
</DropdownMenuRadioItem>
73+
<DropdownMenuRadioItem value="other">
74+
Other
75+
</DropdownMenuRadioItem>
76+
</DropdownMenuRadioGroup>
77+
</DropdownMenuSubContent>
78+
</DropdownMenuSub>
79+
</DropdownMenuGroup>
80+
<DropdownMenuSeparator />
81+
<DropdownMenuGroup>
82+
<DropdownMenuItem variant="destructive">
83+
<Trash2Icon />
84+
Trash
85+
</DropdownMenuItem>
86+
</DropdownMenuGroup>
87+
</DropdownMenuContent>
88+
</DropdownMenu>
89+
</ButtonGroup>
90+
</ButtonGroup>
91+
</template>

apps/v4/pages/index.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
<ComponentWrapper name="Button">
2828
<LazyButtonDemo />
2929
</ComponentWrapper>
30+
<ComponentWrapper name="ButtonGroup">
31+
<LazyButtonGroupDemo />
32+
</ComponentWrapper>
3033
<ComponentWrapper name="Calendar">
3134
<LazyCalendarDemo />
3235
</ComponentWrapper>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<script lang='ts' setup>
2+
import type { HTMLAttributes } from "vue"
3+
import type { ButtonGroupVariants } from "."
4+
import { cn } from "@/lib/utils"
5+
import { buttonGroupVariants } from "."
6+
7+
const props = defineProps<{
8+
class?: HTMLAttributes["class"]
9+
orientation?: ButtonGroupVariants["orientation"]
10+
}>()
11+
</script>
12+
13+
<template>
14+
<div
15+
role="group"
16+
data-slot="button-group"
17+
:data-orientation="props.orientation"
18+
:class="cn(buttonGroupVariants({ orientation: props.orientation }), props.class)"
19+
>
20+
<slot />
21+
</div>
22+
</template>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<script lang='ts' setup>
2+
import type { SeparatorProps } from "reka-ui"
3+
import type { HTMLAttributes } from "vue"
4+
import { reactiveOmit } from "@vueuse/core"
5+
import { cn } from "@/lib/utils"
6+
import { Separator } from "@/registry/new-york-v4/ui/separator"
7+
8+
const props = withDefaults(defineProps<SeparatorProps & { class?: HTMLAttributes["class"] }>(), {
9+
orientation: "vertical",
10+
})
11+
const delegatedProps = reactiveOmit(props, "class")
12+
</script>
13+
14+
<template>
15+
<Separator
16+
data-slot="button-group-separator"
17+
v-bind="delegatedProps"
18+
:orientation="props.orientation"
19+
:class="cn(
20+
'bg-input relative !m-0 self-stretch data-[orientation=vertical]:h-auto',
21+
props.class,
22+
)"
23+
/>
24+
</template>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<script lang='ts' setup>
2+
import type { PrimitiveProps } from "reka-ui"
3+
import type { HTMLAttributes } from "vue"
4+
import type { ButtonGroupVariants } from "."
5+
import { Primitive } from "reka-ui"
6+
import { cn } from "@/lib/utils"
7+
8+
interface Props extends PrimitiveProps {
9+
class?: HTMLAttributes["class"]
10+
orientation?: ButtonGroupVariants["orientation"]
11+
}
12+
13+
const props = withDefaults(defineProps<Props>(), {
14+
as: "div",
15+
})
16+
</script>
17+
18+
<template>
19+
<Primitive
20+
role="group"
21+
data-slot="button-group"
22+
:data-orientation="props.orientation"
23+
:as="as"
24+
:as-child="asChild"
25+
:class="cn('bg-muted flex items-center gap-2 rounded-md border px-4 text-sm font-medium shadow-xs [&_svg]:pointer-events-none [&_svg:not([class*=`size-`])]:size-4', props.class)"
26+
>
27+
<slot />
28+
</Primitive>
29+
</template>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import type { VariantProps } from "class-variance-authority"
2+
import { cva } from "class-variance-authority"
3+
4+
export { default as ButtonGroup } from "./ButtonGroup.vue"
5+
export { default as ButtonGroupSeparator } from "./ButtonGroupSeparator.vue"
6+
export { default as ButtonGroupText } from "./ButtonGroupText.vue"
7+
8+
export const buttonGroupVariants = cva(
9+
"flex w-fit items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2",
10+
{
11+
variants: {
12+
orientation: {
13+
horizontal:
14+
"[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
15+
vertical:
16+
"flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none",
17+
},
18+
},
19+
defaultVariants: {
20+
orientation: "horizontal",
21+
},
22+
},
23+
)
24+
25+
export type ButtonGroupVariants = VariantProps<typeof buttonGroupVariants>

apps/v4/registry/new-york-v4/ui/button/index.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ export const buttonVariants = cva(
2121
link: "text-primary underline-offset-4 hover:underline",
2222
},
2323
size: {
24-
default: "h-9 px-4 py-2 has-[>svg]:px-3",
25-
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
26-
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
27-
icon: "size-9",
24+
"default": "h-9 px-4 py-2 has-[>svg]:px-3",
25+
"sm": "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
26+
"lg": "h-10 rounded-md px-6 has-[>svg]:px-4",
27+
"icon": "size-9",
28+
"icon-sm": "size-8",
29+
"icon-lg": "size-10",
2830
},
2931
},
3032
defaultVariants: {

apps/www/.vitepress/theme/config/docs.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,10 @@ export const docsConfig: DocsConfig = {
209209
title: 'Button',
210210
href: '/docs/components/button',
211211
},
212+
{
213+
title: 'ButtonGroup',
214+
href: '/docs/components/button-group',
215+
},
212216
{
213217
title: 'Calendar',
214218
href: '/docs/components/calendar',

0 commit comments

Comments
 (0)