ToggleButton

Toggle a state between two values.

Documentation
React Aria
Pattern
W3C ARIA
Source
GitHub
Issues
Report
ToggleButton example
import { PushPin } from "@phosphor-icons/react/dist/ssr";
import { ToggleButton } from "@/shim-ui/toggle-button";

export default () => (
  <ToggleButton>
    <PushPin size={16} weight="duotone" />
  </ToggleButton>
);

Install

Use the CLI or copy the source code manually.

pnpm dlx @kkga/shim add toggle-button

Size

Adjust the size prop to scale the toggle button.

Size example
import { PushPin } from "@phosphor-icons/react/dist/ssr";
import { ToggleButton } from "@/shim-ui/toggle-button";

export default () => (
  <>
    <ToggleButton size={1}>
      <PushPin size={16} weight="duotone" />
    </ToggleButton>

    <ToggleButton size={2}>
      <PushPin size={16} weight="duotone" />
    </ToggleButton>

    <ToggleButton size={3}>
      <PushPin size={16} weight="duotone" />
    </ToggleButton>

    <ToggleButton size={4}>
      <PushPin size={20} weight="duotone" />
    </ToggleButton>
  </>
);

Intent

Use the intent prop to apply semantic color styling.

Intent example
import { ToggleButton } from "@/shim-ui/toggle-button";

export default () => (
  <>
    <ToggleButton intent="neutral">Neutral</ToggleButton>
    <ToggleButton intent="accent">Accent</ToggleButton>
    <ToggleButton intent="success">Success</ToggleButton>
    <ToggleButton intent="warning">Warning</ToggleButton>
    <ToggleButton intent="danger">Danger</ToggleButton>
  </>
);

Variant

Select the visual treatment with the variant prop.

Variant example
import { ToggleButton } from "@/shim-ui/toggle-button";

export default () => (
  <>
    <ToggleButton variant="soft">Soft</ToggleButton>
    <ToggleButton variant="ghost">Ghost</ToggleButton>
  </>
);

States

Combine isSelected and isDisabled to communicate state.

States example
import { PushPin } from "@phosphor-icons/react/dist/ssr";
import { ToggleButton } from "@/shim-ui/toggle-button";

export default () => (
  <>
    <ToggleButton isSelected>
      <PushPin size={16} weight="fill" />
      Selected
    </ToggleButton>
    <ToggleButton isDisabled>
      <PushPin size={16} />
      Disabled
    </ToggleButton>
  </>
);

Controlled

Control state explicitly with isSelected and onChange.

Controlled example
"use client";
import { PushPin } from "@phosphor-icons/react";
import { useState } from "react";
import { ToggleButton } from "@/shim-ui/toggle-button";

export default () => {
  const [isSelected, setSelected] = useState(false);

  return (
    <ToggleButton
      aria-label="pin"
      isIconOnly
      isSelected={isSelected}
      onChange={setSelected}
    >
      <PushPin size={16} weight={isSelected ? "fill" : "regular"} />
    </ToggleButton>
  );
};