Dropdown
Canonical dropdown trigger + overlay menu pair. Uses the published
DropdownMotion snapshot for entry / exit timing.
PromeoDropdownV2 via Flutter micro-app at /preview. Live state pushed via postMessage.
// from snapshot v2026.05.15-001import 'package:flutter/material.dart';import 'package:promeo_design_system/promeo_design_system.dart';
class DropdownSample extends StatefulWidget { const DropdownSample({super.key}); @override State<DropdownSample> createState() => _DropdownSampleState();}
class _DropdownSampleState extends State<DropdownSample> { String _value = 'opt1';
@override Widget build(BuildContext context) { return PromeoDropdownV2( value: _value, items: const [ DropdownItem(value: 'opt1', label: 'Option 1'), DropdownItem(value: 'opt2', label: 'Option 2'), DropdownItem(value: 'opt3', label: 'Option 3'), ], onChanged: (v) => setState(() => _value = v), motion: const DropdownMotion( durationMs: 240, exitEasing: 'easeInOut', ), ); }}Anatomy
Section titled “Anatomy”Anatomy diagram pending. The pattern composes a button-style trigger
with an animated overlay menu portal; selected row and caret visuals
follow the published DropdownMotion snapshot.
When to use
Section titled “When to use”Do
- Use for a discrete choice from a short, known set of options.
- Let the trigger fill its parent constraints unless the layout demands a fixed width.
Don’t
- Don’t use for free-form text entry — reach for
PromeoInputinstead. - Don’t nest a dropdown inside another overlay; the portal stacking will fight you.
In Flutter
Section titled “In Flutter”PromeoDropdownV2( value: selected, items: const [ PromeoDropdownItem(value: 'opt1', label: 'Option 1'), PromeoDropdownItem(value: 'opt2', label: 'Option 2'), ], onChanged: (next) => setState(() => selected = next),)| Prop | Type | Default | Notes |
|---|---|---|---|
value | String | required | Currently-selected item `value`. |
items | List | required | Items: pass either `String` or `DropdownItem(value, label)`. |
onChanged | ValueChanged<String> | required | Fired when the user picks an item. |
disabled | bool | false | Locks interaction; renders disabled style. |
width | double? | null | Trigger width. `null` (default) lets the trigger fill its parent's constraints — matches the layout expectation of consumers like the mk-post settings panel where dropdowns stretch to the section width. Pass a concrete value (e.g. 252) for fixed-width usages like the lab. |
placement | DropdownPlacement | auto | `auto` (default) flips based on viewport space; `top` / `bottom` force. |
motion | DropdownMotion? | null | Per-instance motion override; `null` = use registry defaults. |
open | bool? | null | Controlled-open mode. Pair with [onOpenChange] to drive open state from outside the widget (mirrors React lab). |
onOpenChange | ValueChanged<bool>? | null | Fired when the menu's open state changes. |
- The snippet above reflects the currently-published snapshot’s
DropdownMotionoverrides; drag the Workshop lab sliders + Apply + Sync to bump the snapshot tag (PRD 02 §6 + slice 3.5). - Width default = “fill parent” is intentional (regression from the
width: 252incident, 2026-05-14). Pass a concrete width only when the layout demands it.