fix: the stop button overlapped the recording counter
Two absolutely-positioned boxes at guessed offsets: right-14 and right-2. They collided as soon as the counter passed a minute and the text grew — a layout that only looked right for the first 60 seconds, and did not even manage that at this font size. One flex row with a gap, so spacing is a consequence of the content rather than an arithmetic guess about it. The callsign field also gains right padding while the badges are shown, so a long call runs under them instead of being typed over.
This commit is contained in:
+11
-5
@@ -3735,7 +3735,7 @@ export default function App() {
|
|||||||
recording. Both sit where the counter is, which has shifted left to
|
recording. Both sit where the counter is, which has shifted left to
|
||||||
make room. */}
|
make room. */}
|
||||||
{recording && recStopped && RECORDABLE_MODES.has(mode.toUpperCase()) && (
|
{recording && recStopped && RECORDABLE_MODES.has(mode.toUpperCase()) && (
|
||||||
<span className="absolute right-2 top-1/2 -translate-y-1/2 z-10 inline-flex items-center gap-1">
|
<span className="absolute right-2 top-1/2 -translate-y-1/2 z-10 inline-flex items-center gap-1.5">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onMouseDown={(e) => e.preventDefault()}
|
onMouseDown={(e) => e.preventDefault()}
|
||||||
@@ -3759,28 +3759,31 @@ export default function App() {
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
{/* Stop and the running counter share ONE flex row. They were two absolute
|
||||||
|
boxes at guessed offsets and overlapped as soon as the counter passed a
|
||||||
|
minute — a layout that only looked right for the first 60 seconds. */}
|
||||||
{recording && !recStopped && RECORDABLE_MODES.has(mode.toUpperCase()) && (
|
{recording && !recStopped && RECORDABLE_MODES.has(mode.toUpperCase()) && (
|
||||||
|
<span className="absolute right-2 top-1/2 -translate-y-1/2 z-10 inline-flex items-center gap-1.5">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onMouseDown={(e) => e.preventDefault()}
|
onMouseDown={(e) => e.preventDefault()}
|
||||||
onClick={(e) => { e.stopPropagation(); stopRecording(); }}
|
onClick={(e) => { e.stopPropagation(); stopRecording(); }}
|
||||||
title={t('rec.stop')}
|
title={t('rec.stop')}
|
||||||
className="absolute right-14 top-1/2 -translate-y-1/2 z-10 inline-flex items-center justify-center size-4 rounded text-muted-foreground hover:bg-muted"
|
className="inline-flex items-center justify-center size-4 rounded text-muted-foreground hover:bg-muted"
|
||||||
>
|
>
|
||||||
<span className="size-2 bg-current" />
|
<span className="size-2 bg-current" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
|
||||||
{recording && !recStopped && RECORDABLE_MODES.has(mode.toUpperCase()) && (
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onMouseDown={(e) => e.preventDefault()}
|
onMouseDown={(e) => e.preventDefault()}
|
||||||
onClick={resetRecordingClock}
|
onClick={resetRecordingClock}
|
||||||
title="Click to restart the recording from 0 — drops everything captured so far (incl. pre-roll) so the file holds only your exchange"
|
title="Click to restart the recording from 0 — drops everything captured so far (incl. pre-roll) so the file holds only your exchange"
|
||||||
className="absolute right-2 top-1/2 -translate-y-1/2 z-10 inline-flex items-center gap-1 text-[10px] font-semibold tabular-nums text-destructive whitespace-nowrap cursor-pointer rounded px-1 hover:bg-destructive-muted"
|
className="inline-flex items-center gap-1 text-[10px] font-semibold tabular-nums text-destructive whitespace-nowrap cursor-pointer rounded px-1 hover:bg-destructive-muted"
|
||||||
>
|
>
|
||||||
<span className="size-2 rounded-full bg-destructive animate-pulse" />
|
<span className="size-2 rounded-full bg-destructive animate-pulse" />
|
||||||
{String(Math.floor(recSeconds / 60)).padStart(2, '0')}:{String(recSeconds % 60).padStart(2, '0')}
|
{String(Math.floor(recSeconds / 60)).padStart(2, '0')}:{String(recSeconds % 60).padStart(2, '0')}
|
||||||
</button>
|
</button>
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
<Input
|
<Input
|
||||||
ref={callsignRef}
|
ref={callsignRef}
|
||||||
@@ -3789,7 +3792,10 @@ export default function App() {
|
|||||||
// exactly the same. A primary-tinted border plus an inset left bar make
|
// exactly the same. A primary-tinted border plus an inset left bar make
|
||||||
// it the obvious one without adding a colour the theme doesn't own. The
|
// it the obvious one without adding a colour the theme doesn't own. The
|
||||||
// contest-dupe state still overrides it — that one is a warning.
|
// contest-dupe state still overrides it — that one is a warning.
|
||||||
|
// Room on the right for the REC badges while they are shown, so a long
|
||||||
|
// callsign runs under them instead of being typed over.
|
||||||
className={cn('font-mono text-base font-bold tracking-wider uppercase h-9 bg-muted/40 focus:bg-card',
|
className={cn('font-mono text-base font-bold tracking-wider uppercase h-9 bg-muted/40 focus:bg-card',
|
||||||
|
recording && RECORDABLE_MODES.has(mode.toUpperCase()) && 'pr-24',
|
||||||
'border-primary/45 shadow-[inset_3px_0_0_0_var(--primary)]',
|
'border-primary/45 shadow-[inset_3px_0_0_0_var(--primary)]',
|
||||||
contest.active && contestDupe && 'ring-2 ring-destructive !bg-destructive-muted focus:!bg-destructive-muted text-destructive-muted-foreground shadow-none')}
|
contest.active && contestDupe && 'ring-2 ring-destructive !bg-destructive-muted focus:!bg-destructive-muted text-destructive-muted-foreground shadow-none')}
|
||||||
value={callsign}
|
value={callsign}
|
||||||
|
|||||||
Reference in New Issue
Block a user