Skip to content

🎨 Palette: Replace native disabled with aria-disabled for editor save button - #630

Closed
seonghobae wants to merge 1 commit into
developfrom
jules-palette-editor-validation-aria-4426802201096243990
Closed

🎨 Palette: Replace native disabled with aria-disabled for editor save button#630
seonghobae wants to merge 1 commit into
developfrom
jules-palette-editor-validation-aria-4426802201096243990

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

💡 What

Replaced the native disabled attribute on the editor save button with aria-disabled="true" when form validation errors are present. Updated event listeners in app.js (submit and click) to intercept the save action and display a toast notification explaining why the action is blocked. Added new Playwright end-to-end tests that explicitly run in mobile resolution to verify these new behaviors.

🎯 Why

Native disabled attributes swallow DOM events (such as clicks) and prevent the element from receiving focus. This breaks keyboard accessibility because users tabbing through the page skip the element entirely. It also prevents the application from providing contextual feedback when a user interacts with the button. By using aria-disabled, the button remains focusable, and when the user tries to save an invalid form, they receive explicit feedback via a toast notification, which is especially helpful for mobile users and screen readers.

📸 Before/After

Before: Save button uses the disabled attribute, which silently swallows clicks and prevents focus.
After: Save button uses aria-disabled="true", remains focusable, and triggers a helpful toast notification ("입력값을 올바르게 수정해야 저장할 수 있습니다.") when clicked or submitted with invalid data.

♿ Accessibility

  • Improves keyboard accessibility by ensuring the "Save" button remains in the tab order.
  • Provides immediate, accessible feedback (via showToast()) explaining why the form cannot be submitted, rather than silently failing.

PR created automatically by Jules for task 4426802201096243990 started by @seonghobae


Devin Review

Replaces the native disabled attribute on the editor save button with
aria-disabled="true" to preserve keyboard focusability and interaction for
screen readers. The form and button click handlers have been updated
to intercept actions when the button is aria-disabled, showing a toast
message explaining that validation errors must be fixed first. Mobile UI
end-to-end tests were added to ensure proper coverage of these new edge cases.
@google-labs-jules

Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 58 minutes.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fe3450ef-489d-4935-9f7e-621890499ea2

📥 Commits

Reviewing files that changed from the base of the PR and between 2c32887 and 1fdc72d.

📒 Files selected for processing (4)
  • .jules/palette.md
  • app.js
  • tests/e2e/test-toast.spec.js
  • tests/e2e/test-validation.spec.js

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.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

Devin Review

Comment thread app.js
Comment on lines +387 to +390
const submitBtn = event.target.closest('button[type="submit"]');
if (submitBtn && submitBtn.getAttribute('aria-disabled') === 'true') {
event.preventDefault();
showToast(submitBtn.title || '입력값을 올바르게 수정해야 저장할 수 있습니다.');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Fresh corrections trigger false warning

After the last correction, submitBtn.getAttribute() can read stale debounced state and block a valid save. Users receive an incorrect validation warning.

Prompt for agents
The editor draft updates synchronously on input, but renderEditorValidation is debounced by 150 ms. Both the delegated click guard at app.js bindTableEvents and the submit guard decide from the button's aria-disabled attribute before flushing pending validation. A user who corrects the last error and immediately saves is blocked using stale state; the reverse transition can bypass the toast. Flush pending validation before either guard reads aria-disabled, or derive the guard directly from validateDraft(state.editor.draft, state.editor.depth), while preserving saveEditor as the final validation boundary.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Closing this lane as superseded by #468 after an exact semantic comparison against current develop@2c328875e00e86537df3e965170be80532571cad.

#630's aria-disabled direction is already implemented more defensibly in #468, which keeps the Save control focusable, binds it to #editor-errors, disables native constraint interception with form.noValidate, and—critically—keeps saveEditor() as the synchronous validation/persistence authority. The current #630 head 1fdc72d8b26434c9d68ed7cbe10cdee84722f147 instead treats the debounced presentation attribute as an enforcement gate in both click and submit handlers. Devin's current-head review reproduces the resulting race: a user can correct the last invalid value and immediately click Save while aria-disabled="true" is still stale, causing a false rejection/toast; the inverse stale transition can also misrepresent validity.

The mobile toast tests in #630 do not cover that immediate-correction race, while #468 already carries browser regressions for immediate valid click/Enter, immediate invalid submission, focus preservation, and accessible error description. The Jules palette note is implementation-process metadata rather than unique product behavior. No unique production behavior in #630 should be integrated ahead of #468's existing owner lane.

@seonghobae seonghobae closed this Aug 29, 2026
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.

1 participant