FxDropdown
A modern, overlay-based selective input for forms and menus.
FxDropdown
FxDropdown is a premium selector component that uses a CompositedTransformFollower to ensure the menu follows the trigger widget even during scrolls and animations. It is fully reactive and binds directly to Flux<T> signals.
Usage
final selectedCity = flux("New York");
FxDropdown(
signal: selectedCity,
items: ["New York", "London", "Tokyo"],
placeholder: "Select city",
)Features
Smart Labeling
Use itemLabel to transform complex objects into display strings automatically.
FxDropdown<User>(
signal: selectedUser,
items: userList,
itemLabel: (user) => user.lastName, // Displays last name in list
)Custom Builders
Provide itemBuilder for complete control over list item rendering.
FxDropdown<User>(
itemBuilder: (user) => Fx.row().children([
FxAvatar(image: user.avatar),
Fx.text(user.name).ml(8),
]),
)Dual Styling
Control the trigger button and the overlay menu independently.
FxDropdown(
style: FxStyle(padding: 12), // Trigger Style
dropdownStyle: FxStyle(shadow: Shadows.lg), // Menu Style
)API Reference
| Name | Type | Default | Description |
|---|---|---|---|
signal | Flux<T>? | null | The reactive state to bind to. (Or value) |
items | List<T> | required | The list of selectable options. |
value | T? | null | Initial value if not using signal. |
onChanged | ValueChanged<T>? | null | Callback when selection changes. |
itemLabel | String Function(T)? | toString() | Transform item to display text. |
itemBuilder | Widget Function(T)? | null | Custom widget builder for dropdown items. |
responsive | FxResponsiveStyle? | null | Responsive style overrides. |
The Master Dropdown Implementation
A complex multi-select user selector with custom avatars and reactive state management.
class TeamSelector extends StatelessWidget {
@override
Widget build(BuildContext context) {
final team = [
User(name: "Aiden", role: "DevOps", avatar: "A"),
User(name: "Bianca", role: "Frontend", avatar: "B"),
User(name: "Charlie", role: "Backend", avatar: "C"),
];
final selectedMember = flux<User?>(null);
return Fx.box(
child: Fx.col(
cross: CrossAxisAlignment.start,
children: [
Fx.text("Assign Task To").font.sm().bold().mb(12),
// Advanced Dropdown with custom item builder
Fx.dropdown<User>(
signal: selectedMember,
items: team,
placeholder: "Select lead architect...",
// Custom item display logic
itemBuilder: (user) => Fx.row(
gap: 12,
children: [
Fx.avatar(fallback: user.avatar).sizeSm(),
Fx.col(
cross: CrossAxisAlignment.start,
children: [
Fx.text(user.name).font.sm().bold(),
Fx.text(user.role).font.xs().muted(),
],
),
],
).p(8),
// Style the trigger
style: FxStyle(
bg: Colors.white,
rounded: 12,
border: Border.all(color: Colors.slate200),
p: 16,
),
// Style the overlay menu
dropdownStyle: FxStyle(
bg: Colors.white,
rounded: 16,
shadowLg: true,
border: Border.all(color: Colors.slate100),
),
),
Fx.gap(20),
// Reactive Preview
Fx(() => selectedMember.value == null
? const SizedBox.shrink()
: Fx.text("Selected: ${selectedMember.value!.name}")
.font.xs().bold().color(Colors.blue)
.animate(fadeIn: true, slideUp: 10)
),
],
)
)
.p(32)
.bg(Colors.slate50)
.rounded(24);
}
}Fluxy's dropdown system uses a high-performance overlay layer that bypasses standard Flutter z-index issues, ensuring that your selectors are always accessible even in dense industrial UIs.