Dropdown

PreviousNext

A composable dropdown with slot-based trigger content, outside-click handling, and open/close animations.

'use client';

import { Avatar } from '@/ui/Avatar';
import { Dropdown } from '@/ui/Dropdown';
import { Button } from '@/ui/buttons/Button';

export function DropdownDemo() {
  const user = { firstName: 'John', lastName: 'Doe' };

  return (
    <Dropdown aria-label="Open user actions">
      <span data-slot="label" className="hidden md:inline text-body">
        {user.firstName} {user.lastName}
      </span>
      <Avatar
        data-slot="label"
        alt={`${user.firstName} ${user.lastName}`}
        className="w-40 h-40 cursor-pointer hover:opacity-80 transition-opacity"
        style={{ width: '40px', height: '40px' }}
      />

      <Button>Logout</Button>
    </Dropdown>
  );
}

Usage

import { Dropdown } from '@/ui/Dropdown';
import { Avatar } from '@/ui/Avatar';
import { Button } from '@/ui/buttons/Button';
 
export function Component() {
  const user = { firstName: 'John', lastName: 'Doe' };
 
  return (
    <Dropdown aria-label="Open user actions">
      <span data-slot="label" className="hidden md:inline text-body">
        {user.firstName} {user.lastName}
      </span>
      <Avatar
        data-slot="label"
        alt={`${user.firstName} ${user.lastName}`}
        className="w-40 h-40 cursor-pointer hover:opacity-80 transition-opacity"
        style={{ width: '40px', height: '40px' }}
      />
 
      <Button>Logout</Button>
    </Dropdown>
  );
}

API Reference

PropTypeDefaultDescription
iconIconicNamesArrowOutlinedDownIcon shown on the trigger button
classNamestringundefinedAdditional classes for the root dropdown container
childrenReactNodeundefinedSlot content (label) and overlay content
...propsbutton props-Standard button attributes passed to the trigger button

Slots

The component is composable through slots using data-slot.

SlotDescription
data-slot="label"Trigger content. You can provide one or multiple elements (text, avatar...).

Children without data-slot="label" are rendered inside the dropdown overlay panel.

Behavior

  • Clicking the trigger toggles the overlay.
  • Clicking outside closes the overlay.
  • The overlay stays mounted and uses animation classes for transitions:
    • open: animate-zoomIn
    • closing: animate-zoomOut
    • hidden state: opacity-0 scale-90 pointer-events-none

Accessibility

  • Provide an explicit aria-label on Dropdown for the trigger.
  • Ensure overlay actions are keyboard reachable (buttons/links).
  • Keep slot label content meaningful for assistive technologies.