Gate search behind CompanySettings.searchEnabled; fix two reported bugs

Search icon now gated behind the new backend toggle, same pattern as
wishlistEnabled — off by default.

Fixed: blog category filter bar was invisible — it was wrapped in
<Reveal>, which sits right at/just past the hero's bottom edge, the
exact "already near the initial viewport" position Reveal.tsx's own
comment documents as a whileInView(margin:"-80px") trap (an element
already visible without scrolling can permanently never register as
"entered view", since `once: true` never gets a second chance). Now a
plain div, no scroll-reveal animation needed for a filter bar anyway.

Fixed: wishlist count showing one behind on the Navbar badge —
useWishlist.ts's toggle() broadcast the "refetch me" event immediately
after the optimistic local update, before the POST request was even
sent. Another instance's resulting refetch could race the actual
server-side write, get the pre-toggle list, and then never get told to
refetch again. Broadcast now only fires after the request settles.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Marco
2026-07-30 22:51:37 +00:00
parent 2eda211a29
commit bc40e22910
5 changed files with 59 additions and 13 deletions
+12 -2
View File
@@ -74,8 +74,18 @@ export default async function BlogOverviewPage({
</div>
</Reveal>
{/* Plain div, not <Reveal> — this bar sits right at/just past the
hero's bottom edge, exactly the "already near the initial
viewport top" position Reveal.tsx's own comment documents as a
whileInView(margin:"-80px") trap: the shrunk viewport can
permanently miss triggering "entered view" for an element
that's already visible without any further scroll, since
`once: true` never gets a second chance. The Hero brand dot
hit the identical bug and switched to a plain animate — this
filter bar doesn't need a scroll-reveal animation at all, so
it's simplest to just not wrap it in Reveal in the first place. */}
{allCategories.length > 1 && (
<Reveal className="flex flex-wrap gap-2 w-full max-w-[80rem] mx-auto px-[var(--layout-padding-x)] pt-6">
<div className="flex flex-wrap gap-2 w-full max-w-[80rem] mx-auto px-[var(--layout-padding-x)] pt-6">
{allCategories.map((category) => {
const active = activeCategories.includes(category);
return (
@@ -100,7 +110,7 @@ export default async function BlogOverviewPage({
Zurücksetzen
</Link>
)}
</Reveal>
</div>
)}
{posts.length === 0 && (