A compact two-state action with distinct pressed styling, visible keyboard focus, and outline or filled variants.
Atlas launch
Pinned to your sidebar
"use client";
import * as React from "react";
import { Pin } from "lucide-react";
import { Toggle } from "@/components/ballmac/toggle";
export default function ToggleDemo() {
const [pinned, setPinned] = React.useState(true);
return (
<div className="flex w-full max-w-sm items-center gap-3 rounded-xl border bg-card p-4 shadow-sm">
<div className="min-w-0 flex-1">
<p className="text-sm font-semibold">Atlas launch</p>
<p className="text-xs text-muted-foreground">
{pinned ? "Pinned to your sidebar" : "Not pinned"}
</p>
</div>
<Toggle
variant="outline"
pressed={pinned}
onPressedChange={setPinned}
aria-label={pinned ? "Unpin Atlas launch" : "Pin Atlas launch"}
>
<Pin aria-hidden="true" />
{pinned ? "Pinned" : "Pin"}
</Toggle>
</div>
);
}Installation
$ pnpm dlx shadcn@latest add @ballmac/toggleInstall the dependencies.
$ pnpm add radix-uiCopy the source into your project.
components/ballmac/toggle.tsx// Ballmac UI: Toggle. https://ui.ballmac.com/components/toggle "use client"; import * as React from "react"; import { Toggle as Primitive } from "radix-ui"; import { cn } from "@/lib/utils"; type ToggleProps = React.ComponentProps<typeof Primitive.Root> & { /** Surface treatment of the two-state control. */ variant?: "default" | "outline"; /** Control height and horizontal padding. */ size?: "sm" | "default" | "lg"; }; function Toggle({ className, variant = "default", size = "default", ...props }: ToggleProps) { return ( <Primitive.Root data-slot="toggle" data-variant={variant} data-size={size} className={cn( "inline-flex min-w-0 shrink-0 items-center justify-center gap-2 rounded-md px-3 text-sm font-medium text-muted-foreground outline-none transition-[color,background-color,box-shadow] duration-150 hover:bg-muted hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground data-[variant=outline]:border data-[variant=outline]:border-input data-[variant=outline]:bg-background data-[variant=outline]:data-[state=on]:border-primary data-[variant=outline]:data-[state=on]:bg-primary/10 data-[size=sm]:h-8 data-[size=sm]:px-2 data-[size=default]:h-9 data-[size=lg]:h-11 data-[size=lg]:px-4 motion-reduce:transition-none [&_svg]:size-4", className, )} {...props} /> ); } export { Toggle, type ToggleProps };Update the import paths to match your project setup.
Usage
import { Toggle } from "@/components/ballmac/toggle"The full example is in the Code tab above.
Examples
Sizes and states
import { Bold, Italic, Underline } from "lucide-react";
import { Toggle } from "@/components/ballmac/toggle";
export default function ToggleStates() {
return (
<div className="flex w-full max-w-xs flex-wrap items-center gap-2">
<Toggle aria-label="Bold" defaultPressed size="sm">
<Bold aria-hidden="true" />
</Toggle>
<Toggle aria-label="Italic" variant="outline">
<Italic aria-hidden="true" />
</Toggle>
<Toggle aria-label="Underline" variant="outline" size="lg" disabled>
<Underline aria-hidden="true" />
</Toggle>
<span className="text-xs text-muted-foreground">
Small, outline, disabled
</span>
</div>
);
}API reference
| Prop | Type | Default |
|---|---|---|
variantSurface treatment of the two-state control. | "default" | "outline" | "default" |
sizeControl height and horizontal padding. | "sm" | "default" | "lg" | "default" |
Also accepts the standard attributes of its root element.
Accessibility
| Key | Action |
|---|---|
| Tab | Focuses the toggle |
| Enter / Space | Changes pressed state |
Use with AI
An on/off action such as pinning or formatting that communicates its pressed state to assistive technology. With the shadcn MCP server set up (guide), ask your agent:
Add the Ballmac UI Toggle (@ballmac/toggle) to this project with the shadcn MCP, then use it where it fits.
Use it for
- A toolbar action with persistent pressed state
- Favorite or pin control
Not for
- Boolean form field; use switch
- Multiple related choices; use toggle-group
Registry JSON: https://ui.ballmac.com/r/toggle.json
Credits
Free to use in personal and commercial projects.
- npm
- radix-ui
- Registry
- shadcn/utils
Pairs well with
Button Group
Join adjacent actions into one compact control surface while retaining each button's visible keyboard focus and accessible name.
Accordion
Vertically stacked disclosure sections on Radix Accordion, single or multiple open, with hairline dividers, a rotating plus and height animation.
Avatar
A Radix avatar with image and initials fallback, three sizes, an optional presence dot, and AvatarGroup for overlapping stacks with a +N overflow counter.
Badge
A small pill label in four variants with an optional status dot and success, warning and error tones. Style links with badgeVariants().