fix(cuesheet): align lazy cell placeholder with its editor

Two regressions from the lazy text-cell placeholders:
- single-line placeholders centered their text in the full (possibly tall)
  cell, so the text jumped upward when the top-aligned editor mounted. Keep
  the glyph in a 2rem band at the top (scoped to editable cells via a
  `topAligned` prop so the time/duration delay indicator is unaffected).
- multi-line placeholders only grew to their content height, so a short note
  in a row made tall by another column was not fully clickable. Use
  `min-height: 100%` so the placeholder fills the cell (and still grows with
  content, no clipping).

Verified by measuring text/editor positions: single-line jump ~0px; all text
placeholders fill the cell and the whole area is clickable. Cuesheet e2e (4/4).
This commit is contained in:
Claude
2026-06-21 06:19:29 +00:00
parent dd8cfef4de
commit 8b8885d0b7
3 changed files with 22 additions and 2 deletions
@@ -69,6 +69,7 @@ function EditableCell({ initialValue, multiline, fieldId, fieldLabel, handleUpda
onClick={enterEdit}
onFocus={enterEdit}
multiline={multiline}
topAligned
aria-label={fieldLabel ? `${fieldLabel} cell` : undefined}
>
{initialValue}
@@ -35,9 +35,16 @@
cursor: text;
}
// single-line placeholder: keep the glyph in a 2rem band at the top of the cell so it lines up
// with the editor (which mounts top-aligned) and does not jump when the cell is taller than 2rem
&.topAligned:not(.multiline) {
align-items: flex-start;
line-height: 2rem;
}
&.multiline {
height: auto;
min-height: 2rem;
min-height: 100%; // fill the cell so the whole area is clickable (grows with content)
text-wrap: wrap;
white-space: break-spaces;
overflow: hidden;
@@ -9,11 +9,22 @@ interface TextLikeInputProps extends HTMLAttributes<HTMLSpanElement> {
muted?: boolean;
disabled?: boolean;
multiline?: boolean;
/** keep the content at the top of the cell (matches an editor that mounts top-aligned) */
topAligned?: boolean;
}
const TextLikeInput = forwardRef(
(
{ offset, muted, disabled, multiline, children, className, ...elementProps }: PropsWithChildren<TextLikeInputProps>,
{
offset,
muted,
disabled,
multiline,
topAligned,
children,
className,
...elementProps
}: PropsWithChildren<TextLikeInputProps>,
textRef,
) => {
const ref = useRef<HTMLDivElement | null>(null);
@@ -23,6 +34,7 @@ const TextLikeInput = forwardRef(
muted && style.muted,
disabled && style.disabled,
multiline && style.multiline,
topAligned && style.topAligned,
className,
]);