Public Access
feat(ui): add the ToBePlayed logo and name
The logo is a traced SVG whose colors follow the accent color; violet shows it as designed. Favicon, PWA and Apple icons use it with fixed colors. The header and landing page say ToBePlayed instead of Game Log. Below 380 px the header shows only the logo, and the home link keeps its name for screen readers.
This commit is contained in:
1 parent
25d2f0d0bd
commit
c52c5e02d2
13 files changed
+195
-16
No files matched your search
@@ -0,0 +1,64 @@
|
||||
import {useId} from 'react';
|
||||
|
||||
import {BODY, CHECKLIST, DPAD, OUTLINE, PROGRESS_BAR} from './logoPaths.js';
|
||||
|
||||
// Each color is [themed CSS, fixed hex]. The hex is the logo as designed; it also stands in where a browser
|
||||
// cannot read color-mix, which would otherwise make that stop black.
|
||||
const violet = ['var(--logo-violet, #7467f9)', '#7467f9'];
|
||||
const blue = ['var(--logo-blue, #0192ef)', '#0192ef'];
|
||||
const teal = ['var(--logo-teal, #17c7a4)', '#17c7a4'];
|
||||
const mix = ([a], [b], percentOfB, hex) => [`color-mix(in oklch, ${a}, ${b} ${percentOfB}%)`, hex];
|
||||
|
||||
function Gradient({id, from, to, stops}) {
|
||||
return (
|
||||
<linearGradient id={id} gradientUnits="userSpaceOnUse" x1={from[0]} y1={from[1]} x2={to[0]} y2={to[1]}>
|
||||
{stops.map(([offset, [color, hex]]) => <stop key={offset} offset={offset} stopColor={hex} style={{stopColor: color}}/>)}
|
||||
</linearGradient>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ToBePlayed logo. Its three colors come from --logo-violet, --logo-blue and --logo-teal, which style.css sets
|
||||
* per accent color.
|
||||
*/
|
||||
export default function Logo({className, title}) {
|
||||
// Every copy on the page needs its own ids, or a hidden copy can take the gradients of a visible one with it.
|
||||
const id = useId().replace(/[^a-zA-Z0-9_-]/g, '');
|
||||
const ref = (name) => `${name}-${id}`;
|
||||
const url = (name) => `url(#${ref(name)})`;
|
||||
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="255 225 690 445" className={className}
|
||||
role={title ? 'img' : undefined} aria-label={title} aria-hidden={title ? undefined : true}>
|
||||
<defs>
|
||||
<clipPath id={ref('outline')}><path d={OUTLINE}/></clipPath>
|
||||
<Gradient id={ref('ring')} from={[265, 660]} to={[935, 235]}
|
||||
stops={[[0, violet], [0.15, violet], [0.42, blue], [0.7, teal], [1, teal]]}/>
|
||||
<Gradient id={ref('list')} from={[674, 326]} to={[525, 489]}
|
||||
stops={[[0, teal], [0.45, mix(blue, teal, 45, '#1dacad')], [0.7, blue], [1, mix(violet, blue, 50, '#4f6ad1')]]}/>
|
||||
<Gradient id={ref('dpad')} from={[478, 336]} to={[363, 451]}
|
||||
stops={[[0, blue], [1, mix(blue, violet, 20, '#2a83e4')]]}/>
|
||||
<Gradient id={ref('buttons')} from={[843, 326]} to={[708, 463]}
|
||||
stops={[[0, teal], [1, mix(teal, blue, 25, '#15b4ae')]]}/>
|
||||
<Gradient id={ref('bar')} from={[476, 610]} to={[723, 610]}
|
||||
stops={[[0, violet], [0.45, blue], [0.75, mix(blue, teal, 45, '#1dacad')], [1, teal]]}/>
|
||||
</defs>
|
||||
<path fill={url('ring')} d={OUTLINE}/>
|
||||
<path fill="#2d3641" d={BODY}/>
|
||||
<g fill="#192330" clipPath={url('outline')}>
|
||||
<rect x="502" y="289" width="195" height="233"/>
|
||||
<path d="M593.6 250H616.6L588 295H563Z"/>
|
||||
<path d="M595.3 516H620.3L591.4 560H567.4Z"/>
|
||||
</g>
|
||||
<path fill={url('dpad')} d={DPAD}/>
|
||||
<g fill={url('buttons')}>
|
||||
<circle cx="775.5" cy="347.5" r="22"/>
|
||||
<circle cx="729.5" cy="394" r="22"/>
|
||||
<circle cx="821.5" cy="393.5" r="22"/>
|
||||
<circle cx="775.5" cy="441" r="22"/>
|
||||
</g>
|
||||
<path fill={url('list')} fillRule="evenodd" d={CHECKLIST}/>
|
||||
<path fill={url('bar')} fillRule="evenodd" d={PROGRESS_BAR}/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user