Skip to content

Commit 08d85f0

Browse files
style: improve hand & brain + play controls
1 parent aa609d2 commit 08d85f0

File tree

3 files changed

+224
-146
lines changed

3 files changed

+224
-146
lines changed

src/components/Play/HandBrainPlayControls.tsx

Lines changed: 150 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/* eslint-disable jsx-a11y/alt-text */
33
import { PieceSymbol } from 'chess.ts'
44

5-
import { Color } from 'src/types'
5+
import { BaseGame, Color } from 'src/types'
66

77
const pieceTypes: PieceSymbol[] = ['k', 'q', 'r', 'b', 'n', 'p']
88

@@ -22,6 +22,7 @@ const pieceColorMap: { [key: string]: string } = {
2222
}
2323

2424
interface Props {
25+
game: BaseGame
2526
isBrain: boolean
2627
color: Color
2728
movablePieceTypes: PieceSymbol[]
@@ -37,6 +38,7 @@ interface Props {
3738
}
3839

3940
export const HandBrainPlayControls: React.FC<Props> = ({
41+
game,
4042
playerActive,
4143
gameOver,
4244
isBrain,
@@ -61,118 +63,175 @@ export const HandBrainPlayControls: React.FC<Props> = ({
6163
: 'Waiting for opponent'
6264

6365
return (
64-
<div>
65-
<div
66-
id="play-controls"
67-
className="flex flex-col items-center justify-center p-6"
68-
>
66+
<div className="flex h-full w-full flex-col border-white/40 bg-background-1">
67+
<div id="play-controls" className="flex h-full flex-col">
6968
{gameOver ? (
70-
<>
69+
<div className="flex flex-col gap-2 p-4">
70+
{game.id ? (
71+
<button
72+
onClick={() => {
73+
window.open(
74+
`/analysis/${game.id}/${isBrain ? 'brain' : 'hand'}`,
75+
'_blank',
76+
)
77+
}}
78+
className="flex items-center justify-center rounded border border-engine-2/20 bg-engine-3/5 px-4 py-2 text-sm font-semibold text-engine-1 transition-colors duration-200 hover:border-engine-2/50 hover:bg-engine-3/10"
79+
>
80+
ANALYZE GAME
81+
</button>
82+
) : null}
7183
{playAgain ? (
7284
<button
7385
onClick={playAgain}
74-
className="flex w-full justify-center rounded bg-human-3 py-2 text-primary transition duration-200 hover:bg-human-4"
86+
className="flex w-full items-center justify-center rounded border border-human-2/20 bg-human-3/5 px-4 py-2 text-sm font-semibold tracking-wider text-human-1 transition-colors duration-200 hover:border-human-2/50 hover:bg-human-3/10"
7587
>
76-
Play again
88+
PLAY AGAIN
7789
</button>
7890
) : null}
79-
</>
91+
</div>
8092
) : (
81-
<div className="flex w-full flex-col items-center justify-center gap-4">
82-
<div className="flex flex-col items-center justify-center">
83-
<p className="font-bold">{status}</p>
84-
<h2 className="text-base">
85-
{isBrain ? 'You are the brain' : 'You are the hand'}
86-
</h2>
87-
</div>
88-
{isBrain ? (
89-
<div className="flex w-full flex-wrap items-start justify-center gap-2">
90-
{pieceTypes.map((p) => (
91-
<button
92-
key={p}
93-
onClick={() => selectPiece(p)}
94-
disabled={
95-
movablePieceTypes.indexOf(p) == -1 ||
96-
!playerActive ||
97-
!!selectedPiece
98-
}
99-
className="flex h-16 w-16 items-center justify-center rounded border border-primary/10 bg-[#f0d9b5] disabled:bg-background-1"
100-
>
101-
<img
102-
src={`/assets/pieces/${pieceColorMap[color[0] + p]}.svg`}
103-
/>
104-
</button>
105-
))}
106-
</div>
107-
) : (
108-
<div className="h-30 w-30 flex items-center justify-center">
109-
{selectedPiece ? (
110-
<img
111-
src={`/assets/pieces/${pieceColorMap[color[0] + selectedPiece]}.svg`}
112-
className="h-20 w-20 rounded bg-[#f0d9b5] bg-contain"
113-
/>
114-
) : null}
93+
<>
94+
{/* Status Section */}
95+
<div className="border-b border-white/10 bg-background-1 p-3">
96+
<div className="space-y-1 text-center">
97+
<p
98+
className={`text-sm font-semibold uppercase tracking-wider ${
99+
playerActive ? 'text-human-1' : 'text-secondary'
100+
}`}
101+
>
102+
{status}
103+
</p>
104+
<p className="text-xs font-medium text-secondary/70">
105+
{isBrain ? 'You are the brain' : 'You are the hand'}
106+
</p>
115107
</div>
116-
)}
108+
</div>
117109

118-
{/* Maia timing toggle */}
110+
{/* Piece Selection or Display */}
111+
<div className="border-b border-white/5 bg-human-3/5 p-4">
112+
{isBrain ? (
113+
<div className="flex flex-col gap-3">
114+
<p className="text-center text-xs font-semibold uppercase tracking-wide text-human-2">
115+
SELECT PIECE
116+
</p>
117+
<div className="mx-auto grid max-w-48 grid-cols-3 gap-2">
118+
{pieceTypes.map((p) => (
119+
<button
120+
key={p}
121+
onClick={() => selectPiece(p)}
122+
disabled={
123+
movablePieceTypes.indexOf(p) == -1 ||
124+
!playerActive ||
125+
!!selectedPiece
126+
}
127+
className={`flex h-12 w-12 items-center justify-center border transition-colors duration-200 ${
128+
movablePieceTypes.indexOf(p) !== -1 &&
129+
playerActive &&
130+
!selectedPiece
131+
? 'border-white/20 bg-[#f0d9b5] hover:border-white/30 hover:bg-[#e6d0a6]'
132+
: 'cursor-not-allowed border-white/5 bg-background-2 opacity-50'
133+
}`}
134+
>
135+
<img
136+
src={`/assets/pieces/${pieceColorMap[color[0] + p]}.svg`}
137+
className="h-6 w-6"
138+
alt={pieceColorMap[color[0] + p]}
139+
/>
140+
</button>
141+
))}
142+
</div>
143+
</div>
144+
) : (
145+
<div className="flex flex-col items-center gap-3">
146+
<p className="text-center text-xs font-semibold uppercase tracking-wide text-human-2">
147+
SELECTED PIECE
148+
</p>
149+
<div className="flex h-16 w-16 items-center justify-center">
150+
{selectedPiece ? (
151+
<div className="border border-white/20 bg-[#f0d9b5] p-2">
152+
<img
153+
src={`/assets/pieces/${pieceColorMap[color[0] + selectedPiece]}.svg`}
154+
className="h-12 w-12"
155+
alt={pieceColorMap[color[0] + selectedPiece]}
156+
/>
157+
</div>
158+
) : (
159+
<div className="flex h-12 w-12 items-center justify-center border border-dashed border-white/20 bg-background-2">
160+
<span className="text-xs text-secondary/50">...</span>
161+
</div>
162+
)}
163+
</div>
164+
</div>
165+
)}
166+
</div>
167+
168+
{/* Maia Timing Toggle */}
119169
{simulateMaiaTime !== undefined && setSimulateMaiaTime && (
120-
<div className="w-full">
121-
<div className="mb-2 text-center text-xs font-medium text-primary/70">
122-
Maia thinking time
170+
<div className="border-b border-white/5 bg-human-3/5 p-3">
171+
<div className="flex flex-col gap-2">
172+
<p className="text-center text-xs font-semibold tracking-wider text-human-2">
173+
MAIA THINKING TIME
174+
</p>
175+
<div className="flex overflow-hidden border border-white/10 bg-background-1">
176+
<button
177+
className={`flex-1 px-3 py-1.5 text-xs font-medium transition-colors duration-200 ${
178+
!simulateMaiaTime
179+
? 'bg-human-3 text-white'
180+
: 'text-primary hover:bg-background-2'
181+
}`}
182+
onClick={() => setSimulateMaiaTime(false)}
183+
>
184+
Instant
185+
</button>
186+
<button
187+
className={`flex-1 px-3 py-1.5 text-xs font-medium transition-colors duration-200 ${
188+
simulateMaiaTime
189+
? 'bg-human-3 text-white'
190+
: 'text-primary hover:bg-background-2'
191+
}`}
192+
onClick={() => setSimulateMaiaTime(true)}
193+
>
194+
Human-like
195+
</button>
196+
</div>
123197
</div>
124-
<div className="flex w-full overflow-hidden rounded border border-primary/10">
198+
</div>
199+
)}
200+
201+
{/* Action Buttons */}
202+
<div className="flex-1 p-3">
203+
<div className="flex flex-col gap-2">
204+
{offerDraw && (
125205
<button
126-
className={`flex-1 px-3 py-1 text-xs font-medium transition-all duration-200 ${
127-
!simulateMaiaTime
128-
? 'bg-human-3 text-white'
129-
: 'bg-background-1 text-primary hover:bg-background-2'
206+
onClick={offerDraw}
207+
disabled={!playerActive}
208+
className={`w-full border px-4 py-2 text-sm font-semibold transition-colors duration-200 ${
209+
playerActive
210+
? 'border-white/10 bg-engine-3/5 text-engine-1 hover:border-white/20 hover:bg-engine-3/10'
211+
: 'cursor-not-allowed border-white/5 bg-background-2 text-secondary/40'
130212
}`}
131-
onClick={() => setSimulateMaiaTime(false)}
132213
>
133-
Instant
214+
OFFER DRAW
134215
</button>
216+
)}
217+
218+
{/* Resign Button - Smaller and Less Prominent */}
219+
<div className="flex justify-center">
135220
<button
136-
className={`flex-1 px-3 py-1 text-xs font-medium transition-all duration-200 ${
137-
simulateMaiaTime
138-
? 'bg-human-3 text-white'
139-
: 'bg-background-1 text-primary hover:bg-background-2'
221+
onClick={resign}
222+
disabled={!resign || !playerActive}
223+
className={`rounded px-3 py-1 text-xs font-medium transition-colors duration-200 ${
224+
resign && playerActive
225+
? 'text-red-400/80 hover:bg-red-500/5 hover:text-red-300'
226+
: 'cursor-not-allowed text-secondary/30'
140227
}`}
141-
onClick={() => setSimulateMaiaTime(true)}
142228
>
143-
Human-like
229+
Resign
144230
</button>
145231
</div>
146232
</div>
147-
)}
148-
149-
{offerDraw ? (
150-
<button
151-
onClick={offerDraw}
152-
disabled={!playerActive}
153-
className={`flex w-full justify-center rounded px-4 py-2 text-primary transition duration-200 ${
154-
playerActive
155-
? 'bg-engine-3 hover:bg-engine-4'
156-
: 'cursor-not-allowed bg-background-2 text-primary/50'
157-
}`}
158-
>
159-
<p className="font-medium uppercase tracking-wide">
160-
Offer draw
161-
</p>
162-
</button>
163-
) : null}
164-
<button
165-
onClick={resign}
166-
disabled={!resign || !playerActive}
167-
className={`flex w-full justify-center rounded px-4 py-1.5 text-primary transition duration-200 ${
168-
resign && playerActive
169-
? 'bg-human-3 hover:bg-human-4'
170-
: 'cursor-not-allowed bg-background-2 text-primary/50'
171-
}`}
172-
>
173-
<p className="text-sm font-medium">Resign</p>
174-
</button>
175-
</div>
233+
</div>
234+
</>
176235
)}
177236
</div>
178237
</div>

0 commit comments

Comments
 (0)