Chakra ui - page shell -如何基于侧边栏菜单填充页面



我想弄清楚如何使用Chakra UI页面外壳,这样我就可以在外壳的主要部分添加组件来呈现,对于每个侧边栏菜单项。

侧边栏菜单的NavButton项如下:

<NavButton label="Settings" />

我正试图找到一种方法来添加一个组件(说,设置),它的内容在外壳的主要部分呈现。

我该怎么做呢?

完整的仪表盘如下:

import {
// As,
Avatar,
Box,
BoxProps,
Button,
ButtonProps,
chakra, 
Container,
Divider, 
Drawer,
DrawerContent,
DrawerOverlay,
Flex,
Heading,
HStack,
Icon,
Input,
InputLeftElement,
InputGroup,
// Progress, 
// SimpleGrid,
Stack,
Text,
useBreakpointValue,
useColorModeValue,
useDisclosure,
IconButton, 
IconButtonProps
} from '@chakra-ui/react'
import * as React from 'react'
import { FiDownloadCloud } from 'react-icons/fi'
// import { CgWorkAlt } from 'react-icons/cg'

import {
// FiBarChart2,
// FiBookmark,
// FiCheckSquare,
// FiHelpCircle,
// FiHome,
FiSearch,
// FiSettings
} from 'react-icons/fi'

const Card = (props: BoxProps) => (
<Box
minH="3xs"
bg="bg-surface"
boxShadow={useColorModeValue('sm', 'sm-dark')}
borderRadius="lg"
{...props}
/>
)  
const Bar = chakra('span', {
baseStyle: {
display: 'block',
pos: 'absolute',
w: '1.25rem',
h: '0.125rem',
rounded: 'full',
bg: 'currentcolor',
mx: 'auto',
insetStart: '0.125rem',
transition: 'all 0.12s',
},
})
const ToggleIcon = (props: { active: boolean }) => {
const { active } = props
return (
<Box
className="group"
data-active={active ? '' : undefined}
as="span"
display="block"
w="1.5rem"
h="1.5rem"
pos="relative"
aria-hidden
pointerEvents="none"
>
<Bar top="0.4375rem" _groupActive={{ top: '0.6875rem', transform: 'rotate(45deg)' }} />
<Bar bottom="0.4375rem" _groupActive={{ bottom: '0.6875rem', transform: 'rotate(-45deg)' }} />
</Box>
)
}

interface ToggleButtonProps extends IconButtonProps {
isOpen: boolean
}

const ToggleButton = (props: ToggleButtonProps) => {
const { isOpen, ...iconButtonProps } = props
return (
<IconButton
position="relative"
variant="unstyled"
size="sm"
color={isOpen ? 'white' : 'muted'}
zIndex="skipLink"
icon={<ToggleIcon active={isOpen} />}
{...iconButtonProps}
/>
)
}
interface UserProfileProps {
name: string
// image: string
title: string
}
const UserProfile = (props: UserProfileProps) => {
const { name, title } = props
return (
<HStack spacing="3" ps="2">
<Avatar name={name} boxSize="10" />
<Box>
<Text fontWeight="medium" fontSize="sm">
{name}
</Text>
<Text color="muted" fontSize="sm">
{title}
</Text>
</Box>
</HStack>
)
}  
const Sidebar = () => (
<Flex as="section" minH="100vh" bg="bg-canvas" maxW="100%" p="0">
<Flex
flex="1"
bg="brand.white"
// overflowY="auto"
maxW="100%" p="0"
// maxW={{ base: 'full', sm: 'xs' }}
py={{ base: '6', sm: '8' }}
pl={4}
pr={6}
mr={4}
// px={{ base: '4', sm: '6' }}
>
<Stack justify="space-between" spacing="1">
<Stack spacing={{ base: '5', sm: '6' }} shouldWrapChildren>

<InputGroup>
<InputLeftElement pointerEvents="none">
<Icon as={FiSearch} color="muted" boxSize="5" />
</InputLeftElement>
<Input placeholder="Search" />
</InputGroup>
<Stack spacing="1" >
<NavButton label="Home"  fontWeight="normal"/>
<NavButton label="Dashboard" aria-current="page" fontWeight="normal" />
<NavButton label="Tasks"  fontWeight="normal"  />

<NavButton label="ddd"  fontWeight="normal"/>
</Stack>
</Stack>
<Stack spacing={{ base: '5', sm: '6' }}>
<Stack spacing="1">
<NavButton label="Library" fontWeight="normal" />
<NavButton label="Help"  fontWeight="normal"/>
<NavButton label="Settings"  fontWeight="normal"/>
</Stack>
{/* <Box bg="bg-subtle" px="4" py="5" borderRadius="lg">
<Stack spacing="4">
<Stack spacing="1">
<Text fontSize="sm" fontWeight="medium">
Almost there
</Text>
<Text fontSize="sm" color="muted">
Fill in some more information about you and your person.
</Text>
</Stack>
<Progress value={80} size="sm" aria-label="Profile Update Progress" />
<HStack spacing="3">
<Button variant="link" size="sm">
Dismiss
</Button>
<Button variant="link" size="sm" colorScheme="blue">
Update profile
</Button>
</HStack>
</Stack>
</Box> */}
<Divider />
<UserProfile
name="Asdfon"
// image="adsf"
title="adsf, asdf"
/>
</Stack>
</Stack>
</Flex>
</Flex>
)  
const Navbar = () => {
const { isOpen, onToggle, onClose } = useDisclosure()
return (
<Box
width="full"
maxW="100%"
py="4"
px={0}
// px={{ base: '4', md: '8' }}
bg="bg-surface"
boxShadow={useColorModeValue('sm', 'sm-dark')}

>
<Flex justify="space-between">

<ToggleButton isOpen={isOpen} aria-label="Open Menu" onClick={onToggle} />
<Drawer
isOpen={isOpen}
placement="left"
onClose={onClose}
isFullHeight
preserveScrollBarGap
// Only disabled for showcase
trapFocus={false}
>
<DrawerOverlay />
<DrawerContent>
<Sidebar />
</DrawerContent>
</Drawer>
</Flex>
</Box>
)
}  

interface NavButtonProps extends ButtonProps {
// icon: As
label: string
}

const NavButton = (props: NavButtonProps) => {
const {  label, ...buttonProps } = props
return (
<Button variant="ghost" justifyContent="start" {...buttonProps}>
<HStack spacing="3">
{/* <Icon as={icon} boxSize="6" color="subtle" /> */}
<Text>{label}</Text>
</HStack>
</Button>
)
}  

const DashBase = () => {
const isDesktop = useBreakpointValue({ base: false, lg: true })
return (
<Flex
as="section"
direction={{ base: 'column', lg: 'row' }}
height="100vh"
bg="white"
mb="100px"
overflowY="auto"
minW="100%" 
px={0}
mx="0px"
// minW="120em"
// margin="auto"
>
{isDesktop ? <Sidebar /> : <Navbar />}

<Container py="8" flex="1">
<Stack spacing={{ base: '8', lg: '6' }}>
<Stack
spacing="4"
direction={{ base: 'column', lg: 'row' }}
//   justify="space-between"
align={{ base: 'start', lg: 'center' }}
>
<Stack spacing="1">
<Heading size={useBreakpointValue({ base: 'xs', lg: 'sm' })} fontWeight="medium">
Dashboard
</Heading>
<Text color="muted">All important metrics at a glance</Text>
</Stack>
<HStack spacing="3">
<Button variant="secondary" leftIcon={<FiDownloadCloud fontSize="1.25rem" />}>
Download
</Button>
<Button variant="primary">Create</Button>
</HStack>
</Stack>
{/* <Stack spacing={{ base: '5', lg: '6' }} maxW="100%">
<SimpleGrid columns={{ base: 1, md: 3 }} gap="6">
<Card />
<Card />
<Card />
</SimpleGrid>
</Stack> */}
<Card minH="sm" />
</Stack>
</Container>
</Flex>
)
}
export default DashBase;

你可以把你的NavButton包装成Link

<Link href="/settings">
<NavButton label="Home"  fontWeight="normal"/>
</Link>

pages/settings.tsx中,有一个组件来呈现您的设置页面。

_app.tsx中,将Component作为子传递给Sidebar

<Sidebar>
<Component {...pageProps} />
</Sidebar>

Sidebar中,为children添加一个参数。Component将在children道具中。在菜单后渲染children道具。

const Sidebar = ({ children }) => (
...
</Flex>
{children}
</Flex>
)

最新更新