Skip to content

hussainint/quick_search_flutter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

quick_search_flutter_web

A cmd+k style search overlay for Flutter web — similar to Notion's search popup.
Drop it in, wire up a keyboard shortcut, and your users get instant, keyboard-navigable search.

pub.dev license: MIT


Features

  • 🔍 Static & async data sources — filter a local list or call an API
  • ⌨️ Full keyboard navigation — ↑↓ to move, Enter to select, Escape to close
  • 🎨 Fully themeable — via ThemeExtension, zero default opinions
  • Animated entry/exitScaleTransition + FadeTransition (150 ms)
  • 🌐 Flutter web primary, mobile compatible
  • 📦 Zero external dependencies — only the Flutter SDK

Installation

dependencies:
  quick_search_flutter_web: ^0.1.0
flutter pub get

Minimal usage

final controller = SpotlightController();

SpotlightSearch(
  controller: controller,
  delegate: StaticSearchDelegate(items: [
    SpotlightItem(title: 'Home',     onSelected: () => goHome()),
    SpotlightItem(title: 'Settings', onSelected: () => goSettings()),
  ]),
  child: MyApp(),
)

Wiring cmd+k keyboard shortcut

The package does not register any global keyboard shortcuts internally.
Register your own handler in initState and call controller.toggle():

@override
void initState() {
  super.initState();
  HardwareKeyboard.instance.addHandler(_onKey);
}

bool _onKey(KeyEvent event) {
  if (event is KeyDownEvent &&
      event.logicalKey == LogicalKeyboardKey.keyK &&
      HardwareKeyboard.instance.isMetaPressed) {
    controller.toggle();
    return true; // consume the event
  }
  return false;
}

@override
void dispose() {
  HardwareKeyboard.instance.removeHandler(_onKey);
  controller.dispose();
  super.dispose();
}

Tip — Windows / Linux: swap isMetaPressed for isControlPressed to support Ctrl+K.


Async data source with debounce

final delegate = AsyncSearchDelegate(
  onSearch: (query) async {
    final hits = await myApi.search(query);
    return hits.map((h) => SpotlightItem(
      title: h.name,
      subtitle: h.description,
      onSelected: () => openItem(h.id),
    )).toList();
  },
  debounceDuration: const Duration(milliseconds: 300), // default
);

SpotlightTheme fields

Register SpotlightTheme as a ThemeExtension in your MaterialApp.theme:

MaterialApp(
  theme: ThemeData(
    extensions: [SpotlightTheme(surfaceColor: Color(0xFF1E1E2E))],
  ),
)

All fields are nullable — unset fields fall back to ambient Theme values.

Field Type Default Description
overlayColor Color? Colors.black54 Modal barrier color
surfaceColor Color? ColorScheme.surface Card background
surfaceElevation double? 12 Material shadow depth
borderRadius BorderRadius? circular(12) Card corner radius
inputTextStyle TextStyle? Query text style
inputHintStyle TextStyle? Placeholder text style
inputDecoration InputDecoration? Full input decoration override
dividerColor Color? Colors.white12 Line between input and results
itemHoverColor Color? Colors.white10 Hovered tile background
selectedItemColor Color? primaryContainer Keyboard-selected tile background
titleStyle TextStyle? Result title text style
subtitleStyle TextStyle? Result subtitle text style
highlightStyle TextStyle? FontWeight.bold Matched-substring style
loadingIndicatorColor Color? Spinner color
emptyStateWidget Widget? "No results" text Custom empty state widget
maxHeight double? 360 Max results list height (px)
width double? 0.45 Card width as fraction of screen (clamped 320–720 px)
animationDuration Duration? 150ms Entry/exit animation duration

Custom item builder

SpotlightSearch(
  controller: controller,
  delegate: delegate,
  itemBuilder: (context, item, isSelected, query) {
    return ListTile(
      selected: isSelected,
      title: Text(item.title),
      subtitle: item.subtitle != null ? Text(item.subtitle!) : null,
      leading: item.leading,
      onTap: item.onSelected,
    );
  },
  child: child,
)

Running the example

cd example
flutter pub get
flutter run -d chrome

Coming soon 🚀

  • groupBy support — divide results into labelled sections (e.g. "Pages", "Actions")
  • Fuzzy search — built-in fuzzy matching with score-based ranking
  • SpotlightSearchBar trigger button — a pre-built button widget that opens the overlay and displays the keyboard shortcut hint

License

MIT © 2026 Sarwer Hussain

About

No description, website, or topics provided.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages