diff --git a/packages/dev/s2-docs/pages/s2/Tabs.mdx b/packages/dev/s2-docs/pages/s2/Tabs.mdx
new file mode 100644
index 00000000000..33a82e34bb8
--- /dev/null
+++ b/packages/dev/s2-docs/pages/s2/Tabs.mdx
@@ -0,0 +1,294 @@
+import {Layout} from '../../src/Layout';
+export default Layout;
+import docs from 'docs:@react-spectrum/s2';
+
+# Tabs
+
+{docs.exports.Tabs.description}
+```tsx render docs={docs.exports.Tabs} props={['density', 'isDisabled', 'orientation', 'keyboardActivation']} initialProps={{'aria-label': 'Tabs'}} links={docs.links} expanded type="s2"
+import {Tabs, TabList, TabPanel, Tab} from '@react-spectrum/s2';
+
+
+ Explore
+ Shop
+ Profile
+
+
+ Content for Explore tab.
+
+
+ Content for Shop tab.
+
+
+ Content for Profile tab.
+
+
+```
+
+## Content
+
+`TabList` follows the **Collection Components API**, accepting both static and dynamic collections. This example shows a dynamic collection, passing a list of objects to the `items` prop, and a function to render the children.
+```tsx render
+"use client";
+import {ActionButton, Tabs, TabList, Tab, TabPanel, Button, ButtonGroup} from '@react-spectrum/s2';
+import {Collection} from 'react-aria-components';
+import {useState} from 'react';
+import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
+interface Item {
+ id: number,
+ title: string,
+ description: string
+}
+
+function Example() {
+ ///- begin collapse -///
+ let [tabs, setTabs] = useState([
+ {id: 1, title: 'Tab 1', description: 'Tab 1'},
+ {id: 2, title: 'Tab 2', description: 'Tab 2'},
+ {id: 3, title: 'Tab 3', description: 'Tab 3'}
+ ]);
+ ///- end collapse -///
+
+ ///- begin collapse -///
+ let addTab = () => {
+ setTabs(tabs => [
+ ...tabs,
+ {
+ id: tabs.length + 1,
+ title: `Tab ${tabs.length + 1}`,
+ description: `Tab body ${tabs.length + 1}`
+ }
+ ]);
+ };
+ ///- end collapse -///
+
+ ///- begin collapse -///
+ let removeTab = () => {
+ if (tabs.length > 1) {
+ setTabs(tabs => tabs.slice(0, -1));
+ }
+ };
+ ///- end collapse -///
+
+ return (
+
+
+
+ {/*- begin highlight -*/}
+
+ {item => {item.title}}
+
+ {/*- end highlight -*/}
+
+
+ {/*- begin highlight -*/}
+
+ {item => {item.description}}
+
+ {/*- end highlight -*/}
+
+
+ )
+}
+```
+### Links
+
+Use the `href` prop on a `` to create a link. See the **client side routing guide** to learn how to integrate with your framework. This example uses a simple hash-based router to sync the selected tab to the URL.
+```tsx render
+"use client";
+import {Tabs, TabList, Tab, TabPanel} from '@react-spectrum/s2';
+import {useSyncExternalStore} from 'react';
+
+export default function Example() {
+ let hash = useSyncExternalStore(subscribe, getHash, getHashServer);
+ return (
+
+
+ {/*- begin highlight -*/}
+ Home
+ {/*- end highlight -*/}
+ Shared
+ Deleted
+
+ Home
+ Shared
+ Deleted
+
+ );
+}
+function getHash() {
+ return location.hash.startsWith('#/') ? location.hash : '#/';
+}
+function getHashServer() {
+ return '#/';
+}
+function subscribe(fn) {
+ addEventListener('hashchange', fn);
+ return () => removeEventListener('hashchange', fn);
+}
+```
+### Icons
+Icons can also be used in Tabs in addition to a text label.
+```tsx render
+"use client"
+import {Tabs, TabList, Tab, TabPanel, Text} from '@react-spectrum/s2';
+import Edit from '@react-spectrum/s2/icons/Edit';
+import Bell from '@react-spectrum/s2/icons/Bell';
+import Heart from '@react-spectrum/s2/icons/Heart';
+
+function Example() {
+ return (
+
+
+
+ {/*- begin highlight -*/}
+ Edit
+ Notifications
+ Likes
+ {/*- end highlight -*/}
+
+
+ Review your edits
+
+
+ Check your notifications
+
+
+ See your likes
+
+
+
+ )
+}
+```
+### Internationalization
+To internationalize Tabs, a localized string should be passed as children to the TabList ``. Any text content within the Tab's panel should also be localized accordingly. For languages that are read right-to-left (e.g. Hebrew and Arabic), the layout of Tabs is automatically flipped.
+
+### Accessibility
+While an `aria-label` is not explicitly required for a tab list, Tabs must be labeled using a aria-label in the absence of an ancestor landmark. This will prevent screen readers from announcing non-focused tabs, allowing for a more focused experience.
+
+## Selection
+
+Use the `defaultSelectedKey` or `selectedKey` prop to set the selected tab. The selected key corresponds to the `id` prop of a ``. Tabs can be disabled with the `isDisabled` prop. See the [selection guide](selection.html) for more details.
+```tsx render
+"use client";
+import type {Key} from 'react-aria-components';
+import {Tabs, TabList, Tab, TabPanel} from '@react-spectrum/s2';
+import Home from '@react-spectrum/s2/illustrations/gradient/generic2/Home';
+import Folder from '@react-spectrum/s2/illustrations/gradient/generic2/FolderOpen';
+import Search from '@react-spectrum/s2/illustrations/gradient/generic2/Search';
+import Settings from '@react-spectrum/s2/illustrations/gradient/generic1/GearSetting';
+import {useState} from 'react';
+function Example() {
+ let [tab, setTab] = useState("files");
+ return (
+
+
+
+ Home
+ Files
+ Search
+ Settings
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Selected tab: {tab}
+
+ );
+}
+```
+
+## Collaspe behavior
+
+If there isn't enough horizontal room to render every tab on a single line, the component will collapse all tabs into a `Picker`. Note that this does not apply to vertical Tabs.
+Try the example below to see the above behavior.
+```tsx render
+"use client";
+import {ToggleButton, Tabs, TabList, Tab, TabPanel} from '@react-spectrum/s2';
+import {useState} from 'react';
+import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
+
+function Example() {
+ let [isCollasped, setCollaspe] = useState(false);
+ return (
+
+
+
+ Home
+ Profile
+ Contact
+ About
+
+
+
+ Welcome home
+
+
+
+
+ View your profile
+
+
+
+
+ Find your contacts
+
+
+
+
+ Learn more
+
+
+
+
setCollaspe((isCollasped) => !isCollasped)}>
+ Toggle tab container size
+
+
+ );
+}
+```
+## API
+
+### Tabs
+
+
+### TabList
+
+
+### Tab
+
+
+### TabPanel
+
\ No newline at end of file