✨(app-desk) component DropButton
Button that opens a dropdown menu when clicked. It will manage all the state related to the dropdown menu. Can be used controlled or uncontrolled.
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
"luxon": "3.4.4",
|
||||
"next": "14.1.1",
|
||||
"react": "18.2.0",
|
||||
"react-aria-components": "1.1.1",
|
||||
"react-dom": "18.2.0",
|
||||
"react-i18next": "14.0.5",
|
||||
"styled-components": "6.1.8",
|
||||
|
||||
64
src/frontend/apps/desk/src/components/DropButton.tsx
Normal file
64
src/frontend/apps/desk/src/components/DropButton.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import React, {
|
||||
PropsWithChildren,
|
||||
ReactNode,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Button, DialogTrigger, Popover } from 'react-aria-components';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const StyledPopover = styled(Popover)`
|
||||
background-color: white;
|
||||
border-radius: 4px;
|
||||
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
|
||||
padding: 0.5rem;
|
||||
border: 1px solid #dddddd;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
`;
|
||||
|
||||
const StyledButton = styled(Button)`
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
background: none;
|
||||
outline: none;
|
||||
transition: all 0.2s ease-in-out;
|
||||
`;
|
||||
|
||||
interface DropButtonProps {
|
||||
button: ReactNode;
|
||||
isOpen?: boolean;
|
||||
onOpenChange?: (isOpen: boolean) => void;
|
||||
}
|
||||
|
||||
export const DropButton = ({
|
||||
button,
|
||||
isOpen = false,
|
||||
onOpenChange,
|
||||
children,
|
||||
}: PropsWithChildren<DropButtonProps>) => {
|
||||
const [opacity, setOpacity] = useState(false);
|
||||
const [isLocalOpen, setIsLocalOpen] = useState(isOpen);
|
||||
|
||||
useEffect(() => {
|
||||
setIsLocalOpen(isOpen);
|
||||
}, [isOpen]);
|
||||
|
||||
return (
|
||||
<DialogTrigger
|
||||
onOpenChange={(isOpen) => {
|
||||
setIsLocalOpen(isOpen);
|
||||
onOpenChange?.(isOpen);
|
||||
setTimeout(() => {
|
||||
setOpacity(isOpen);
|
||||
}, 10);
|
||||
}}
|
||||
isOpen={isLocalOpen}
|
||||
>
|
||||
<StyledButton>{button}</StyledButton>
|
||||
<StyledPopover style={{ opacity: opacity ? 1 : 0 }} isOpen={isLocalOpen}>
|
||||
{children}
|
||||
</StyledPopover>
|
||||
</DialogTrigger>
|
||||
);
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from './Box';
|
||||
export * from './Text';
|
||||
export * from './Link';
|
||||
export * from './TextErrors';
|
||||
export * from './Card';
|
||||
export * from './DropButton';
|
||||
export * from './Link';
|
||||
export * from './Text';
|
||||
export * from './TextErrors';
|
||||
|
||||
Reference in New Issue
Block a user