qmd-web / src /components /ResultCard.tsx
shreyask's picture
feat: manual generation for no-KV-cache model, fix blend scoring, add coffee doc
6c0127c verified
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>
);
}