feat: add dropdown menu component

This commit is contained in:
Hachi-R 2024-11-12 04:10:19 -03:00
parent 40ec773425
commit 2c1c3e3c98
4 changed files with 463 additions and 6 deletions

View file

@ -0,0 +1,69 @@
@use "../../scss/globals.scss";
.dropdown-menu {
&__content {
background-color: globals.$dark-background-color;
border: 1px solid globals.$border-color;
border-radius: 4px;
min-width: 200px;
flex-direction: column;
align-items: center;
}
&__group {
width: 100%;
padding: 4px;
}
&__title-bar {
width: 100%;
padding: 4px 12px;
font-size: 14px;
font-weight: 500;
color: globals.$muted-color;
}
&__separator {
width: 100%;
height: 1px;
background-color: globals.$border-color;
}
&__item {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
gap: 8px;
border-radius: 4px;
padding: 5px 12px;
cursor: pointer;
transition: background-color 0.1s ease-in-out;
font-size: 14px;
}
&__item--disabled {
cursor: default;
opacity: 0.6;
}
&:not(&__item--disabled) &__item:hover {
background-color: globals.$background-color;
color: globals.$muted-color;
}
&__item:focus {
background-color: globals.$background-color;
outline: none;
}
&__item-icon {
width: 16px;
height: 16px;
display: flex;
align-items: center;
justify-content: center;
}
}

View file

@ -0,0 +1,78 @@
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import "./dropdown-menu.scss";
export interface DropdownMenuItem {
icon?: React.ReactNode;
label: string;
disabled?: boolean;
show?: boolean;
onClick?: () => void;
}
interface DropdownMenuProps {
children: React.ReactNode;
title?: string;
loop?: boolean;
items: DropdownMenuItem[];
sideOffset?: number;
side?: "top" | "bottom" | "left" | "right";
align?: "start" | "center" | "end";
alignOffset?: number;
}
export default ({
children,
title,
items,
sideOffset = 5,
side = "bottom",
loop = true,
align = "center",
alignOffset = 0,
}: DropdownMenuProps) => (
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild>
<button aria-label={title}>{children}</button>
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content
sideOffset={sideOffset}
side={side}
loop={loop}
align={align}
alignOffset={alignOffset}
className="dropdown-menu__content"
>
{title && (
<DropdownMenu.Group className="dropdown-menu__group">
<div className="dropdown-menu__title-bar">
{title}
</div>
</DropdownMenu.Group>
)}
<DropdownMenu.Separator className="dropdown-menu__separator" />
<DropdownMenu.Group className="dropdown-menu__group">
{items.map((item) =>
item.show !== false && (
<DropdownMenu.Item
key={item.label}
aria-label={item.label}
onSelect={item.onClick}
className={`dropdown-menu__item ${item.disabled ? "dropdown-menu__item--disabled" : ""}`}
disabled={item.disabled}
>
{item.icon && (
<div className="dropdown-menu__item-icon">{item.icon}</div>
)}
{item.label}
</DropdownMenu.Item>
)
)}
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
);