Skip to content

Commit a95ddae

Browse files
Toggle group (#168)
* feat: Add toggle group component * chore: Fix registry build path for toggle group * Build Registry * Remove styles * Run registry * Fix styles
1 parent f9cc070 commit a95ddae

File tree

10 files changed

+448
-0
lines changed

10 files changed

+448
-0
lines changed
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
import { Metadata } from "next"
2+
import { Separator } from "@radix-ui/react-select"
3+
import { Bold, Italic, Underline } from "lucide-react"
4+
5+
import { toggleGroupMetaData } from "@/lib/metadata"
6+
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/8bit/toggle-group"
7+
8+
import CodeSnippet from "../code-snippet"
9+
import CopyCommandButton from "../copy-command-button"
10+
import InstallationCommands from "../installation-commands"
11+
import { OpenInV0Button } from "../open-in-v0-button"
12+
13+
export const metadata: Metadata = {
14+
title: "8bit Toggle Group",
15+
description: "Displays Toggle Group Component.",
16+
openGraph: { images: toggleGroupMetaData },
17+
}
18+
export default function ToggleGroupPage() {
19+
return (
20+
<div className="flex flex-col gap-4">
21+
<div className="flex flex-col md:flex-row items-center justify-between gap-2">
22+
<h1 className="text-3xl font-bold">Toggle Group</h1>
23+
<CopyCommandButton
24+
copyCommand={`pnpm dlx shadcn@canary add ${process.env.NEXT_PUBLIC_BASE_URL}/r/8bit-toggle-group.json`}
25+
command={"pnpm dlx shadcn@canary add 8bit-toggle-group"}
26+
/>
27+
</div>
28+
<p className="text-muted-foreground">
29+
A set of two-state buttons that can be toggled on or off.
30+
</p>
31+
<div className="flex flex-col gap-4 border rounded-lg p-4 min-h-[450px] relative">
32+
<div className="flex items-center justify-between">
33+
<h2 className="text-sm text-muted-foreground sm:pl-3">
34+
A simple 8-bit Toggle Group component
35+
</h2>
36+
<div className="flex items-center gap-2">
37+
<OpenInV0Button name="8bit-toggle-group" className="w-fit" />
38+
</div>
39+
</div>
40+
<div className="flex items-center justify-center min-h-[400px] relative">
41+
<ToggleGroup type="multiple">
42+
<ToggleGroupItem
43+
variant="outline"
44+
value="bold"
45+
aria-label="Toggle bold"
46+
>
47+
<Bold className="size-4" />
48+
</ToggleGroupItem>
49+
<ToggleGroupItem value="italic" aria-label="Toggle italic">
50+
<Italic className="size-4" />
51+
</ToggleGroupItem>
52+
<ToggleGroupItem
53+
value="strikethrough"
54+
aria-label="Toggle strikethrough"
55+
>
56+
<Underline className="size-4" />
57+
</ToggleGroupItem>
58+
</ToggleGroup>
59+
</div>
60+
</div>
61+
<h3 className="text-lg font-bold">Installation</h3> <Separator />
62+
<InstallationCommands
63+
packageUrl={`${process.env.NEXT_PUBLIC_BASE_URL}/r/8bit-toggle-group.json`}
64+
/>
65+
<h3 className="text-lg font-bold">Examples</h3> <Separator />
66+
<h3 className="text-lg font-bold">Default</h3>
67+
<div className="flex flex-col gap-4 border rounded-lg p-4 min-h-[450px] relative">
68+
<div className="flex items-center justify-between">
69+
<h2 className="text-sm text-muted-foreground sm:pl-3">
70+
Default example
71+
</h2>
72+
<div className="flex items-center gap-2">
73+
<OpenInV0Button name="8bit-toggle-group" className="w-fit" />
74+
</div>
75+
</div>
76+
<div className="flex items-center justify-center min-h-[400px] relative">
77+
<ToggleGroup type="multiple">
78+
<ToggleGroupItem value="bold" aria-label="Toggle bold">
79+
<Bold className="size-4" />
80+
</ToggleGroupItem>
81+
<ToggleGroupItem value="italic" aria-label="Toggle italic">
82+
<Italic className="size-4" />
83+
</ToggleGroupItem>
84+
<ToggleGroupItem
85+
value="strikethrough"
86+
aria-label="Toggle strikethrough"
87+
>
88+
<Underline className="size-4" />
89+
</ToggleGroupItem>
90+
</ToggleGroup>
91+
</div>
92+
</div>
93+
<CodeSnippet>{`<ToggleGroup type="multiple">
94+
<ToggleGroupItem value="bold" aria-label="Toggle bold">
95+
<Bold className="size-4" />
96+
</ToggleGroupItem>
97+
<ToggleGroupItem value="italic" aria-label="Toggle italic">
98+
<Italic className="size-4" />
99+
</ToggleGroupItem>
100+
<ToggleGroupItem value="strikethrough" aria-label="Toggle strikethrough">
101+
<Underline className="size-4" />
102+
</ToggleGroupItem>
103+
</ToggleGroup>`}</CodeSnippet>
104+
<h3 className="text-lg font-bold">Outline</h3>
105+
<div className="flex flex-col gap-4 border rounded-lg p-4 min-h-[450px] relative">
106+
<div className="flex items-center justify-between">
107+
<h2 className="text-sm text-muted-foreground sm:pl-3">
108+
Outline example
109+
</h2>
110+
<div className="flex items-center gap-2">
111+
<OpenInV0Button name="8bit-toggle-group" className="w-fit" />
112+
</div>
113+
</div>
114+
<div className="flex items-center justify-center min-h-[400px] relative">
115+
<ToggleGroup type="multiple">
116+
<ToggleGroupItem
117+
variant="outline"
118+
value="bold"
119+
aria-label="Toggle bold"
120+
>
121+
<Bold className="size-4" />
122+
</ToggleGroupItem>
123+
<ToggleGroupItem
124+
variant="outline"
125+
value="italic"
126+
aria-label="Toggle italic"
127+
>
128+
<Italic className="size-4" />
129+
</ToggleGroupItem>
130+
<ToggleGroupItem
131+
variant="outline"
132+
value="strikethrough"
133+
aria-label="Toggle strikethrough"
134+
>
135+
<Underline className="size-4" />
136+
</ToggleGroupItem>
137+
</ToggleGroup>
138+
</div>
139+
<CodeSnippet>{`<ToggleGroup type="multiple" variant="outline">
140+
<ToggleGroupItem value="bold" aria-label="Toggle bold">
141+
<Bold className="size-4" />
142+
</ToggleGroupItem>
143+
<ToggleGroupItem value="italic" aria-label="Toggle italic">
144+
<Italic className="size-4" />
145+
</ToggleGroupItem>
146+
<ToggleGroupItem value="strikethrough" aria-label="Toggle strikethrough">
147+
<Underline className="size-4" />
148+
</ToggleGroupItem>
149+
</ToggleGroup>`}</CodeSnippet>
150+
<h3 className="text-lg font-bold">Single</h3>
151+
<div className="flex flex-col gap-4 border rounded-lg p-4 min-h-[450px] relative">
152+
<div className="flex items-center justify-between">
153+
<h2 className="text-sm text-muted-foreground sm:pl-3">
154+
Single example
155+
</h2>
156+
<div className="flex items-center gap-2">
157+
<OpenInV0Button name="8bit-toggle-group" className="w-fit" />
158+
</div>
159+
</div>
160+
<div className="flex items-center justify-center min-h-[400px] relative">
161+
<ToggleGroup type="single">
162+
<ToggleGroupItem value="bold" aria-label="Toggle bold">
163+
<Bold className="size-4" />
164+
</ToggleGroupItem>
165+
<ToggleGroupItem value="italic" aria-label="Toggle italic">
166+
<Italic className="size-4" />
167+
</ToggleGroupItem>
168+
<ToggleGroupItem
169+
value="strikethrough"
170+
aria-label="Toggle strikethrough"
171+
>
172+
<Underline className="size-4" />
173+
</ToggleGroupItem>
174+
</ToggleGroup>
175+
</div>
176+
</div>
177+
<CodeSnippet>{`<ToggleGroup type="single">
178+
<ToggleGroupItem value="bold" aria-label="Toggle bold">
179+
<Bold className="size-4" />
180+
</ToggleGroupItem>
181+
<ToggleGroupItem value="italic" aria-label="Toggle italic">
182+
<Italic className="size-4" />
183+
</ToggleGroupItem>
184+
<ToggleGroupItem value="strikethrough" aria-label="Toggle strikethrough">
185+
<Underline className="size-4" />
186+
</ToggleGroupItem>
187+
</ToggleGroup>`}</CodeSnippet>
188+
<h3 className="text-lg font-bold">Disabled</h3>
189+
<div className="flex flex-col gap-4 border rounded-lg p-4 min-h-[450px] relative">
190+
<div className="flex items-center justify-between">
191+
<h2 className="text-sm text-muted-foreground sm:pl-3">
192+
Disabled example
193+
</h2>
194+
<div className="flex items-center gap-2">
195+
<OpenInV0Button name="8bit-toggle-group" className="w-fit" />
196+
</div>
197+
</div>
198+
<div className="flex items-center justify-center min-h-[400px] relative">
199+
<ToggleGroup type="multiple" disabled>
200+
<ToggleGroupItem value="bold" aria-label="Toggle bold">
201+
<Bold className="h-1 w-1" />
202+
</ToggleGroupItem>
203+
<ToggleGroupItem value="italic" aria-label="Toggle italic">
204+
<Italic className="h-1 w-1" />
205+
</ToggleGroupItem>
206+
<ToggleGroupItem
207+
value="strikethrough"
208+
aria-label="Toggle strikethrough"
209+
>
210+
<Underline className="h-1 w-1" />
211+
</ToggleGroupItem>
212+
</ToggleGroup>
213+
</div>
214+
</div>
215+
<CodeSnippet>{`<ToggleGroup type="multiple" disabled>
216+
<ToggleGroupItem value="bold" aria-label="Toggle bold">
217+
<Bold className="size-4" />
218+
</ToggleGroupItem>
219+
<ToggleGroupItem value="italic" aria-label="Toggle italic">
220+
<Italic className="size-4" />
221+
</ToggleGroupItem>
222+
<ToggleGroupItem value="strikethrough" aria-label="Toggle strikethrough">
223+
<Underline className="size-4" />
224+
</ToggleGroupItem>
225+
</ToggleGroup>`}</CodeSnippet>
226+
</div>
227+
</div>
228+
)
229+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { Press_Start_2P } from "next/font/google"
2+
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group"
3+
import { cva, type VariantProps } from "class-variance-authority"
4+
5+
import { cn } from "@/lib/utils"
6+
7+
import {
8+
ToggleGroup as ShadcnToggleGroup,
9+
ToggleGroupItem as ShadcnToggleGroupItem,
10+
} from "../toggle-group"
11+
12+
const pressStart = Press_Start_2P({ weight: ["400"], subsets: ["latin"] })
13+
14+
export const toggleGroupVariants = cva("", {
15+
variants: {
16+
font: { normal: "", retro: pressStart.className },
17+
variant: {
18+
default: "bg-transparent",
19+
outline:
20+
"bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground",
21+
},
22+
size: {
23+
default: "h-9 px-2 min-w-9",
24+
sm: "h-4 px-1.5 min-w-4",
25+
lg: "h-10 px-2.5 min-w-10",
26+
},
27+
},
28+
defaultVariants: { variant: "default", font: "retro", size: "default" },
29+
})
30+
31+
export type BitToggleGroupProps = React.ComponentPropsWithoutRef<
32+
typeof ToggleGroupPrimitive.Root
33+
> &
34+
VariantProps<typeof toggleGroupVariants>
35+
36+
export type BitToggleGroupItemProps = React.ComponentPropsWithoutRef<
37+
typeof ToggleGroupPrimitive.Item
38+
> &
39+
VariantProps<typeof toggleGroupVariants>
40+
41+
function ToggleGroup({ ...props }: BitToggleGroupProps) {
42+
const { className, font, children } = props
43+
44+
return (
45+
<ShadcnToggleGroup
46+
className={cn(
47+
"gap-3",
48+
className,
49+
font !== "normal" && pressStart.className
50+
)}
51+
{...props}
52+
>
53+
{" "}
54+
{children}{" "}
55+
</ShadcnToggleGroup>
56+
)
57+
}
58+
function ToggleGroupItem({ ...props }: BitToggleGroupItemProps) {
59+
const { className, font, children, variant } = props
60+
return (
61+
<ShadcnToggleGroupItem
62+
className={cn(
63+
"relative transition-transform active:translate-x-1 active:translate-y-1",
64+
className,
65+
font !== "normal" && pressStart.className
66+
)}
67+
{...props}
68+
>
69+
{" "}
70+
{children}{" "}
71+
{variant === "outline" && (
72+
<>
73+
{" "}
74+
<div
75+
className="absolute inset-0 -my-1.5 border-y-6 border-foreground dark:border-ring pointer-events-none"
76+
aria-hidden="true"
77+
/>{" "}
78+
<div
79+
className="absolute inset-0 -mx-1.5 border-x-6 border-foreground dark:border-ring pointer-events-none"
80+
aria-hidden="true"
81+
/>{" "}
82+
</>
83+
)}{" "}
84+
</ShadcnToggleGroupItem>
85+
)
86+
}
87+
88+
export { ToggleGroup, ToggleGroupItem }

components/ui/toggle-group.tsx

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group"
5+
import { type VariantProps } from "class-variance-authority"
6+
7+
import { cn } from "@/lib/utils"
8+
import { toggleVariants } from "@/components/ui/toggle"
9+
10+
const ToggleGroupContext = React.createContext<
11+
VariantProps<typeof toggleVariants>
12+
>({
13+
size: "default",
14+
variant: "default",
15+
})
16+
17+
const ToggleGroup = React.forwardRef<
18+
React.ElementRef<typeof ToggleGroupPrimitive.Root>,
19+
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &
20+
VariantProps<typeof toggleVariants>
21+
>(({ className, variant, size, children, ...props }, ref) => (
22+
<ToggleGroupPrimitive.Root
23+
ref={ref}
24+
className={cn("flex items-center justify-center gap-1", className)}
25+
{...props}
26+
>
27+
<ToggleGroupContext.Provider value={{ variant, size }}>
28+
{children}
29+
</ToggleGroupContext.Provider>
30+
</ToggleGroupPrimitive.Root>
31+
))
32+
33+
ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName
34+
35+
const ToggleGroupItem = React.forwardRef<
36+
React.ElementRef<typeof ToggleGroupPrimitive.Item>,
37+
React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &
38+
VariantProps<typeof toggleVariants>
39+
>(({ className, children, variant, size, ...props }, ref) => {
40+
const context = React.useContext(ToggleGroupContext)
41+
42+
return (
43+
<ToggleGroupPrimitive.Item
44+
ref={ref}
45+
className={cn(
46+
toggleVariants({
47+
variant: context.variant || variant,
48+
size: context.size || size,
49+
}),
50+
className
51+
)}
52+
{...props}
53+
>
54+
{children}
55+
</ToggleGroupPrimitive.Item>
56+
)
57+
})
58+
59+
ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName
60+
61+
export { ToggleGroup, ToggleGroupItem }

config/nav-items.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ export const navItems = {
166166
title: "Toggle",
167167
url: "/docs/components/toggle",
168168
},
169+
{
170+
title: "Toggle Group",
171+
url: "/docs/components/toggle-group",
172+
new: true,
173+
},
169174
{
170175
title: "Tooltip",
171176
url: "/docs/components/tooltip",

lib/metadata.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,4 @@ export const resizableMetaData = "/assets/8bitcn-resizable-light.png"
4545
export const paginationMetaData = "/assets/8bitcn-pagination-light.png"
4646
export const scrollAreaMetaData = "/assets/8bitcn-scrollarea-light.png"
4747
export const chartMetaData = "/assets/8bitcn-chart-light.png"
48+
export const toggleGroupMetaData = "/assets/8bitcn-toggle-group-light.png"

0 commit comments

Comments
 (0)