ConceptPortal-public/rsconcept/frontend/src/components/Dropdown/Dropdown.tsx

65 lines
1.6 KiB
TypeScript
Raw Normal View History

import clsx from 'clsx';
import { PARAMETER } from '@/utils/constants';
import { type Styling } from '../props';
interface DropdownProps extends Styling {
/** Indicates whether the dropdown should stretch to the left. */
2023-12-28 14:04:44 +03:00
stretchLeft?: boolean;
/** Indicates whether the dropdown should stretch to the top. */
2024-06-26 19:00:29 +03:00
stretchTop?: boolean;
/** Indicates whether the dropdown is open. */
2023-12-28 14:04:44 +03:00
isOpen: boolean;
2023-07-20 17:11:03 +03:00
}
/**
2024-10-30 21:35:55 +03:00
* Animated list of children with optional positioning and visibility control.
*/
2025-02-07 10:54:47 +03:00
export function Dropdown({
2024-09-19 17:49:25 +03:00
isOpen,
stretchLeft,
stretchTop,
className,
children,
style,
2024-09-19 17:49:25 +03:00
...restProps
}: React.PropsWithChildren<DropdownProps>) {
2023-07-20 17:11:03 +03:00
return (
2023-12-28 14:04:44 +03:00
<div className='relative'>
<div
2024-05-11 20:53:36 +03:00
tabIndex={-1}
2023-12-28 14:04:44 +03:00
className={clsx(
'z-topmost',
2023-12-28 14:04:44 +03:00
'absolute mt-3',
'flex flex-col',
'border rounded-md shadow-lg',
'text-sm',
'clr-input',
{
'right-0': stretchLeft,
2024-06-26 19:00:29 +03:00
'left-0': !stretchLeft,
'bottom-[2rem]': stretchTop
2023-12-28 14:04:44 +03:00
},
className
)}
style={{
2025-02-22 16:46:42 +03:00
willChange: 'clip-path, transform',
transitionProperty: 'clip-path, transform',
transitionDuration: `${PARAMETER.dropdownDuration}ms`,
transitionTimingFunction: 'ease-in-out',
transform: isOpen ? 'translateY(0)' : 'translateY(-10%)',
clipPath: isOpen ? 'inset(0% 0% 0% 0%)' : 'inset(10% 0% 90% 0%)',
...style
}}
aria-hidden={!isOpen}
2023-12-28 14:04:44 +03:00
{...restProps}
>
{children}
</div>
2023-12-28 14:04:44 +03:00
</div>
);
2023-07-20 17:11:03 +03:00
}