feat(frontend): show the RD mark beside the storefront wordmark
Puts the monogram to the left of "Redefined Designs" in the site header. Inline SVG rather than an <img src="/favicon.svg"> for two reasons. The tile is drawn in currentColor so it follows the antd text token and inverts with the app's own theme switch — the favicon file inverts on prefers-color-scheme, which tracks the operating system and would disagree with the app whenever someone toggles the theme themselves. And the letters are knocked out with a mask rather than painted in the background colour, so the mark sits correctly on any surface instead of carrying a backdrop that only matches this header. The mask id is generated per instance, since two marks on one page would otherwise share an id and the second would reference the first. It is stripped to alphanumerics because React's generated ids contain colons. Marked aria-hidden: the wordmark beside it already says the name, so announcing it again would be noise. Verified by screenshotting the header in both themes rather than by reasoning about the colours.
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { useId } from 'react';
|
||||
|
||||
interface Props {
|
||||
size?: number;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* The RD monogram, as an inline SVG rather than an `<img src="/favicon.svg">`.
|
||||
*
|
||||
* Two reasons it has to be inline. The tile is drawn in `currentColor`, so it
|
||||
* follows the antd text token and inverts with the app's own theme switch — the
|
||||
* favicon file inverts on `prefers-color-scheme`, which tracks the operating
|
||||
* system and would disagree with the app whenever someone toggles the theme
|
||||
* themselves. And the letters are knocked out with a mask rather than painted in
|
||||
* the background colour, so the mark sits correctly on any surface instead of
|
||||
* carrying a hardcoded backdrop that only matches the header.
|
||||
*
|
||||
* Decorative: the header already says "Redefined Designs" beside it, so it is
|
||||
* hidden from assistive technology rather than read out twice.
|
||||
*/
|
||||
export default function BrandMark({ size = 28, className }: Props) {
|
||||
// Unique per instance — two marks on one page would otherwise share a mask id
|
||||
// and the second would reference the first. The id is stripped to alphanumerics
|
||||
// because React's generated ids contain colons.
|
||||
const maskId = `rd-knockout-${useId().replace(/[^a-zA-Z0-9]/g, '')}`;
|
||||
|
||||
return (
|
||||
<svg
|
||||
className={className}
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 64 64"
|
||||
aria-hidden="true"
|
||||
focusable="false"
|
||||
>
|
||||
<mask id={maskId}>
|
||||
{/* White shows the tile, black punches the letters through it. */}
|
||||
<rect x="2" y="2" width="60" height="60" rx="15" fill="#fff" />
|
||||
<g
|
||||
fill="none"
|
||||
stroke="#000"
|
||||
strokeWidth="6.5"
|
||||
strokeLinecap="butt"
|
||||
strokeLinejoin="miter"
|
||||
>
|
||||
<path d="M15 18 V46" />
|
||||
<path d="M15 18 H20 A7 7 0 0 1 20 32 H15" />
|
||||
<path d="M20 32 L27 46" />
|
||||
<path d="M37 18 V46" />
|
||||
<path d="M37 18 H38 A14 14 0 0 1 38 46 H37" />
|
||||
</g>
|
||||
</mask>
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="60"
|
||||
height="60"
|
||||
rx="15"
|
||||
fill="currentColor"
|
||||
mask={`url(#${maskId})`}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user