Files
ToBePlayed-Frontend/src/components/Logo.jsx
T

68 lines
3.5 KiB
React

import {useId} from 'react';
import {BODY, CHECKLIST, DPAD, OUTLINE, PROGRESS_BAR} from './logoPaths.js';
/**
* The three logo colors as [CSS variable, hex as designed]; style.css sets the variables per accent.
*/
export const LOGO_COLORS = [['--logo-violet', '#7467f9'], ['--logo-blue', '#0192ef'], ['--logo-teal', '#17c7a4']];
// Each color is [themed CSS, fixed hex]. The hex also stands in where a browser cannot read color-mix, which
// would otherwise make that stop black.
const [violet, blue, teal] = LOGO_COLORS.map(([name, hex]) => [`var(${name}, ${hex})`, hex]);
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>
);
}