all
This commit is contained in:
129
Downloads/Voltaserve/ui/src/lib/components/drawer/drawer.tsx
Normal file
129
Downloads/Voltaserve/ui/src/lib/components/drawer/drawer.tsx
Normal file
@@ -0,0 +1,129 @@
|
||||
import { ReactNode, useEffect, useMemo, useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import cx from 'classnames'
|
||||
import { StorageOptions } from '../../types'
|
||||
import { IconChevronLeft, IconChevronRight } from '../icons'
|
||||
import { DrawerContext } from './drawer-context'
|
||||
|
||||
type DrawerProps = {
|
||||
children?: ReactNode
|
||||
logo?: ReactNode
|
||||
storage?: StorageOptions
|
||||
}
|
||||
|
||||
export const Drawer = ({ children, storage, logo }: DrawerProps) => {
|
||||
const [isCollapsed, setIsCollapsed] = useState<boolean | undefined>(undefined)
|
||||
const [isTouched, setIsTouched] = useState(false)
|
||||
const localStorageCollapsedKey = useMemo(
|
||||
() =>
|
||||
`${storage?.prefix || 'app'}_${
|
||||
storage?.namespace || 'main'
|
||||
}_drawer_collapsed`,
|
||||
[storage],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
let collapse = false
|
||||
if (typeof localStorage !== 'undefined') {
|
||||
const value = localStorage.getItem(localStorageCollapsedKey)
|
||||
if (value) {
|
||||
collapse = JSON.parse(value)
|
||||
} else {
|
||||
localStorage.setItem(localStorageCollapsedKey, JSON.stringify(false))
|
||||
}
|
||||
}
|
||||
if (collapse) {
|
||||
setIsCollapsed(true)
|
||||
} else {
|
||||
setIsCollapsed(false)
|
||||
}
|
||||
}, [localStorageCollapsedKey, setIsCollapsed])
|
||||
|
||||
if (isCollapsed === undefined) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<DrawerContext.Provider
|
||||
value={{
|
||||
isCollapsed,
|
||||
isTouched,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={cx(
|
||||
'flex',
|
||||
'flex-col',
|
||||
'h-full',
|
||||
'border-r',
|
||||
'border-r-gray-200',
|
||||
'dark:border-r-gray-700',
|
||||
'shrink-0',
|
||||
'gap-0',
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={cx('flex', 'items-center', 'justify-center', 'h-[80px]')}
|
||||
>
|
||||
<Link to="/">
|
||||
<div className={cx('flex', 'h-[40px]')}>
|
||||
<div
|
||||
className={cx(
|
||||
'flex',
|
||||
'items-center',
|
||||
'justify-center',
|
||||
'w-[40px]',
|
||||
'h-[40px]',
|
||||
)}
|
||||
>
|
||||
{logo}
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
<div
|
||||
className={cx(
|
||||
'flex',
|
||||
'flex-col',
|
||||
'items-center',
|
||||
'gap-0.5',
|
||||
'pt-0',
|
||||
'pr-1.5',
|
||||
'pb-1.5',
|
||||
'pl-1.5',
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
<div className={cx('grow')} />
|
||||
<div
|
||||
className={cx(
|
||||
'flex',
|
||||
'flex-row',
|
||||
'items-center',
|
||||
'gap-0',
|
||||
{ 'justify-center': isCollapsed, 'justify-end': !isCollapsed },
|
||||
'h-[50px]',
|
||||
'w-full',
|
||||
{ 'px-0': isCollapsed, 'px-1.5': !isCollapsed },
|
||||
'cursor-pointer',
|
||||
'hover:bg-gray-100',
|
||||
'hover:dark:bg-gray-600',
|
||||
'active:bg-gray-200',
|
||||
'active:dark:bg-gray-700',
|
||||
)}
|
||||
onClick={() => {
|
||||
setIsCollapsed(!isCollapsed)
|
||||
setIsTouched(true)
|
||||
localStorage.setItem(
|
||||
localStorageCollapsedKey,
|
||||
JSON.stringify(!isCollapsed),
|
||||
)
|
||||
}}
|
||||
>
|
||||
{isCollapsed ? <IconChevronRight /> : <IconChevronLeft />}
|
||||
</div>
|
||||
</div>
|
||||
</DrawerContext.Provider>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user