ArcaneJaspr Codex
Documentation
ArcaneSearch
Specialized search input with clear functionality
Live Demo
Type to search...

ArcaneSearch#

A specialized search input with built-in search icon, clear button, and search-specific behavior.

Basic Usage#

ArcaneSearch(
  placeholder: 'Search...',
  onChanged: (value) {
    setState(() => searchQuery = value);
  },
  onSubmit: (value) {
    performSearch(value);
  },
)

Properties#

PropertyTypeDefaultDescription
value String? null Current search value
placeholder String? 'Search...' Placeholder text
onChanged ValueChanged<String>? null Value change handler
onSubmit ValueChanged<String>? null Submit handler (Enter)
onClear VoidCallback? null Clear button handler
isLoading bool false Show loading indicator
autofocus bool false Auto-focus on mount
size SearchSize medium Input size
styles ArcaneStyleData? null Custom styling

Sizes#

// Small
ArcaneSearch(
  size: SearchSize.small,
  placeholder: 'Search...',
  onChanged: (v) {},
)

// Medium (default)
ArcaneSearch(
  size: SearchSize.medium,
  placeholder: 'Search...',
  onChanged: (v) {},
)

// Large
ArcaneSearch(
  size: SearchSize.large,
  placeholder: 'Search...',
  onChanged: (v) {},
)

Loading State#

Show a loading indicator during search:

ArcaneSearch(
  value: query,
  isLoading: isSearching,
  onChanged: (v) {
    setState(() => query = v);
    debounceSearch(v);
  },
)

Clear Functionality#

ArcaneSearch(
  value: query,
  onChanged: (v) => setState(() => query = v),
  onClear: () {
    setState(() => query = '');
    clearResults();
  },
)

Examples#

ArcaneDiv(
  styles: const ArcaneStyleData(
    display: Display.flex,
    alignItems: AlignItems.center,
    gap: Gap.lg,
  ),
  children: [
    ArcaneText('Logo'),
    ArcaneSearch(
      value: searchQuery,
      placeholder: 'Search products...',
      styles: const ArcaneStyleData(
        widthCustom: '300px',
      ),
      onChanged: (v) => setState(() => searchQuery = v),
      onSubmit: (v) => navigateToSearch(v),
    ),
    // Other nav items...
  ],
)

Search with Results#

ArcaneDiv(
  styles: const ArcaneStyleData(
    display: Display.flex,
    flexDirection: FlexDirection.column,
    gap: Gap.md,
  ),
  children: [
    ArcaneSearch(
      value: query,
      isLoading: isSearching,
      autofocus: true,
      onChanged: (v) {
        setState(() => query = v);
        if (v.length >= 2) {
          searchDebounced(v);
        }
      },
      onClear: () {
        setState(() {
          query = '';
          results = [];
        });
      },
    ),

    // Results
    if (results.isNotEmpty)
      ArcaneDiv(
        styles: const ArcaneStyleData(
          background: Background.surface,
          borderRadius: Radius.lg,
          border: BorderPreset.subtle,
        ),
        children: [
          for (final result in results)
            _buildResultItem(result),
        ],
      ),
  ],
)
ArcaneDiv(
  styles: const ArcaneStyleData(
    display: Display.flex,
    gap: Gap.md,
    alignItems: AlignItems.center,
    padding: PaddingPreset.md,
    background: Background.surface,
    borderRadius: Radius.lg,
  ),
  children: [
    ArcaneSearch(
      value: search,
      placeholder: 'Filter items...',
      size: SearchSize.small,
      onChanged: (v) => setState(() => search = v),
      styles: const ArcaneStyleData(flexGrow: 1),
    ),
    ArcaneSelect<String>(
      value: category,
      placeholder: 'Category',
      options: categoryOptions,
      onChanged: (v) => setState(() => category = v),
    ),
    ArcaneSelect<String>(
      value: sortBy,
      placeholder: 'Sort',
      options: sortOptions,
      onChanged: (v) => setState(() => sortBy = v),
    ),
  ],
)

Command Palette Style#

ArcaneDiv(
  styles: const ArcaneStyleData(
    maxWidth: MaxWidth.form,
    margin: MarginPreset.autoX,
  ),
  children: [
    ArcaneSearch(
      value: command,
      placeholder: 'Type a command or search...',
      size: SearchSize.large,
      autofocus: true,
      onChanged: (v) => filterCommands(v),
      onSubmit: (v) => executeCommand(v),
    ),
    if (filteredCommands.isNotEmpty)
      ArcaneDiv(
        styles: const ArcaneStyleData(
          margin: MarginPreset.topSm,
          background: Background.card,
          borderRadius: Radius.lg,
          border: BorderPreset.subtle,
          overflow: Overflow.hidden,
        ),
        children: [
          for (final cmd in filteredCommands)
            _buildCommandItem(cmd),
        ],
      ),
  ],
)

With Results Dropdown#

Use the .withResults() factory for a search with built-in results dropdown:

ArcaneSearch.withResults(
  placeholder: 'Search...',
  results: [
    SearchResult(
      title: 'Getting Started',
      subtitle: 'Introduction to the framework',
      href: '/docs/getting-started',
    ),
    SearchResult(
      title: 'Components',
      subtitle: 'UI component reference',
      onTap: () => navigateTo('/docs/components'),
    ),
  ],
  showDropdown: query.isNotEmpty,
  onChanged: (v) => setState(() => query = v),
)

SearchResult Properties#

PropertyTypeDescription
titleStringPrimary text
subtitleString?Secondary text
hrefString?Link URL
onTapVoidCallback?Tap handler