first commit
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
import {
|
||||
Dropdown,
|
||||
DropdownMenu,
|
||||
DropdownToggle,
|
||||
} from '@/features/ui/components/bootstrap-5/dropdown-menu'
|
||||
import { FC, forwardRef, useCallback } from 'react'
|
||||
import classNames from 'classnames'
|
||||
import { useNestableDropdown } from '@/shared/hooks/use-nestable-dropdown'
|
||||
import { NestableDropdownContextProvider } from '@/shared/context/nestable-dropdown-context'
|
||||
import { AnchorProps } from 'react-bootstrap-5'
|
||||
import MaterialIcon from '../material-icon'
|
||||
import { DropdownMenuProps } from '@/features/ui/components/types/dropdown-menu-props'
|
||||
|
||||
type MenuBarDropdownProps = {
|
||||
title: string
|
||||
id: string
|
||||
className?: string
|
||||
align?: 'start' | 'end'
|
||||
}
|
||||
|
||||
export const MenuBarDropdown: FC<MenuBarDropdownProps> = ({
|
||||
title,
|
||||
children,
|
||||
id,
|
||||
className,
|
||||
align = 'start',
|
||||
}) => {
|
||||
const { menuId, selected, setSelected } = useNestableDropdown()
|
||||
|
||||
const onToggle = useCallback(
|
||||
show => {
|
||||
setSelected(show ? id : null)
|
||||
},
|
||||
[id, setSelected]
|
||||
)
|
||||
|
||||
const onHover = useCallback(() => {
|
||||
setSelected(prev => {
|
||||
if (prev === null) {
|
||||
return null
|
||||
}
|
||||
return id
|
||||
})
|
||||
}, [id, setSelected])
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
show={selected === id}
|
||||
align={align}
|
||||
onToggle={onToggle}
|
||||
autoClose
|
||||
>
|
||||
<DropdownToggle
|
||||
id={`${menuId}-${id}`}
|
||||
variant="secondary"
|
||||
className={classNames(className, 'menu-bar-toggle')}
|
||||
onMouseEnter={onHover}
|
||||
>
|
||||
{title}
|
||||
</DropdownToggle>
|
||||
<NestableDropdownMenu renderOnMount id={`${menuId}-${id}`}>
|
||||
{children}
|
||||
</NestableDropdownMenu>
|
||||
</Dropdown>
|
||||
)
|
||||
}
|
||||
|
||||
const NestableDropdownMenu: FC<DropdownMenuProps & { id: string }> = ({
|
||||
children,
|
||||
id,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<DropdownMenu {...props}>
|
||||
<NestableDropdownContextProvider id={id}>
|
||||
{children}
|
||||
</NestableDropdownContextProvider>
|
||||
</DropdownMenu>
|
||||
)
|
||||
}
|
||||
|
||||
const NestedDropdownToggle: FC = forwardRef<HTMLAnchorElement, AnchorProps>(
|
||||
function NestedDropdownToggle(
|
||||
{ children, className, onMouseEnter, id },
|
||||
ref
|
||||
) {
|
||||
return (
|
||||
// eslint-disable-next-line jsx-a11y/anchor-is-valid
|
||||
<a
|
||||
id={id}
|
||||
href="#"
|
||||
ref={ref}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onClick={onMouseEnter}
|
||||
className={classNames(
|
||||
className,
|
||||
'nested-dropdown-toggle',
|
||||
'dropdown-item'
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
<MaterialIcon type="chevron_right" />
|
||||
</a>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
export const NestedMenuBarDropdown: FC<{ id: string; title: string }> = ({
|
||||
children,
|
||||
id,
|
||||
title,
|
||||
}) => {
|
||||
const { menuId, selected, setSelected } = useNestableDropdown()
|
||||
const select = useCallback(() => {
|
||||
setSelected(id)
|
||||
}, [id, setSelected])
|
||||
const onToggle = useCallback(
|
||||
show => {
|
||||
setSelected(show ? id : null)
|
||||
},
|
||||
[setSelected, id]
|
||||
)
|
||||
const active = selected === id
|
||||
return (
|
||||
<Dropdown
|
||||
align="start"
|
||||
drop="end"
|
||||
show={active}
|
||||
autoClose
|
||||
onToggle={onToggle}
|
||||
>
|
||||
<DropdownToggle
|
||||
id={`${menuId}-${id}`}
|
||||
onMouseEnter={select}
|
||||
className={classNames({ 'nested-dropdown-toggle-shown': active })}
|
||||
as={NestedDropdownToggle}
|
||||
>
|
||||
{title}
|
||||
</DropdownToggle>
|
||||
<NestableDropdownMenu renderOnMount id={`${menuId}-${id}`}>
|
||||
{children}
|
||||
</NestableDropdownMenu>
|
||||
</Dropdown>
|
||||
)
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
import DropdownListItem from '@/features/ui/components/bootstrap-5/dropdown-list-item'
|
||||
import { DropdownItem } from '@/features/ui/components/bootstrap-5/dropdown-menu'
|
||||
import { useNestableDropdown } from '@/shared/hooks/use-nestable-dropdown'
|
||||
import { MouseEventHandler, ReactNode } from 'react'
|
||||
|
||||
type MenuBarOptionProps = {
|
||||
title: string
|
||||
onClick?: MouseEventHandler
|
||||
disabled?: boolean
|
||||
trailingIcon?: ReactNode
|
||||
href?: string
|
||||
target?: string
|
||||
rel?: string
|
||||
}
|
||||
|
||||
export const MenuBarOption = ({
|
||||
title,
|
||||
onClick,
|
||||
href,
|
||||
disabled,
|
||||
trailingIcon,
|
||||
target,
|
||||
rel,
|
||||
}: MenuBarOptionProps) => {
|
||||
const { setSelected } = useNestableDropdown()
|
||||
return (
|
||||
<DropdownListItem>
|
||||
<DropdownItem
|
||||
onMouseEnter={() => setSelected(null)}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
trailingIcon={trailingIcon}
|
||||
href={href}
|
||||
rel={rel}
|
||||
target={target}
|
||||
>
|
||||
{title}
|
||||
</DropdownItem>
|
||||
</DropdownListItem>
|
||||
)
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
import { NestableDropdownContextProvider } from '@/shared/context/nestable-dropdown-context'
|
||||
import { FC, HTMLProps } from 'react'
|
||||
|
||||
export const MenuBar: FC<HTMLProps<HTMLDivElement> & { id: string }> = ({
|
||||
children,
|
||||
id,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<div {...props}>
|
||||
<NestableDropdownContextProvider id={id}>
|
||||
{children}
|
||||
</NestableDropdownContextProvider>
|
||||
</div>
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user