LLM_Comparison_Tool / frontend /src /components /ResponseCarousel.js
NeonClary
LLM Comparison Tool: deploy snapshot for Hugging Face Space (orphan history)
08b0543
import { useState, useEffect } from 'react';
import ResponseBlock from './ResponseBlock';
function useWindowWidth() {
const [w, setW] = useState(typeof window !== 'undefined' ? window.innerWidth : 1200);
useEffect(() => {
const h = () => setW(window.innerWidth);
window.addEventListener('resize', h);
return () => window.removeEventListener('resize', h);
}, []);
return w;
}
export default function ResponseCarousel({ neonResponse, comparisonResponses, offset = 0, showPrePromptIndicator = false }) {
const screenWidth = useWindowWidth();
const isMobile = screenWidth <= 480;
const isTablet = screenWidth <= 900;
const visible = isMobile ? 1 : (isTablet ? 1 : 2);
const visibleComparisons = comparisonResponses.slice(offset, offset + visible);
return (
<div className={`carousel-track ${isMobile ? 'carousel-track--stacked' : ''} ${isTablet && !isMobile ? 'carousel-track--tablet' : ''}`}>
<div className="carousel-sticky">
<ResponseBlock
response={neonResponse}
isNeonEmphasis={true}
showBadge={false}
showModelName={true}
showPersona={true}
showFooterParams={false}
showPrePromptIndicator={showPrePromptIndicator}
/>
</div>
<div className="carousel-scrollable">
{visibleComparisons.map((r, i) => (
<ResponseBlock
key={`${r.model_id}-${offset + i}`}
response={r}
showBadge={false}
showModelName={false}
showFooterParams={false}
isComparisonEmphasis={true}
showPrePromptIndicator={showPrePromptIndicator}
/>
))}
{comparisonResponses.length === 0 && (
<div className="carousel-empty">No comparison models selected</div>
)}
</div>
<style>{`
.carousel-track {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 12px;
align-items: stretch;
}
.carousel-track--tablet {
grid-template-columns: 1fr 1fr;
}
.carousel-track--stacked {
grid-template-columns: 1fr;
}
.carousel-sticky {
min-width: 0;
display: flex;
}
.carousel-scrollable {
display: flex;
gap: 12px;
min-width: 0;
overflow: hidden;
}
.carousel-scrollable .response-block {
flex: 1;
min-width: 0;
}
.carousel-empty {
display: flex;
align-items: center;
justify-content: center;
flex: 1;
color: var(--text-muted);
font-size: 13px;
font-style: italic;
border: 1px dashed var(--border-primary);
border-radius: 12px;
padding: 24px;
}
`}</style>
</div>
);
}