SPB Git forge

spb/uqo-chat

Public
14commits 1branches 0releases
1.4 MBsize
maindefault branch
17 days agolast push
Python 64.6% TypeScript 33.7% CSS 0.8%
1.8 KB · 30 lines tsx
Raw Blame History
1import { ExternalLink, Globe } from 'lucide-react';2import type { ToolCallView } from '@/lib/types';34interface Result { title: string; url: string; date?: string; excerpt: string; domain?: string }56export function WebSearchCard({ call }: { call: ToolCallView }) {7  const p = call.payload as { query?: string; results?: Result[]; error?: string; mode?: string };8  const results = p.results || [];9  if (!results.length) return <p className="text-sm text-neutral-muted">{p.error ? "Le web n'a pas pu être consulté." : 'Aucun résultat pertinent.'}</p>;10  return (11    <ul className="space-y-2">12      {results.map((r, i) => {13        const domain = r.domain || (() => { try { return new URL(r.url).hostname.replace(/^www\./, ''); } catch { return ''; } })();14        return (15          <li key={i}>16            <a href={r.url} target="_blank" rel="noopener noreferrer" className="flex gap-3 rounded-xl border border-neutral-line bg-white p-3 hover:bg-neutral-surface">17              <img src={`https://www.google.com/s2/favicons?domain=${domain}&sz=32`} alt="" width={20} height={20} className="mt-0.5 h-5 w-5 rounded shrink-0" onError={(e) => ((e.target as HTMLImageElement).style.visibility = 'hidden')} />18              <span className="min-w-0 flex-1">19                <span className="block text-sm font-medium text-uqo-blue-dark truncate">{r.title}</span>20                <span className="block text-xs text-neutral-muted truncate inline-flex items-center gap-1"><Globe size={11} /> {domain}{r.date ? ` · ${r.date.slice(0, 10)}` : ''} <ExternalLink size={11} /></span>21                {r.excerpt && <span className="block text-xs text-neutral-text/80 mt-1 line-clamp-3">{r.excerpt}</span>}22              </span>23            </a>24          </li>25        );26      })}27    </ul>28  );29}30