補上先攻勾選顯示並更新 README

This commit is contained in:
2026-04-16 16:49:02 +08:00
parent af7ebda9f4
commit b3809b5d4f
3 changed files with 73 additions and 2 deletions

View File

@@ -547,6 +547,7 @@
}
.serve-lane {
position: relative;
display: grid;
grid-template-columns: 32px auto 1fr;
align-items: center;
@@ -579,11 +580,29 @@
0 10px 18px rgba(8, 47, 73, 0.12);
}
.serve-lane-prompt {
background: rgba(255, 248, 232, 0.12);
box-shadow: inset 0 0 0 1px rgba(255, 236, 202, 0.12);
}
.serve-lane-arrow {
display: none;
}
.serve-lane small {
justify-self: end;
color: rgba(248, 244, 234, 0.72);
}
.serve-lane-prompt > span:nth-of-type(2) {
color: #f7ffbe;
font-weight: 800;
text-shadow:
0 0 12px rgba(235, 248, 164, 0.5),
0 0 22px rgba(235, 248, 164, 0.24);
animation: serve-label-pulse 0.9s ease-in-out infinite;
}
.serve-lane-locked {
box-shadow: inset 0 0 0 1px rgba(214, 225, 100, 0.42);
}
@@ -593,6 +612,39 @@
height: 24px;
border-radius: 4px;
background: linear-gradient(180deg, #fff8e8, #f0dfbd);
box-shadow: inset 0 0 0 1px rgba(195, 154, 88, 0.22);
}
.serve-lane-box-checked {
position: relative;
background: linear-gradient(180deg, #ebf8a4, #d6e164);
box-shadow:
inset 0 0 0 1px rgba(111, 128, 27, 0.26),
0 0 0 1px rgba(214, 225, 100, 0.14);
}
.serve-lane-box-checked::after {
content: '✓';
position: absolute;
inset: 0;
display: grid;
place-items: center;
font-size: 1rem;
font-weight: 800;
color: #38501f;
}
@keyframes serve-label-pulse {
0%,
100% {
transform: scale(1);
opacity: 0.82;
}
50% {
transform: scale(1.08);
opacity: 1;
}
}
.score-panel-surface {
@@ -1479,6 +1531,10 @@
padding: 4px 6px;
}
.serve-lane-arrow {
left: 52px;
}
.team-number {
width: 28px;
height: 28px;

View File

@@ -276,6 +276,7 @@ export function ScoreboardPage({
onSwapTeams={onSwapMatchup}
score={scoreState.scoreLeft}
serviceCourt={scoreState.serving === 'left' ? servingCourt : null}
showServingPrompt={scoreState.serving === null}
team={leftTeam}
teamSlot="top"
/>
@@ -303,6 +304,7 @@ export function ScoreboardPage({
onSwapTeams={onSwapMatchup}
score={scoreState.scoreRight}
serviceCourt={scoreState.serving === 'right' ? servingCourt : null}
showServingPrompt={scoreState.serving === null}
team={rightTeam}
teamSlot="bottom"
/>
@@ -379,6 +381,7 @@ type ScoreboardTeamPanelProps = {
onSwapTeams: () => void
score: number
serviceCourt: CourtSide | null
showServingPrompt: boolean
team: GroupTeam | null
teamSlot: 'top' | 'bottom'
}
@@ -395,6 +398,7 @@ function ScoreboardTeamPanel({
onSwapTeams,
score,
serviceCourt,
showServingPrompt,
team,
teamSlot,
}: ScoreboardTeamPanelProps) {
@@ -450,13 +454,22 @@ function ScoreboardTeamPanel({
const serveBar = (
<button
className={
currentServer && !canArrangeMatch ? 'serve-lane serve-lane-locked' : 'serve-lane'
currentServer && !canArrangeMatch
? 'serve-lane serve-lane-locked'
: showServingPrompt
? 'serve-lane serve-lane-prompt'
: 'serve-lane'
}
disabled={!canArrangeMatch || !team}
type="button"
onClick={onSetServing}
>
<span className="serve-lane-box" />
{showServingPrompt ? (
<span aria-hidden="true" className="serve-lane-arrow">
{teamSlot === 'top' ? '↓' : '↑'}
</span>
) : null}
<span className={currentServer ? 'serve-lane-box serve-lane-box-checked' : 'serve-lane-box'} />
<span></span>
{currentServer ? (
<small>