Components/FlatDropdown

FlatDropdown

Slot-driven floating dropdown panel (`TxFlatDropdown`). Hover / click / manual triggers, flip-aware placement, and a scale + blur exit animation.

Since 0.3.9BETA

This page was migrated by AI, please review carefully

Migration is complete, but please validate against source code and manual review.

FlatDropdown

Basic Usage

Hover the trigger to open. The panel stays alive for closeDelay ms after the pointer leaves, so you can travel into it. close-on-content-click dismisses the panel after any click inside.

FlatDropdown (basic)

Loading demo...

Trigger Modes

trigger decides how the panel is summoned:

  • hover (default) — opens on pointer enter / focus, closes after closeDelay.
  • click — toggles on click; closeDelay is not applied.
  • manual — the component never opens itself. Drive it with v-model.

Use manual when the panel must follow application state rather than pointer intent — for example a dropdown that opens as the result of a keyboard shortcut.

Controlled vs Uncontrolled

Omit v-model and the component tracks its own open state. Bind v-model and you own it — the component still emits open / close, but will not change the value itself unless the interaction is allowed.

disabled blocks every opening path, including programmatic ones through the trigger slot's show().

Sizing

By default the panel sizes to its content. Two escape hatches:

  • match-trigger-width — sets the panel's min-width to the measured trigger width. Good for select-like menus.
  • width — a fixed px number or any CSS length. Overrides match-trigger-width.

Dismissal Contract

Three independent dismissal paths, each separately switchable:

PropDefaultDismisses when
closeOnClickOutsidetrueA click lands outside both trigger and panel
closeOnEsctrueEscape is pressed
closeOnContentClickfalseAny click inside the panel

closeOnClickOutside only applies to the click and hover triggers — under manual the host owns dismissal entirely.

API

TxFlatDropdown

Props

PropTypeDefaultDescription
modelValuebooleanundefinedControlled open state. Omit for uncontrolled behaviour.
trigger'hover' | 'click' | 'manual''hover'How the panel is summoned.
placementPlacement'bottom-start'Floating placement relative to the trigger.
offsetnumber10Gap in px between trigger and panel.
openDelaynumber0Delay before opening on hover/focus (ms).
closeDelaynumber600Delay before closing after pointer leave (ms).
exitDurationnumber280Duration of the scale + blur exit animation (ms).
disabledbooleanfalseDisable every interaction.
teleportboolean | string'body'Teleport target; pass false to render inline.
matchTriggerWidthbooleanfalseMatch the panel's min-width to the trigger width.
widthnumber | stringundefinedFixed panel width. Overrides matchTriggerWidth.
closeOnClickOutsidebooleantrueClose when clicking outside.
closeOnEscbooleantrueClose when pressing Escape.
closeOnContentClickbooleanfalseClose after any click inside the panel.
panelClassTxFlatDropdownClassundefinedExtra class(es) merged onto the panel element.

Events

EventPayloadDescription
update:modelValuebooleanOpen state changed.
openThe panel opened.
closeThe panel closed.

Slots

SlotPropsDescription
trigger{ open, toggle, show, hide }The anchor element.
default{ open, close, side }Panel body. side is the resolved side after flip.

Best Practices

  • Prefer trigger="click" for destructive or state-changing menus — hover-opened panels are easy to trip over on trackpads.
  • Keep closeDelay generous (the 600 default) for hover; a short delay makes diagonal pointer travel into the panel frustrating.
  • Set teleport="false" when the dropdown lives inside a container with its own stacking or clipping context and you need it to inherit that context. Note that inline rendering re-exposes the panel to ancestor overflow: hidden.
  • Use the side slot prop to flip your own decorations (arrows, shadows) when the panel flips above the trigger.
  • Do not rely on the panel being positioned synchronously after opening — placement is written back reactively, so measure in a requestAnimationFrame if you need absolute geometry.
  • The reference wrapper advertises the panel with aria-haspopup, aria-expanded, and aria-controls (pointing at the panel's generated id), so a slotted <button> trigger inherits disclosure semantics automatically.

Source

  • Component: packages/tuffex/packages/components/src/flat-dropdown/src/TxFlatDropdown.vue
  • Types: packages/tuffex/packages/components/src/flat-dropdown/src/types.ts