diff --git a/docs/src/app/(private)/experiments/tabs/_icons.tsx b/docs/src/app/(private)/experiments/tabs/_icons.tsx
new file mode 100644
index 0000000000..0aa7450059
--- /dev/null
+++ b/docs/src/app/(private)/experiments/tabs/_icons.tsx
@@ -0,0 +1,30 @@
+'use client';
+import * as React from 'react';
+
+export default function Nothing() {
+ return
This is just a dummy file to hold icons
;
+}
+
+export function OverviewIcon(props: React.ComponentProps<'svg'>) {
+ return (
+
+ );
+}
+
+export function ProjectIcon(props: React.ComponentProps<'svg'>) {
+ return (
+
+ );
+}
+
+export function PersonIcon(props: React.ComponentProps<'svg'>) {
+ return (
+
+ );
+}
diff --git a/docs/src/app/(private)/experiments/tabs/motion.module.css b/docs/src/app/(private)/experiments/tabs/motion.module.css
new file mode 100644
index 0000000000..27cd646b50
--- /dev/null
+++ b/docs/src/app/(private)/experiments/tabs/motion.module.css
@@ -0,0 +1,7 @@
+.Indicator {
+ position: absolute;
+ z-index: -1;
+ inset: 4px 0 5px 0;
+ border-radius: 0.25rem;
+ background-color: var(--color-gray-100);
+}
diff --git a/docs/src/app/(private)/experiments/tabs/motion.tsx b/docs/src/app/(private)/experiments/tabs/motion.tsx
new file mode 100644
index 0000000000..b2ba3ec5fd
--- /dev/null
+++ b/docs/src/app/(private)/experiments/tabs/motion.tsx
@@ -0,0 +1,131 @@
+'use client';
+import * as React from 'react';
+import { Tabs } from '@base-ui-components/react/tabs';
+import { AnimatePresence, motion, type HTMLMotionProps } from 'motion/react';
+import styles from '../../../(public)/(content)/react/components/tabs/demos/hero/css-modules/index.module.css';
+import { OverviewIcon, ProjectIcon, PersonIcon } from './_icons';
+import motionStyles from './motion.module.css';
+
+const DURATION = 1; // seconds
+
+const MotionTabPanel = React.forwardRef(function MotionTabPanel(
+ props: Tabs.Panel.Props,
+ forwardedRef: React.ForwardedRef,
+) {
+ const { children, value, ...otherProps } = props;
+ return (
+ {
+ const direction = state.tabActivationDirection === 'right' ? -1 : 1;
+ return (
+ )}
+ initial={{
+ opacity: 0,
+ x: -100 * direction,
+ }}
+ animate={{
+ zIndex: 1,
+ opacity: 1,
+ x: 0,
+ transition: { duration: DURATION },
+ }}
+ exit={{
+ zIndex: 0,
+ opacity: 0,
+ x: 100 * direction,
+ transition: { duration: DURATION },
+ }}
+ />
+ );
+ }}
+ >
+ {children}
+
+ );
+});
+
+const MotionTab = React.forwardRef(function MotionTab(
+ props: Tabs.Tab.Props & {
+ selectedValue: Tabs.Tab.Props['value'];
+ },
+ forwardedRef: React.ForwardedRef,
+) {
+ const { value, selectedValue, style, children, ...otherProps } = props;
+ return (
+
+ {children}
+ {value === selectedValue ? (
+
+ }
+ />
+ ) : null}
+
+ );
+});
+
+export default function ExampleTabs() {
+ const [value, setValue] = React.useState('overview');
+ return (
+
+
+
+ Overview
+
+
+ Projects
+
+
+ Account
+
+
+
+
+ {value === 'overview' && (
+
+
+
+ )}
+
+ {value === 'projects' && (
+
+
+
+ )}
+
+ {value === 'account' && (
+
+
+
+ )}
+
+
+ );
+}
diff --git a/docs/src/app/(private)/experiments/tabs.module.css b/docs/src/app/(private)/experiments/tabs/tabs.module.css
similarity index 100%
rename from docs/src/app/(private)/experiments/tabs.module.css
rename to docs/src/app/(private)/experiments/tabs/tabs.module.css
diff --git a/docs/src/app/(private)/experiments/tabs.tsx b/docs/src/app/(private)/experiments/tabs/tabs.tsx
similarity index 96%
rename from docs/src/app/(private)/experiments/tabs.tsx
rename to docs/src/app/(private)/experiments/tabs/tabs.tsx
index de114b8cde..1abc0ca55d 100644
--- a/docs/src/app/(private)/experiments/tabs.tsx
+++ b/docs/src/app/(private)/experiments/tabs/tabs.tsx
@@ -5,8 +5,8 @@ import { Tabs } from '@base-ui-components/react/tabs';
import {
SettingsMetadata,
useExperimentSettings,
-} from '../../../components/Experiments/SettingsPanel';
-import '../../../demo-theme.css';
+} from '../../../../components/Experiments/SettingsPanel';
+import '../../../../demo-theme.css';
import classes from './tabs.module.css';
export default function TabsExperiment() {