1- import { AppShell , Group , Title , UnstyledButton , rem , useMantineColorScheme } from '@mantine/core' ;
1+ import { AppShell , Group , Title , UnstyledButton , Text , rem , Box , Collapse , ActionIcon } from '@mantine/core' ;
22import { Outlet , Link , useLocation } from 'react-router-dom' ;
33import { ThemeCustomizer } from './components/ThemeCustomizer' ;
44import { ColorSchemeToggle } from './components/ColorSchemeToggle' ;
@@ -7,12 +7,18 @@ import { useTheme } from './context/ThemeContext';
77import { useStyles } from './hooks/useStyles' ;
88import { Prefetcher } from './components/Prefetcher' ;
99import { useState } from 'react' ;
10+ import { useDisclosure } from '@mantine/hooks' ;
11+ import { IconChevronRight , IconChevronDown , IconBook , IconMenu2 } from '@tabler/icons-react' ;
12+ import { useAbilityManuals } from './hooks/useAbilityManuals' ;
1013
1114export default function App ( ) {
1215 const location = useLocation ( ) ;
1316 const { colors } = useTheme ( ) ;
1417 const { isDark } = useStyles ( ) ; // Use the isDark from useStyles which gets it from Mantine
1518 const [ themeSettingsOpened , setThemeSettingsOpened ] = useState ( false ) ;
19+ const [ navbarCollapsed , { toggle : toggleNavbar } ] = useDisclosure ( false ) ;
20+ const [ manualsExpanded , { toggle : toggleManuals } ] = useDisclosure ( false ) ;
21+ const { AbilityManuals } = useAbilityManuals ( ) ;
1622
1723 // Generate inline styles based on theme settings
1824 const getComponentStyles = ( ) => ( {
@@ -49,16 +55,29 @@ export default function App() {
4955 }
5056 return isDark ? 'gray.3' : 'dark.6' ;
5157 } ;
52-
5358 return (
5459 < AppShell
5560 header = { { height : 60 } }
56- navbar = { { width : 300 , breakpoint : 'sm' } }
61+ navbar = { {
62+ width : 300 ,
63+ breakpoint : 'sm' ,
64+ collapsed : { desktop : navbarCollapsed , mobile : true }
65+ } }
5766 padding = "md"
5867 >
5968 < AppShell . Header p = "md" style = { styles . header } >
6069 < Group h = "100%" px = "md" justify = "space-between" >
61- < Title order = { 1 } size = "h3" c = "white" > SAGA Abilities Manager</ Title >
70+ < Group >
71+ < ActionIcon
72+ variant = "subtle"
73+ color = { isDark ? 'gray.0' : 'dark.0' }
74+ onClick = { toggleNavbar }
75+ aria-label = "Toggle navigation"
76+ >
77+ < IconMenu2 size = { 24 } />
78+ </ ActionIcon >
79+ < Title order = { 1 } size = "h3" c = "white" > SAGA Abilities Manager</ Title >
80+ </ Group >
6281 < ColorSchemeToggle />
6382 </ Group >
6483 </ AppShell . Header >
@@ -80,18 +99,53 @@ export default function App() {
8099 Abilities Library
81100 </ UnstyledButton >
82101
83- < UnstyledButton
84- component = { Link }
85- to = "/AbilityManuals"
86- fw = { location . pathname . includes ( '/AbilityManuals' ) ? 'bold' : 'normal' }
87- c = { getNavLinkColor ( location . pathname . includes ( '/AbilityManuals' ) ) }
88- display = "block"
89- style = { styles . navButton }
90- >
91- My Ability Manuals
92- </ UnstyledButton >
102+ < Box mb = { rem ( 10 ) } >
103+ < Group justify = "space-between" style = { { ...styles . navButton , cursor : 'pointer' } } onClick = { toggleManuals } >
104+ < UnstyledButton
105+ component = { Link }
106+ to = "/AbilityManuals"
107+ fw = { location . pathname . includes ( '/AbilityManuals' ) ? 'bold' : 'normal' }
108+ c = { getNavLinkColor ( location . pathname . includes ( '/AbilityManuals' ) ) }
109+ style = { { flex : 1 } }
110+ >
111+ My Ability Manuals
112+ </ UnstyledButton >
113+ { manualsExpanded ?
114+ < IconChevronDown size = { 16 } color = { isDark ? 'var(--mantine-color-gray-5)' : 'var(--mantine-color-dark-3)' } /> :
115+ < IconChevronRight size = { 16 } color = { isDark ? 'var(--mantine-color-gray-5)' : 'var(--mantine-color-dark-3)' } />
116+ }
117+ </ Group >
118+
119+ < Collapse in = { manualsExpanded } >
120+ < Box pl = { 20 } pt = { 5 } >
121+ { AbilityManuals . length === 0 ? (
122+ < Text size = "sm" c = { isDark ? 'gray.5' : 'gray.6' } fs = "italic" > No ability manuals</ Text >
123+ ) : (
124+ AbilityManuals . map ( ( manual ) => (
125+ < UnstyledButton
126+ key = { manual . id }
127+ component = { Link }
128+ to = { `/AbilityManuals/${ manual . id } ` }
129+ fw = { location . pathname === `/AbilityManuals/${ manual . id } ` ? 'bold' : 'normal' }
130+ c = { getNavLinkColor ( location . pathname === `/AbilityManuals/${ manual . id } ` ) }
131+ mb = { rem ( 5 ) }
132+ display = "block"
133+ style = { { ...styles . navButton , fontSize : `${ ( colors . fontScale * 0.85 ) } rem` } }
134+ >
135+ < Group gap = { 5 } >
136+ < IconBook size = { 14 } />
137+ < Text truncate > { manual . name } </ Text >
138+ </ Group >
139+ </ UnstyledButton >
140+ ) )
141+ ) }
142+ </ Box >
143+ </ Collapse >
144+ </ Box >
93145 </ AppShell . Section >
94- </ AppShell . Navbar > < AppShell . Main style = { styles . main } >
146+ </ AppShell . Navbar >
147+
148+ < AppShell . Main style = { styles . main } >
95149 { /* Invisible component that prefetches critical resources */ }
96150 < Prefetcher />
97151 < Outlet />
0 commit comments