Skip to content

Redesign learn search with header search bar, autocomplete, and filter pills#14788

Draft
rtibbles wants to merge 8 commits into
learningequality:developfrom
rtibbles:learn-search-redesign
Draft

Redesign learn search with header search bar, autocomplete, and filter pills#14788
rtibbles wants to merge 8 commits into
learningequality:developfrom
rtibbles:learn-search-redesign

Conversation

@rtibbles
Copy link
Copy Markdown
Member

@rtibbles rtibbles commented Jun 4, 2026

Summary

Extracts the learn search redesign from the ai_assistant prototype branch, rebuilt on develop as reviewable commits.

The library and channel/topic pages get a header search bar with autocomplete (instant fuzzy matching against translated metadata labels, debounced content matches from the backend), recent searches, and resumable content shortcuts. Applied filters and still-available refinements render as a horizontal pill row, with the full filter set moved to a side panel. Keyword search moves from the bespoke ContentNodeSearchViewset to a DRF SearchFilter backend on the main contentnode endpoints, and the old endpoint is removed.

The frontend sends keyword searches as a question query parameter, which the backend treats as plain keyword search for now — groundwork for the AI assistant integration, which will substitute its own handling of question without further frontend changes.

State Screenshot
Library page Library
Autocomplete (metadata suggestions) Autocomplete
Search results with filter pills Results
All filters side panel Panel
Mobile library Mobile library
Mobile channel page Mobile topic

Search flow recording

PCz7gCN.mp4

axe audits on the captured pages report no violations introduced by this branch; pre-existing issues (card progress bar accessible names, KCard <li> outside a list on mobile grids, channel logo missing alt, skip-link contrast) are unchanged from develop.

References

Prototype origin: rtibbles/kolibri:ai_assistant — the AI-specific work remains there and will follow separately.

Reviewer guidance

  • On the library page: type in the search bar — metadata label matches appear instantly, content matches follow; selecting a metadata suggestion applies that filter and strips the matched words from the query; Enter submits the remaining keywords; pills toggle filters on/off
  • Open a channel: the same search bar appears in the header, scoped to that channel/folder
  • Resize to a small viewport: topic pages show the search header below the mobile header, and "All filters" becomes a centred button
  • Keyword search API: /api/content/contentnode/?search=… (also accepts question and legacy keywords); the dedicated contentnode_search endpoint is gone, and custom channel (kolibri-sandbox) search was migrated to the main endpoint — testing custom channels is out of scope here

AI usage

This branch was prepared with Claude Code: it extracted the search frontend from the ai_assistant prototype branch (itself pair-written with Claude), rebuilt it on develop as logical commits, migrated the specs to Vue Testing Library, and verified the flows in a live browser (screenshots and recording above). I reviewed the full diff twice with inline feedback — Composition API conversion, string consolidation out of components, and corrections against the design spec — which Claude then applied.

🤖 Generated with Claude Code

rtibbles added 8 commits June 4, 2026 15:07
Replace the keywords CharFilter on ContentNodeFilter with a
ContentNodeSearchFilter backend that reads the ?search= query parameter,
falling back to ?question= and ?keywords= for backwards compatibility.
Search terms are tokenized with smart_split so quoted phrases are kept
intact, and stopwords are dropped when other terms remain.
categoryIcon maps category metadata constants to KIcon names for use in
search UI. coreString now falls back to a camelCased version of the
given key so callers can pass raw category constants directly, with a
hasKey helper on Translator to test for message availability.
useFuzzyMetadataSearch builds a fuzzy-search index over the translated
metadata labels provided by useBaseSearch globalLabels, returning filter
suggestions for free-text queries along with helpers to strip matched
words from a query. useRecentSearches persists a per-user list of
recent search terms. Adds the @m31coding/fuzzy-search dependency.
Provides a debounced keyword autocomplete handler that combines instant
fuzzy metadata label matches with backend content matches, plus
toggleFilter/isFilterActive/appliedFilters/isLabelAvailable helpers so
filter UI consumers share a single source of truth for applied search
terms. Also owns the keyword input state and its handlers
(setKeywords/clearKeywords/selectFilterSuggestion), provided for search
input components to call directly. Keyword search terms are sent as the
question query parameter, which the backend treats as keyword search.
Accordion select group and category search option updates to align the
full filter side panel with the redesigned search UI, plus a hideKeywords
prop so pages that host their own search bar can omit the keywords
section.
Replace the sidebar search with a header search bar offering
autocomplete suggestions (fuzzy metadata matches plus content matches),
recent searches, and resumable content shortcuts. Applied filters render
as horizontal pills beneath the search bar, and the full filter panel
moves to a side panel modal. Card layout adapts to mobile and ultra-wide
screens.
The topics page header gains the same search bar and filter pills as the
library page, scoped to the current topic. The header tab toggles are
removed in favour of the folders side panel button, and ToggleHeaderTabs
is deleted as it is no longer used.

On small screens TopicsMobileHeader replaces the header that normally
hosts the search bar; no mobile mockups exist for the topics page, so
follow the library page mobile pattern and render the search bar, filter
pills, and an All filters button below the mobile header.
Keyword search is now handled by the ContentNodeSearchFilter backend on
the main contentnode endpoints, so the dedicated contentnode_search
endpoint is redundant. Migrate CustomContentRenderer to the contentnode
list endpoint, which also fixes its more pagination handling - the old
endpoint never returned a more field. Remove the coach lessonResources
search results state, mutations, and action, which had no remaining
callers.
@github-actions github-actions Bot added DEV: backend Python, databases, networking, filesystem... APP: Learn Re: Learn App (content, quizzes, lessons, etc.) APP: Coach Re: Coach App (lessons, quizzes, groups, reports, etc.) DEV: frontend SIZE: very large labels Jun 4, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 4, 2026

npm Package Versions

Warning

The following packages have changed files but no version bump:

Package Version Changed files
kolibri 0.18.0 2

If these changes affect published code, consider bumping the version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

APP: Coach Re: Coach App (lessons, quizzes, groups, reports, etc.) APP: Learn Re: Learn App (content, quizzes, lessons, etc.) DEV: backend Python, databases, networking, filesystem... DEV: frontend SIZE: very large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant