diff --git a/examples/s2-next-macros/src/app/page.tsx b/examples/s2-next-macros/src/app/page.tsx
index e1cef34b79a..16125aac36e 100644
--- a/examples/s2-next-macros/src/app/page.tsx
+++ b/examples/s2-next-macros/src/app/page.tsx
@@ -38,6 +38,10 @@ import {
PickerItem,
Provider,
Row,
+ SideNav,
+ SideNavItem,
+ SideNavItemContent,
+ SideNavItemLink,
SubmenuTrigger,
TableBody,
TableHeader,
@@ -53,9 +57,12 @@ import {
useListData,
useTreeData
} from '@react-spectrum/s2';
+import Delete from '@react-spectrum/s2/icons/Delete';
import Edit from '@react-spectrum/s2/icons/Edit';
+import File from '@react-spectrum/s2/icons/File';
import FileTxt from '@react-spectrum/s2/icons/FileText';
import Folder from '@react-spectrum/s2/icons/Folder';
+import {RouterProvider} from 'react-aria-components';
import Section from './components/Section';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {CardViewExample} from './components/CardViewExample';
@@ -222,6 +229,89 @@ function ReorderableTreeView() {
);
}
+interface SideNavItemData {
+ id: number;
+ title: string;
+ type: 'directory' | 'file';
+ href?: string;
+ children?: SideNavItemData[];
+}
+
+let sideNavItems: SideNavItemData[] = [
+ {
+ id: 1,
+ title: 'Documents',
+ type: 'directory',
+ children: [
+ {
+ id: 2,
+ title: 'Project',
+ type: 'directory',
+ children: [
+ {id: 3, title: 'Notes', type: 'file', href: '/notes'},
+ {id: 4, title: 'Budget', type: 'file', href: '/budget'}
+ ]
+ }
+ ]
+ },
+ {
+ id: 5,
+ title: 'Photos',
+ type: 'directory',
+ children: [
+ {id: 6, title: 'Image 1', type: 'file', href: '/image-1'},
+ {id: 7, title: 'Image 2', type: 'file', href: '/image-2'}
+ ]
+ }
+];
+
+// Wrap SideNav in a RouterProvider whose navigate only updates local state so
+// clicking a link selects the item without actually navigating the page.
+function SideNavExample() {
+ let [selectedRoute, setSelectedRoute] = useState('/notes');
+ return (
+ setSelectedRoute(href)}>
+
+ {function renderItem(item: SideNavItemData) {
+ return (
+
+
+ {item.href ? (
+
+ {item.type === 'directory' ? : }
+ {item.title}
+
+ ) : (
+ <>
+ {item.type === 'directory' ? : }
+ {item.title}
+ >
+ )}
+
+
+
+
+
+ {item.children && {renderItem}}
+
+ );
+ }}
+
+
+ );
+}
+
function App() {
let [isLazyLoaded, setLazyLoaded] = useState(false);
let [cardViewState, setCardViewState] = useState({
@@ -355,6 +445,7 @@ function App() {
+
{!isLazyLoaded && (
diff --git a/examples/s2-parcel-example/src/App.js b/examples/s2-parcel-example/src/App.js
index 67fbe0f7414..2602a87a3a1 100644
--- a/examples/s2-parcel-example/src/App.js
+++ b/examples/s2-parcel-example/src/App.js
@@ -36,6 +36,10 @@ import {
PickerItem,
Provider,
Row,
+ SideNav,
+ SideNavItem,
+ SideNavItemContent,
+ SideNavItemLink,
SubmenuTrigger,
TableBody,
TableHeader,
@@ -51,9 +55,12 @@ import {
useListData,
useTreeData
} from '@react-spectrum/s2';
+import Delete from '@react-spectrum/s2/icons/Delete';
import Edit from '@react-spectrum/s2/icons/Edit';
+import File from '@react-spectrum/s2/icons/File';
import FileTxt from '@react-spectrum/s2/icons/FileText';
import Folder from '@react-spectrum/s2/icons/Folder';
+import {RouterProvider} from 'react-aria-components';
import Section from './components/Section';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {CardViewExample} from './components/CardViewExample';
@@ -218,6 +225,81 @@ function ReorderableTreeView() {
);
}
+let sideNavItems = [
+ {
+ id: 1,
+ title: 'Documents',
+ type: 'directory',
+ children: [
+ {
+ id: 2,
+ title: 'Project',
+ type: 'directory',
+ children: [
+ {id: 3, title: 'Notes', type: 'file', href: '/notes'},
+ {id: 4, title: 'Budget', type: 'file', href: '/budget'}
+ ]
+ }
+ ]
+ },
+ {
+ id: 5,
+ title: 'Photos',
+ type: 'directory',
+ children: [
+ {id: 6, title: 'Image 1', type: 'file', href: '/image-1'},
+ {id: 7, title: 'Image 2', type: 'file', href: '/image-2'}
+ ]
+ }
+];
+
+// Wrap SideNav in a RouterProvider whose navigate only updates local state so
+// clicking a link selects the item without actually navigating the page.
+function SideNavExample() {
+ let [selectedRoute, setSelectedRoute] = useState('/notes');
+ return (
+ setSelectedRoute(href)}>
+
+ {function renderItem(item) {
+ return (
+
+
+ {item.href ? (
+
+ {item.type === 'directory' ? : }
+ {item.title}
+
+ ) : (
+ <>
+ {item.type === 'directory' ? : }
+ {item.title}
+ >
+ )}
+
+
+
+
+
+ {item.children && {renderItem}}
+
+ );
+ }}
+
+
+ );
+}
+
function App() {
let [isLazyLoaded, setLazyLoaded] = useState(false);
let [cardViewState, setCardViewState] = useState({
@@ -349,6 +431,7 @@ function App() {
+
{!isLazyLoaded && (
diff --git a/examples/s2-vite-project/src/App.tsx b/examples/s2-vite-project/src/App.tsx
index 9c317800944..a2418c4ea23 100644
--- a/examples/s2-vite-project/src/App.tsx
+++ b/examples/s2-vite-project/src/App.tsx
@@ -34,6 +34,10 @@ import {
PickerItem,
Provider,
Row,
+ SideNav,
+ SideNavItem,
+ SideNavItemContent,
+ SideNavItemLink,
SubmenuTrigger,
TableBody,
TableHeader,
@@ -48,9 +52,12 @@ import {
useListData,
useTreeData
} from '@react-spectrum/s2';
+import Delete from '@react-spectrum/s2/icons/Delete';
import Edit from '@react-spectrum/s2/icons/Edit';
+import File from '@react-spectrum/s2/icons/File';
import FileTxt from '@react-spectrum/s2/icons/FileText';
import Folder from '@react-spectrum/s2/icons/Folder';
+import {RouterProvider} from 'react-aria-components';
import Section from './components/Section';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {CardViewExample} from './components/CardViewExample';
@@ -217,6 +224,89 @@ function ReorderableTreeView() {
);
}
+interface SideNavItemData {
+ id: number;
+ title: string;
+ type: 'directory' | 'file';
+ href?: string;
+ children?: SideNavItemData[];
+}
+
+let sideNavItems: SideNavItemData[] = [
+ {
+ id: 1,
+ title: 'Documents',
+ type: 'directory',
+ children: [
+ {
+ id: 2,
+ title: 'Project',
+ type: 'directory',
+ children: [
+ {id: 3, title: 'Notes', type: 'file', href: '/notes'},
+ {id: 4, title: 'Budget', type: 'file', href: '/budget'}
+ ]
+ }
+ ]
+ },
+ {
+ id: 5,
+ title: 'Photos',
+ type: 'directory',
+ children: [
+ {id: 6, title: 'Image 1', type: 'file', href: '/image-1'},
+ {id: 7, title: 'Image 2', type: 'file', href: '/image-2'}
+ ]
+ }
+];
+
+// Wrap SideNav in a RouterProvider whose navigate only updates local state so
+// clicking a link selects the item without actually navigating the page.
+function SideNavExample() {
+ let [selectedRoute, setSelectedRoute] = useState('/notes');
+ return (
+ setSelectedRoute(href)}>
+
+ {function renderItem(item: SideNavItemData) {
+ return (
+
+
+ {item.href ? (
+
+ {item.type === 'directory' ? : }
+ {item.title}
+
+ ) : (
+ <>
+ {item.type === 'directory' ? : }
+ {item.title}
+ >
+ )}
+
+
+
+
+
+ {item.children && {renderItem}}
+
+ );
+ }}
+
+
+ );
+}
+
function App() {
let [isLazyLoaded, setLazyLoaded] = useState(false);
let [cardViewState, setCardViewState] = useState({
@@ -344,6 +434,7 @@ function App() {
+
{!isLazyLoaded && (
diff --git a/examples/s2-webpack-5-example/src/App.js b/examples/s2-webpack-5-example/src/App.js
index 3cfecfc5669..5027d8c8a71 100644
--- a/examples/s2-webpack-5-example/src/App.js
+++ b/examples/s2-webpack-5-example/src/App.js
@@ -36,6 +36,10 @@ import {
PickerItem,
Provider,
Row,
+ SideNav,
+ SideNavItem,
+ SideNavItemContent,
+ SideNavItemLink,
SubmenuTrigger,
TableBody,
TableHeader,
@@ -51,9 +55,12 @@ import {
useListData,
useTreeData
} from '@react-spectrum/s2';
+import Delete from '@react-spectrum/s2/icons/Delete';
import Edit from '@react-spectrum/s2/icons/Edit';
+import File from '@react-spectrum/s2/icons/File';
import FileTxt from '@react-spectrum/s2/icons/FileText';
import Folder from '@react-spectrum/s2/icons/Folder';
+import {RouterProvider} from 'react-aria-components';
import Section from './components/Section';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {CardViewExample} from './components/CardViewExample';
@@ -218,6 +225,81 @@ function ReorderableTreeView() {
);
}
+let sideNavItems = [
+ {
+ id: 1,
+ title: 'Documents',
+ type: 'directory',
+ children: [
+ {
+ id: 2,
+ title: 'Project',
+ type: 'directory',
+ children: [
+ {id: 3, title: 'Notes', type: 'file', href: '/notes'},
+ {id: 4, title: 'Budget', type: 'file', href: '/budget'}
+ ]
+ }
+ ]
+ },
+ {
+ id: 5,
+ title: 'Photos',
+ type: 'directory',
+ children: [
+ {id: 6, title: 'Image 1', type: 'file', href: '/image-1'},
+ {id: 7, title: 'Image 2', type: 'file', href: '/image-2'}
+ ]
+ }
+];
+
+// Wrap SideNav in a RouterProvider whose navigate only updates local state so
+// clicking a link selects the item without actually navigating the page.
+function SideNavExample() {
+ let [selectedRoute, setSelectedRoute] = useState('/notes');
+ return (
+ setSelectedRoute(href)}>
+
+ {function renderItem(item) {
+ return (
+
+
+ {item.href ? (
+
+ {item.type === 'directory' ? : }
+ {item.title}
+
+ ) : (
+ <>
+ {item.type === 'directory' ? : }
+ {item.title}
+ >
+ )}
+
+
+
+
+
+ {item.children && {renderItem}}
+
+ );
+ }}
+
+
+ );
+}
+
function App() {
let [isLazyLoaded, setLazyLoaded] = useState(false);
let [cardViewState, setCardViewState] = useState({
@@ -349,6 +431,7 @@ function App() {
+
{!isLazyLoaded && (
diff --git a/examples/s2-webpack-5-typescript-example/src/App.tsx b/examples/s2-webpack-5-typescript-example/src/App.tsx
index f06a7314668..7f2944443c9 100644
--- a/examples/s2-webpack-5-typescript-example/src/App.tsx
+++ b/examples/s2-webpack-5-typescript-example/src/App.tsx
@@ -19,6 +19,7 @@ import {
Button,
ButtonGroup,
Cell,
+ Collection,
Column,
Divider,
Heading,
@@ -31,6 +32,10 @@ import {
PickerItem,
Provider,
Row,
+ SideNav,
+ SideNavItem,
+ SideNavItemContent,
+ SideNavItemLink,
SubmenuTrigger,
TableBody,
TableHeader,
@@ -44,9 +49,12 @@ import {
} from '@react-spectrum/s2';
import {CardViewExample} from './components/CardViewExample';
import {CollectionCardsExample} from './components/CollectionCardsExample';
+import Delete from '@react-spectrum/s2/icons/Delete';
import Edit from '@react-spectrum/s2/icons/Edit';
+import File from '@react-spectrum/s2/icons/File';
import FileTxt from '@react-spectrum/s2/icons/FileText';
import Folder from '@react-spectrum/s2/icons/Folder';
+import {RouterProvider} from 'react-aria-components';
import {LoadingState} from '@react-types/shared';
import React, {useState} from 'react';
import Section from './components/Section';
@@ -54,6 +62,89 @@ import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
const Lazy = React.lazy(() => import('./Lazy'));
+interface SideNavItemData {
+ id: number;
+ title: string;
+ type: 'directory' | 'file';
+ href?: string;
+ children?: SideNavItemData[];
+}
+
+let sideNavItems: SideNavItemData[] = [
+ {
+ id: 1,
+ title: 'Documents',
+ type: 'directory',
+ children: [
+ {
+ id: 2,
+ title: 'Project',
+ type: 'directory',
+ children: [
+ {id: 3, title: 'Notes', type: 'file', href: '/notes'},
+ {id: 4, title: 'Budget', type: 'file', href: '/budget'}
+ ]
+ }
+ ]
+ },
+ {
+ id: 5,
+ title: 'Photos',
+ type: 'directory',
+ children: [
+ {id: 6, title: 'Image 1', type: 'file', href: '/image-1'},
+ {id: 7, title: 'Image 2', type: 'file', href: '/image-2'}
+ ]
+ }
+];
+
+// Wrap SideNav in a RouterProvider whose navigate only updates local state so
+// clicking a link selects the item without actually navigating the page.
+function SideNavExample() {
+ let [selectedRoute, setSelectedRoute] = useState('/notes');
+ return (
+ setSelectedRoute(href)}>
+
+ {function renderItem(item: SideNavItemData) {
+ return (
+
+
+ {item.href ? (
+
+ {item.type === 'directory' ? : }
+ {item.title}
+
+ ) : (
+ <>
+ {item.type === 'directory' ? : }
+ {item.title}
+ >
+ )}
+
+
+
+
+
+ {item.children && {renderItem}}
+
+ );
+ }}
+
+
+ );
+}
+
function App() {
let [isLazyLoaded, setLazyLoaded] = useState(false);
let [cardViewState, setCardViewState] = useState<{
@@ -263,6 +354,7 @@ function App() {
+
{!isLazyLoaded && (