Toggle Group
A coordinated set of single or multiple toggles.
- Chromium
- Firefox
- WebKit
- WCAG 2.2 AA
Preview
"use client";
import {
ToggleGroup,
ToggleGroupItem,
} from "@moe-ui/registry/components/ui/toggle-group";
import { Bold, Italic, Underline } from "lucide-react-native";
import * as React from "react";
export default function ToggleGroupPreview() {
const [value, setValue] = React.useState<string[]>([]);
return (
<ToggleGroup type="multiple" value={value} onValueChange={setValue}>
<ToggleGroupItem value="bold" aria-label="Toggle bold">
<Bold className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
<ToggleGroupItem value="italic" aria-label="Toggle italic">
<Italic className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
<ToggleGroupItem value="underline" aria-label="Toggle underline">
<Underline className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
</ToggleGroup>
);
}
function ToggleGroupExample({
variant,
size,
}: {
variant?: "default" | "outline";
size?: "default" | "sm" | "lg";
}) {
const [value, setValue] = React.useState<string[]>(["bold"]);
return (
<ToggleGroup
type="multiple"
value={value}
onValueChange={setValue}
variant={variant}
size={size}
>
<ToggleGroupItem value="bold" aria-label="Toggle bold">
<Bold className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
<ToggleGroupItem value="italic" aria-label="Toggle italic">
<Italic className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
<ToggleGroupItem value="underline" aria-label="Toggle underline">
<Underline className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
</ToggleGroup>
);
}
export function ToggleGroupOutlinePreview() {
return <ToggleGroupExample variant="outline" />;
}
export function ToggleGroupSizesPreview() {
return (
<div className="flex flex-wrap items-center justify-center gap-3">
<ToggleGroupExample size="sm" />
<ToggleGroupExample size="lg" />
</div>
);
}
One command, your source
Installation
pnpm dlx @moe-ui/cli@beta add toggle-groupUsage
The CLI installs editable source into your application. Import the component from your configured UI directory:
import { ToggleGroup } from "@/components/ui/toggle-group";Variants and composition
Each additional variant has its own live preview and testable section.
Outline
"use client";
import {
ToggleGroup,
ToggleGroupItem,
} from "@moe-ui/registry/components/ui/toggle-group";
import { Bold, Italic, Underline } from "lucide-react-native";
import * as React from "react";
export default function ToggleGroupPreview() {
const [value, setValue] = React.useState<string[]>([]);
return (
<ToggleGroup type="multiple" value={value} onValueChange={setValue}>
<ToggleGroupItem value="bold" aria-label="Toggle bold">
<Bold className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
<ToggleGroupItem value="italic" aria-label="Toggle italic">
<Italic className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
<ToggleGroupItem value="underline" aria-label="Toggle underline">
<Underline className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
</ToggleGroup>
);
}
function ToggleGroupExample({
variant,
size,
}: {
variant?: "default" | "outline";
size?: "default" | "sm" | "lg";
}) {
const [value, setValue] = React.useState<string[]>(["bold"]);
return (
<ToggleGroup
type="multiple"
value={value}
onValueChange={setValue}
variant={variant}
size={size}
>
<ToggleGroupItem value="bold" aria-label="Toggle bold">
<Bold className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
<ToggleGroupItem value="italic" aria-label="Toggle italic">
<Italic className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
<ToggleGroupItem value="underline" aria-label="Toggle underline">
<Underline className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
</ToggleGroup>
);
}
export function ToggleGroupOutlinePreview() {
return <ToggleGroupExample variant="outline" />;
}
export function ToggleGroupSizesPreview() {
return (
<div className="flex flex-wrap items-center justify-center gap-3">
<ToggleGroupExample size="sm" />
<ToggleGroupExample size="lg" />
</div>
);
}
Sizes
"use client";
import {
ToggleGroup,
ToggleGroupItem,
} from "@moe-ui/registry/components/ui/toggle-group";
import { Bold, Italic, Underline } from "lucide-react-native";
import * as React from "react";
export default function ToggleGroupPreview() {
const [value, setValue] = React.useState<string[]>([]);
return (
<ToggleGroup type="multiple" value={value} onValueChange={setValue}>
<ToggleGroupItem value="bold" aria-label="Toggle bold">
<Bold className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
<ToggleGroupItem value="italic" aria-label="Toggle italic">
<Italic className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
<ToggleGroupItem value="underline" aria-label="Toggle underline">
<Underline className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
</ToggleGroup>
);
}
function ToggleGroupExample({
variant,
size,
}: {
variant?: "default" | "outline";
size?: "default" | "sm" | "lg";
}) {
const [value, setValue] = React.useState<string[]>(["bold"]);
return (
<ToggleGroup
type="multiple"
value={value}
onValueChange={setValue}
variant={variant}
size={size}
>
<ToggleGroupItem value="bold" aria-label="Toggle bold">
<Bold className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
<ToggleGroupItem value="italic" aria-label="Toggle italic">
<Italic className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
<ToggleGroupItem value="underline" aria-label="Toggle underline">
<Underline className="h-4 w-4 text-foreground" />
</ToggleGroupItem>
</ToggleGroup>
);
}
export function ToggleGroupOutlinePreview() {
return <ToggleGroupExample variant="outline" />;
}
export function ToggleGroupSizesPreview() {
return (
<div className="flex flex-wrap items-center justify-center gap-3">
<ToggleGroupExample size="sm" />
<ToggleGroupExample size="lg" />
</div>
);
}
Compound parts and variants remain regular source in your project, so you can change them without wrapping a package API.
Public API
The canonical source panel below lists every public export, dependency, and the complete implementation shipped by the registry.
Keyboard and accessibility
Associate the control with a visible label. Keyboard focus, disabled state, and validation semantics are covered by the web test matrix.
Browser support
This beta is release-tested in Chromium, Firefox, and WebKit in light and dark themes. See the web compatibility matrix for the current gate.
Nothing hiddenCanonical source and public exports3 exports
ToggleGroupToggleGroupIconToggleGroupItem"use client";
import { Icon } from "./icon";
import { TextClassContext } from "./text";
import { toggleVariants } from "./toggle";
import { cn } from "../../lib/utils";
import * as ToggleGroupPrimitive from "@rn-primitives/toggle-group";
import type { VariantProps } from "class-variance-authority";
import * as React from "react";
import { Platform } from "react-native";
const ToggleGroupContext = React.createContext<VariantProps<
typeof toggleVariants
> | null>(null);
function ToggleGroup({
className,
variant,
size,
children,
...props
}: ToggleGroupPrimitive.RootProps &
VariantProps<typeof toggleVariants> &
React.RefAttributes<ToggleGroupPrimitive.RootRef>) {
return (
<ToggleGroupPrimitive.Root
className={cn(
"flex flex-row items-center rounded-md shadow-none",
Platform.select({ web: "w-fit" }),
variant === "outline" && "shadow-sm shadow-black/5",
className,
)}
{...props}
>
<ToggleGroupContext.Provider value={{ variant, size }}>
{children}
</ToggleGroupContext.Provider>
</ToggleGroupPrimitive.Root>
);
}
function useToggleGroupContext() {
const context = React.useContext(ToggleGroupContext);
if (context === null) {
throw new Error(
"ToggleGroup compound components cannot be rendered outside the ToggleGroup component",
);
}
return context;
}
function ToggleGroupItem({
className,
children,
variant,
size,
isFirst,
isLast,
...props
}: ToggleGroupPrimitive.ItemProps &
VariantProps<typeof toggleVariants> &
React.RefAttributes<ToggleGroupPrimitive.ItemRef> & {
isFirst?: boolean;
isLast?: boolean;
}) {
const context = useToggleGroupContext();
const { value } = ToggleGroupPrimitive.useRootContext();
return (
<TextClassContext.Provider
value={cn(
"text-sm text-foreground font-medium",
ToggleGroupPrimitive.utils.getIsSelected(value, props.value)
? "text-accent-foreground"
: Platform.select({ web: "group-hover:text-muted-foreground" }),
)}
>
<ToggleGroupPrimitive.Item
className={cn(
toggleVariants({
variant: context.variant || variant,
size: context.size || size,
}),
props.disabled && "opacity-50",
ToggleGroupPrimitive.utils.getIsSelected(value, props.value) &&
"bg-accent",
"min-w-0 shrink-0 rounded-none shadow-none",
isFirst && "rounded-l-md",
isLast && "rounded-r-md",
(context.variant === "outline" || variant === "outline") &&
"border-l-0",
(context.variant === "outline" || variant === "outline") &&
isFirst &&
"border-l",
Platform.select({
web: "flex-1 focus:z-10 focus-visible:z-10",
}),
className,
)}
{...props}
>
{children}
</ToggleGroupPrimitive.Item>
</TextClassContext.Provider>
);
}
function ToggleGroupIcon({
className,
...props
}: React.ComponentProps<typeof Icon>) {
const textClass = React.useContext(TextClassContext);
return (
<Icon className={cn("size-4 shrink-0", textClass, className)} {...props} />
);
}
export { ToggleGroup, ToggleGroupIcon, ToggleGroupItem };