Skip to content

Commit 00a5b83

Browse files
ChengaDevclaude
andcommitted
Redesign shot clock page layout and UX
- Responsive 3-column grid layout with named areas (horn/display/clear, corr, start/reset14/reset24) - Horn button to play buzzer manually, aligned with Clear button - Buttons scale by breakpoint: 70px mobile / 100px tablet / 130px desktop - Seconds display scales by breakpoint with ghost digit alignment fix (inset: 0) - Compact 3-column mobile layout with portrait orientation banners (mobile + desktop) - Press-down active effect on all buttons - courtFilter theme property for light/dark mode SVG handling Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 0bb4417 commit 00a5b83

6 files changed

Lines changed: 361 additions & 62 deletions

File tree

src/components/Controls.tsx

Lines changed: 59 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,70 +9,95 @@ type ControlsProps = {
99
on14SecondsClick: () => void;
1010
on24SecondsClick: () => void;
1111
toggleDisplay: () => void;
12+
layout?: 'all' | 'clearOnly' | 'actionsOnly' | 'startOnly' | 'reset14Only' | 'reset24Only';
1213
};
1314

1415
function Buttons(props: ControlsProps) {
1516
const { locals } = useLocalization();
17+
const layout = props.layout ?? 'all';
18+
19+
const showStart = layout === 'all' || layout === 'actionsOnly' || layout === 'startOnly';
20+
const showReset14 = layout === 'all' || layout === 'actionsOnly' || layout === 'reset14Only';
21+
const showReset24 = layout === 'all' || layout === 'actionsOnly' || layout === 'reset24Only';
22+
const showClear = layout === 'all' || layout === 'clearOnly';
1623

1724
return (
18-
<Container>
19-
<TimeToggleButton id='btnStart' onClick={props.onTickToggle} $isCurrentlyTicking={props.isTicking}>
20-
{props.isTicking ? locals.stopLabel : locals.startLabel}
21-
</TimeToggleButton>
22-
<ResetButton id='btnReset14' onClick={props.on14SecondsClick}>
23-
<div>{locals.resetButtonText}</div>
24-
<div>14s</div>
25-
</ResetButton>
26-
<ResetButton id='btnReset24' onClick={props.on24SecondsClick}>
27-
<div>{locals.resetButtonText}</div>
28-
<div>{locals.possessionLabel}</div>
29-
</ResetButton>
30-
<ClockButton id='btnToggleDisplay' onClick={props.toggleDisplay}>
31-
{locals.removeDisplayLabel}
32-
</ClockButton>
25+
<Container $layout={layout}>
26+
{showStart && (
27+
<TimeToggleButton id='btnStart' onClick={props.onTickToggle} $isCurrentlyTicking={props.isTicking}>
28+
{props.isTicking ? locals.stopLabel : locals.startLabel}
29+
</TimeToggleButton>
30+
)}
31+
{showReset14 && (
32+
<ResetButton id='btnReset14' onClick={props.on14SecondsClick}>
33+
<div>{locals.resetButtonText}</div>
34+
<div>14s</div>
35+
</ResetButton>
36+
)}
37+
{showClear && (
38+
<ClockButton id='btnToggleDisplay' onClick={props.toggleDisplay}>
39+
{locals.removeDisplayLabel}
40+
</ClockButton>
41+
)}
42+
{showReset24 && (
43+
<ResetButton id='btnReset24' onClick={props.on24SecondsClick}>
44+
<div>{locals.resetButtonText}</div>
45+
<div>{locals.possessionLabel}</div>
46+
</ResetButton>
47+
)}
3348
</Container>
3449
);
3550
}
3651

37-
const Container = styled.div`
52+
const Container = styled.div<{ $layout: string }>`
3853
display: flex;
3954
flex-direction: row;
40-
justify-content: space-between;
41-
max-width: 65%;
42-
margin: 0 auto;
43-
margin-bottom: 50px;
55+
justify-content: center;
56+
align-items: center;
57+
gap: 100px;
58+
margin-bottom: ${(props) => props.$layout === 'all' ? '50px' : '0'};
4459
4560
@media ${(props) => props.theme.mediaQueries.mobile} {
4661
flex-direction: column;
47-
48-
#btnToggleDisplay {
49-
margin-bottom: 0;
50-
}
62+
margin-bottom: ${(props) => props.$layout === 'all' ? '20px' : '0'};
5163
}
5264
`;
5365

5466
const ClockButton = styled.button`
55-
font-size: 17px;
56-
height: 100px;
57-
min-width: 100px;
67+
font-size: 14px;
68+
height: 80px;
69+
width: 80px;
5870
padding: 10px;
5971
border: 4px solid ${(props) => props.theme.colors.white};
6072
background: ${(props) => props.theme.defaulButtonBackground};
6173
outline: none;
6274
border-radius: 20px;
6375
cursor: pointer;
6476
font-weight: bold;
77+
transition: transform 0.08s ease, box-shadow 0.08s ease;
78+
79+
&:active {
80+
transform: scale(0.92) translateY(2px);
81+
box-shadow: inset 0 3px 6px rgba(0, 0, 0, 0.35);
82+
}
83+
84+
@media ${'(min-width: 768px)'} {
85+
font-size: 16px;
86+
height: 100px;
87+
width: 100px;
88+
}
6589
6690
@media ${'(min-width: 1200px)'} {
67-
width: 130px;
91+
font-size: 18px;
6892
height: 130px;
93+
width: 130px;
6994
}
7095
7196
@media ${(props) => props.theme.mediaQueries.mobile} {
72-
font-size: 16px;
97+
font-size: 13px;
7398
margin: 0 auto;
74-
height: 80px;
75-
margin-bottom: 20px;
99+
height: 70px;
100+
width: 70px;
76101
}
77102
`;
78103

@@ -92,8 +117,9 @@ const ResetButton = styled(ClockButton)`
92117
font-weight: bold;
93118
94119
@media ${(props) => props.theme.mediaQueries.mobile} {
95-
height: 80px;
96-
font-size: 16px;
120+
height: 70px;
121+
width: 70px;
122+
font-size: 13px;
97123
}
98124
`;
99125

src/components/Correction.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ const AdjustButton = styled.button`
5151
display: flex;
5252
align-items: center;
5353
justify-content: center;
54+
transition: transform 0.08s ease;
55+
56+
&:active {
57+
transform: scale(0.8) translateY(2px);
58+
}
5459
`
5560

5661
const CorrectionSign = styled.span`

0 commit comments

Comments
 (0)