From 8f12b3afe5c201812a85bb8a13b4401264289fbf Mon Sep 17 00:00:00 2001 From: Josh Bairstow Date: Tue, 2 Jun 2026 01:17:04 +1000 Subject: [PATCH 1/8] fix(blog): use curly quotes around empty-state query span Spec called for U+201C / U+201D; commit d7dc22d landed ASCII quotes. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/pages/blog/index.astro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/blog/index.astro b/src/pages/blog/index.astro index 14329fc..5f2a80d 100644 --- a/src/pages/blog/index.astro +++ b/src/pages/blog/index.astro @@ -129,7 +129,7 @@ for (const post of posts) { From 8423759f03ac51bb94d9db154b3ec3aecc5ac6d4 Mon Sep 17 00:00:00 2001 From: Josh Bairstow Date: Tue, 2 Jun 2026 01:25:26 +1000 Subject: [PATCH 2/8] fix(blog): drop duplicated hairline and align class names 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) --- src/components/molecules/BlogSearch.astro | 28 +++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/components/molecules/BlogSearch.astro b/src/components/molecules/BlogSearch.astro index c694e11..3e6763b 100644 --- a/src/components/molecules/BlogSearch.astro +++ b/src/components/molecules/BlogSearch.astro @@ -8,29 +8,29 @@
- +
+ + From 963ea563147b994c2d8a84ba95f9558b0591f167 Mon Sep 17 00:00:00 2001 From: Josh Bairstow Date: Tue, 2 Jun 2026 01:32:08 +1000 Subject: [PATCH 4/8] feat(blog): / focuses search, Esc clears and blurs Co-Authored-By: Claude Sonnet 4.6 --- src/components/molecules/BlogSearch.astro | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/components/molecules/BlogSearch.astro b/src/components/molecules/BlogSearch.astro index 991d398..c7b461e 100644 --- a/src/components/molecules/BlogSearch.astro +++ b/src/components/molecules/BlogSearch.astro @@ -140,5 +140,30 @@ } input.addEventListener("input", applyFilter); + + // `/` from anywhere on the page focuses the search input — unless the user + // is already typing somewhere editable (text input, textarea, or any + // contenteditable element). `Esc` while the input is focused clears the + // query, blurs, and restores the full archive. + document.addEventListener("keydown", (event) => { + if (event.key === "/" && !event.metaKey && !event.ctrlKey && !event.altKey) { + const target = event.target as HTMLElement | null; + const tag = target?.tagName; + const editable = + tag === "INPUT" || + tag === "TEXTAREA" || + target?.isContentEditable === true; + if (!editable) { + event.preventDefault(); + input!.focus(); + } + } else if (event.key === "Escape" && document.activeElement === input) { + if (input!.value !== "") { + input!.value = ""; + applyFilter(); + } + input!.blur(); + } + }); } From 75e78591461713111c2abed604c4ef24afa6353f Mon Sep 17 00:00:00 2001 From: Josh Bairstow Date: Tue, 2 Jun 2026 01:35:53 +1000 Subject: [PATCH 5/8] chore(blog): guard keydown for IME composition and 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) --- src/components/molecules/BlogSearch.astro | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/molecules/BlogSearch.astro b/src/components/molecules/BlogSearch.astro index c7b461e..d38b1e5 100644 --- a/src/components/molecules/BlogSearch.astro +++ b/src/components/molecules/BlogSearch.astro @@ -146,12 +146,14 @@ // contenteditable element). `Esc` while the input is focused clears the // query, blurs, and restores the full archive. document.addEventListener("keydown", (event) => { + if (event.isComposing) return; if (event.key === "/" && !event.metaKey && !event.ctrlKey && !event.altKey) { const target = event.target as HTMLElement | null; const tag = target?.tagName; const editable = tag === "INPUT" || tag === "TEXTAREA" || + tag === "SELECT" || target?.isContentEditable === true; if (!editable) { event.preventDefault(); From d80cd255d4d0a16788b84f9b85333e9a437610b8 Mon Sep 17 00:00:00 2001 From: Josh Bairstow Date: Tue, 2 Jun 2026 01:45:27 +1000 Subject: [PATCH 6/8] fix(blog): make .is-hidden global, strip HTML tags from search text, add role=search 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 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) --- src/components/molecules/BlogSearch.astro | 2 +- src/pages/blog/index.astro | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/molecules/BlogSearch.astro b/src/components/molecules/BlogSearch.astro index d38b1e5..0aad4ac 100644 --- a/src/components/molecules/BlogSearch.astro +++ b/src/components/molecules/BlogSearch.astro @@ -5,7 +5,7 @@ // Filter script is added in Task 5; this file ships markup + styles only. --- -
+