feat(home): inline search for recent classrooms #476

PR
PR description

Closes #475.

Summary

  • Add a minimal inline search to the Home page's "Recent" classroom section — a Search icon button in the title row that expands in-place into a pill-style input and filters the list by name + description.
  • Case-insensitive substring match, real-time filtering. Clearing via the inline ✕ keeps the input open; Escape clears or collapses; blur with an empty query auto-collapses.
  • Grid re-render is deferred via useDeferredValue so fast typing stays snappy even with many classroom cards.

Changes

  • app/page.tsx — new searchOpen / searchQuery local state, filteredClassrooms = useMemo(...) driven by useDeferredValue(searchQuery), AnimatePresence-based icon ↔ input toggle, pill-style InputGroup, empty-state row in the expanded grid.
  • lib/i18n/locales/{en-US,zh-CN,ja-JP,ru-RU,ar-SA}.json — new keys under classroom.*: searchPlaceholder, searchAriaLabel, clearSearch, searchEmpty.

Type of Change

  • New feature (non-breaking change that adds functionality)

Test Plan

Manual (verified locally via `pnpm dev`):

  • Default state shows only the 🔍 icon; other UI unchanged.
  • Click 🔍 → input expands in place, auto-focuses, and auto-expands the collapsed section.
  • Real-time filtering by name and description is case-insensitive.
  • Typing with many classrooms does not lag the input (deferred grid render).
  • No match → empty-state text shown.
  • ✕ clears but keeps input open and focused; Escape clears, then collapses + restores focus to the toggle; blur with empty query collapses.
  • Existing open / rename / delete / import flows still work.
  • Language switch (en/zh/ja/ru/ar) — placeholder, empty state, aria labels all translated.
CUT
cutter bot commented just now

Cutter Summary

The Recent classrooms header now includes a search icon button that expands inline into a pill-style input, and an empty-state message appears when a query has no matches.