Propel

Toggle

Two-state pressed buttons — icon-only (`IconToggle`) or labeled (`Toggle`) with optional start/end icons.

Show code
import { Icon } from "@makeplane/propel/components/icon";
import { IconToggle } from "@makeplane/propel/components/toggle";
import { Star } from "lucide-react";
import { useState } from "react";

export default function BasicDemo() {
  const [pressed, setPressed] = useState(false);
  return (
    <IconToggle
      size="md"
      aria-label="Favorite"
      pressed={pressed}
      onPressedChange={setPressed}
      icon={<Icon icon={<Star fill={pressed ? "currentColor" : "none"} />} />}
    />
  );
}

Installation

import { IconToggle, Toggle } from "@makeplane/propel/components/toggle";

Usage

import { Icon } from "@makeplane/propel/components/icon";
import { IconToggle } from "@makeplane/propel/components/toggle";
import { Star } from "lucide-react";
import { useState } from "react";

export default function BasicDemo() {
  const [pressed, setPressed] = useState(false);
  return (
    <IconToggle
      size="md"
      aria-label="Favorite"
      pressed={pressed}
      onPressedChange={setPressed}
      icon={<Icon icon={<Star fill={pressed ? "currentColor" : "none"} />} />}
    />
  );
}

Examples

IconToggle sizes and variants

IconToggle is the icon-only specialization. The size axis is xs·sm·md (20/24/28px). variant is secondary (raised bordered, default) or ghost (transparent).

Show code
import { Icon } from "@makeplane/propel/components/icon";
import { IconToggle } from "@makeplane/propel/components/toggle";
import { Star } from "lucide-react";

export default function SizesDemo() {
  return (
    <div className="flex items-center gap-2">
      <IconToggle size="xs" aria-label="Favorite (xs)" icon={<Icon icon={Star} />} />
      <IconToggle size="sm" aria-label="Favorite (sm)" icon={<Icon icon={Star} />} />
      <IconToggle size="md" aria-label="Favorite (md)" icon={<Icon icon={Star} />} />
      <IconToggle size="xs" variant="ghost" aria-label="Ghost (xs)" icon={<Icon icon={Star} />} />
      <IconToggle size="sm" variant="ghost" aria-label="Ghost (sm)" icon={<Icon icon={Star} />} />
      <IconToggle size="md" variant="ghost" aria-label="Ghost (md)" icon={<Icon icon={Star} />} />
    </div>
  );
}

IconToggle states

Start pressed via defaultPressed; a disabled toggle does not respond to clicks.

Show code
import { Icon } from "@makeplane/propel/components/icon";
import { IconToggle } from "@makeplane/propel/components/toggle";
import { Star } from "lucide-react";

export default function StatesDemo() {
  return (
    <div className="flex items-center gap-2">
      <IconToggle size="md" aria-label="Off" icon={<Icon icon={<Star fill="none" />} />} />
      <IconToggle
        size="md"
        defaultPressed
        aria-label="On"
        icon={<Icon icon={<Star fill="currentColor" />} />}
      />
      <IconToggle
        size="md"
        disabled
        aria-label="Disabled"
        icon={<Icon icon={<Star fill="none" />} />}
      />
    </div>
  );
}

Controlled IconToggle

Own the state with pressed and onPressedChange to derive the glyph from it.

Show code
import { Icon } from "@makeplane/propel/components/icon";
import { IconToggle } from "@makeplane/propel/components/toggle";
import { Heart } from "lucide-react";
import { useState } from "react";

export default function ControlledDemo() {
  const [pressed, setPressed] = useState(false);
  return (
    <IconToggle
      size="md"
      aria-label="Favorite"
      pressed={pressed}
      onPressedChange={setPressed}
      icon={<Icon icon={<Heart fill={pressed ? "currentColor" : "none"} />} />}
    />
  );
}

Text Toggle

Toggle is the labeled form — optional startIcon / endIcon, a required label, and the same xs·sm·md size ladder. Labels truncate past 120px.

Show code
import { Icon } from "@makeplane/propel/components/icon";
import { Toggle } from "@makeplane/propel/components/toggle";
import { Plus } from "lucide-react";

export default function TextToggleDemo() {
  return (
    <div className="flex items-center gap-2">
      <Toggle
        size="xs"
        startIcon={<Icon icon={Plus} />}
        endIcon={<Icon icon={Plus} />}
        label="Pill"
      />
      <Toggle
        size="sm"
        startIcon={<Icon icon={Plus} />}
        endIcon={<Icon icon={Plus} />}
        label="Pill"
      />
      <Toggle
        size="md"
        startIcon={<Icon icon={Plus} />}
        endIcon={<Icon icon={Plus} />}
        label="Pill"
      />
    </div>
  );
}

API Reference

IconToggle

The ready-made icon-only toggle: grafts Base UI's `Toggle` behavior onto the styled `IconToggle` button (behavior outer, the styled button as the render target).

PropTypeDefaultDescription
icon(required)ReactNodeIcon element rendered inside the toggle, usually `<Icon icon={...} />`.
aria-labelstringDefines a string value that labels the current element. Required: icon-only toggles have no visible text, so they must be labeled. @see aria-labelledby.
renderReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ToggleState>Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.
variant"secondary" | "ghost""secondary"Look: raised bordered (`secondary`) or transparent (`ghost`).
size"xs" | "sm" | "md""md"Square scale (`xs`·`sm`·`md`).

Toggle

The ready-made label toggle: grafts Base UI's `Toggle` behavior onto the styled `Toggle` button (behavior outer, the styled button as the render target), with an optional leading node, the `ToggleLabel`, and an optional trailing node. The selected look is the container's pressed state.

PropTypeDefaultDescription
label(required)stringVisible toggle label.
renderReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ToggleState>Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.
size"xs" | "sm" | "md""md"Label-toggle scale (`xs`·`sm`·`md`).
startIconReactNodeElement rendered before the label (inline-start), e.g. `<Icon icon={Tag} />`.
endIconReactNodeElement rendered after the label (inline-end), e.g. `<Icon icon={X} />`.