Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | 7x 7x 7x 7x 14x 14x 1x 7x 1x 2x 1x | import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useTheme } from '@mui/material/styles'; import Box from '@mui/material/Box'; import List from '@mui/material/List'; import ListItemButton from '@mui/material/ListItemButton'; import ListItemText from '@mui/material/ListItemText'; import Typography from '@mui/material/Typography'; import IconButton from '@mui/material/IconButton'; import Drawer from '@mui/material/Drawer'; import MenuIcon from '@mui/icons-material/Menu'; interface TocProps { sections: readonly [string, string][]; // [subKey, textKey] makeId: (key: string) => string; titleKey: string; // ex. 'legal.subtitleTableOfContents' namespace: string; // ex. 'legal' } export function TableOfContents({ sections, makeId, titleKey, namespace, }: TocProps) { const theme = useTheme(); const { t } = useTranslation(namespace); const [open, setOpen] = useState(false); const TocList = ( <List disablePadding> {sections.map(([subKey]) => { const anchor = makeId(subKey); return ( <ListItemButton key={subKey} component="a" href={`#${anchor}`} sx={{ pl: 2 }} onClick={() => setOpen(false)} > {/* on traduit la clé du titre de section */} <ListItemText primary={t(`${namespace}.${subKey}`)} /> </ListItemButton> ); })} </List> ); return ( <> {/* Sidebar desktop */} <Box component="nav" sx={{ display: { xs: 'none', md: 'block' }, position: 'sticky', top: theme.mixins.toolbar.minHeight, width: 240, bgcolor: 'background.paper', border: theme => `1px solid ${theme.palette.divider}`, borderRadius: 1, p: 2, flexShrink: 0, overflowY: 'auto', WebkitOverflowScrolling: 'touch', overscrollBehaviorY: 'contain', }} > <Typography variant="h6" gutterBottom> {t(titleKey)} </Typography> {TocList} </Box> {/* Drawer mobile */} <Box sx={{ display: { xs: 'block', md: 'none' }, mb: 2 }}> <IconButton onClick={() => setOpen(true)} aria-label={t(titleKey)} > <MenuIcon /> </IconButton> <Drawer anchor="left" open={open} onClose={() => setOpen(false)} ModalProps={{ keepMounted: true }} > <Box role="presentation" sx={{ width: 250, p: 2, bgcolor: 'background.paper', height: '100%', overflowY: 'auto', WebkitOverflowScrolling: 'touch', overscrollBehaviorY: 'contain', }} > <Typography variant="h6" gutterBottom> {t(titleKey)} </Typography> {TocList} </Box> </Drawer> </Box> </> ); } |