React NextJS中Tailwind下拉菜单无法从Card组件弹出的问题
问题解决:下拉菜单被Card容器裁剪,无法正常弹出
问题描述
我有一个名为DropdownWithSearch的下拉菜单组件,点击时菜单不会向外弹出,而是被所在的UserAssignForm组件的Card容器包裹,在内部展开。
组件代码
DropdownWithSearch组件
import { Menu, Transition } from '@headlessui/react'; import { Fragment, useState } from 'react'; type DropdownWithSearchProps = { users: string[]; }; const DropdownWithSearch = ({ users }: DropdownWithSearchProps) => { const [searchTerm, setSearchTerm] = useState(''); const [isOpen, setIsOpen] = useState(false); const toggleDropdown = () => { setIsOpen(!isOpen); }; const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => { setSearchTerm(event.target.value.toLowerCase()); }; const filteredUsers = users.filter((user) => user.toLowerCase().includes(searchTerm) ); return ( <Menu as="div" className="relative"> <Menu.Button className="focus:outline-none inline-flex items-center gap-x-1 text-sm font-semibold leading-6 text-gray-900" > <button onClick={toggleDropdown} className="focus:outline-none linear px-10 rounded-xl bg-brand-500 py-3 text-base font-medium text-white transition duration-200 hover:bg-brand-600 active:bg-brand-700 dark:bg-brand-400 dark:text-white dark:hover:bg-brand-300 dark:active:bg-brand-200" > Select Assignee </button> </Menu.Button> <Transition show={isOpen} as={Fragment} enter="transition ease-out duration-200" enterFrom="opacity-0 translate-y-1" enterTo="opacity-100 translate-y-0" leave="transition ease-in duration-150" leaveFrom="opacity-100 translate-y-0" leaveTo="opacity-0 translate-y-1" > <Menu.Items static className="origin-top-left absolute left-0 mt-2 w-full max-w-md rounded-3xl shadow-lg bg-white ring-1 ring-gray-900/5 focus:outline-none z-50" > <div className="p-4"> <input onChange={handleSearchChange} className="block w-full px-4 py-2 mb-4 text-gray-800 border rounded-md border-gray-300 focus:outline-none" type="text" placeholder="Search assignees" autoComplete="off" /> {filteredUsers.map((user, index) => ( <Menu.Item key={index}> {({ active }) => ( <a href="#" className="group relative flex gap-x-6 rounded-lg p-4 hover:bg-gray-50 cursor-pointer focus:outline-none" onClick={(e) => { // e.preventDefault(); // handleAssigneeSelect(assignee); }} > <span className="font-semibold text-gray-900">{user}</span> </a> )} </Menu.Item> ))} </div> </Menu.Items> </Transition> </Menu> ); }; export default DropdownWithSearch;
UserAssignForm组件
import Card from "components/card"; import { useState } from 'react'; import DropdownWithSearch from './DropdownWithSearch'; export default function UserAssignForm() { const [selectedAssignee, setSelectedAssignee] = useState(''); const userList = ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace', 'Hank', 'Ivy', 'Jack']; return ( <Card extra="mb-3 w-full h-full px-6 pb-6 sm:overflow-x-auto relative"> <div className="relative flex items-center justify-between pt-4"> <div className="text-xl font-bold text-navy-700 dark:text-white"> Assign Users </div> </div> <div className="mt-8 overflow-x-scroll xl:overflow-x-hidden"> <div className="mt-5 mb-5 grid h-full grid-cols-1 gap-5 md:grid-cols-2"> <div className="flex justify-center flex-row pl-3 pt-1"> <DropdownWithSearch users={userList}/> <input disabled={true} type="text" id="assigneeInput" placeholder="Selected Assignee" value={selectedAssignee} onChange={(e) => setSelectedAssignee(e.target.value)} className={`cursor-not-allowed ml-4 w-100 flex h-12 items-center justify-center rounded-xl border bg-white/0 p-3 text-sm outline-none `} /> </div> {/*...*/} </div> <div className="flex justify-center"> <button className="linear px-10 rounded-xl bg-brand-500 py-3 text-base font-medium text-white transition duration-200 hover:bg-brand-600 active:bg-brand-700 dark:bg-brand-400 dark:text-white dark:hover:bg-brand-300 dark:active:bg-brand-200" // onClick={handleSubmit} > Assign </button> </div> </div> </Card> ); }
问题原因及解决办法
核心问题1:Menu.Items的static属性
Headless UI的Menu.Items默认是absolute定位,但你给它加了static属性,这会强制它变成静态定位(正常文档流元素),导致下拉菜单被Card容器的overflow-x-scroll和h-full样式裁剪,无法跳出容器。
解决:移除Menu.Items上的static属性
修改DropdownWithSearch中的Menu.Items部分:
<Menu.Items className="origin-top-left absolute left-0 mt-2 w-full max-w-md rounded-3xl shadow-lg bg-white ring-1 ring-gray-900/5 focus:outline-none z-50" >
核心问题2:Card容器的overflow样式
UserAssignForm中的Card内部有overflow-x-scroll和h-full,这会让容器内部超出部分被裁剪。如果必须保留这些样式,需要让下拉菜单相对于Card外部的元素定位:
可选优化:调整Dropdown的定位上下文
如果Card的overflow无法移除,可以给DropdownWithSearch的外层容器(或者UserAssignForm的某个上层元素)添加relative,同时确保Dropdown的z-index足够高(已经设置了z-50,一般足够)。
次要问题:拼写错误
Card组件的extra属性里reletive是拼写错误,改为relative,确保定位上下文正确。
最终效果
修改后,下拉菜单会以DropdownWithSearch的外层relative容器为基准,absolute定位跳出Card容器,正常弹出显示。
内容的提问来源于stack exchange,提问作者Damika
相关产品推荐
相关产品推荐

