This is a submission for DEV's Summer Bug Smash: Clear the Lineup powered by Sentry.
Project Overview
The Comfort Table is an interactive comfort-food editorial experience originally built for the DEV Frontend Challenge.
Visitors can discover comfort dishes through mood and moment, explore a global menu, and open detailed dish stories inside a custom modal.
The project uses semantic HTML, responsive CSS, vanilla JavaScript, visible focus states, aria-pressed, aria-live, reduced-motion support, and touch-friendly interactions.
Bug Fix or Performance Improvement
The bug was in the custom dish-details modal.
The component declared itself with role="dialog" and aria-modal="true", but its behavior did not fully satisfy what those semantics promised.
The visual modal worked, but the focus-management lifecycle was incomplete.
A robust modal needs to:
- move focus into the dialog when it opens
- keep
TabandShift+Tabinside the dialog - close with
Escape - restore focus to the element that opened it
- prevent interaction with the background while open
The root problem was treating ARIA semantics and modal behavior as separate concerns.
A dialog should not claim to be modal while still allowing its interaction model to behave like a normal page.
Code
The accessibility fix is documented in this commit:
62a7f04 — fix: harden modal accessibility
Repository:
github.com/pawansatoshi/the-comfort-table
Primary implementation:
The fixed modal lifecycle is:
Invoking button → Open modal → Move focus inside → Contain Tab / Shift+Tab → Escape or close → Restore focus → Return to invoking button
The implementation also makes the background inert while the dialog is active and keeps overlay and close behavior within the same lifecycle.
My Improvements
I approached the bug as an accessibility behavior problem rather than simply adding ARIA attributes.
1. Initial Focus
When the modal opens, focus is moved into the dialog instead of leaving the user somewhere behind the modal.
2. Focus Containment
Tab and Shift+Tab are handled so keyboard focus remains within the modal boundary.
3. Escape Handling
The dialog can be dismissed with Escape, providing a predictable keyboard exit.
4. Focus Restoration
When the modal closes, focus returns to the dish control that originally opened it.
This prevents keyboard users from losing their position in the page.
5. Background Inertness
The page behind the modal is treated as unavailable while the dialog is open.
This makes the implementation consistent with the declared aria-modal="true" behavior.
6. Regression Safety
The fix was designed around the existing UI rather than replacing the component with a new visual implementation.
The responsive layout, dish experience, and existing interaction design remain intact.
The key engineering principle was:
ARIA should describe real behavior, not replace it.
Verification
I manually verified the deployed application on mobile.
The following behaviors were checked:
- modal opens from the dish details control
- modal closes correctly
- overlay interaction behaves correctly
- repeated open and close cycles remain stable
- refresh does not leave the interface in a broken modal state
- responsive layout remains usable
The implementation also contains the keyboard lifecycle for Tab, Shift+Tab, Escape, and focus restoration.
I am deliberately not claiming an independently performed desktop keyboard pass because this submission was prepared from a mobile device.
Impact
This was a focused code fix with a meaningful accessibility impact.
Without proper focus management, a custom modal can be visually correct while still creating a confusing experience for keyboard and assistive-technology users.
The fix brings the component's actual interaction model closer to the semantics it already declared.
It also establishes a reusable pattern for future dialogs in the project:
semantic state + focus management + keyboard behavior + background isolation + focus restoration
Live Demo
https://the-comfort-table.vercel.app/
Repository
https://github.com/pawansatoshi/the-comfort-table
Accessibility Fix Commit
https://github.com/pawansatoshi/the-comfort-table/commit/62a7f04a88d798c0dc6221f7c647b344f84f221b
Supporting Documentation
https://github.com/pawansatoshi/the-comfort-table/blob/main/DEV-SUBMISSION.md
https://github.com/pawansatoshi/the-comfort-table/blob/main/README.md
Top comments (0)