direct-select-flutter replaces the dropdown with a full-screen picker
DirectSelect is a selection widget with an ethereal, full-screen modal popup displaying the available choices when the widget is interact with. https://dribbble.com/shots/3876250-DirectSelect-Dropdown-ux
At a glance
- What is it?
- direct-select_flutter is a BSD-2-Clause Flutter package whose DirectSelectList opens an ethereal, full-screen modal popup of choices instead of a traditional dropdown. It suits apps that want the selection moment to feel deliberate rather than incidental.
- Who is it for?
- Flutter teams building a settings screen, a location chooser or a category filter can adopt direct-select_flutter when the standard dropdown feels too quiet for the decision being made, since the package handles the modal presentation and the selection callback while you keep control of row content and focus decoration.
- Can I use it commercially?
- Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 52 days ago.
- What is it written in?
- Mainly Dart, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A picker that takes over the screen instead of dropping down
Most selection controls in Flutter are quiet. A dropdown opens a menu, you tap an entry, the menu closes. direct-select-flutter takes a different position: the selection widget opens a full-screen modal popup that displays the available choices, and the README describes that popup as ethereal.
That design choice is the whole point of the package, and it has consequences for the app around it. Because the choices occupy the screen rather than a menu anchored to a button, the interaction reads as a deliberate step in a flow. For a settings panel where the user picks a city or a currency, that is often the difference between a control people use and a control people swipe past.
The package is published on pub.dev as direct_select_flutter, is listed in the awesome-flutter collection, and was made at lanars.com. The README shows the effect on both platforms with recorded GIFs, one for iOS and one for Android, captured from the example application in the repository.
The audience is Flutter developers who already have a working dropdown and want to change the moment of selection, not a set of primitives to assemble from scratch. The whole widget is three classes, and the README documents them with runnable snippets.
DirectSelectList holds the values and hands back the choice
DirectSelectList is the class you put on screen, and it is where the data and the selection handling live. The README's first example constructs it directly and fills it with items through itemBuilder:
final dsl = DirectSelectList<String>(
values: _cities,
defaultItemIndex: 3,
itemBuilder: (String value) => getDropDownMenuItem(value),
focusedItemDecoration: _getDslDecoration(),
onItemSelectedListener: (item, index, context) {
Scaffold.of(context).showSnackBar(SnackBar(content: Text(item)));
});Five parameters carry the behaviour. values is the list of choices, here a list of city strings. defaultItemIndex sets which entry is selected when the list first appears, and the example uses 3. itemBuilder is a callback that turns a value into a widget, which is how the same list widget serves any type. focusedItemDecoration controls the highlight on the focused row. onItemSelectedListener receives the chosen item, its index, and a context.
Two details are worth noting. The list is generic, so DirectSelectList<String> here would be DirectSelectList<SomethingElse> for another payload, and the builder callback receives the value rather than an index, so the list does not have to be indexable by position. And the selection callback passes a context, which the example uses to reach a Scaffold and show a snack bar.
Rows are your own widgets, so item height is yours to set
The second piece of the API is DirectSelectItem, which is what itemBuilder returns. The README shows a helper that builds one row from a value:
DirectSelectItem<String> getDropDownMenuItem(String value) {
return DirectSelectItem<String>(
itemHeight: 56,
value: value,
itemBuilder: (context, value) {
return Text(value);
});
}A DirectSelectItem carries the value, a fixed itemHeight, and its own itemBuilder callback that receives the context and the value and returns a widget. That is a slightly different callback shape from the one on DirectSelectList, and it is the more useful of the two: because the row builder gets the context, a row can show an avatar, a secondary label, or anything else your design calls for.
The fixed height is a decision worth making deliberately. A single 56 pixel row suits a one-line label, but if you want two lines of text per choice or an icon alongside the text, you need to set itemHeight yourself and make sure the row content fits it.
The focus decoration is the third piece, and it is what gives the popup its character. The README's helper returns a BoxDecoration with a top and bottom border on a directional border:
_getDslDecoration() {
return BoxDecoration(
border: BorderDirectional(
bottom: BorderSide(width: 1, color: Colors.black12),
top: BorderSide(width: 1, color: Colors.black12),
),
);
}The README does not state what happens when focusedItemDecoration is omitted, so treat the decoration as required if you want the user to see where they are in the list.
DirectSelectContainer is the box the trigger sits in
The third class is DirectSelectContainer, and the README uses it as the wrapper for the part of your screen that opens the picker. In the example it sits inside a Scaffold body and holds a Card with a row of text and a trailing icon:
Scaffold(
appBar: appBar,
body: DirectSelectContainer(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
verticalDirection: VerticalDirection.down,
children: <Widget>[
SizedBox(height: 150.0),The container is where a DirectSelectList lives inside your own layout, so it inherits whatever padding, card styling and row arrangement you already use. The rest of the example nests the DirectSelectList inside an Expanded inside a Padding, and puts an Icons.unfold_more icon at the end of the row to signal that the area is interactive. That is a good pattern to copy: the affordance that opens the popup is drawn by you, not by the package.
The example is not a minimal one. It stacks a spacer, a label reading City, a Card and the list, all inside a DirectSelectContainer. Read it as a layout demonstration rather than a required structure, because the package exposes only the three classes and nothing in the README suggests the container imposes a particular arrangement.
Adding the package and running the example
The package lives on pub.dev under the name direct_select_flutter, and the README links the package page from the badge at the top. It does not print an installation command, so the addition is the usual one for a Flutter dependency: declare direct_select_flutter in the dependencies of your pubspec.yaml and let the tool fetch it. The repository itself contains an example directory with its own pubspec.yaml, an android folder, an ios folder, a lib folder and a test folder, so the fastest way to see the widget work is to open that example in your IDE and run it.
There is no configuration file, no code generation step and no platform setup described in the README. That simplicity is a real advantage for a UI package, and it is also why the package is a reasonable candidate for vendoring into an app that wants a single pinned widget rather than a dependency tree.
The CHANGELOG.md file sits at the root of the repository, which is where you would look to see what changed between versions. The README itself carries no version numbers and no changelog excerpt, so on the pub.dev page you will find the authoritative version history.
When you write your own picker, keep the three pieces separate as the README does: a function that turns a value into a DirectSelectItem, a decoration function for the focused row, and a DirectSelectList that wires the values, the default index and the selection callback together.
What the documentation does not cover, and what that means
This is a small package, and the gaps in the documentation are as informative as the features.
There is no accessibility section. Nothing in the README describes semantics labels for the popup, screen reader behaviour, or how the focused row is announced. For a full-screen modal that takes over the app, that is a notable silence.
There is no description of keyboard input. A full-screen list of choices on a device with a hardware keyboard raises an obvious question about arrow keys and enter to confirm, and the README does not answer it. Nor does it describe how the popup behaves when the list is long, whether it scrolls, or whether it paginates.
There is no programmatic API described. The README shows no method for opening the picker from a button, and no method for setting the selection from outside the widget. That constrains you to a tap-driven flow.
The version story is also thin. The repository has no GitHub releases, the README does not state a version, and the only changelog reference is the file name. With a last push on 2026-09-01 and no release tags to point at, you have less to rely on when deciding whether a newer version on pub.dev is safe to take.
None of this makes the widget unusable. It makes it a package you should look at rather than assume.
Licence, platform reach and the shape of the project
The package is released under BSD-2-Clause, which permits use in commercial applications and requires that the copyright notice and licence conditions travel with redistributed copies. That is a light obligation, but it is one you have to honour when you vendor the code into a closed-source app, and the LICENSE file at the repository root is the text that governs.
The widget is platform neutral in the Flutter sense. It is pure Dart with no platform channels in the README's description, and the example ships recordings for iOS and Android, which suggests it was exercised on both. Nothing in the README suggests platform-specific behaviour, and nothing suggests it works on desktop or web either.
The repository layout is minimal and readable. There is a lib directory holding the package source, an example directory holding the runnable sample, a pubspec.yaml, a CHANGELOG.md, a LICENSE file and a README.md. There is no separate documentation site, no test directory at the root and no CI configuration listed at the top level, though the example directory does include a test folder.
For a package this small, that is a sensible amount of structure. The decision to adopt comes down to whether the full-screen selection moment fits your design, and the BSD-2-Clause terms mean there is nothing licensing-wise to argue about once it does.
Editorial conclusion
Flutter teams building a settings screen, a location chooser or a category filter can adopt direct-select_flutter when the standard dropdown feels too quiet for the decision being made, since the package handles the modal presentation and the selection callback while you keep control of row content and focus decoration. It is the wrong choice when you need keyboard navigation, screen reader semantics or a programmatic API to open the picker, because the README documents none of those, and it is the wrong choice for a high-volume list given the popup renders every choice. Before adopting, check the pub.dev entry for direct_select_flutter against your Flutter version, and read LICENSE for the BSD-2-Clause notice requirement.
Frequently asked questions
How do I add direct-select-flutter to a Flutter project?
The package is published on pub.dev as direct_select_flutter, and the README links that package page. The repository also ships a runnable example with its own pubspec.yaml, android, ios, lib and test folders, which is the quickest way to see the widget work.
What are the three classes in direct-select-flutter?
DirectSelectList holds the values, the default item index, the item builder, the focused item decoration and the selection callback. DirectSelectItem represents a single row with a value, an itemHeight and its own builder. DirectSelectContainer wraps the widget inside your own layout.
Does direct-select-flutter support keyboard navigation or screen readers?
The README does not document keyboard input, focus traversal or accessibility semantics for the full-screen popup. It describes the focused row decoration as the way to show which entry is highlighted, and nothing further about non-touch interaction.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/lanarsinc-direct-select-flutter)Was this useful?