Skip to content

Commit

Permalink
feat(toggle-group): add toggle-group component (#1547)
Browse files Browse the repository at this point in the history
* feat: added toggle-group component

* fix(components): ran build:registry script

* fix(components): fixed colors in toggle-group
- Dark mode border color is now consistent with the toggle component

* fix(components): fixed component.json toggle-group
- Added the content field to `components.json` for toggle-group
- Ran build:registry again

* feat(toggle-group): simplify implementation

---------

Co-authored-by: shadcn <[email protected]>
  • Loading branch information
maxwiseman and shadcn authored Nov 12, 2023
1 parent 3dc6207 commit 1db90ba
Show file tree
Hide file tree
Showing 23 changed files with 705 additions and 0 deletions.
98 changes: 98 additions & 0 deletions apps/www/__registry__/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,13 @@ export const Index: Record<string, any> = {
component: React.lazy(() => import("@/registry/default/ui/toggle")),
files: ["registry/default/ui/toggle.tsx"],
},
"toggle-group": {
name: "toggle-group",
type: "components:ui",
registryDependencies: ["toggle"],
component: React.lazy(() => import("@/registry/default/ui/toggle-group")),
files: ["registry/default/ui/toggle-group.tsx"],
},
"tooltip": {
name: "tooltip",
type: "components:ui",
Expand Down Expand Up @@ -873,6 +880,48 @@ export const Index: Record<string, any> = {
component: React.lazy(() => import("@/registry/default/example/toast-with-title")),
files: ["registry/default/example/toast-with-title.tsx"],
},
"toggle-group-demo": {
name: "toggle-group-demo",
type: "components:example",
registryDependencies: ["toggle-group"],
component: React.lazy(() => import("@/registry/default/example/toggle-group-demo")),
files: ["registry/default/example/toggle-group-demo.tsx"],
},
"toggle-group-disabled": {
name: "toggle-group-disabled",
type: "components:example",
registryDependencies: ["toggle-group"],
component: React.lazy(() => import("@/registry/default/example/toggle-group-disabled")),
files: ["registry/default/example/toggle-group-disabled.tsx"],
},
"toggle-group-lg": {
name: "toggle-group-lg",
type: "components:example",
registryDependencies: ["toggle-group"],
component: React.lazy(() => import("@/registry/default/example/toggle-group-lg")),
files: ["registry/default/example/toggle-group-lg.tsx"],
},
"toggle-group-outline": {
name: "toggle-group-outline",
type: "components:example",
registryDependencies: ["toggle-group"],
component: React.lazy(() => import("@/registry/default/example/toggle-group-outline")),
files: ["registry/default/example/toggle-group-outline.tsx"],
},
"toggle-group-sm": {
name: "toggle-group-sm",
type: "components:example",
registryDependencies: ["toggle-group"],
component: React.lazy(() => import("@/registry/default/example/toggle-group-sm")),
files: ["registry/default/example/toggle-group-sm.tsx"],
},
"toggle-group-single": {
name: "toggle-group-single",
type: "components:example",
registryDependencies: ["toggle-group"],
component: React.lazy(() => import("@/registry/default/example/toggle-group-single")),
files: ["registry/default/example/toggle-group-single.tsx"],
},
"toggle-demo": {
name: "toggle-demo",
type: "components:example",
Expand Down Expand Up @@ -1287,6 +1336,13 @@ export const Index: Record<string, any> = {
component: React.lazy(() => import("@/registry/new-york/ui/toggle")),
files: ["registry/new-york/ui/toggle.tsx"],
},
"toggle-group": {
name: "toggle-group",
type: "components:ui",
registryDependencies: ["toggle"],
component: React.lazy(() => import("@/registry/new-york/ui/toggle-group")),
files: ["registry/new-york/ui/toggle-group.tsx"],
},
"tooltip": {
name: "tooltip",
type: "components:ui",
Expand Down Expand Up @@ -1903,6 +1959,48 @@ export const Index: Record<string, any> = {
component: React.lazy(() => import("@/registry/new-york/example/toast-with-title")),
files: ["registry/new-york/example/toast-with-title.tsx"],
},
"toggle-group-demo": {
name: "toggle-group-demo",
type: "components:example",
registryDependencies: ["toggle-group"],
component: React.lazy(() => import("@/registry/new-york/example/toggle-group-demo")),
files: ["registry/new-york/example/toggle-group-demo.tsx"],
},
"toggle-group-disabled": {
name: "toggle-group-disabled",
type: "components:example",
registryDependencies: ["toggle-group"],
component: React.lazy(() => import("@/registry/new-york/example/toggle-group-disabled")),
files: ["registry/new-york/example/toggle-group-disabled.tsx"],
},
"toggle-group-lg": {
name: "toggle-group-lg",
type: "components:example",
registryDependencies: ["toggle-group"],
component: React.lazy(() => import("@/registry/new-york/example/toggle-group-lg")),
files: ["registry/new-york/example/toggle-group-lg.tsx"],
},
"toggle-group-outline": {
name: "toggle-group-outline",
type: "components:example",
registryDependencies: ["toggle-group"],
component: React.lazy(() => import("@/registry/new-york/example/toggle-group-outline")),
files: ["registry/new-york/example/toggle-group-outline.tsx"],
},
"toggle-group-sm": {
name: "toggle-group-sm",
type: "components:example",
registryDependencies: ["toggle-group"],
component: React.lazy(() => import("@/registry/new-york/example/toggle-group-sm")),
files: ["registry/new-york/example/toggle-group-sm.tsx"],
},
"toggle-group-single": {
name: "toggle-group-single",
type: "components:example",
registryDependencies: ["toggle-group"],
component: React.lazy(() => import("@/registry/new-york/example/toggle-group-single")),
files: ["registry/new-york/example/toggle-group-single.tsx"],
},
"toggle-demo": {
name: "toggle-demo",
type: "components:example",
Expand Down
4 changes: 4 additions & 0 deletions apps/www/app/sink/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import TabsDemo from "@/registry/default/example/tabs-demo"
import ToastDemo from "@/registry/default/example/toast-demo"
import ToggleDemo from "@/registry/default/example/toggle-demo"
import ToggleDisabled from "@/registry/default/example/toggle-disabled"
import ToggleGroupDemo from "@/registry/default/example/toggle-group-demo"
import ToggleOutline from "@/registry/default/example/toggle-outline"
import ToggleWithText from "@/registry/default/example/toggle-with-text"
import TooltipDemo from "@/registry/default/example/tooltip-demo"
Expand Down Expand Up @@ -126,6 +127,9 @@ export default function KitchenSinkPage() {
<SwitchDemo />
<SelectDemo />
</ComponentWrapper>
<ComponentWrapper>
<ToggleGroupDemo />
</ComponentWrapper>
<ComponentWrapper>
<SeparatorDemo />
</ComponentWrapper>
Expand Down
5 changes: 5 additions & 0 deletions apps/www/config/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,11 @@ export const docsConfig: DocsConfig = {
href: "/docs/components/toggle",
items: [],
},
{
title: "Toggle Group",
href: "/docs/components/toggle-group",
items: [],
},
{
title: "Tooltip",
href: "/docs/components/tooltip",
Expand Down
88 changes: 88 additions & 0 deletions apps/www/content/docs/components/toggle-group.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
title: Toggle Group
description: A set of two-state buttons that can be toggled on or off.
component: true
radix:
link: https://www.radix-ui.com/docs/primitives/components/toggle-group
api: https://www.radix-ui.com/docs/primitives/components/toggle-group#api-reference
---

<ComponentPreview name="toggle-group-demo" />

## Installation

<Tabs defaultValue="cli">

<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">

```bash
npx shadcn-ui@latest add toggle-group
```

</TabsContent>

<TabsContent value="manual">

<Steps>

<Step>Install the following dependencies:</Step>

```bash
npm install @radix-ui/react-toggle-group
```

<Step>Copy and paste the following code into your project.</Step>

<ComponentSource name="toggle-group" />

<Step>Update the import paths to match your project setup.</Step>

</Steps>

</TabsContent>

</Tabs>

## Usage

```tsx
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
```

```tsx
<ToggleGroup type="single">
<ToggleGroupItem value="a">A</ToggleGroupItem>
<ToggleGroupItem value="b">B</ToggleGroupItem>
<ToggleGroupItem value="c">C</ToggleGroupItem>
</ToggleGroup>
```

## Examples

### Default

<ComponentPreview name="toggle-group-demo" />

### Outline

<ComponentPreview name="toggle-group-outline" />

### Single

<ComponentPreview name="toggle-group-single" />

### Small

<ComponentPreview name="toggle-group-sm" />

### Large

<ComponentPreview name="toggle-group-lg" />

### Disabled

<ComponentPreview name="toggle-group-disabled" />
12 changes: 12 additions & 0 deletions apps/www/pages/api/components.json
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,18 @@
],
"type": "ui"
},
{
"name": "toggle-group",
"dependencies": ["@radix-ui/react-toggle-group"],
"files": [
{
"name": "toggle-group.tsx",
"dir": "components/ui",
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as ToggleGroupPrimitive from \"@radix-ui/react-toggle-group\"\nimport { VariantProps, cva } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst ToggleGroupContext = React.createContext<\n VariantProps<typeof toggleGroupItemVariants>\n>({\n size: \"default\",\n variant: \"default\",\n})\n\nconst toggleGroupItemVariants = cva(\n \"inline-flex items-center justify-center text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n outline:\n \"border-r border-input bg-transparent last:border-0 hover:bg-accent hover:text-accent-foreground\",\n },\n size: {\n default: \"h-10 px-3\",\n sm: \"h-9 px-2.5\",\n lg: \"h-11 px-5\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nconst ToggleGroup = React.forwardRef<\n React.ElementRef<typeof ToggleGroupPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &\n VariantProps<typeof toggleGroupItemVariants>\n>(({ className, variant, size, children, ...props }, ref) => (\n <ToggleGroupPrimitive.Root\n ref={ref}\n className={cn(\n \"inline-flex items-center justify-center overflow-hidden rounded-md border border-input bg-transparent shadow\",\n className\n )}\n {...props}\n >\n <ToggleGroupContext.Provider value={{ variant, size }}>\n {children}\n </ToggleGroupContext.Provider>\n </ToggleGroupPrimitive.Root>\n))\n\nToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName\n\nconst ToggleGroupItem = React.forwardRef<\n React.ElementRef<typeof ToggleGroupPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &\n VariantProps<typeof toggleGroupItemVariants>\n>(({ className, children, variant, size, ...props }, ref) => {\n const context = React.useContext(ToggleGroupContext)\n\n return (\n <ToggleGroupPrimitive.Item\n ref={ref}\n className={cn(\n toggleGroupItemVariants({\n variant: context.variant || variant,\n size: context.size || size,\n }),\n className\n )}\n {...props}\n >\n {children}\n </ToggleGroupPrimitive.Item>\n )\n})\n\nToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName\n\nexport { ToggleGroup, ToggleGroupItem }\n"
}
],
"type": "ui"
},
{
"name": "tooltip",
"dependencies": ["@radix-ui/react-tooltip"],
Expand Down
13 changes: 13 additions & 0 deletions apps/www/public/registry/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,19 @@
],
"type": "components:ui"
},
{
"name": "toggle-group",
"dependencies": [
"@radix-ui/react-toggle-group"
],
"registryDependencies": [
"toggle"
],
"files": [
"ui/toggle-group.tsx"
],
"type": "components:ui"
},
{
"name": "tooltip",
"dependencies": [
Expand Down
16 changes: 16 additions & 0 deletions apps/www/public/registry/styles/default/toggle-group.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "toggle-group",
"dependencies": [
"@radix-ui/react-toggle-group"
],
"registryDependencies": [
"toggle"
],
"files": [
{
"name": "toggle-group.tsx",
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as ToggleGroupPrimitive from \"@radix-ui/react-toggle-group\"\nimport { VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { toggleVariants } from \"@/registry/default/ui/toggle\"\n\nconst ToggleGroupContext = React.createContext<\n VariantProps<typeof toggleVariants>\n>({\n size: \"default\",\n variant: \"default\",\n})\n\nconst ToggleGroup = React.forwardRef<\n React.ElementRef<typeof ToggleGroupPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &\n VariantProps<typeof toggleVariants>\n>(({ className, variant, size, children, ...props }, ref) => (\n <ToggleGroupPrimitive.Root\n ref={ref}\n className={cn(\"flex items-center justify-center gap-1\", className)}\n {...props}\n >\n <ToggleGroupContext.Provider value={{ variant, size }}>\n {children}\n </ToggleGroupContext.Provider>\n </ToggleGroupPrimitive.Root>\n))\n\nToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName\n\nconst ToggleGroupItem = React.forwardRef<\n React.ElementRef<typeof ToggleGroupPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &\n VariantProps<typeof toggleVariants>\n>(({ className, children, variant, size, ...props }, ref) => {\n const context = React.useContext(ToggleGroupContext)\n\n return (\n <ToggleGroupPrimitive.Item\n ref={ref}\n className={cn(\n toggleVariants({\n variant: context.variant || variant,\n size: context.size || size,\n }),\n className\n )}\n {...props}\n >\n {children}\n </ToggleGroupPrimitive.Item>\n )\n})\n\nToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName\n\nexport { ToggleGroup, ToggleGroupItem }\n"
}
],
"type": "components:ui"
}
16 changes: 16 additions & 0 deletions apps/www/public/registry/styles/new-york/toggle-group.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "toggle-group",
"dependencies": [
"@radix-ui/react-toggle-group"
],
"registryDependencies": [
"toggle"
],
"files": [
{
"name": "toggle-group.tsx",
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as ToggleGroupPrimitive from \"@radix-ui/react-toggle-group\"\nimport { VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { toggleVariants } from \"@/registry/new-york/ui/toggle\"\n\nconst ToggleGroupContext = React.createContext<\n VariantProps<typeof toggleVariants>\n>({\n size: \"default\",\n variant: \"default\",\n})\n\nconst ToggleGroup = React.forwardRef<\n React.ElementRef<typeof ToggleGroupPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &\n VariantProps<typeof toggleVariants>\n>(({ className, variant, size, children, ...props }, ref) => (\n <ToggleGroupPrimitive.Root\n ref={ref}\n className={cn(\"flex items-center justify-center gap-1\", className)}\n {...props}\n >\n <ToggleGroupContext.Provider value={{ variant, size }}>\n {children}\n </ToggleGroupContext.Provider>\n </ToggleGroupPrimitive.Root>\n))\n\nToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName\n\nconst ToggleGroupItem = React.forwardRef<\n React.ElementRef<typeof ToggleGroupPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &\n VariantProps<typeof toggleVariants>\n>(({ className, children, variant, size, ...props }, ref) => {\n const context = React.useContext(ToggleGroupContext)\n\n return (\n <ToggleGroupPrimitive.Item\n ref={ref}\n className={cn(\n toggleVariants({\n variant: context.variant || variant,\n size: context.size || size,\n }),\n className\n )}\n {...props}\n >\n {children}\n </ToggleGroupPrimitive.Item>\n )\n})\n\nToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName\n\nexport { ToggleGroup, ToggleGroupItem }\n"
}
],
"type": "components:ui"
}
22 changes: 22 additions & 0 deletions apps/www/registry/default/example/toggle-group-demo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Bold, Italic, Underline } from "lucide-react"

import {
ToggleGroup,
ToggleGroupItem,
} from "@/registry/default/ui/toggle-group"

export default function ToggleGroupDemo() {
return (
<ToggleGroup type="multiple">
<ToggleGroupItem value="bold" aria-label="Toggle bold">
<Bold className="h-4 w-4" />
</ToggleGroupItem>
<ToggleGroupItem value="italic" aria-label="Toggle italic">
<Italic className="h-4 w-4" />
</ToggleGroupItem>
<ToggleGroupItem value="strikethrough" aria-label="Toggle strikethrough">
<Underline className="h-4 w-4" />
</ToggleGroupItem>
</ToggleGroup>
)
}
22 changes: 22 additions & 0 deletions apps/www/registry/default/example/toggle-group-disabled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Bold, Italic, Underline } from "lucide-react"

import {
ToggleGroup,
ToggleGroupItem,
} from "@/registry/default/ui/toggle-group"

export default function ToggleGroupDemo() {
return (
<ToggleGroup disabled type="single">
<ToggleGroupItem value="bold" aria-label="Toggle bold">
<Bold className="h-4 w-4" />
</ToggleGroupItem>
<ToggleGroupItem value="italic" aria-label="Toggle italic">
<Italic className="h-4 w-4" />
</ToggleGroupItem>
<ToggleGroupItem value="strikethrough" aria-label="Toggle strikethrough">
<Underline className="h-4 w-4" />
</ToggleGroupItem>
</ToggleGroup>
)
}
22 changes: 22 additions & 0 deletions apps/www/registry/default/example/toggle-group-lg.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Bold, Italic, Underline } from "lucide-react"

import {
ToggleGroup,
ToggleGroupItem,
} from "@/registry/default/ui/toggle-group"

export default function ToggleGroupDemo() {
return (
<ToggleGroup size={"lg"} type="multiple">
<ToggleGroupItem value="bold" aria-label="Toggle bold">
<Bold className="h-4 w-4" />
</ToggleGroupItem>
<ToggleGroupItem value="italic" aria-label="Toggle italic">
<Italic className="h-4 w-4" />
</ToggleGroupItem>
<ToggleGroupItem value="strikethrough" aria-label="Toggle strikethrough">
<Underline className="h-4 w-4" />
</ToggleGroupItem>
</ToggleGroup>
)
}
Loading

1 comment on commit 1db90ba

@vercel
Copy link

@vercel vercel bot commented on 1db90ba Nov 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

ui – ./apps/www

ui-shadcn-pro.vercel.app
ui-git-main-shadcn-pro.vercel.app
ui.shadcn.com
example-playground.vercel.app

Please sign in to comment.