Dropdown

Contextual menu triggered by a button for inline actions.

Overview

The Dropdown component is a core building block of the Byteion design system, providing a robust, accessibility-compliant interface for its specific UI capabilities.

Why this exists

Dropdowns organize actions and navigation into a compact, context-triggered menu. They prevent toolbar clutter by hiding secondary actions behind a single click.

Mental model

A dropdown is a contextual menu that appears near a trigger element. It contains links or actions. Clicking outside or pressing Escape dismisses it.

When to use

• User menu (Profile, Settings, Logout) • Row actions in data tables (Edit, Delete, Duplicate) • Toolbar overflow items • Context menus (right-click alternatives)

When not to use

• Do not use dropdowns for forms — use a modal • Avoid for single-action triggers — use a button • Do not nest dropdowns inside dropdowns — it is confusing

Basic example

The following example demonstrates standard usage, fully compliant with Byteion's token-first approach.

Variants

Each variant communicates a different meaning. Choose based on priority, not aesthetics.

Single default variant.

Sizes

Size should match the importance and context of the component.

  • md — md size.

States

This component reacts seamlessly to the following interaction and data states:

  • hidden — Not rendered in the DOM.
  • visible — Rendered and interactive.
  • default — Resting appearance before interaction.
  • hover — Pointer is over the element — visual feedback via color or shadow.
  • focus — Keyboard or tab focus — shows ring indicator for accessibility.
  • active — Currently selected or in use.
  • disabled — Non-interactive — grayed out, cursor not-allowed.
  • open — Component is expanded or visible.
  • closed — Component is collapsed or hidden.

Anatomy

• Trigger — button or link that opens the menu • Menu panel — list of items • Menu item — link, button, or divider • Header — optional section title

Usage guidelines

  • Close on click outside or Escape.
  • Limit items to 7 ± 2.
  • Group related items with headers or dividers.

Do and Don't

Do

  • Close on outside click.
  • Group related items.
  • Limit to ~7 items.

Don't

  • Do not nest dropdowns.
  • Do not use for forms.
  • Do not exceed ~7 items without grouping.

Accessibility

Trigger has aria-expanded and aria-controls. Menu has role="menu". Arrow keys navigate items. Escape closes.

Role:menu

ARIA Attributes

  • aria-haspopup
  • aria-expanded

Keyboard Navigation

  • ArrowDown: Moves focus to next item
  • ArrowUp: Moves focus to previous item
  • Enter: Activates or submits the element
  • Escape: Closes the overlay or cancels the action

Customization

Panel follows popover tokens. Items use standard list styling.

Compose with React cva()

Use the exportedcva() +cn() utilities to compose your own variant on top of the Byteion tokens.

import { cva, cn, type VariantProps } from '@byteion/react';

const myDropdown = cva('base classes…', {
 variants: {
  accent: { soft:'border-primary-200', loud:'border-primary-500' },
 },
 defaultVariants: { accent:'soft' },
});

type Props = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof myDropdown>;

Compose with Vue cva()

Use the exportedcva() +cn() utilities inside standard Vue setup blocks.

<script setup lang="ts">
import { computed, useAttrs } from 'vue';
import { cva, type VariantProps } from '@byteion/vue';

interface Props { accent?:'soft' |'loud' }
const props = withDefaults(defineProps<Props>(), { accent:'soft' });
const attrs = useAttrs();

const myDropdown = cva('base classes…', {
  variants: { accent: { soft:'border-primary-200', loud:'border-primary-500' } },
});

const cls = computed(() => myDropdown({ accent: props.accent, class: attrs.class as string | undefined }));
</script>

Runtime events

Byteion keeps framework APIs idiomatic: HTML uses DOM custom events, React uses callback props, and Vue uses emitted events / v-model updates.

HTML / JS events

  • bi:dropdown:hide
  • bi:dropdown:show

React callbacks

  • onOpenChange(open: boolean) => void

Vue emits

  • update:open[v: boolean]

Remote / AJAX

This component does not implement Byteion JS remote loading. Use normal HTML form submission, framework state, or your application data layer around it.

API Reference

Requires data-bi-component="dropdown". Toggle with data-bi-dropdown-toggle.

HTML Data Attributes

  • data-bi-dropdown
  • data-bi-dropdown-toggle

React Props · DropdownProps

Extracted directly fromreact/src/components/Dropdown.tsx.

export interface DropdownProps {
  /** The trigger button (must accept onClick + aria-* via cloneElement). */
  trigger: ReactElement<any>;
  items: DropdownItem[];
  /** Menu alignment relative to the trigger. */
  align?: 'start' | 'end';
  /** Menu side. */
  side?: 'top' | 'bottom';
  /** Controlled open state. */
  open?: boolean;
  onOpenChange?: (open: boolean) => void;
  className?: string;
}

Vue Props · DropdownProps

Extracted directly fromvue/src/components/Dropdown.vue.

export interface DropdownProps {
  items: DropdownItem[];
  /** Controlled open. Use v-model:open. */
  open?: boolean;
  defaultOpen?: boolean;
  align?: 'start' | 'end';
  side?: 'top' | 'bottom';
}

Developer tips

• Best practice: place destructive actions at the bottom of the dropdown, separated by a divider. • Edge case: ensure the dropdown does not overflow the viewport — flip or reposition if near edges.

Common mistakes

Avoid hardcoded neutral colors, placeholder-only labels, duplicated primary actions, and missing keyboard states. Keep this component on Byteion tokens so dashboard, admin, POS, ERP, ecommerce back-office, Laravel, React, and Vue starter-kit screens can be rebranded without rewriting markup.

Production usage tips

1. Static HTML dropdowns require @byteion/js for data-bi-dropdown behavior. React and Vue manage behavior internally.

2. Test inside tables, cards, navbars, modals, and scroll containers. The overflow: hidden on parent containers is the most common cause of clipped menus.

3. Test near viewport edges — the menu should not overflow the visible area. Use side="top" or align="end" to adjust positioning.

4. Test keyboard navigation: ArrowDown, ArrowUp, Home, End (React only), Escape, Enter.

5. Test dark mode and brand themes — the dropdown uses bg-popover/text-popover-foreground tokens that respond to theme changes.

6. For destructive actions that need confirmation, pair the dropdown item with a Modal. Do not execute irreversible actions from a dropdown without confirmation.

7. Keep React/Vue item shapes aligned with core schema. React uses separatorBefore for dividers; Vue currently does not support item-level separators.

Premium examples

Advanced patterns available in Byteion Pro:

• Dropdown with search filter • Mega-dropdown with multi-column layout • Dropdown with live notification dots

Unlock Premium Patterns

Get access to copy-paste ready Pro blocks, SaaS templates, and advanced data-tables built with this component.

Explore Pro Components