Adds light client-side keyword filter to /blog. Data-search attributes
on each post row (and the featured article) drive a small inline script
that hides non-matches as the reader types, collapses empty year heads,
and shows a no-results message. Keyboard shortcuts: / focuses, Esc
clears.
Known follow-up: featured article currently hides on any query; should
respect match state instead. See
docs/superpowers/follow-ups/2026-06-02-blog-search-featured-match.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- @astrojs/check + typescript bump are needed to run `npx astro check`,
which is the type-verification command used throughout this branch.
- docs/superpowers/plans/ pairs with the existing spec under specs/.
- docs/superpowers/follow-ups/ records the featured-match behaviour
change surfaced during manual test; addresses in a later branch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Final-review findings:
- .is-hidden was scoped to blog/index.astro, so it didn't match PostRow
or YearHead roots (which carry their own component scope hashes). Net
effect: the filter visibly only hid the featured article, while all
archive rows + year heads stayed on screen. Wrap in :global() so the
runtime-toggled class actually fires its display rule everywhere.
- buildSearchText regex stripped > but not <, so inline HTML open-tags
like <span class="leadin"> leaked into data-search. Add < to the
character class so the haystack stays plain text.
- Add role="search" landmark to the BlogSearch wrapper so screen-reader
users can navigate to it directly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code review forward-proofing:
- Early-return on event.isComposing so the / shortcut doesn't disrupt
IME composition (multi-keystroke input methods).
- Treat <select> as editable so / doesn't steal focus while a dropdown
is open and the user is typing to seek.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code review nits:
- .bsearch border-bottom + .feature border-top rendered a doubled
hairline; removed the bottom border (feature's top is sufficient).
- Renamed bsearch__input / bsearch__hint to binput / bhint to match
the project's flat single-class convention (postrow, pdate, yr, ln).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code review nit: searchText (required) was appended after the optional
deck/tag, breaking the required-then-optional convention used by the
rest of the interface.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tiny client-side filter on /blog using data-search attributes on each
row. No new deps, no JSON index, no React island. Filters in place
within the year-grouped archive.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>