Skip to content

Commit c508d70

Browse files
Merge pull request #174 from CSSLab/dev
Improve UI consistency and appearance + responsive design
2 parents b7ddf1e + 7956690 commit c508d70

23 files changed

+647
-1228
lines changed
Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
import {
2+
MoveMap,
3+
Highlight,
4+
BlunderMeter,
5+
MovesByRating,
6+
} from 'src/components/Analysis'
7+
import { motion } from 'framer-motion'
8+
import type { DrawShape } from 'chessground/draw'
9+
import { Dispatch, SetStateAction, useCallback, useMemo } from 'react'
10+
import { useAnalysisController } from 'src/hooks/useAnalysisController'
11+
import type { MaiaEvaluation, StockfishEvaluation } from 'src/types'
12+
13+
interface Props {
14+
hover: (move?: string) => void
15+
makeMove: (move: string) => void
16+
setHoverArrow: Dispatch<SetStateAction<DrawShape | null>>
17+
analysisEnabled: boolean
18+
controller: ReturnType<typeof useAnalysisController>
19+
handleToggleAnalysis: () => void
20+
itemVariants?: {
21+
hidden: {
22+
opacity: number
23+
y: number
24+
}
25+
visible: {
26+
opacity: number
27+
y: number
28+
transition: {
29+
duration: number
30+
ease: number[]
31+
type: string
32+
}
33+
}
34+
exit: {
35+
opacity: number
36+
y: number
37+
transition: {
38+
duration: number
39+
ease: number[]
40+
type: string
41+
}
42+
}
43+
}
44+
}
45+
46+
export const AnalysisSidebar: React.FC<Props> = ({
47+
hover,
48+
makeMove,
49+
controller,
50+
setHoverArrow,
51+
analysisEnabled,
52+
handleToggleAnalysis,
53+
itemVariants,
54+
}) => {
55+
// Mock handlers for when analysis is disabled
56+
const emptyBlunderMeterData = useMemo(
57+
() => ({
58+
goodMoves: { moves: [], probability: 0 },
59+
okMoves: { moves: [], probability: 0 },
60+
blunderMoves: { moves: [], probability: 0 },
61+
}),
62+
[],
63+
)
64+
65+
const emptyRecommendations = useMemo(
66+
() => ({
67+
maia: undefined,
68+
stockfish: undefined,
69+
}),
70+
[],
71+
)
72+
const mockHover = useCallback(() => void 0, [])
73+
const mockSetHoverArrow = useCallback(() => void 0, [])
74+
const mockMakeMove = useCallback(() => void 0, [])
75+
76+
return (
77+
<motion.div
78+
id="analysis"
79+
variants={itemVariants ?? {}}
80+
className="desktop-right-column-container flex flex-col gap-2"
81+
style={{ willChange: 'transform, opacity' }}
82+
>
83+
{/* Analysis Toggle Bar */}
84+
<div className="flex h-10 min-h-10 items-center justify-between rounded bg-background-1 px-4">
85+
<div className="flex items-center gap-2">
86+
<span className="material-symbols-outlined text-xl">analytics</span>
87+
<h3 className="font-semibold">Analysis</h3>
88+
</div>
89+
<button
90+
onClick={handleToggleAnalysis}
91+
className={`flex items-center gap-1 rounded px-2 py-1 text-xs transition-colors ${
92+
analysisEnabled
93+
? 'bg-human-4 text-white hover:bg-human-4/80'
94+
: 'bg-background-2 text-secondary hover:bg-background-3'
95+
}`}
96+
>
97+
<span className="material-symbols-outlined !text-xs">
98+
{analysisEnabled ? 'visibility' : 'visibility_off'}
99+
</span>
100+
{analysisEnabled ? 'Visible' : 'Hidden'}
101+
</button>
102+
</div>
103+
104+
{/* Large screens : 2-row layout */}
105+
<div className="hidden xl:flex xl:h-full xl:flex-col xl:gap-2">
106+
{/* Combined Highlight + MovesByRating container */}
107+
<div className="desktop-analysis-big-row-1-container relative flex gap-2">
108+
<div className="flex h-full w-full overflow-hidden rounded border-[0.5px] border-white/40">
109+
<div className="flex h-full w-auto min-w-[40%] max-w-[40%] border-r-[0.5px] border-white/40">
110+
<Highlight
111+
hover={analysisEnabled ? hover : mockHover}
112+
makeMove={analysisEnabled ? makeMove : mockMakeMove}
113+
currentMaiaModel={controller.currentMaiaModel}
114+
setCurrentMaiaModel={controller.setCurrentMaiaModel}
115+
recommendations={
116+
analysisEnabled
117+
? controller.moveRecommendations
118+
: emptyRecommendations
119+
}
120+
moveEvaluation={
121+
analysisEnabled
122+
? (controller.moveEvaluation as {
123+
maia?: MaiaEvaluation
124+
stockfish?: StockfishEvaluation
125+
})
126+
: {
127+
maia: undefined,
128+
stockfish: undefined,
129+
}
130+
}
131+
colorSanMapping={
132+
analysisEnabled ? controller.colorSanMapping : {}
133+
}
134+
boardDescription={
135+
analysisEnabled
136+
? controller.boardDescription
137+
: {
138+
segments: [
139+
{
140+
type: 'text',
141+
content:
142+
'Analysis is disabled. Enable analysis to see detailed move evaluations and recommendations.',
143+
},
144+
],
145+
}
146+
}
147+
currentNode={controller.currentNode}
148+
/>
149+
</div>
150+
<div className="flex h-full w-full bg-background-1">
151+
<MovesByRating
152+
moves={analysisEnabled ? controller.movesByRating : undefined}
153+
colorSanMapping={
154+
analysisEnabled ? controller.colorSanMapping : {}
155+
}
156+
/>
157+
</div>
158+
</div>
159+
{!analysisEnabled && (
160+
<div className="absolute inset-0 z-10 flex items-center justify-center overflow-hidden rounded bg-background-1/80 backdrop-blur-sm">
161+
<div className="rounded bg-background-2/90 p-4 text-center shadow-lg">
162+
<span className="material-symbols-outlined mb-2 text-3xl text-human-3">
163+
lock
164+
</span>
165+
<p className="font-medium text-primary">Analysis Disabled</p>
166+
<p className="text-sm text-secondary">
167+
Enable analysis to see move evaluations
168+
</p>
169+
</div>
170+
</div>
171+
)}
172+
</div>
173+
174+
{/* MoveMap + BlunderMeter container */}
175+
<div className="desktop-analysis-big-row-2-container relative flex flex-row gap-2">
176+
<div className="flex h-full w-full flex-col">
177+
<MoveMap
178+
moveMap={analysisEnabled ? controller.moveMap : undefined}
179+
colorSanMapping={
180+
analysisEnabled ? controller.colorSanMapping : {}
181+
}
182+
setHoverArrow={
183+
analysisEnabled ? setHoverArrow : mockSetHoverArrow
184+
}
185+
makeMove={analysisEnabled ? makeMove : mockMakeMove}
186+
/>
187+
</div>
188+
<BlunderMeter
189+
hover={analysisEnabled ? hover : mockHover}
190+
makeMove={analysisEnabled ? makeMove : mockMakeMove}
191+
data={
192+
analysisEnabled ? controller.blunderMeter : emptyBlunderMeterData
193+
}
194+
colorSanMapping={analysisEnabled ? controller.colorSanMapping : {}}
195+
moveEvaluation={
196+
analysisEnabled ? controller.moveEvaluation : undefined
197+
}
198+
/>
199+
{!analysisEnabled && (
200+
<div className="absolute inset-0 z-10 flex items-center justify-center overflow-hidden rounded bg-background-1/80 backdrop-blur-sm">
201+
<div className="rounded bg-background-2/90 p-4 text-center shadow-lg">
202+
<span className="material-symbols-outlined mb-2 text-3xl text-human-3">
203+
lock
204+
</span>
205+
<p className="font-medium text-primary">Analysis Disabled</p>
206+
<p className="text-sm text-secondary">
207+
Enable analysis to see position evaluation
208+
</p>
209+
</div>
210+
</div>
211+
)}
212+
</div>
213+
</div>
214+
215+
{/* Smaller screens: 3-row layout */}
216+
<div className="flex h-full flex-col gap-2 xl:hidden">
217+
{/* Row 1: Combined Highlight + BlunderMeter container */}
218+
<div className="desktop-analysis-small-row-1-container relative flex overflow-hidden rounded border-[0.5px] border-white/40 bg-background-1">
219+
<div className="flex h-full w-full border-r-[0.5px] border-white/40">
220+
<Highlight
221+
hover={analysisEnabled ? hover : mockHover}
222+
makeMove={analysisEnabled ? makeMove : mockMakeMove}
223+
currentMaiaModel={controller.currentMaiaModel}
224+
setCurrentMaiaModel={controller.setCurrentMaiaModel}
225+
recommendations={
226+
analysisEnabled
227+
? controller.moveRecommendations
228+
: emptyRecommendations
229+
}
230+
moveEvaluation={
231+
analysisEnabled
232+
? (controller.moveEvaluation as {
233+
maia?: MaiaEvaluation
234+
stockfish?: StockfishEvaluation
235+
})
236+
: {
237+
maia: undefined,
238+
stockfish: undefined,
239+
}
240+
}
241+
colorSanMapping={
242+
analysisEnabled ? controller.colorSanMapping : {}
243+
}
244+
boardDescription={
245+
analysisEnabled
246+
? controller.boardDescription
247+
: {
248+
segments: [
249+
{
250+
type: 'text',
251+
content:
252+
'Analysis is disabled. Enable analysis to see detailed move evaluations and recommendations.',
253+
},
254+
],
255+
}
256+
}
257+
currentNode={controller.currentNode}
258+
/>
259+
</div>
260+
<div className="flex h-full w-auto min-w-[40%] max-w-[40%] bg-background-1 p-3">
261+
<div className="h-full w-full">
262+
<BlunderMeter
263+
hover={analysisEnabled ? hover : mockHover}
264+
makeMove={analysisEnabled ? makeMove : mockMakeMove}
265+
data={
266+
analysisEnabled
267+
? controller.blunderMeter
268+
: emptyBlunderMeterData
269+
}
270+
colorSanMapping={
271+
analysisEnabled ? controller.colorSanMapping : {}
272+
}
273+
moveEvaluation={
274+
analysisEnabled ? controller.moveEvaluation : undefined
275+
}
276+
showContainer={false}
277+
/>
278+
</div>
279+
</div>
280+
{!analysisEnabled && (
281+
<div className="absolute inset-0 z-10 flex items-center justify-center overflow-hidden rounded bg-background-1/80 backdrop-blur-sm">
282+
<div className="rounded bg-background-2/90 p-4 text-center shadow-lg">
283+
<span className="material-symbols-outlined mb-2 text-3xl text-human-3">
284+
lock
285+
</span>
286+
<p className="font-medium text-primary">Analysis Disabled</p>
287+
<p className="text-sm text-secondary">
288+
Enable analysis to see move evaluations
289+
</p>
290+
</div>
291+
</div>
292+
)}
293+
</div>
294+
295+
{/* Row 2: MoveMap */}
296+
<div className="desktop-analysis-small-row-2-container relative flex w-full">
297+
<div className="h-full w-full">
298+
<MoveMap
299+
moveMap={analysisEnabled ? controller.moveMap : undefined}
300+
colorSanMapping={
301+
analysisEnabled ? controller.colorSanMapping : {}
302+
}
303+
setHoverArrow={
304+
analysisEnabled ? setHoverArrow : mockSetHoverArrow
305+
}
306+
makeMove={analysisEnabled ? makeMove : mockMakeMove}
307+
/>
308+
</div>
309+
{!analysisEnabled && (
310+
<div className="absolute inset-0 z-10 flex items-center justify-center overflow-hidden rounded bg-background-1/80 backdrop-blur-sm">
311+
<div className="rounded bg-background-2/90 p-4 text-center shadow-lg">
312+
<span className="material-symbols-outlined mb-2 text-3xl text-human-3">
313+
lock
314+
</span>
315+
<p className="font-medium text-primary">Analysis Disabled</p>
316+
<p className="text-sm text-secondary">
317+
Enable analysis to see position evaluation
318+
</p>
319+
</div>
320+
</div>
321+
)}
322+
</div>
323+
324+
{/* Row 3: MovesByRating */}
325+
<div className="desktop-analysis-small-row-3-container relative flex w-full">
326+
<div className="h-full w-full">
327+
<MovesByRating
328+
moves={analysisEnabled ? controller.movesByRating : undefined}
329+
colorSanMapping={
330+
analysisEnabled ? controller.colorSanMapping : {}
331+
}
332+
/>
333+
</div>
334+
{!analysisEnabled && (
335+
<div className="absolute inset-0 z-10 flex items-center justify-center overflow-hidden rounded bg-background-1/80 backdrop-blur-sm">
336+
<div className="rounded bg-background-2/90 p-4 text-center shadow-lg">
337+
<span className="material-symbols-outlined mb-2 text-3xl text-human-3">
338+
lock
339+
</span>
340+
<p className="font-medium text-primary">Analysis Disabled</p>
341+
<p className="text-sm text-secondary">
342+
Enable analysis to see move evaluations
343+
</p>
344+
</div>
345+
</div>
346+
)}
347+
</div>
348+
</div>
349+
</motion.div>
350+
)
351+
}

src/components/Analysis/HorizontalEvaluationBar.tsx

Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
 (0)