diff options
| author | shu <nvcsadjkojf@outlook.com> | 2026-09-07 15:48:36 +0800 |
|---|---|---|
| committer | shu <nvcsadjkojf@outlook.com> | 2026-09-07 15:48:36 +0800 |
| commit | 481402e09fe760634b826b09e302e2e1bfec88b1 (patch) | |
| tree | 9b55025bfcd6acd2c5d795f057de27028b422603 /src/components/layout-basic.tsx | |
feat: initialize React Spectrum template with layouts and showcases
Diffstat (limited to 'src/components/layout-basic.tsx')
| -rw-r--r-- | src/components/layout-basic.tsx | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/components/layout-basic.tsx b/src/components/layout-basic.tsx new file mode 100644 index 0000000..05f3eef --- /dev/null +++ b/src/components/layout-basic.tsx @@ -0,0 +1,67 @@ +import { useState, type ReactNode } from 'react' +import { useMatches } from 'react-router' +import type { PageMetadata } from '../route-config' +import CollapsedNavigation from './collapsed-navigation' +import { ActionButton } from '@react-spectrum/s2/ActionButton' +import { Tooltip, TooltipTrigger } from '@react-spectrum/s2/Tooltip' +import SidebarMenu from './sidebar-menu' +import MobileNavigation from './mobile-navigation' +import GlobalSettings from './global-settings' +import HomeIcon from '@react-spectrum/s2/icons/Home' +import ChevronLeftIcon from '@react-spectrum/s2/icons/ChevronLeft' +import ChevronRightIcon from '@react-spectrum/s2/icons/ChevronRight' +import styles from './layout-basic.module.css' + +interface BasicLayoutProps { + children: ReactNode +} + +function BasicLayout({ children }: BasicLayoutProps) { + const [isCollapsed, setIsCollapsed] = useState(false) + const currentPage = useMatches().at(-1)?.handle as PageMetadata | undefined + + return ( + <div className={`${styles.appLayout}${isCollapsed ? ` ${styles.isCollapsed}` : ''}`}> + <a className={styles.skipLink} href="#main-content">Skip to content</a> + <aside id="sidebar" className={styles.sidebar} aria-label="Sidebar"> + <div className={styles.sidebarBrand} aria-label="React Spectrum"> + {isCollapsed ? <HomeIcon /> : 'React Spectrum'} + </div> + <nav className={styles.sidebarNavigation} aria-label="Main navigation"> + {isCollapsed && <CollapsedNavigation activePageId={currentPage?.id} />} + <div className={styles.expandedNavigation} hidden={isCollapsed}> + <SidebarMenu /> + </div> + </nav> + </aside> + <div className={styles.contentLayout}> + <header className={styles.topbar}> + <MobileNavigation /> + <div className={styles.desktopMenuToggle}> + <TooltipTrigger> + <ActionButton + aria-label={isCollapsed ? 'Expand sidebar' : 'Collapse sidebar'} + aria-expanded={!isCollapsed} + aria-controls="sidebar" + isQuiet + onPress={() => setIsCollapsed((collapsed) => !collapsed)} + > + {isCollapsed ? <ChevronRightIcon /> : <ChevronLeftIcon />} + </ActionButton> + <Tooltip>{isCollapsed ? 'Expand sidebar' : 'Collapse sidebar'}</Tooltip> + </TooltipTrigger> + </div> + <span>{currentPage?.title}</span> + <div className={styles.topbarActions}> + <GlobalSettings /> + </div> + </header> + <main id="main-content" className={styles.pageContent} tabIndex={-1}> + {children} + </main> + </div> + </div> + ) +} + +export default BasicLayout |
