more changes

- Restore the SHARP-ER in the homepage hero section
- Match the design for the 3-image section in the homepage
This commit is contained in:
2026-09-23 23:36:36 +02:00
parent cc2b426119
commit 2ff5cf47cf
6 changed files with 130 additions and 28 deletions
@@ -42,11 +42,17 @@ export interface BrandProps {
/** Accessible name of the link; the images are decorative. */
label: string;
surface: NavSurface;
/**
* Run the "-ER" reveal and its breathing loop. Off on the home page, whose
* hero plays the same reveal once - a second, looping copy beside it is
* jarring. Anywhere else the two animations run as designed.
*/
animate?: boolean;
className?: string;
}
/** The SHARP-ER wordmark, linking home. Sits at the inline start of the bar. */
export function Brand({ href, label, surface, className }: BrandProps) {
export function Brand({ href, label, surface, animate = true, className }: BrandProps) {
const { base, suffix } = BRAND_LOCKUP[surface];
return (
@@ -75,10 +81,12 @@ export function Brand({ href, label, surface, className }: BrandProps) {
/>
{/* The clipping box starts at the P's right edge, so the mark inside
it can slide out from behind the P (Navigation.css). */}
it can slide out from behind the P (Navigation.css). Without
`animate` the box and the reveal classes are dropped and the full
lockup simply sits there. */}
<span
style={{ flex: `${suffix.drawnWidth} 1 0%` }}
className="sh-brand-suffix block min-w-0"
className={cx("block min-w-0", animate && "sh-brand-suffix")}
>
<img
src={suffix.src}
@@ -88,7 +96,7 @@ export function Brand({ href, label, surface, className }: BrandProps) {
loading="eager"
decoding="async"
draggable={false}
className="sh-brand-suffix__mark block h-auto w-full"
className={cx("block h-auto w-full", animate && "sh-brand-suffix__mark")}
/>
</span>
</span>
@@ -268,7 +268,12 @@ export function MobileNav({
{/* Mirrors the compact bar it replaces (20:220): the same 64px row and
the same gutter, so the wordmark does not shift when it opens. */}
<div className="flex h-[64px] shrink-0 items-center justify-between gap-md px-[var(--layout-gutter)]">
<Brand href={homeHref} label={strings.homeLinkLabel} surface={surface} />
<Brand
href={homeHref}
label={strings.homeLinkLabel}
surface={surface}
animate={!isCurrentPath(homeHref, pathname)}
/>
<button
ref={closeRef}
type="button"
@@ -34,7 +34,10 @@
After that one-time reveal the mark keeps breathing: after a long rest
(~26s of stillness per cycle) it slides back out from behind the P and
returns, so the wordmark quietly draws the eye without the glyphs moving
while they are visible. The two
while they are visible. On the home page none of this runs (Brand.tsx
drops the classes when the lockup links the page you are on): the hero
there plays the same reveal once, and a second, looping copy right above
it would be jarring. The two
animations are sequenced by delay - the reveal (once, `both` fill, so the
suffix stays hidden through its delay instead of flashing in) hands over
to the loop, whose later position in the list wins from its start, and
@@ -3,6 +3,7 @@ import { useMemo } from "react";
import {
buildLocalizedHref,
getDirection,
isCurrentPath,
LanguageToggle,
type Locale,
} from "../LanguageSwitcher";
@@ -114,6 +115,9 @@ export function Navigation({
href={resolvedHomeHref}
label={strings.homeLinkLabel}
surface={surface}
/* The home page's own hero plays the reveal once; the brand beside
it stays still there instead of running a second copy. */
animate={!isCurrentPath(resolvedHomeHref, pathname)}
/>
<DesktopNav