feat: add sidebar nav generator

This commit is contained in:
Łukasz Holeczek 2021-08-01 19:20:23 +02:00
parent ff42ed744b
commit 5ee17f85e9
3 changed files with 210 additions and 151 deletions

View File

@ -1,12 +1,10 @@
import React from 'react' import React from 'react'
import CIcon from '@coreui/icons-react' import CIcon from '@coreui/icons-react'
import { NavLink } from 'react-router-dom'
const _nav = [ const _nav = [
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink, name: 'Dashboard',
anchor: 'Dashboard',
to: '/dashboard', to: '/dashboard',
icon: <CIcon name="cil-speedometer" customClassName="nav-icon" />, icon: <CIcon name="cil-speedometer" customClassName="nav-icon" />,
badge: { badge: {
@ -15,210 +13,206 @@ const _nav = [
}, },
}, },
{ {
_component: 'CNavTitle', component: 'CNavTitle',
anchor: 'Theme', name: 'Theme',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink, name: 'Colors',
anchor: 'Colors',
to: '/theme/colors', to: '/theme/colors',
icon: <CIcon name="cil-drop" customClassName="nav-icon" />, icon: <CIcon name="cil-drop" customClassName="nav-icon" />,
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink, name: 'Typography',
anchor: 'Typography',
to: '/theme/typography', to: '/theme/typography',
icon: <CIcon name="cil-pencil" customClassName="nav-icon" />, icon: <CIcon name="cil-pencil" customClassName="nav-icon" />,
}, },
{ {
_component: 'CNavTitle', component: 'CNavTitle',
anchor: 'Components', name: 'Components',
}, },
{ {
_component: 'CNavGroup', component: 'CNavGroup',
as: NavLink, name: 'Base',
anchor: 'Base', to: '/base',
to: '/to', icon: 'cil-puzzle',
icon: <CIcon name="cil-puzzle" customClassName="nav-icon" />,
items: [ items: [
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Accordion', name: 'Accordion',
to: '/base/accordion', to: '/base/accordion',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Breadcrumb', name: 'Breadcrumb',
to: '/base/breadcrumbs', to: '/base/breadcrumbs',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Cards', name: 'Cards',
to: '/base/cards', to: '/base/cards',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Carousel', name: 'Carousel',
to: '/base/carousels', to: '/base/carousels',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Collapse', name: 'Collapse',
to: '/base/collapses', to: '/base/collapses',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'List group', name: 'List group',
to: '/base/list-groups', to: '/base/list-groups',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Navs & Tabs', name: 'Navs & Tabs',
to: '/base/navs', to: '/base/navs',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Pagination', name: 'Pagination',
to: '/base/paginations', to: '/base/paginations',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Popovers', name: 'Popovers',
to: '/base/popovers', to: '/base/popovers',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Progress', name: 'Progress',
to: '/base/progress', to: '/base/progress',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Spinners', name: 'Spinners',
to: '/base/spinners', to: '/base/spinners',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Tables', name: 'Tables',
to: '/base/tables', to: '/base/tables',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Tooltips', name: 'Tooltips',
to: '/base/tooltips', to: '/base/tooltips',
}, },
], ],
}, },
{ {
_component: 'CNavGroup', component: 'CNavGroup',
anchor: 'Buttons', name: 'Buttons',
icon: <CIcon name="cil-cursor" customClassName="nav-icon" />, icon: <CIcon name="cil-cursor" customClassName="nav-icon" />,
items: [ items: [
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Buttons', name: 'Buttons',
to: '/buttons/buttons', to: '/buttons/buttons',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Buttons groups', name: 'Buttons groups',
to: '/buttons/button-groups', to: '/buttons/button-groups',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Dropdowns', name: 'Dropdowns',
to: '/buttons/dropdowns', to: '/buttons/dropdowns',
}, },
], ],
}, },
{ {
_component: 'CNavGroup', component: 'CNavGroup',
anchor: 'Forms', name: 'Forms',
icon: <CIcon name="cil-notes" customClassName="nav-icon" />, icon: <CIcon name="cil-notes" customClassName="nav-icon" />,
items: [ items: [
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Form Control', name: 'Form Control',
to: '/forms/form-control', to: '/forms/form-control',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Select', name: 'Select',
to: '/forms/select', to: '/forms/select',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Checks & Radios', name: 'Checks & Radios',
to: '/forms/checks-radios', to: '/forms/checks-radios',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Range', name: 'Range',
to: '/forms/range', to: '/forms/range',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Input Group', name: 'Input Group',
to: '/forms/input-group', to: '/forms/input-group',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Floating Labels', name: 'Floating Labels',
to: '/forms/floating-labels', to: '/forms/floating-labels',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Layout', name: 'Layout',
to: '/forms/layout', to: '/forms/layout',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Validation', name: 'Validation',
to: '/forms/validation', to: '/forms/validation',
}, },
], ],
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink, name: 'Charts',
anchor: 'Charts',
to: '/charts', to: '/charts',
icon: <CIcon name="cil-chart-pie" customClassName="nav-icon" />, icon: <CIcon name="cil-chart-pie" customClassName="nav-icon" />,
}, },
{ {
_component: 'CNavGroup', component: 'CNavGroup',
anchor: 'Icons', name: 'Icons',
icon: <CIcon name="cil-star" customClassName="nav-icon" />, icon: <CIcon name="cil-star" customClassName="nav-icon" />,
items: [ items: [
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'CoreUI Free', name: 'CoreUI Free',
to: '/icons/coreui-icons', to: '/icons/coreui-icons',
badge: { badge: {
color: 'success', color: 'success',
@ -226,54 +220,53 @@ const _nav = [
}, },
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'CoreUI Flags', name: 'CoreUI Flags',
to: '/icons/flags', to: '/icons/flags',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'CoreUI Brands', name: 'CoreUI Brands',
to: '/icons/brands', to: '/icons/brands',
}, },
], ],
}, },
{ {
_component: 'CNavGroup', component: 'CNavGroup',
anchor: 'Notifications', name: 'Notifications',
icon: <CIcon name="cil-bell" customClassName="nav-icon" />, icon: <CIcon name="cil-bell" customClassName="nav-icon" />,
items: [ items: [
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Alerts', name: 'Alerts',
to: '/notifications/alerts', to: '/notifications/alerts',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Badges', name: 'Badges',
to: '/notifications/badges', to: '/notifications/badges',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Modal', name: 'Modal',
to: '/notifications/modals', to: '/notifications/modals',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Toasts', name: 'Toasts',
to: '/notifications/toasts', to: '/notifications/toasts',
}, },
], ],
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink, name: 'Widgets',
anchor: 'Widgets',
to: '/widgets', to: '/widgets',
icon: <CIcon name="cil-calculator" customClassName="nav-icon" />, icon: <CIcon name="cil-calculator" customClassName="nav-icon" />,
badge: { badge: {
@ -282,36 +275,36 @@ const _nav = [
}, },
}, },
{ {
_component: 'CNavTitle', component: 'CNavTitle',
anchor: 'Extras', name: 'Extras',
}, },
{ {
_component: 'CNavGroup', component: 'CNavGroup',
anchor: 'Pages', name: 'Pages',
icon: <CIcon name="cil-star" customClassName="nav-icon" />, icon: <CIcon name="cil-star" customClassName="nav-icon" />,
items: [ items: [
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Login', name: 'Login',
to: '/login', to: '/login',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Register', name: 'Register',
to: '/register', to: '/register',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Error 404', name: 'Error 404',
to: '/404', to: '/404',
}, },
{ {
_component: 'CNavItem', component: 'CNavItem',
as: NavLink,
anchor: 'Error 500', name: 'Error 500',
to: '/500', to: '/500',
}, },
], ],

View File

@ -1,13 +1,9 @@
import React from 'react' import React from 'react'
import { useSelector, useDispatch } from 'react-redux' import { useSelector, useDispatch } from 'react-redux'
import { import { CSidebar, CSidebarBrand, CSidebarNav, CSidebarToggler } from '@coreui/react'
CSidebar,
CSidebarBrand, import { AppSidebarNav } from './AppSidebarNav'
CSidebarNav,
CSidebarToggler,
CCreateNavItem,
} from '@coreui/react'
import CIcon from '@coreui/icons-react' import CIcon from '@coreui/icons-react'
@ -27,7 +23,7 @@ const AppSidebar = () => {
position="fixed" position="fixed"
selfHiding="md" selfHiding="md"
unfoldable={unfoldable} unfoldable={unfoldable}
show={sidebarShow} visible={sidebarShow}
onShow={() => console.log('show')} onShow={() => console.log('show')}
onHide={() => { onHide={() => {
dispatch({ type: 'set', sidebarShow: false }) dispatch({ type: 'set', sidebarShow: false })
@ -39,7 +35,7 @@ const AppSidebar = () => {
</CSidebarBrand> </CSidebarBrand>
<CSidebarNav> <CSidebarNav>
<SimpleBar> <SimpleBar>
<CCreateNavItem items={navigation} /> <AppSidebarNav items={navigation} />
</SimpleBar> </SimpleBar>
</CSidebarNav> </CSidebarNav>
<CSidebarToggler <CSidebarToggler

View File

@ -0,0 +1,70 @@
import React from 'react'
import { NavLink, useLocation } from 'react-router-dom'
import PropTypes from 'prop-types'
import { CBadge, CNavGroup, CNavGroupItems, CNavItem, CNavLink, CNavTitle } from '@coreui/react'
import CIcon from '@coreui/icons-react'
export const AppSidebarNav = ({ items }) => {
const components = { CNavGroup, CNavGroupItems, CNavItem, CNavLink, CNavTitle }
const location = useLocation()
const navLink = (name, icon, badge) => {
return (
<>
{icon && typeof icon === 'string' ? <CIcon name={icon} customClassName="nav-icon" /> : icon}
{name && name}
{badge && (
<CBadge color={badge.color} className="ms-auto">
{badge.text}
</CBadge>
)}
</>
)
}
const navItem = (item, index) => {
const { component, name, badge, icon, ...rest } = item
const Component = components[component] || component
return (
<Component
{...(component === 'CNavItem' && {
component: NavLink,
activeClassName: 'active',
})}
key={index}
{...rest}
>
{navLink(name, icon, badge)}
</Component>
)
}
const navGroup = (item, index) => {
const { component, name, icon, items, to, ...rest } = item
const Component = components[component] || component
return (
<Component
toggler={navLink(name, icon)}
visible={location.pathname.startsWith(to)}
idx={String(index)}
key={index}
{...rest}
>
{item.items.map((item, index) =>
item.items ? navGroup(item, index) : navItem(item, index),
)}
</Component>
)
}
return (
<React.Fragment>
{items &&
items.map((item, index) => (item.items ? navGroup(item, index) : navItem(item, index)))}
</React.Fragment>
)
}
AppSidebarNav.propTypes = {
items: PropTypes.arrayOf(PropTypes.any).isRequired,
}