+```
+
+
+
+## Accessibility
+
+- The `Root` component, and every `Item` must be given must be given an accessible name with `aria-label` or `aria-labelledby`.
+- The `Item`'s label or accessible name _must not_ change based on the pressed state to ensure a smooth screen-reader experience, otherwise it may duplicate the announcement of the pressed state based on `aria-pressed`.
diff --git a/docs/data/components/toggle-button/ToggleButtonIntroduction.js b/docs/data/components/toggle-button/ToggleButtonIntroduction.js
new file mode 100644
index 0000000000..f0a607b4f0
--- /dev/null
+++ b/docs/data/components/toggle-button/ToggleButtonIntroduction.js
@@ -0,0 +1,26 @@
+'use client';
+import * as React from 'react';
+import { ToggleButton } from '@base-ui-components/react/ToggleButton';
+import classes from './styles.module.css';
+
+export default function ToggleButtonIntroduction() {
+ const [pressed, setPressed] = React.useState(false);
+ return (
+
+
+
+ );
+}
diff --git a/docs/data/components/toggle-button/ToggleButtonIntroduction.tsx b/docs/data/components/toggle-button/ToggleButtonIntroduction.tsx
new file mode 100644
index 0000000000..f0a607b4f0
--- /dev/null
+++ b/docs/data/components/toggle-button/ToggleButtonIntroduction.tsx
@@ -0,0 +1,26 @@
+'use client';
+import * as React from 'react';
+import { ToggleButton } from '@base-ui-components/react/ToggleButton';
+import classes from './styles.module.css';
+
+export default function ToggleButtonIntroduction() {
+ const [pressed, setPressed] = React.useState(false);
+ return (
+
+
+
+ );
+}
diff --git a/docs/data/components/toggle-button/ToggleButtonIntroduction.tsx.preview b/docs/data/components/toggle-button/ToggleButtonIntroduction.tsx.preview
new file mode 100644
index 0000000000..3109ca040b
--- /dev/null
+++ b/docs/data/components/toggle-button/ToggleButtonIntroduction.tsx.preview
@@ -0,0 +1,16 @@
+
+
+
\ No newline at end of file
diff --git a/docs/data/components/toggle-button/styles.module.css b/docs/data/components/toggle-button/styles.module.css
new file mode 100644
index 0000000000..1c18fed1ca
--- /dev/null
+++ b/docs/data/components/toggle-button/styles.module.css
@@ -0,0 +1,38 @@
+.button {
+ --size: 2.5rem;
+ --corner: 0.4rem;
+
+ display: flex;
+ flex-flow: row nowrap;
+ justify-content: center;
+ align-items: center;
+ height: var(--size);
+ width: var(--size);
+ border: 1px solid var(--gray-outline-2);
+ border-radius: var(--corner);
+ background-color: var(--gray-container-1);
+ color: var(--gray-text-1);
+}
+
+.button:hover {
+ background-color: var(--gray-surface-1);
+ color: var(--gray-text-2);
+}
+
+.button:focus-visible {
+ outline: 2px solid var(--color-violet);
+}
+
+.icon {
+ fill: none;
+ stroke: currentColor;
+ stroke-width: 2;
+ stroke-linecap: round;
+ stroke-linejoin: round;
+}
+
+.button[data-pressed] .icon {
+ color: var(--gray-text-2);
+ fill: currentColor;
+ stroke-width: 0;
+}
diff --git a/docs/data/components/toggle-button/toggle-button.mdx b/docs/data/components/toggle-button/toggle-button.mdx
new file mode 100644
index 0000000000..54aa15635c
--- /dev/null
+++ b/docs/data/components/toggle-button/toggle-button.mdx
@@ -0,0 +1,75 @@
+---
+productId: base-ui
+title: React ToggleButton component
+description: Toggle Buttons are a two-state button that can either be off (not pressed) or on (pressed).
+components: ToggleButtonRoot
+githubLabel: 'component: toggle button'
+waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/button/
+packageName: '@base-ui-components/react'
+---
+
+# ToggleButton
+
+
+
+
+
+
+
+## Installation
+
+
+
+## Anatomy
+
+ToggleButton is a single component that renders a `