Toggle
A two-state button that can be on or off.
- Chromium
- Firefox
- WebKit
- WCAG 2.2 AA
Preview
import { Toggle } from "@moe-ui/registry/components/ui/toggle";
import { Bold } from "lucide-react-native";
import { View } from "react-native";
export default function TogglePreview() {
return (
<Toggle aria-label="Toggle bold">
<Bold className="h-4 w-4 text-foreground" />
</Toggle>
);
}
export function ToggleOutlinePreview() {
return (
<Toggle variant="outline" aria-label="Toggle bold outline">
<Bold className="h-4 w-4 text-foreground" />
</Toggle>
);
}
export function ToggleSizesPreview() {
return (
<View className="flex-row items-center gap-3">
<Toggle size="sm" aria-label="Toggle bold small">
<Bold className="h-4 w-4 text-foreground" />
</Toggle>
<Toggle size="default" aria-label="Toggle bold default size">
<Bold className="h-4 w-4 text-foreground" />
</Toggle>
<Toggle size="lg" aria-label="Toggle bold large">
<Bold className="h-4 w-4 text-foreground" />
</Toggle>
</View>
);
}
One command, your source
Installation
pnpm dlx @moe-ui/cli@beta add toggleUsage
The CLI installs editable source into your application. Import the component from your configured UI directory:
import { Toggle } from "@/components/ui/toggle";Variants and composition
Each additional variant has its own live preview and testable section.
Outline
import { Toggle } from "@moe-ui/registry/components/ui/toggle";
import { Bold } from "lucide-react-native";
import { View } from "react-native";
export default function TogglePreview() {
return (
<Toggle aria-label="Toggle bold">
<Bold className="h-4 w-4 text-foreground" />
</Toggle>
);
}
export function ToggleOutlinePreview() {
return (
<Toggle variant="outline" aria-label="Toggle bold outline">
<Bold className="h-4 w-4 text-foreground" />
</Toggle>
);
}
export function ToggleSizesPreview() {
return (
<View className="flex-row items-center gap-3">
<Toggle size="sm" aria-label="Toggle bold small">
<Bold className="h-4 w-4 text-foreground" />
</Toggle>
<Toggle size="default" aria-label="Toggle bold default size">
<Bold className="h-4 w-4 text-foreground" />
</Toggle>
<Toggle size="lg" aria-label="Toggle bold large">
<Bold className="h-4 w-4 text-foreground" />
</Toggle>
</View>
);
}
Sizes
import { Toggle } from "@moe-ui/registry/components/ui/toggle";
import { Bold } from "lucide-react-native";
import { View } from "react-native";
export default function TogglePreview() {
return (
<Toggle aria-label="Toggle bold">
<Bold className="h-4 w-4 text-foreground" />
</Toggle>
);
}
export function ToggleOutlinePreview() {
return (
<Toggle variant="outline" aria-label="Toggle bold outline">
<Bold className="h-4 w-4 text-foreground" />
</Toggle>
);
}
export function ToggleSizesPreview() {
return (
<View className="flex-row items-center gap-3">
<Toggle size="sm" aria-label="Toggle bold small">
<Bold className="h-4 w-4 text-foreground" />
</Toggle>
<Toggle size="default" aria-label="Toggle bold default size">
<Bold className="h-4 w-4 text-foreground" />
</Toggle>
<Toggle size="lg" aria-label="Toggle bold large">
<Bold className="h-4 w-4 text-foreground" />
</Toggle>
</View>
);
}
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
ToggleToggleIcontoggleVariants"use client";
import { Icon } from "./icon";
import { TextClassContext } from "./text";
import { cn } from "../../lib/utils";
import * as TogglePrimitive from "@rn-primitives/toggle";
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import { Platform } from "react-native";
const toggleVariants = cva(
cn(
"active:bg-muted group flex flex-row items-center justify-center gap-2 rounded-md",
Platform.select({
web: "hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex cursor-default whitespace-nowrap outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:pointer-events-none [&_svg]:pointer-events-none",
}),
),
{
variants: {
variant: {
default: "bg-transparent",
outline: cn(
"border-input active:bg-accent border bg-transparent shadow-sm shadow-black/5",
Platform.select({
web: "hover:bg-accent hover:text-accent-foreground",
}),
),
},
size: {
default: "h-10 min-w-10 px-2.5 sm:h-9 sm:min-w-9 sm:px-2",
sm: "h-9 min-w-9 px-2 sm:h-8 sm:min-w-8 sm:px-1.5",
lg: "h-11 min-w-11 px-3 sm:h-10 sm:min-w-10 sm:px-2.5",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
},
);
function Toggle({
className,
variant,
size,
pressed: pressedProp,
defaultPressed = false,
onPressedChange,
...props
}: Omit<TogglePrimitive.RootProps, "pressed" | "onPressedChange"> &
VariantProps<typeof toggleVariants> &
React.RefAttributes<TogglePrimitive.RootRef> & {
pressed?: boolean;
defaultPressed?: boolean;
onPressedChange?: (pressed: boolean) => void;
}) {
const [uncontrolledPressed, setUncontrolledPressed] =
React.useState(defaultPressed);
const pressed = pressedProp ?? uncontrolledPressed;
return (
<TextClassContext.Provider
value={cn(
"text-sm text-foreground font-medium",
pressed
? "text-accent-foreground"
: Platform.select({ web: "group-hover:text-muted-foreground" }),
className,
)}
>
<TogglePrimitive.Root
className={cn(
toggleVariants({ variant, size }),
props.disabled && "opacity-50",
pressed && "bg-accent",
className,
)}
pressed={pressed}
onPressedChange={(nextPressed) => {
if (pressedProp === undefined) setUncontrolledPressed(nextPressed);
onPressedChange?.(nextPressed);
}}
{...props}
/>
</TextClassContext.Provider>
);
}
function ToggleIcon({
className,
...props
}: React.ComponentProps<typeof Icon>) {
const textClass = React.useContext(TextClassContext);
return (
<Icon className={cn("size-4 shrink-0", textClass, className)} {...props} />
);
}
export { Toggle, ToggleIcon, toggleVariants };