Dropdowns
Ported from HyperUI’s Dropdowns — see Attribution. hyperui’s own static gallery
capture for this pattern component type shows the dropdown menu already
open (no interactive open/close state to port — see
docs/agents/parity-pipeline.md’s hazard legend) — all 3 variants are a
single static state, fully parity-green.
class CurrentColorIcon extends StatelessWidget implements StyleReplacedElementWrapper { const CurrentColorIcon(this.svg, {super.key});
final String svg;
@override Widget build(BuildContext context) { final color = IconTheme.of(context).color ?? const Color(0xFF000000); return SvgPicture.string(svg, theme: SvgTheme(currentColor: color)); }}
const _chevronDownSvg = '''<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"/></svg>''';
class Dropdown1Example extends StatelessWidget { const Dropdown1Example({super.key});
@override Widget build(BuildContext context) { return Style( 'mx-auto flex max-w-sm justify-center p-6', child: Style( 'relative inline-flex', children: [ Style( 'inline-flex divide-x divide-gray-300 overflow-hidden rounded border border-gray-300 bg-white shadow-sm', children: [ Style( 'px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900 focus:relative', cursor: SystemMouseCursors.click, child: const Text('Product'), ), Style( 'px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900 focus:relative', cursor: SystemMouseCursors.click, child: Style( 'size-4', child: const CurrentColorIcon(_chevronDownSvg), ), ), ], ), Style( 'absolute end-0 top-12 z-auto w-56 overflow-hidden rounded border border-gray-300 bg-white shadow-sm', children: [ Style( 'block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900', cursor: SystemMouseCursors.click, child: const Text('Storefront'), ), Style( 'block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900', cursor: SystemMouseCursors.click, child: const Text('Warehouse'), ), Style( 'block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900', cursor: SystemMouseCursors.click, child: const Text('Stock'), ), Style( 'block w-full px-3 py-2 text-sm font-medium text-red-700 transition-colors hover:bg-red-50 ltr:text-left rtl:text-right', cursor: SystemMouseCursors.click, child: const Text('Delete'), ), ], ), ], ), ); }}<div class="relative inline-flex"> <span class="inline-flex divide-x divide-gray-300 overflow-hidden rounded border border-gray-300 bg-white shadow-sm" > <button type="button" class="px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900 focus:relative" > Product </button>
<button type="button" class="px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900 focus:relative" aria-label="Menu" > <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4" > <path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" /> </svg> </button> </span>
<div role="menu" class="absolute end-0 top-12 z-auto w-56 overflow-hidden rounded border border-gray-300 bg-white shadow-sm" > <a href="#" class="block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900" role="menuitem" > Storefront </a>
<a href="#" class="block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900" role="menuitem" > Warehouse </a>
<a href="#" class="block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900" role="menuitem" > Stock </a>
<button type="button" class="block w-full px-3 py-2 text-sm font-medium text-red-700 transition-colors hover:bg-red-50 ltr:text-left rtl:text-right" > Delete </button> </div></div>Divided
Section titled “Divided”class CurrentColorIcon extends StatelessWidget implements StyleReplacedElementWrapper { const CurrentColorIcon(this.svg, {super.key});
final String svg;
@override Widget build(BuildContext context) { final color = IconTheme.of(context).color ?? const Color(0xFF000000); return SvgPicture.string(svg, theme: SvgTheme(currentColor: color)); }}
const _chevronDownSvg = '''<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"/></svg>''';
class Dropdown2Example extends StatelessWidget { const Dropdown2Example({super.key});
@override Widget build(BuildContext context) { return Style( 'mx-auto flex max-w-sm justify-center p-6', child: Style( 'relative inline-flex', children: [ Style( 'inline-flex divide-x divide-gray-300 overflow-hidden rounded border border-gray-300 bg-white shadow-sm', children: [ Style( 'px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900 focus:relative', cursor: SystemMouseCursors.click, child: const Text('Product'), ), Style( 'px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900 focus:relative', cursor: SystemMouseCursors.click, child: Style( 'size-4', child: const CurrentColorIcon(_chevronDownSvg), ), ), ], ), Style( 'absolute end-0 top-12 z-auto w-56 divide-y divide-gray-200 overflow-hidden rounded border border-gray-300 bg-white shadow-sm', children: [ Style.empty( children: [ Style( 'block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900', cursor: SystemMouseCursors.click, child: const Text('Storefront'), ), Style( 'block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900', cursor: SystemMouseCursors.click, child: const Text('Warehouse'), ), Style( 'block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900', cursor: SystemMouseCursors.click, child: const Text('Stock'), ), ], ), Style( 'block w-full px-3 py-2 text-sm font-medium text-red-700 transition-colors hover:bg-red-50 ltr:text-left rtl:text-right', cursor: SystemMouseCursors.click, child: const Text('Delete'), ), ], ), ], ), ); }}<div class="relative inline-flex"> <span class="inline-flex divide-x divide-gray-300 overflow-hidden rounded border border-gray-300 bg-white shadow-sm" > <button type="button" class="px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900 focus:relative" > Product </button>
<button type="button" class="px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900 focus:relative" aria-label="Menu" > <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4" > <path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" /> </svg> </button> </span>
<div role="menu" class="absolute end-0 top-12 z-auto w-56 divide-y divide-gray-200 overflow-hidden rounded border border-gray-300 bg-white shadow-sm" > <div> <a href="#" class="block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900" role="menuitem" > Storefront </a>
<a href="#" class="block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900" role="menuitem" > Warehouse </a>
<a href="#" class="block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900" role="menuitem" > Stock </a> </div> <button type="button" class="block w-full px-3 py-2 text-sm font-medium text-red-700 transition-colors hover:bg-red-50 ltr:text-left rtl:text-right" > Delete </button> </div></div>Grouped
Section titled “Grouped”class CurrentColorIcon extends StatelessWidget implements StyleReplacedElementWrapper { const CurrentColorIcon(this.svg, {super.key});
final String svg;
@override Widget build(BuildContext context) { final color = IconTheme.of(context).color ?? const Color(0xFF000000); return SvgPicture.string(svg, theme: SvgTheme(currentColor: color)); }}
const _chevronDownSvg = '''<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"/></svg>''';
class Dropdown3Example extends StatelessWidget { const Dropdown3Example({super.key});
@override Widget build(BuildContext context) { return Style( 'mx-auto flex max-w-sm justify-center p-6', child: Style( 'relative inline-flex', children: [ Style( 'inline-flex divide-x divide-gray-300 overflow-hidden rounded border border-gray-300 bg-white shadow-sm', children: [ Style( 'px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900 focus:relative', cursor: SystemMouseCursors.click, child: const Text('Product'), ), Style( 'px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900 focus:relative', cursor: SystemMouseCursors.click, child: Style( 'size-4', child: const CurrentColorIcon(_chevronDownSvg), ), ), ], ), Style( 'absolute end-0 top-12 z-auto w-56 divide-y divide-gray-200 overflow-hidden rounded border border-gray-300 bg-white shadow-sm', children: [ Style.empty( children: [ const Style( 'block px-3 py-2 text-sm text-gray-500', child: Text('General'), ), Style( 'block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900', cursor: SystemMouseCursors.click, child: const Text('Storefront'), ), Style( 'block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900', cursor: SystemMouseCursors.click, child: const Text('Warehouse'), ), Style( 'block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900', cursor: SystemMouseCursors.click, child: const Text('Stock'), ), ], ), Style.empty( children: [ const Style( 'block px-3 py-2 text-sm text-gray-500', child: Text('Actions'), ), Style( 'block w-full px-3 py-2 text-sm font-medium text-red-700 transition-colors hover:bg-red-50 ltr:text-left rtl:text-right', cursor: SystemMouseCursors.click, child: const Text('Delete'), ), ], ), ], ), ], ), ); }}<div class="relative inline-flex"> <span class="inline-flex divide-x divide-gray-300 overflow-hidden rounded border border-gray-300 bg-white shadow-sm" > <button type="button" class="px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900 focus:relative" > Product </button>
<button type="button" class="px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900 focus:relative" aria-label="Menu" > <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4" > <path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" /> </svg> </button> </span>
<div role="menu" class="absolute end-0 top-12 z-auto w-56 divide-y divide-gray-200 overflow-hidden rounded border border-gray-300 bg-white shadow-sm" > <div> <p class="block px-3 py-2 text-sm text-gray-500">General</p>
<a href="#" class="block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900" role="menuitem" > Storefront </a>
<a href="#" class="block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900" role="menuitem" > Warehouse </a>
<a href="#" class="block px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 hover:text-gray-900" role="menuitem" > Stock </a> </div>
<div> <p class="block px-3 py-2 text-sm text-gray-500">Actions</p>
<button type="button" class="block w-full px-3 py-2 text-sm font-medium text-red-700 transition-colors hover:bg-red-50 ltr:text-left rtl:text-right" > Delete </button> </div> </div></div>