feat: animate the logo in the navbar
This commit is contained in:
@@ -3,21 +3,43 @@ import { Link } from "react-router";
|
||||
import { cx, FOCUS_RING } from "./styles";
|
||||
import type { NavSurface } from "./types";
|
||||
|
||||
/* Exported from Figma logo/sharp-er (317:5571) and logo/sharp-er-dark
|
||||
(317:7812). Intrinsic 334x46; the navigation draws it at 100px wide, which
|
||||
is the designed size in every navigation frame (desktop and mobile). */
|
||||
const LOGO_SRC: Record<NavSurface, string> = {
|
||||
light: "/assets/sharp-er-logo.png",
|
||||
dark: "/assets/sharp-er-logo-dark.png",
|
||||
};
|
||||
/** One half of the animated brand lockup, drawn as its own SVG file. */
|
||||
interface BrandMark {
|
||||
src: string;
|
||||
/** Intrinsic size of the file, for the aspect ratio the browser reserves. */
|
||||
width: number;
|
||||
height: number;
|
||||
/** The mark's own drawn width, so the pair flexes to one scale. */
|
||||
drawnWidth: number;
|
||||
}
|
||||
|
||||
const LOGO_INTRINSIC_WIDTH = 334;
|
||||
const LOGO_INTRINSIC_HEIGHT = 46;
|
||||
/**
|
||||
* The SHARP-ER lockup, split into its two drawn pieces so the "-ER" can slide
|
||||
* out from behind the P and fade in once the page has settled (Navigation.css).
|
||||
* Each surface ships its own export of the two pieces: white on the dark
|
||||
* surface, the two-tone ink on the light surface. Both exports of a piece are
|
||||
* the exact same box (218x46 and 112x46), so the pair shares one scale; each
|
||||
* mark takes the share of the row its box gives it, and the suffix rides flush
|
||||
* against the P's right edge.
|
||||
*/
|
||||
const BRAND_LOCKUP: Record<
|
||||
NavSurface,
|
||||
{ base: BrandMark; suffix: BrandMark }
|
||||
> = {
|
||||
light: {
|
||||
base: { src: "/assets/sharp-wordmark.svg", width: 218, height: 46, drawnWidth: 218 },
|
||||
suffix: { src: "/assets/sharp-er-suffix.svg", width: 112, height: 46, drawnWidth: 112 },
|
||||
},
|
||||
dark: {
|
||||
base: { src: "/assets/sharp-wordmark-inverse.svg", width: 218, height: 46, drawnWidth: 218 },
|
||||
suffix: { src: "/assets/sharp-er-suffix-inverse.svg", width: 112, height: 46, drawnWidth: 112 },
|
||||
},
|
||||
};
|
||||
|
||||
export interface BrandProps {
|
||||
/** Locale-prefixed home path, e.g. "/en". */
|
||||
href: string;
|
||||
/** Accessible name of the link; the image itself is decorative. */
|
||||
/** Accessible name of the link; the images are decorative. */
|
||||
label: string;
|
||||
surface: NavSurface;
|
||||
className?: string;
|
||||
@@ -25,6 +47,8 @@ export interface BrandProps {
|
||||
|
||||
/** The SHARP-ER wordmark, linking home. Sits at the inline start of the bar. */
|
||||
export function Brand({ href, label, surface, className }: BrandProps) {
|
||||
const { base, suffix } = BRAND_LOCKUP[surface];
|
||||
|
||||
return (
|
||||
<Link
|
||||
to={href}
|
||||
@@ -35,16 +59,39 @@ export function Brand({ href, label, surface, className }: BrandProps) {
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<img
|
||||
src={LOGO_SRC[surface]}
|
||||
alt=""
|
||||
width={LOGO_INTRINSIC_WIDTH}
|
||||
height={LOGO_INTRINSIC_HEIGHT}
|
||||
loading="eager"
|
||||
decoding="async"
|
||||
draggable={false}
|
||||
className="block h-auto w-[100px]"
|
||||
/>
|
||||
{/* `dir="ltr"` because a Latin wordmark never mirrors; its position on
|
||||
the bar still follows the page's direction. */}
|
||||
<span dir="ltr" className="flex w-[100px] items-start">
|
||||
<img
|
||||
src={base.src}
|
||||
alt=""
|
||||
width={base.width}
|
||||
height={base.height}
|
||||
loading="eager"
|
||||
decoding="async"
|
||||
draggable={false}
|
||||
style={{ flex: `${base.drawnWidth} 1 0%` }}
|
||||
className="block h-auto min-w-0"
|
||||
/>
|
||||
|
||||
{/* The clipping box starts at the P's right edge, so the mark inside
|
||||
it can slide out from behind the P (Navigation.css). */}
|
||||
<span
|
||||
style={{ flex: `${suffix.drawnWidth} 1 0%` }}
|
||||
className="sh-brand-suffix block min-w-0"
|
||||
>
|
||||
<img
|
||||
src={suffix.src}
|
||||
alt=""
|
||||
width={suffix.width}
|
||||
height={suffix.height}
|
||||
loading="eager"
|
||||
decoding="async"
|
||||
draggable={false}
|
||||
className="sh-brand-suffix__mark block h-auto w-full"
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user