Dropdown flyout is rendered via portal

This commit is contained in:
Manoj Vivek 2023-11-15 17:01:35 +05:30
parent adac5eba3e
commit cf2cd4a6b2
3 changed files with 106 additions and 54 deletions

View file

@ -104,6 +104,7 @@
},
"dependencies": {
"@fontsource/lato": "^5.0.17",
"@headlessui-float/react": "^0.12.0",
"@headlessui/react": "^1.7.4",
"@iconify/react": "^3.2.2",
"@reduxjs/toolkit": "^1.9.5",

View file

@ -1,4 +1,5 @@
import { Menu, Transition } from '@headlessui/react';
import { Float } from '@headlessui-float/react';
import { Icon } from '@iconify/react';
import cx from 'classnames';
import { Fragment } from 'react';
@ -23,66 +24,66 @@ interface Props {
export function DropDown({ label, options, className }: Props) {
return (
<div className="text-right">
<Menu as="div" className={`relative inline-block text-left ${className}`}>
<div>
<div className="relative text-right">
<Menu as="div" className={`inline-block text-left ${className}`}>
<Float placement="bottom-end" flip portal>
<Menu.Button className="inline-flex w-full justify-center gap-1 rounded-md bg-opacity-20 p-2 text-sm font-medium hover:bg-slate-300 hover:bg-opacity-30 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 dark:hover:bg-slate-700">
{label}
<Icon icon="mdi:chevron-down" />
</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 z-50 mt-2 w-fit origin-top-right divide-y divide-slate-100 rounded-md bg-slate-100 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:bg-slate-900">
<div className="px-1 py-1 ">
{options.map((option, idx) => {
if (option.type === 'separator') {
<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="z-50 mt-2 w-fit origin-top-right divide-y divide-slate-100 rounded-md bg-slate-100 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:bg-slate-900">
<div className="px-1 py-1 ">
{options.map((option, idx) => {
if (option.type === 'separator') {
return (
<div
className="m-1 border-t-[1px] border-t-slate-500"
// eslint-disable-next-line react/no-array-index-key
key={`divider-${idx}`}
/>
);
}
return (
<div
className="m-1 border-t-[1px] border-t-slate-500"
// eslint-disable-next-line react/no-array-index-key
key={`divider-${idx}`}
/>
// eslint-disable-next-line react/no-array-index-key
<Menu.Item key={idx.toString()}>
{({ active }) =>
option.onClick !== null ? (
<button
className={cx(
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
{ 'bg-slate-200 dark:bg-slate-800': active }
)}
type="button"
onClick={option.onClick}
>
{option.label}
</button>
) : (
<div
className={cx(
'group mt-2 flex w-full items-center rounded-md px-2'
)}
>
{option.label}
</div>
)
}
</Menu.Item>
);
}
return (
// eslint-disable-next-line react/no-array-index-key
<Menu.Item key={idx.toString()}>
{({ active }) =>
option.onClick !== null ? (
<button
className={cx(
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
{ 'bg-slate-200 dark:bg-slate-800': active }
)}
type="button"
onClick={option.onClick}
>
{option.label}
</button>
) : (
<div
className={cx(
'group mt-2 flex w-full items-center rounded-md px-2'
)}
>
{option.label}
</div>
)
}
</Menu.Item>
);
})}
</div>
</Menu.Items>
</Transition>
})}
</div>
</Menu.Items>
</Transition>
</Float>
</Menu>
</div>
);

View file

@ -1381,6 +1381,42 @@
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.36.0.tgz#9837f768c03a1e4a30bd304a64fb8844f0e72efe"
integrity sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==
"@floating-ui/core@^1.3.0", "@floating-ui/core@^1.4.2":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.5.0.tgz#5c05c60d5ae2d05101c3021c1a2a350ddc027f8c"
integrity sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==
dependencies:
"@floating-ui/utils" "^0.1.3"
"@floating-ui/dom@^1.3.0", "@floating-ui/dom@^1.5.1":
version "1.5.3"
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.5.3.tgz#54e50efcb432c06c23cd33de2b575102005436fa"
integrity sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==
dependencies:
"@floating-ui/core" "^1.4.2"
"@floating-ui/utils" "^0.1.3"
"@floating-ui/react-dom@^2.0.3":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.0.4.tgz#b076fafbdfeb881e1d86ae748b7ff95150e9f3ec"
integrity sha512-CF8k2rgKeh/49UrnIBs4BdxPUV6vize/Db1d/YbCLyp9GiVZ0BEwf5AiDSxJRCr6yOkGqTFHtmrULxkEfYZ7dQ==
dependencies:
"@floating-ui/dom" "^1.5.1"
"@floating-ui/react@^0.26.0":
version "0.26.2"
resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.26.2.tgz#1a548f0f9aae64a742c868ae36aa620d15dec728"
integrity sha512-ocpz3MxYoZlgsASiVFayiTnKukR8QZDQUMqxMdF0YFLbu8lw/IL6AHKLROI8SOpp6CxpUGPh9Q4a03eBAVEZNQ==
dependencies:
"@floating-ui/react-dom" "^2.0.3"
"@floating-ui/utils" "^0.1.5"
tabbable "^6.0.1"
"@floating-ui/utils@^0.1.3", "@floating-ui/utils@^0.1.5":
version "0.1.6"
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.1.6.tgz#22958c042e10b67463997bd6ea7115fe28cbcaf9"
integrity sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==
"@fontsource/lato@^5.0.17":
version "5.0.17"
resolved "https://registry.yarnpkg.com/@fontsource/lato/-/lato-5.0.17.tgz#7c75c443da1e3ae203ed1977b6455bb15c62c106"
@ -1399,6 +1435,15 @@
normalize-path "^2.0.1"
through2 "^2.0.3"
"@headlessui-float/react@^0.12.0":
version "0.12.0"
resolved "https://registry.yarnpkg.com/@headlessui-float/react/-/react-0.12.0.tgz#092ef8ee39a87526895f314fe8e4765e2e077cda"
integrity sha512-/oikFriS8t5nirJnRlHrvltrGx0PwhGUsUFNxxyfLOC/wNGX8k5kvNy+XCmSXBJ3fCYsSHYaDsPLct3lWDMXuw==
dependencies:
"@floating-ui/core" "^1.3.0"
"@floating-ui/dom" "^1.3.0"
"@floating-ui/react" "^0.26.0"
"@headlessui/react@^1.7.4":
version "1.7.4"
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.4.tgz#ba7f50fda20667276ee84fcd4c2a459aa26187e3"
@ -12960,6 +13005,11 @@ synckit@^0.8.4:
"@pkgr/utils" "^2.3.1"
tslib "^2.4.0"
tabbable@^6.0.1:
version "6.2.0"
resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-6.2.0.tgz#732fb62bc0175cfcec257330be187dcfba1f3b97"
integrity sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==
tailwindcss@^3.1.4:
version "3.2.1"
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.2.1.tgz#1bd828fff3172489962357f8d531c184080a6786"