Skip to content

fix(cuesheet): prevent timer cells from submitting on tab-out or escape#2083

Open
cpvalente wants to merge 1 commit into
masterfrom
claude/fix-cuesheet-submit-events-4RAzR
Open

fix(cuesheet): prevent timer cells from submitting on tab-out or escape#2083
cpvalente wants to merge 1 commit into
masterfrom
claude/fix-cuesheet-submit-events-4RAzR

Conversation

@cpvalente
Copy link
Copy Markdown
Owner

Disable submit on cuesheet when tabbing through time fields
Pressing Escape should in no case submit a value

Tab-out and Escape on time inputs (start, end, duration) were triggering
a submit that destructively changed the timer strategy. Added isEscaping
and isTabbing guards to useReactiveTextInput; timer cells opt out of
tab-submit via submitOnTab=false and supply a handleTabCancel that exits
edit mode without stealing focus. E2e tests added first (TDD).

https://claude.ai/code/session_01LJnSMxNiMz8DWZ8eXH8krJ
@cpvalente cpvalente requested a review from Copilot May 9, 2026 20:19
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 9, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 73a7653f-0085-4ae8-a38e-47e431e5554c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/fix-cuesheet-submit-events-4RAzR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the cuesheet timer-cell editing behavior so that leaving a time field via Tab or Escape does not submit the in-progress value, aligning cuesheet keyboard navigation with expected spreadsheet-like interactions.

Changes:

  • Added a Playwright e2e regression test covering timer-cell Tab-out and Escape behavior.
  • Extended useReactiveTextInput with Tab/Escape tracking to avoid blur-driven submission in those cases.
  • Wired timer inputs (DurationInput, TimeInputDuration) through SingleLineCell to opt out of Tab-submit and to cancel cleanly on Tab-out.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
e2e/tests/features/202-cuesheet.spec.ts Adds e2e coverage ensuring timer cells don’t submit on Tab-out or Escape.
apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/TimeInput.tsx Disables Tab-submit for time inputs and exits edit mode on Tab-out without refocusing parent.
apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/DurationInput.tsx Disables Tab-submit for duration inputs and exits edit mode on Tab-out without refocusing parent.
apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/SingleLineCell.tsx Plumbs submitOnTab + handleTabCancel into the reactive input hook.
apps/client/src/common/components/input/text-input/useReactiveTextInput.tsx Implements Tab/Escape flags to prevent blur-triggered submits in those flows.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 160 to 175
return {
value: text,
onChange: (event: ChangeEvent) => handleChange((event.target as HTMLInputElement).value),
onBlur: (event: ChangeEvent) => {
if (isTabbing.current) {
isTabbing.current = false;
(options?.onTabCancel ?? options?.onCancelUpdate)?.();
return;
}
if (isEscaping.current) {
isEscaping.current = false;
return;
}
if (!isKeyboardSubmitting.current) {
handleSubmit((event.target as HTMLInputElement).value);
}
Copy link
Copy Markdown
Collaborator

@alex-Arc alex-Arc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small comment and sugestion that could make it so we don't have to type cast

setIsEditing(false);
setTimeout(() => textRef.current?.focusParentElement()); // Immediate timeout to ensure state change takes place first
};
const handleTabOut = useCallback(() => {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I there a reason for this to be a callback when handleFakeBlur is not

Comment on lines 4 to 9
interface UseReactiveTextInputReturn {
value: string;
onChange: (event: ChangeEvent) => void;
onBlur: (event: ChangeEvent) => void;
onKeyDown: (event: KeyboardEvent<HTMLElement>) => void;
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
interface UseReactiveTextInputReturn {
value: string;
onChange: (event: ChangeEvent<HTMLInputElement |HTMLTextAreaElement>) => void;
onBlur: (event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
onKeyDown: (event: KeyboardEvent<HTMLElement>) => void;
}

Comment on lines +150 to +154
// for cells that opt out of tab-submit, track tab-out without preventing navigation
if (event.key === 'Tab' && options?.submitOnTab === false) {
isTabbing.current = true;
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
onChange: (event) => handleChange(event.target.value),
onBlur: (event) => {
if (isTabbing.current) {
isTabbing.current = false;
(options?.onTabCancel ?? options?.onCancelUpdate)?.();
return;
}
if (isEscaping.current) {
isEscaping.current = false;
return;
}
if (!isKeyboardSubmitting.current) {
handleSubmit(event.target.value);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants