简体   繁体   English

Headless UI Dropdown - 打开按钮上方的菜单

[英]Headless UI Dropdown - Open menu above the button

Headless UI provides an example for a dropdown menu, where when you click the button, the dropdown opens below. Headless UI 提供了一个下拉菜单示例,当您单击按钮时,下拉菜单会在下方打开。

在此处输入图像描述

The code for this is here:代码在这里:

import { Menu, Transition } from '@headlessui/react'
import { Fragment, useEffect, useRef, useState } from 'react'
import { ChevronDownIcon } from '@heroicons/react/solid'

export default function Example() {
  return (
    <div className="w-56 text-right fixed top-16">
      <Menu as="div" className="relative inline-block text-left">
        <div>
          <Menu.Button className="inline-flex justify-center w-full px-4 py-2 text-sm font-medium text-white bg-black rounded-md bg-opacity-20 hover:bg-opacity-30 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75">
            Options
            <ChevronDownIcon
              className="w-5 h-5 ml-2 -mr-1 text-violet-200 hover:text-violet-100"
              aria-hidden="true"
            />
          </Menu.Button>
        </div>
        <Transition
          as={Fragment}
          enter="transition ease-out duration-100"
          enterFrom="transform opacity-0 scale-95"
          enterTo="transform opacity-100 scale-100"
          leave="transition ease-in duration-75"
          leaveFrom="transform opacity-100 scale-100"
          leaveTo="transform opacity-0 scale-95"
        >
          <Menu.Items className="absolute right-0 w-56 mt-2 origin-top-right bg-white divide-y divide-gray-100 rounded-md shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
            <div className="px-1 py-1 ">
              <Menu.Item>
                {({ active }) => (
                  <button
                    className={`${
                      active ? 'bg-violet-500 text-white' : 'text-gray-900'
                    } group flex rounded-md items-center w-full px-2 py-2 text-sm`}
                  >
                    {active ? (
                      <EditActiveIcon
                        className="w-5 h-5 mr-2"
                        aria-hidden="true"
                      />
                    ) : (
                      <EditInactiveIcon
                        className="w-5 h-5 mr-2"
                        aria-hidden="true"
                      />
                    )}
                    Edit
                  </button>
                )}
              </Menu.Item>
              <Menu.Item>
                {({ active }) => (
                  <button
                    className={`${
                      active ? 'bg-violet-500 text-white' : 'text-gray-900'
                    } group flex rounded-md items-center w-full px-2 py-2 text-sm`}
                  >
                    {active ? (
                      <DuplicateActiveIcon
                        className="w-5 h-5 mr-2"
                        aria-hidden="true"
                      />
                    ) : (
                      <DuplicateInactiveIcon
                        className="w-5 h-5 mr-2"
                        aria-hidden="true"
                      />
                    )}
                    Duplicate
                  </button>
                )}
              </Menu.Item>
            </div>
            <div className="px-1 py-1">
              <Menu.Item>
                {({ active }) => (
                  <button
                    className={`${
                      active ? 'bg-violet-500 text-white' : 'text-gray-900'
                    } group flex rounded-md items-center w-full px-2 py-2 text-sm`}
                  >
                    {active ? (
                      <ArchiveActiveIcon
                        className="w-5 h-5 mr-2"
                        aria-hidden="true"
                      />
                    ) : (
                      <ArchiveInactiveIcon
                        className="w-5 h-5 mr-2"
                        aria-hidden="true"
                      />
                    )}
                    Archive
                  </button>
                )}
              </Menu.Item>
              <Menu.Item>
                {({ active }) => (
                  <button
                    className={`${
                      active ? 'bg-violet-500 text-white' : 'text-gray-900'
                    } group flex rounded-md items-center w-full px-2 py-2 text-sm`}
                  >
                    {active ? (
                      <MoveActiveIcon
                        className="w-5 h-5 mr-2"
                        aria-hidden="true"
                      />
                    ) : (
                      <MoveInactiveIcon
                        className="w-5 h-5 mr-2"
                        aria-hidden="true"
                      />
                    )}
                    Move
                  </button>
                )}
              </Menu.Item>
            </div>
            <div className="px-1 py-1">
              <Menu.Item>
                {({ active }) => (
                  <button
                    className={`${
                      active ? 'bg-violet-500 text-white' : 'text-gray-900'
                    } group flex rounded-md items-center w-full px-2 py-2 text-sm`}
                  >
                    {active ? (
                      <DeleteActiveIcon
                        className="w-5 h-5 mr-2 text-violet-400"
                        aria-hidden="true"
                      />
                    ) : (
                      <DeleteInactiveIcon
                        className="w-5 h-5 mr-2 text-violet-400"
                        aria-hidden="true"
                      />
                    )}
                    Delete
                  </button>
                )}
              </Menu.Item>
            </div>
          </Menu.Items>
        </Transition>
      </Menu>
    </div>
  )
}

function EditInactiveIcon(props) {
  return (
    <svg
      {...props}
      viewBox="0 0 20 20"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <path
        d="M4 13V16H7L16 7L13 4L4 13Z"
        fill="#EDE9FE"
        stroke="#A78BFA"
        strokeWidth="2"
      />
    </svg>
  )
}

function EditActiveIcon(props) {
  return (
    <svg
      {...props}
      viewBox="0 0 20 20"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <path
        d="M4 13V16H7L16 7L13 4L4 13Z"
        fill="#8B5CF6"
        stroke="#C4B5FD"
        strokeWidth="2"
      />
    </svg>
  )
}

function DuplicateInactiveIcon(props) {
  return (
    <svg
      {...props}
      viewBox="0 0 20 20"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <path
        d="M4 4H12V12H4V4Z"
        fill="#EDE9FE"
        stroke="#A78BFA"
        strokeWidth="2"
      />
      <path
        d="M8 8H16V16H8V8Z"
        fill="#EDE9FE"
        stroke="#A78BFA"
        strokeWidth="2"
      />
    </svg>
  )
}

function DuplicateActiveIcon(props) {
  return (
    <svg
      {...props}
      viewBox="0 0 20 20"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <path
        d="M4 4H12V12H4V4Z"
        fill="#8B5CF6"
        stroke="#C4B5FD"
        strokeWidth="2"
      />
      <path
        d="M8 8H16V16H8V8Z"
        fill="#8B5CF6"
        stroke="#C4B5FD"
        strokeWidth="2"
      />
    </svg>
  )
}

function ArchiveInactiveIcon(props) {
  return (
    <svg
      {...props}
      viewBox="0 0 20 20"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <rect
        x="5"
        y="8"
        width="10"
        height="8"
        fill="#EDE9FE"
        stroke="#A78BFA"
        strokeWidth="2"
      />
      <rect
        x="4"
        y="4"
        width="12"
        height="4"
        fill="#EDE9FE"
        stroke="#A78BFA"
        strokeWidth="2"
      />
      <path d="M8 12H12" stroke="#A78BFA" strokeWidth="2" />
    </svg>
  )
}

function ArchiveActiveIcon(props) {
  return (
    <svg
      {...props}
      viewBox="0 0 20 20"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <rect
        x="5"
        y="8"
        width="10"
        height="8"
        fill="#8B5CF6"
        stroke="#C4B5FD"
        strokeWidth="2"
      />
      <rect
        x="4"
        y="4"
        width="12"
        height="4"
        fill="#8B5CF6"
        stroke="#C4B5FD"
        strokeWidth="2"
      />
      <path d="M8 12H12" stroke="#A78BFA" strokeWidth="2" />
    </svg>
  )
}

function MoveInactiveIcon(props) {
  return (
    <svg
      {...props}
      viewBox="0 0 20 20"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <path d="M10 4H16V10" stroke="#A78BFA" strokeWidth="2" />
      <path d="M16 4L8 12" stroke="#A78BFA" strokeWidth="2" />
      <path d="M8 6H4V16H14V12" stroke="#A78BFA" strokeWidth="2" />
    </svg>
  )
}

function MoveActiveIcon(props) {
  return (
    <svg
      {...props}
      viewBox="0 0 20 20"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <path d="M10 4H16V10" stroke="#C4B5FD" strokeWidth="2" />
      <path d="M16 4L8 12" stroke="#C4B5FD" strokeWidth="2" />
      <path d="M8 6H4V16H14V12" stroke="#C4B5FD" strokeWidth="2" />
    </svg>
  )
}

function DeleteInactiveIcon(props) {
  return (
    <svg
      {...props}
      viewBox="0 0 20 20"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <rect
        x="5"
        y="6"
        width="10"
        height="10"
        fill="#EDE9FE"
        stroke="#A78BFA"
        strokeWidth="2"
      />
      <path d="M3 6H17" stroke="#A78BFA" strokeWidth="2" />
      <path d="M8 6V4H12V6" stroke="#A78BFA" strokeWidth="2" />
    </svg>
  )
}

function DeleteActiveIcon(props) {
  return (
    <svg
      {...props}
      viewBox="0 0 20 20"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <rect
        x="5"
        y="6"
        width="10"
        height="10"
        fill="#8B5CF6"
        stroke="#C4B5FD"
        strokeWidth="2"
      />
      <path d="M3 6H17" stroke="#C4B5FD" strokeWidth="2" />
      <path d="M8 6V4H12V6" stroke="#C4B5FD" strokeWidth="2" />
    </svg>
  )
}

What I need to do is to have the dropdown menu open above the button instead of below.我需要做的是在按钮上方而不是下方打开下拉菜单。 Something like below:如下所示:

在此处输入图像描述

Can anyone please help me figure out the correct styling to achieve this?谁能帮我找出正确的样式来实现这一目标? It uses TailwindCSS styles.它使用 TailwindCSS 样式。

 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> import { Menu, Transition } from '@headlessui/react' import { Fragment, useEffect, useRef, useState } from 'react' import { ChevronDownIcon } from '@heroicons/react/solid' export default function Example() { return ( <div className="w-56 text-right fixed top-16"> <Menu as="div" className="relative inline-block text-left"> <div> <Menu.Button className="inline-flex justify-center w-full px-4 py-2 text-sm font-medium text-white bg-black rounded-md bg-opacity-20 hover:bg-opacity-30 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75"> Options <ChevronDownIcon className="w-5 h-5 ml-2 -mr-1 text-violet-200 hover:text-violet-100" aria-hidden="true" /> </Menu.Button> </div> <Transition as={Fragment} enter="transition ease-out duration-100" enterFrom="transform opacity-0 scale-95" enterTo="transform opacity-100 scale-100" leave="transition ease-in duration-75" leaveFrom="transform opacity-100 scale-100" leaveTo="transform opacity-0 scale-95" > <Menu.Items className="-top-2 transform -translate-y-full absolute right-0 w-56 origin-top-right bg-white divide-y divide-gray-100 rounded-md shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"> <div className="px-1 py-1 "> <Menu.Item> {({ active }) => ( <button className={`${active ? 'bg-violet-500 text-white' : 'text-gray-900' } group flex rounded-md items-center w-full px-2 py-2 text-sm`} > {active ? ( <EditActiveIcon className="w-5 h-5 mr-2" aria-hidden="true" /> ) : ( <EditInactiveIcon className="w-5 h-5 mr-2" aria-hidden="true" /> )} Edit </button> )} </Menu.Item> <Menu.Item> {({ active }) => ( <button className={`${active ? 'bg-violet-500 text-white' : 'text-gray-900' } group flex rounded-md items-center w-full px-2 py-2 text-sm`} > {active ? ( <DuplicateActiveIcon className="w-5 h-5 mr-2" aria-hidden="true" /> ) : ( <DuplicateInactiveIcon className="w-5 h-5 mr-2" aria-hidden="true" /> )} Duplicate </button> )} </Menu.Item> </div> <div className="px-1 py-1"> <Menu.Item> {({ active }) => ( <button className={`${active ? 'bg-violet-500 text-white' : 'text-gray-900' } group flex rounded-md items-center w-full px-2 py-2 text-sm`} > {active ? ( <ArchiveActiveIcon className="w-5 h-5 mr-2" aria-hidden="true" /> ) : ( <ArchiveInactiveIcon className="w-5 h-5 mr-2" aria-hidden="true" /> )} Archive </button> )} </Menu.Item> <Menu.Item> {({ active }) => ( <button className={`${active ? 'bg-violet-500 text-white' : 'text-gray-900' } group flex rounded-md items-center w-full px-2 py-2 text-sm`} > {active ? ( <MoveActiveIcon className="w-5 h-5 mr-2" aria-hidden="true" /> ) : ( <MoveInactiveIcon className="w-5 h-5 mr-2" aria-hidden="true" /> )} Move </button> )} </Menu.Item> </div> <div className="px-1 py-1"> <Menu.Item> {({ active }) => ( <button className={`${active ? 'bg-violet-500 text-white' : 'text-gray-900' } group flex rounded-md items-center w-full px-2 py-2 text-sm`} > {active ? ( <DeleteActiveIcon className="w-5 h-5 mr-2 text-violet-400" aria-hidden="true" /> ) : ( <DeleteInactiveIcon className="w-5 h-5 mr-2 text-violet-400" aria-hidden="true" /> )} Delete </button> )} </Menu.Item> </div> </Menu.Items> </Transition> </Menu> </div> ) } function EditInactiveIcon(props) { return ( <svg {...props} viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" > <path d="M4 13V16H7L16 7L13 4L4 13Z" fill="#EDE9FE" stroke="#A78BFA" strokeWidth="2" /> </svg> ) } function EditActiveIcon(props) { return ( <svg {...props} viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" > <path d="M4 13V16H7L16 7L13 4L4 13Z" fill="#8B5CF6" stroke="#C4B5FD" strokeWidth="2" /> </svg> ) } function DuplicateInactiveIcon(props) { return ( <svg {...props} viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" > <path d="M4 4H12V12H4V4Z" fill="#EDE9FE" stroke="#A78BFA" strokeWidth="2" /> <path d="M8 8H16V16H8V8Z" fill="#EDE9FE" stroke="#A78BFA" strokeWidth="2" /> </svg> ) } function DuplicateActiveIcon(props) { return ( <svg {...props} viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" > <path d="M4 4H12V12H4V4Z" fill="#8B5CF6" stroke="#C4B5FD" strokeWidth="2" /> <path d="M8 8H16V16H8V8Z" fill="#8B5CF6" stroke="#C4B5FD" strokeWidth="2" /> </svg> ) } function ArchiveInactiveIcon(props) { return ( <svg {...props} viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" > <rect x="5" y="8" width="10" height="8" fill="#EDE9FE" stroke="#A78BFA" strokeWidth="2" /> <rect x="4" y="4" width="12" height="4" fill="#EDE9FE" stroke="#A78BFA" strokeWidth="2" /> <path d="M8 12H12" stroke="#A78BFA" strokeWidth="2" /> </svg> ) } function ArchiveActiveIcon(props) { return ( <svg {...props} viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" > <rect x="5" y="8" width="10" height="8" fill="#8B5CF6" stroke="#C4B5FD" strokeWidth="2" /> <rect x="4" y="4" width="12" height="4" fill="#8B5CF6" stroke="#C4B5FD" strokeWidth="2" /> <path d="M8 12H12" stroke="#A78BFA" strokeWidth="2" /> </svg> ) } function MoveInactiveIcon(props) { return ( <svg {...props} viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" > <path d="M10 4H16V10" stroke="#A78BFA" strokeWidth="2" /> <path d="M16 4L8 12" stroke="#A78BFA" strokeWidth="2" /> <path d="M8 6H4V16H14V12" stroke="#A78BFA" strokeWidth="2" /> </svg> ) } function MoveActiveIcon(props) { return ( <svg {...props} viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" > <path d="M10 4H16V10" stroke="#C4B5FD" strokeWidth="2" /> <path d="M16 4L8 12" stroke="#C4B5FD" strokeWidth="2" /> <path d="M8 6H4V16H14V12" stroke="#C4B5FD" strokeWidth="2" /> </svg> ) } function DeleteInactiveIcon(props) { return ( <svg {...props} viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" > <rect x="5" y="6" width="10" height="10" fill="#EDE9FE" stroke="#A78BFA" strokeWidth="2" /> <path d="M3 6H17" stroke="#A78BFA" strokeWidth="2" /> <path d="M8 6V4H12V6" stroke="#A78BFA" strokeWidth="2" /> </svg> ) } function DeleteActiveIcon(props) { return ( <svg {...props} viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" > <rect x="5" y="6" width="10" height="10" fill="#8B5CF6" stroke="#C4B5FD" strokeWidth="2" /> <path d="M3 6H17" stroke="#C4B5FD" strokeWidth="2" /> <path d="M8 6V4H12V6" stroke="#C4B5FD" strokeWidth="2" /> </svg> ) }

What I changed was <Menu.Items className="-top-2 transform -translate-y-full absolute right-0 w-56 origin-top-right bg-white divide-y divide-gray-100 rounded-md shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">我改变的是<Menu.Items className="-top-2 transform -translate-y-full absolute right-0 w-56 origin-top-right bg-white divide-y divide-gray-100 rounded-md shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">

please checkout if it works as you prefer.请检查它是否按您的喜好工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM