AniUI

Toggle

A two-state button that can be toggled on or off.

import { Toggle } from "@/components/ui/toggle";
import { useState } from "react";

export function MyScreen() {
  const [bold, setBold] = useState(false);
  return (
    <Toggle pressed={bold} onPressedChange={setBold}>
      B
    </Toggle>
  );
}

Installation

npx @aniui/cli add toggle

Usage

app/index.tsx
import { Toggle } from "@/components/ui/toggle";
import { useState } from "react";

export function MyScreen() {
  const [bold, setBold] = useState(false);
  return (
    <Toggle pressed={bold} onPressedChange={setBold}>
      B
    </Toggle>
  );
}

Variants

<Toggle variant="default" pressed={false}>Default</Toggle>
<Toggle variant="outline" pressed={false}>Outline</Toggle>

Sizes

<Toggle size="sm">S</Toggle>
<Toggle size="md">M</Toggle>
<Toggle size="lg">L</Toggle>

Props

PropTypeDefault
variant
"default" | "outline"
"default"
size
"sm" | "md" | "lg"
"md"
pressed
boolean
false
onPressedChange
(pressed: boolean) => void
className
string
children
ReactNode
required

Also accepts all Pressable props from React Native.

Source

components/ui/toggle.tsx
import React from "react";
import { Pressable, Text } from "react-native";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";

const toggleVariants = cva(
  "items-center justify-center rounded-md min-h-12 min-w-12",
  {
    variants: {
      variant: {
        default: "bg-transparent",
        outline: "border border-input bg-transparent",
      },
      size: {
        sm: "px-2 py-1.5",
        md: "px-3 py-2",
        lg: "px-4 py-2.5",
      },
    },
    defaultVariants: { variant: "default", size: "md" },
  }
);
export interface ToggleProps
  extends React.ComponentPropsWithoutRef<typeof Pressable>,
    VariantProps<typeof toggleVariants> {
  className?: string;
  pressed?: boolean;
  onPressedChange?: (pressed: boolean) => void;
  children: React.ReactNode;
}
export function Toggle({
  pressed = false, onPressedChange, variant, size, className, children, ...props
}: ToggleProps) {
  return (
    <Pressable
      className={cn(
        toggleVariants({ variant, size }),
        pressed && "bg-accent",
        className
      )}
      onPress={() => onPressedChange?.(!pressed)}
      accessibilityRole="button"
      accessibilityState={{ selected: pressed }}
      accessible={true}
      {...props}
    >
      {typeof children === "string" ? (
        <Text className={cn("text-sm font-medium", pressed ? "text-accent-foreground" : "text-muted-foreground")}>
          {children}
        </Text>
      ) : children}
    </Pressable>
  );
}