Merge pull request 'feat(frontend): show the RD mark beside the storefront wordmark' (#75) from feature/header-brand-mark into main
Reviewed-on: #75
This commit was merged in pull request #75.
This commit is contained in:
@@ -4,6 +4,7 @@ import { ShoppingCartOutlined, FilterOutlined } from '@ant-design/icons';
|
||||
import { Link, useLocation, useSearchParams } from 'react-router-dom';
|
||||
import { Item, FilterOptions, fetchItems, fetchFilterOptions } from './api';
|
||||
import ItemCard from './components/ItemCard';
|
||||
import BrandMark from './components/BrandMark';
|
||||
import FilterDrawer from './components/FilterDrawer';
|
||||
import ActiveFilterChips from './components/ActiveFilterChips';
|
||||
import {
|
||||
@@ -118,9 +119,15 @@ export default function App() {
|
||||
borderBottom: `1px solid ${token.colorBorderSecondary}`
|
||||
}}
|
||||
>
|
||||
{/* Wrapped so the mark and the wordmark travel together — the title
|
||||
keeps its own ellipsis behaviour when the header gets narrow, and the
|
||||
mark is never what gets truncated. */}
|
||||
<div className="site-header-brand" style={{ color: token.colorText }}>
|
||||
<BrandMark size={28} />
|
||||
<Title level={3} className="site-header-title" style={{ color: token.colorText }}>
|
||||
Redefined Designs
|
||||
</Title>
|
||||
</div>
|
||||
<div className="site-header-actions">
|
||||
<Switch checked={mode === 'dark'} onChange={toggle} checkedChildren="Dark" unCheckedChildren="Light" />
|
||||
<Link to="/cart">
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -45,6 +45,19 @@ body { margin: 0; }
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.site-header-brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* The mark holds its size while the wordmark absorbs the squeeze. */
|
||||
.site-header-brand svg {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.site-header-title {
|
||||
margin: 0 !important;
|
||||
font-size: clamp(16px, 5vw, 24px);
|
||||
|
||||
Reference in New Issue
Block a user