NakedSelect<T> class

A fully customizable select/dropdown widget with no default styling.

NakedSelect provides complete control over the appearance and behavior of a dropdown menu while handling all the complex interaction patterns and accessibility requirements.

Key features:

  • Full styling control through callbacks for hover, press, and focus states
  • Support for single and multiple selection modes
  • Keyboard navigation and type-ahead functionality
  • Automatic positioning with fallback alignments
  • ARIA-compliant accessibility support

The component uses NakedPortal to render the dropdown content in the app overlay, ensuring proper z-indexing and maintaining context inheritance.

Example usage:

NakedSelect<String>(
  selectedValue: selectedValue,
  onSelectedValueChanged: (value) => setState(() => selectedValue = value),
  child: NakedSelectTrigger(
    child: Text(selectedValue ?? 'Select an option'),
  ),
  menu: NakedSelectMenu(
    child: Column(
      children: [
        NakedSelectItem(
          value: 'apple',
          child: Text('Apple'),
        ),
        NakedSelectItem(
          value: 'banana',
          child: Text('Banana'),
        ),
        NakedSelectItem(
          value: 'orange',
          child: Text('Orange'),
        ),
      ],
    ),
  ),
  onMenuClose: () => {},
)
Inheritance
Implemented types

Constructors

NakedSelect({Key? key, required Widget child, required Widget menu, VoidCallback? onClose, VoidCallback? onOpen, T? selectedValue, void onStateChange(OverlayChildLifecycleState state)?, Duration removalDelay = Duration.zero, ValueChanged<T?>? onSelectedValueChanged, bool enabled = true, String? semanticLabel, bool closeOnSelect = true, bool autofocus = false, bool enableTypeAhead = true, Duration typeAheadDebounceTime = const Duration(milliseconds: 500), PositionConfig menuAlignment = const PositionConfig(target: Alignment.bottomLeft, follower: Alignment.topLeft, offset: Offset(0, 4)), List<PositionConfig> fallbackAlignments = const [PositionConfig(target: Alignment.topLeft, follower: Alignment.bottomLeft, offset: Offset(0, -8))], bool closeOnClickOutside = true})
Creates a naked select dropdown.
const
NakedSelect.multiple({Key? key, required Widget child, required Widget menu, VoidCallback? onClose, VoidCallback? onOpen, void onStateChange(OverlayChildLifecycleState state)?, Duration removalDelay = Duration.zero, Set<T>? selectedValues, ValueChanged<Set<T>>? onSelectedValuesChanged, bool enabled = true, String? semanticLabel, bool closeOnSelect = true, bool autofocus = false, bool enableTypeAhead = true, Duration typeAheadDebounceTime = const Duration(milliseconds: 500), PositionConfig menuAlignment = const PositionConfig(target: Alignment.bottomLeft, follower: Alignment.topLeft, offset: Offset(0, 4)), List<PositionConfig> fallbackAlignments = const [PositionConfig(target: Alignment.topLeft, follower: Alignment.bottomLeft, offset: Offset(0, -8))], bool closeOnClickOutside = true})
const

Properties

allowMultiple bool
Whether to allow selecting multiple items. When true, selectedValues and onSelectedValuesChanged must be provided.
final
autofocus bool
Whether to automatically focus the menu when opened. When true, enables immediate keyboard navigation.
final
child Widget
The target widget that triggers the select dropdown. This should typically be a NakedSelectTrigger.
final
closeOnClickOutside bool
Whether to close the menu when clicking outside.
final
closeOnSelect bool
Whether to automatically close the dropdown when an item is selected. Set to false to keep the menu open after selection, useful for multiple selection.
final
enabled bool
Whether the select is enabled and can be interacted with. When false, all interaction is disabled and the trigger shows a forbidden cursor.
final
enableTypeAhead bool
Whether to enable type-ahead selection for quick keyboard navigation. When true, typing characters will focus matching items.
final
fallbackAlignments List<PositionConfig>
Alternative alignments to try if the menu doesn't fit in the preferred position. The menu will try each alignment in order until finding one that fits.
final
hashCode int
The hash code for this object.
no setterinherited
key Key?
Controls how one widget replaces another widget in the tree.
finalinherited
The menu widget to display when the dropdown is open. This should be a NakedSelectMenu containing NakedSelectItem widgets.
final
The alignment of the menu relative to its trigger. Specifies how to position the menu when it opens.
final
onClose VoidCallback?
Called when the menu closes, either through selection or external interaction.
final
onOpen VoidCallback?
Called when the menu is opened.
final
onSelectedValueChanged ValueChanged<T?>?
Called when the selected value changes in single selection mode. Only used when allowMultiple is false.
final
onSelectedValuesChanged ValueChanged<Set<T>>?
Called when selected values change in multiple selection mode. Only used when allowMultiple is true.
final
onStateChange → void Function(OverlayChildLifecycleState state)?
The event handler for the menu.
final
removalDelay Duration
The duration to wait before removing the Widget from the Overlay after the menu is closed.
final
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
selectedValue → T?
The currently selected value in single selection mode. Only used when allowMultiple is false.
final
selectedValues Set<T>?
The set of currently selected values in multiple selection mode. Required when allowMultiple is true.
final
semanticLabel String?
Semantic label for accessibility. Used by screen readers to identify the select component.
final
typeAheadDebounceTime Duration
Duration before resetting the type-ahead search buffer. Controls how long to wait between keystrokes when matching items.
final

Methods

createElement() StatefulElement
Creates a StatefulElement to manage this widget's location in the tree.
inherited
createState() State<NakedSelect<T>>
Creates the mutable state for this widget at a given location in the tree.
override
debugDescribeChildren() List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) String
A string representation of this object.
inherited
toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) String
Returns a string representation of this node and its descendants.
inherited
toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) String
Returns a one-line detailed description of the object.
inherited
toStringShort() String
A short, textual description of this widget.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited