Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

07 — Component Library (Search Module)

Module-specific widgets for global search. Shared primitives come from 00-shared/03_Component_Library.md (authoritative); this file adds the search-specific compositions and their contracts. All names are Flutter widget names (forward-looking).


1. SearchBarField

  • Extends: AppTextField (shared) with search-prefix icon.
  • Props: hint, controller, onQueryChanged(String), onSubmit(String), debounceMs (default 300), enabled.
  • Internal: 300 ms debounce Timer (cancel on dispose/restart — 06 §1.3); clear ✕ button; optional scan action slot (forward-looking).
  • Focus: autofocus false on shell; true when landing on /search.
  • Semantics: hint acts as label; clear button labeled "Clear search".
  • Keyboard: textInputAction: search, autocorrect off, enableSuggestions: false.

2. SearchResultTile

  • Extends: AppListTile.
  • Props: result: SearchResult (search.service.ts:10-16), onTap.
  • Render: avatar (initials / entity icon), title, description (2-line ellipsis), up to 2 AppTags + "+n" for tags (search-indexer.service.ts:83-86).
  • Missing fields: omit subtitle if description == ''; omit tags if empty array (schema defaults ''/[]search-index.schema.ts:18-22).
  • Type icon map (proposed): Student→graduation cap, User→person, Teacher→ presentation, Staff→briefcase, Parent→family, Book→book, Organization→ building, Lead→funnel, Announcement→megaphone. Fallback: generic search icon.

3. SearchGroupHeader

  • Props: entityType, pageCount, onSeeAll.
  • Render: type label + "N on this page" caption + "See all" text button → sets entityType filter (search-query.dto.ts:11-14).
  • Count caveat: pageCount is the per-page count, never a global total (search.service.ts:44-49) — the caption text says "N in this view".
  • Semantics: heading level 2; see-all button labeled "See all <type>".

4. SearchResultSkeleton

  • Extends: AppSkeleton (shared). Three shimmer rows of tile shape (avatar + 2 lines). Used only for first query (06 §2.2); refinements keep prior content.

5. SearchEmptyState / SearchErrorState

  • Thin wrappers over shared AppEmptyState / AppErrorState (00-shared/03) with module copy ("No results for “q”"; retry re-runs the query — 06 §2.4-2.5).

6. SearchLanding (zero-query content)

  • Icon + "Search across your school" + AppChips: "Student name", "Admission no.", "Book title", "Announcement". Tap fills the bar (05 §4). Analytics: search.landing.chip.tap(topic) (proposed).

7. RecentSearchChip (forward-looking)

  • Client-persisted history item (device storage only — ledger B5); single tap re-runs query. No backend history endpoint.

8. Shared components consumed

AppTextField, AppListTile, AppAvatar, AppChips/AppTag, AppSkeleton, AppEmptyState, AppErrorState, AppOfflineBanner, AppSpinner, AppButton (clear/back CTAs), AppBadge (group count). Motion tokens m-fast/m-base from 00-shared/08; tokens from 00-shared/02.

9. Layout containers

NameUse
SearchResultsGroupvertical group: header + SearchResultTiles
SearchResultsGridViewtablet/desktop two-column grouping (06 §6)
SearchBottomLoaderinfinite-scroll loading row (06 §2.3)