vitess.io/vitess@v0.16.2/web/vtadmin/src/components/dropdown/Dropdown.tsx (about) 1 import React, { Fragment } from 'react'; 2 import { Icon, Icons } from '../Icon'; 3 import { Menu, Transition } from '@headlessui/react'; 4 import style from './Dropdown.module.scss'; 5 interface DropdownProps { 6 // Optionally pass in your own button if you don't want it styled like DropdownButton 7 dropdownButton: React.FC | Icons; 8 position?: 'top-left' | 'top-right' | 'bottom-right' | 'bottom-left'; 9 } 10 11 const positions: Record<string, string> = { 12 'top-left': style.topLeft, 13 'top-right': style.topRight, 14 'bottom-right': 'left-0', 15 'bottom-left': 'right-0', 16 default: 'right-0', 17 }; 18 19 export const DropdownButton: React.FC<{ icon: Icons }> = ({ icon }) => ( 20 <Menu.Button 21 type="button" 22 className="flex relative justify-center items-center border border-gray-300 shadow-sm h-12 w-12 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-indigo-500 focus:z-10" 23 id="menu-button" 24 aria-haspopup="true" 25 aria-label="change" 26 title="change" 27 > 28 <div className="transform scale-75"> 29 <Icon icon={icon} /> 30 </div> 31 </Menu.Button> 32 ); 33 34 const Dropdown: React.FC<DropdownProps> = ({ children, dropdownButton, position }) => { 35 let button; 36 if (typeof dropdownButton == 'string') { 37 button = <DropdownButton icon={dropdownButton as Icons} />; 38 } else { 39 const ButtonComponent = dropdownButton as React.FC; 40 button = <ButtonComponent />; 41 } 42 return ( 43 <Menu as="div" className="relative inline-block text-left"> 44 {button} 45 <Transition 46 as={Fragment} 47 enter="transition ease-out duration-100" 48 enterFrom="transform opacity-0 scale-95" 49 enterTo="transform opacity-100 scale-100" 50 leave="transition ease-in duration-75" 51 leaveFrom="transform opacity-100 scale-100" 52 leaveTo="transform opacity-0 scale-95" 53 > 54 <Menu.Items 55 className={`py-2 z-10 origin-top-right absolute ${ 56 positions[position as string] || positions.default 57 } md:-left-3full mt-2 w-max rounded-lg shadow-lg bg-white ring-1 ring-black ring-opacity-5 divide-y divide-gray-100 focus:outline-none`} 58 role="menu" 59 aria-orientation="vertical" 60 aria-labelledby="menu-button" 61 > 62 {children} 63 </Menu.Items> 64 </Transition> 65 </Menu> 66 ); 67 }; 68 69 export default Dropdown;