Files
saladeaula.digital/dashboard_js/app/components/menu.jsx
2025-02-22 09:52:00 -03:00

89 lines
2.2 KiB
JavaScript

import { createContext, useContext, useState } from 'react'
import {
Menu as HeadlessMenu,
MenuButton as HeadlessMenuButton,
MenuItem as HeadlessMenuItem,
MenuItems as HeadlessMenuItems,
} from '@headlessui/react'
import { Loader } from './loader'
import clsx from 'clsx'
const MenuContext = createContext(null)
export function useMenu() {
return useContext(MenuContext)
}
export function Menu({
children,
isLoading: defaultIsLoading = false,
...props
}) {
const [isLoading, setIsLoading] = useState(defaultIsLoading)
return (
<MenuContext.Provider
value={{ isLoading: isLoading || defaultIsLoading, setIsLoading }}
>
<HeadlessMenu {...props}>{children}</HeadlessMenu>
</MenuContext.Provider>
)
}
export function MenuButton({ children, className, disabled, ...props }) {
const { isLoading } = useContext(MenuContext)
return (
<HeadlessMenuButton
className={clsx(
className,
'relative overflow-hidden disabled:pointer-events-none',
)}
disabled={isLoading || disabled}
{...props}
>
{isLoading && (
<div className="absolute inset-0 flex justify-center items-center bg-white dark:bg-slate-800">
<Loader className="w-4" />
</div>
)}
{children}
</HeadlessMenuButton>
)
}
export function MenuItem({ children, className, ...props }) {
return (
<HeadlessMenuItem
className={clsx(
'relative flex items-center gap-1 py-2 px-4 hover:bg-zinc-100 dark:hover:bg-slate-600 w-full transition',
'aria-[disabled=true]:text-gray-400 aria-[disabled=true]:dark:text-gray-600',
'aria-[disabled=true]:pointer-events-none',
className,
)}
{...props}
>
{children}
</HeadlessMenuItem>
)
}
export function MenuItems({ children, className, ...props }) {
return (
<HeadlessMenuItems
className={clsx(
'absolute right-0 origin-top-right bg-white dark:bg-slate-700 rounded-lg drop-shadow shadow overflow-hidden py-2',
className,
)}
{...props}
>
{children}
</HeadlessMenuItems>
)
}
export function MenuSeparator() {
return <hr className="my-2 border-gray-200 dark:border-t-slate-600" />
}