cd ..

tailwindcss 多级菜单

01-06. 1.25 分钟

import { MenuUnfoldOutlined, RightOutlined } from '@ant-design/icons'
import { useMemo, useState } from 'react'
import { GoodsMenu } from '~/types'
import { cn } from '~/utils/cn'

/**
 * @param param0
 * @returns
 */
export const MultiDropDown = ({
  menus,
  onChange,
}: {
  menus: GoodsMenu[]
  onChange(value: string): void
}) => {
  //TODO: 需要处理选中的之后文字展示的问题
  const [menuId, setMenuId] = useState('')
  const subMenuRender = useMemo(() => {
    const subMenu = menus.find((item) => item.id === menuId)
    if (!subMenu) {
      return []
    }
    return subMenu.children?.map((child) => {
      return (
        <li key={child.id}>
          <span className="text-xl font-bold">{child.name}</span>
          <ul className="ml-5 mt-2 flex flex-wrap text-sm">
            {child.children?.map((child) => {
              return (
                <li
                  key={child.id}
                  className="cursor-pointer hover:text-primary"
                  onClick={() => {
                    onChange(child.id ?? '')
                  }}
                >
                  {child.name}
                </li>
              )
            })}
          </ul>
        </li>
      )
    })
  }, [menuId, menus, onChange])

  return (
    <div className="group/first relative flex flex-col ">
      <div
        className={cn(
          'flex h-9 w-60 items-center justify-between rounded-md bg-primary px-4 text-gray-100',
          'cursor-pointer'
        )}
      >
        <span>商品分类</span>
        <MenuUnfoldOutlined />
      </div>
      <div className="group/second absolute w-[740px]">
        <ul
          className={cn(
            'invisible',
            ' absolute top-9 z-10 h-0 w-60 space-y-2 ',
            'overflow-y-scroll rounded bg-slate-400 pt-1 transition-all',
            'group-hover/first:visible group-hover/first:h-96'
          )}
        >
          {menus?.map((item) => {
            return (
              <li
                className="relative flex h-10 cursor-pointer items-center justify-between
              px-4 text-white hover:bg-primary"
                key={item.id}
                onMouseOver={() => {
                  setMenuId(item.id || '')
                }}
              >
                <span className="truncate">{item.name}</span>
                <RightOutlined />
              </li>
            )
          })}
        </ul>
        <ul
          className={cn(
            'invisible absolute left-60 top-9 z-10 h-96 overflow-auto',
            'w-[500px] space-y-3 rounded bg-slate-100 px-8 py-4 text-slate-900',
            'group-hover/second:visible'
          )}
        >
          {subMenuRender}
        </ul>
      </div>
    </div>
  )
}