SPB Git forge
28commits 1branches 0releases
7.7 MBsize
maindefault branch
10 days agolast push
Python 66.3% TypeScript 22.7% JavaScript 8.6% HTML 1.4% CSS 0.7%
1.7 KB · 30 lines tsx
Raw Blame History
1'use client';2import { useState } from 'react';3import { cn } from '@/lib/cn';4import { monogram } from '@/lib/profile';56/**7 * Company logo with graceful degradation: tries each candidate URL in order (profile logo → icon → legacy), falls back8 * to a monogram plate. Plain `<img>` (remote hosts are unknown, so `next/image` optimisation is not used); lazy by9 * default, `referrerPolicy="no-referrer"` so third-party hosts do not learn which profile was viewed.10 */11export function CompanyLogo({ name, candidates, size = 40, className, priority = false, rounded = 'md' }: { name: string; candidates: string[]; size?: number; className?: string; priority?: boolean; rounded?: 'sm' | 'md' | 'lg' }) {12  const [idx, setIdx] = useState(0);13  const src = candidates[idx];14  const radius = rounded === 'sm' ? 'rounded-[3px]' : rounded === 'lg' ? 'rounded-[10px]' : 'rounded-[6px]';15  const style = { width: size, height: size };16  if (!src) {17    return (18      <span className={cn('mono inline-flex shrink-0 select-none items-center justify-center border border-rule bg-surface-2 font-semibold text-ink-2', radius, className)} style={{ ...style, fontSize: Math.max(10, Math.round(size * 0.38)) }} aria-hidden data-logo="monogram">19        {monogram(name)}20      </span>21    );22  }23  return (24    <span className={cn('inline-flex shrink-0 items-center justify-center overflow-hidden border border-rule bg-white', radius, className)} style={style} data-logo="image">25      {/* eslint-disable-next-line @next/next/no-img-element */}26      <img src={src} alt="" width={size} height={size} loading={priority ? 'eager' : 'lazy'} decoding="async" referrerPolicy="no-referrer" className="h-full w-full object-contain p-[12%]" onError={() => setIdx((i) => i + 1)} />27    </span>28  );29}30