Visitza Branded Logo
PartnerLogo, SupplierLogo, and AdminLogo — wordmark plus vertical separator and uppercase product suffix.
Source
registry/client/visitza/ui/branded-logo.tsximport * as React from 'react';
import { cn } from '@/lib/utils';
import { Logo } from '@/components/ui/logo';
import type { LogoProps } from '@/components/ui/logo';
// ── Types ───────────────────────────────────────────────────────────────────
type BrandedLogoVariant = 'default' | 'on-dark' | 'mono';
interface BrandedLogoProps extends Omit<LogoProps, 'markerColor' | 'zaColor'> {
/** Visual variant preset */
variant?: BrandedLogoVariant;
/** Override the suffix label (default derived from component) */
label?: string;
/** Additional className for the suffix text */
labelClassName?: string;
}
// ── Colour presets per variant ───────────────────────────────────────────────
const PARTNER_COLORS: Record<BrandedLogoVariant, { marker: string; za: string; suffix: string; separator: string }> = {
default: { marker: 'hsl(200 80% 45%)', za: 'hsl(24 95% 53%)', suffix: 'hsl(200 80% 45%)', separator: 'hsl(200 80% 45% / 0.5)' },
'on-dark': { marker: 'hsl(200 70% 58%)', za: 'hsl(24 95% 58%)', suffix: 'hsl(200 70% 58%)', separator: 'hsl(200 70% 58% / 0.5)' },
mono: { marker: 'rgba(255,255,255,0.4)', za: 'rgba(255,255,255,0.4)', suffix: 'rgba(255,255,255,0.4)', separator: 'rgba(255,255,255,0.2)' },
};
const SUPPLIER_COLORS: Record<BrandedLogoVariant, { marker: string; za: string; suffix: string; separator: string }> = {
default: { marker: 'hsl(38 92% 45%)', za: 'hsl(24 95% 53%)', suffix: 'hsl(38 92% 45%)', separator: 'hsl(38 92% 45% / 0.5)' },
'on-dark': { marker: 'hsl(38 85% 55%)', za: 'hsl(24 95% 58%)', suffix: 'hsl(38 85% 55%)', separator: 'hsl(38 85% 55% / 0.5)' },
mono: { marker: 'rgba(255,255,255,0.4)', za: 'rgba(255,255,255,0.4)', suffix: 'rgba(255,255,255,0.4)', separator: 'rgba(255,255,255,0.2)' },
};
const ADMIN_COLORS: Record<BrandedLogoVariant, { marker: string; za: string; suffix: string; separator: string }> = {
default: { marker: 'hsl(220 10% 25%)', za: 'hsl(24 95% 53%)', suffix: 'hsl(220 10% 25%)', separator: 'hsl(220 10% 25% / 0.5)' },
'on-dark': { marker: 'hsl(220 10% 50%)', za: 'hsl(24 95% 58%)', suffix: 'hsl(220 10% 50%)', separator: 'hsl(220 10% 50% / 0.5)' },
mono: { marker: 'rgba(255,255,255,0.4)', za: 'rgba(255,255,255,0.4)', suffix: 'rgba(255,255,255,0.4)', separator: 'rgba(255,255,255,0.2)' },
};
// ── Inner builder ───────────────────────────────────────────────────────────
function buildBrandedLogo(
displayName: string,
defaultLabel: string,
palette: Record<BrandedLogoVariant, { marker: string; za: string; suffix: string; separator: string }>,
) {
const BrandedLogo = React.forwardRef<SVGSVGElement, BrandedLogoProps & React.SVGAttributes<SVGSVGElement>>(
({ variant = 'default', label, labelClassName, className, mono, monoColor, visitColor, ringColor, ...props }, ref) => {
const colors = palette[mono ? 'mono' : variant];
const suffixText = (label ?? defaultLabel).toUpperCase();
// The base Logo viewBox is "0 0 960 300".
// Separator line sits after wordmark, then suffix text.
const sepX = 975;
const textX = sepX + 32;
const charWidth = 78; // uppercase char width at fontSize 115 + 0.12em tracking
const suffixWidth = suffixText.length * charWidth + 60;
const totalWidth = textX + suffixWidth;
// Wordmark vertical range is roughly y=108 to y=230
const lineTop = 100;
const lineBottom = 235;
return (
<svg
ref={ref}
viewBox={`0 0 ${totalWidth} 300`}
className={cn('block shrink-0', className)}
xmlns="http://www.w3.org/2000/svg"
{...props}
>
{/* Nested base logo at original viewBox coordinates */}
<Logo
markerColor={colors.marker}
zaColor={colors.za}
visitColor={visitColor}
ringColor={ringColor}
mono={mono}
monoColor={monoColor}
x={0}
y={0}
width={960}
height={300}
/>
{/* Separator line */}
<line
x1={sepX}
y1={lineTop}
x2={sepX}
y2={lineBottom}
stroke={colors.separator}
strokeWidth={4.5}
strokeLinecap="round"
/>
{/* Suffix text — marker colour, all caps */}
<text
x={textX}
y={225}
style={{
fill: colors.suffix,
fontSize: 115,
fontFamily: "'Jost', 'Calibri', system-ui, sans-serif",
fontWeight: 600,
letterSpacing: '0.12em',
transition: 'fill 500ms ease',
}}
>
{suffixText}
</text>
</svg>
);
},
);
BrandedLogo.displayName = displayName;
return BrandedLogo;
}
// ── Exports ─────────────────────────────────────────────────────────────────
const PartnerLogo = buildBrandedLogo('PartnerLogo', 'partner', PARTNER_COLORS);
const SupplierLogo = buildBrandedLogo('SupplierLogo', 'supplier', SUPPLIER_COLORS);
const AdminLogo = buildBrandedLogo('AdminLogo', 'admin', ADMIN_COLORS);
export { PartnerLogo, SupplierLogo, AdminLogo };
export type { BrandedLogoProps, BrandedLogoVariant };