File size: 2,892 Bytes
5e17e07
 
 
 
 
 
 
 
 
 
 
 
6c0127c
 
5e17e07
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6c0127c
5e17e07
 
 
 
 
 
6c0127c
 
5e17e07
 
 
 
 
6c0127c
5e17e07
 
 
 
 
 
 
6c0127c
5e17e07
 
 
 
 
 
 
 
6c0127c
 
5e17e07
 
 
 
 
 
 
6c0127c
5e17e07
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import { useState } from 'react';

interface ResultCardProps {
  title: string;
  score: number;
  snippet: string;
  expanded?: boolean;
  onToggle?: () => void;
}

function ScoreBadge({ score }: { score: number }) {
  const pct = Math.round(score * 100);
  const bg = pct >= 80 ? 'var(--score-good-bg)' : pct >= 50 ? 'var(--score-mid-bg)' : 'var(--score-bad-bg)';
  const color = pct >= 80 ? '#2e7d32' : pct >= 50 ? '#f57f17' : 'var(--text-secondary)';

  return (
    <span style={{
      display: 'inline-block',
      padding: '0.15rem 0.45rem',
      borderRadius: '4px',
      background: bg,
      color,
      fontFamily: "'SF Mono', 'Fira Code', 'Cascadia Code', monospace",
      fontSize: '0.72rem',
      fontWeight: 700,
    }}>
      {pct}%
    </span>
  );
}

export default function ResultCard({ title, score, snippet, expanded: expandedProp, onToggle }: ResultCardProps) {
  const [localExpanded, setLocalExpanded] = useState(false);
  const isControlled = expandedProp !== undefined;
  const expanded = isControlled ? expandedProp : localExpanded;

  function handleToggle() {
    if (isControlled) {
      onToggle?.();
    } else {
      setLocalExpanded(e => !e);
    }
  }

  const preview = snippet.length > 200 ? snippet.slice(0, 200) + '\u2026' : snippet;

  return (
    <div
      onClick={handleToggle}
      style={{
        padding: '0.65rem 0.85rem',
        background: 'var(--bg-card)',
        border: '1px solid var(--border)',
        borderRadius: '6px',
        marginBottom: '0.4rem',
        cursor: 'pointer',
        transition: 'box-shadow 0.15s',
      }}
      onMouseEnter={e => { (e.currentTarget as HTMLDivElement).style.boxShadow = '0 2px 8px var(--shadow)'; }}
      onMouseLeave={e => { (e.currentTarget as HTMLDivElement).style.boxShadow = 'none'; }}
    >
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '0.5rem' }}>
        <span style={{
          fontFamily: 'system-ui, -apple-system, sans-serif',
          fontSize: '0.85rem',
          fontWeight: 600,
          color: 'var(--text)',
          overflow: 'hidden',
          textOverflow: 'ellipsis',
          whiteSpace: 'nowrap',
          flex: 1,
        }}>
          {title}
        </span>
        <ScoreBadge score={score} />
        <span style={{ color: 'var(--text-muted)', fontSize: '0.75rem', flexShrink: 0 }}>
          {expanded ? '\u25B2' : '\u25BC'}
        </span>
      </div>

      <div style={{
        marginTop: '0.4rem',
        fontFamily: "'SF Mono', 'Fira Code', 'Cascadia Code', monospace",
        fontSize: '0.72rem',
        color: 'var(--text-secondary)',
        lineHeight: 1.5,
        whiteSpace: expanded ? 'pre-wrap' : 'nowrap',
        overflow: 'hidden',
        textOverflow: expanded ? 'unset' : 'ellipsis',
      }}>
        {expanded ? snippet : preview}
      </div>
    </div>
  );
}