diff --git a/docs/data/api/toggle-button-group-item.json b/docs/data/api/toggle-button-group-item.json
new file mode 100644
index 000000000..a9f4f9398
--- /dev/null
+++ b/docs/data/api/toggle-button-group-item.json
@@ -0,0 +1,29 @@
+{
+ "props": {
+ "value": { "type": { "name": "any" }, "required": true },
+ "aria-label": { "type": { "name": "string" } },
+ "aria-labelledby": { "type": { "name": "string" } },
+ "className": { "type": { "name": "union", "description": "func
| string" } },
+ "onPressedChange": {
+ "type": { "name": "func" },
+ "signature": {
+ "type": "function(pressed: boolean, event: Event) => void",
+ "describedArgs": ["pressed", "event"]
+ }
+ },
+ "render": { "type": { "name": "union", "description": "element
| func" } }
+ },
+ "name": "ToggleButtonGroupItem",
+ "imports": [
+ "import { ToggleButtonGroup } from '@base_ui/react/ToggleButtonGroup';\nconst ToggleButtonGroupItem = ToggleButtonGroup.Item;"
+ ],
+ "classes": [],
+ "spread": true,
+ "themeDefaultProps": true,
+ "muiName": "ToggleButtonGroupItem",
+ "forwardsRefTo": "HTMLButtonElement",
+ "filename": "/packages/mui-base/src/ToggleButtonGroup/Item/ToggleButtonGroupItem.tsx",
+ "inheritance": null,
+ "demos": "
",
+ "cssComponent": false
+}
diff --git a/docs/data/api/toggle-button-group-root.json b/docs/data/api/toggle-button-group-root.json
new file mode 100644
index 000000000..a3b4e1779
--- /dev/null
+++ b/docs/data/api/toggle-button-group-root.json
@@ -0,0 +1,20 @@
+{
+ "props": {
+ "className": { "type": { "name": "union", "description": "func
| string" } },
+ "render": { "type": { "name": "union", "description": "element
| func" } },
+ "toggleMultiple": { "type": { "name": "bool" }, "default": "false" }
+ },
+ "name": "ToggleButtonGroupRoot",
+ "imports": [
+ "import { ToggleButtonGroup } from '@base_ui/react/ToggleButtonGroup';\nconst ToggleButtonGroupRoot = ToggleButtonGroup.Root;"
+ ],
+ "classes": [],
+ "spread": true,
+ "themeDefaultProps": true,
+ "muiName": "ToggleButtonGroupRoot",
+ "forwardsRefTo": "HTMLDivElement",
+ "filename": "/packages/mui-base/src/ToggleButtonGroup/Root/ToggleButtonGroupRoot.tsx",
+ "inheritance": null,
+ "demos": "",
+ "cssComponent": false
+}
diff --git a/docs/data/components/toggle-button-group/ToggleButtonGroupIntroduction.js b/docs/data/components/toggle-button-group/ToggleButtonGroupIntroduction.js
new file mode 100644
index 000000000..dea1da5e1
--- /dev/null
+++ b/docs/data/components/toggle-button-group/ToggleButtonGroupIntroduction.js
@@ -0,0 +1,77 @@
+'use client';
+import * as React from 'react';
+import { ToggleButtonGroup } from '@base_ui/react/ToggleButtonGroup';
+import classes from './styles.module.css';
+
+export default function ToggleButtonGroupIntroduction() {
+ const [value, setValue] = React.useState(['align-center']);
+ return (
+ {
+ if (newValue.length > 0) {
+ setValue(newValue);
+ }
+ }}
+ aria-label="Text alignment"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/docs/data/components/toggle-button-group/ToggleButtonGroupIntroduction.tsx b/docs/data/components/toggle-button-group/ToggleButtonGroupIntroduction.tsx
new file mode 100644
index 000000000..148849601
--- /dev/null
+++ b/docs/data/components/toggle-button-group/ToggleButtonGroupIntroduction.tsx
@@ -0,0 +1,77 @@
+'use client';
+import * as React from 'react';
+import { ToggleButtonGroup } from '@base_ui/react/ToggleButtonGroup';
+import classes from './styles.module.css';
+
+export default function ToggleButtonGroupIntroduction() {
+ const [value, setValue] = React.useState(['align-center']);
+ return (
+ {
+ if (newValue.length > 0) {
+ setValue(newValue as string[]);
+ }
+ }}
+ aria-label="Text alignment"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/docs/data/components/toggle-button-group/styles.module.css b/docs/data/components/toggle-button-group/styles.module.css
new file mode 100644
index 000000000..965b79590
--- /dev/null
+++ b/docs/data/components/toggle-button-group/styles.module.css
@@ -0,0 +1,56 @@
+.root {
+ display: flex;
+}
+
+.button {
+ --size: 2.5rem;
+ --corner: 0.4rem;
+ --border-color: var(--gray-outline-2);
+
+ display: flex;
+ flex-flow: row nowrap;
+ justify-content: center;
+ align-items: center;
+ height: var(--size);
+ width: var(--size);
+ border: 1px solid var(--border-color);
+ background-color: var(--gray-container-2);
+ color: var(--gray-400);
+}
+
+.button:first-child {
+ border-radius: var(--corner) 0 0 var(--corner);
+ border-right-color: transparent;
+}
+
+.button:last-child {
+ border-radius: 0 var(--corner) var(--corner) 0;
+ border-left-color: transparent;
+}
+
+.button:hover {
+ background-color: var(--gray-surface-1);
+ outline: 1px solid var(--gray-500);
+ outline-offset: -1px;
+ color: var(--gray-text-2);
+ cursor: pointer;
+ z-index: 1;
+}
+
+.button:focus-visible {
+ outline: 2px solid var(--gray-900);
+ z-index: 1;
+}
+
+.icon {
+ fill: none;
+ stroke: currentColor;
+ stroke-width: 2;
+ stroke-linecap: round;
+ stroke-linejoin: round;
+}
+
+.button[data-pressed] {
+ background-color: #fefefe;
+ color: var(--gray-text-2);
+}
diff --git a/docs/data/components/toggle-button-group/toggle-button-group.mdx b/docs/data/components/toggle-button-group/toggle-button-group.mdx
new file mode 100644
index 000000000..1ebab1f2f
--- /dev/null
+++ b/docs/data/components/toggle-button-group/toggle-button-group.mdx
@@ -0,0 +1,110 @@
+---
+productId: base-ui
+title: React ToggleButtonGroup component
+description: ToggleButtonGroup provides a set of two-state buttons that can either be off (not pressed) or on (pressed).
+components: ToggleButtonGroupRoot, ToggleButtonGroupItem
+githubLabel: 'component: toggle button'
+waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/radio-group/
+packageName: '@base_ui/react'
+---
+
+# ToggleButtonGroup
+
+
+
+
+
+
+
+## Installation
+
+
+
+## Anatomy
+
+ToggleButtonGroups are composed with two components:
+
+- `` is the outer component that wraps a set of [`toggle buttons`](/components/react-toggle-button)
+- ``s renders the `