How do I prompt for JavaScript that works with a keyboard?
Spell it out in the prompt, control by control: real button and link elements for anything clickable, which keys do what, where focus goes after an action, and that the focus outline stays visible. "Make it accessible" is too vague to check. Then put the mouse away and test the result with Tab, Enter, Space, Escape and the arrow keys.
Cite
CodeLifter Forum, "How do I prompt for JavaScript that works with a keyboard?", https://codelifter.com/forum/posts/how-do-i-prompt-for-javascript-that-works-with-a-keyboard/, accessed 2026-11-12.- CodeLifter editorsStaffStaff, CodeLifter ·
What "works with a keyboard" means
The baseline is WCAG success criterion 2.1.1. The W3C's Understanding 2.1.1: Keyboard states it as: all functionality of the content is operable through a keyboard interface, without specific timings for individual keystrokes, except where the function depends on the path of the user's movement. The same page is clear that dragging an object to a location does not count as path dependent, so a draggable box still needs a keyboard way to move it.
The page also lists the failure that one-line prompts tend to produce: using only pointing-device-specific event handlers for a function (failure F54). A
divwith a click listener is the usual example.Lines to put in the prompt
Each line below names an element, a key or a focus rule, so you can check it in the answer. The quoted lines come from the CodeLifter prompts, whose code the editors tested; the prompts themselves have not been run against a named assistant.
You want Prompt line Where it comes from Controls that reach the keyboard by default "Use real <button>elements for Previous and Next"Slideshow prompt A dialog that opens and closes from the keyboard "Put autofocus on a visible Close button, close the dialog when the backdrop is clicked, leave Escape to the browser" Image popup prompt Focus back where the user was "return focus to the thumbnail that opened it" Image popup prompt A custom widget that keys can move "Make it focusable with tabindex="0", give it an accessible name that mentions the arrow keys, and move it 10 pixels per arrow key press, or 50 with Shift, calling preventDefault only for the arrows" Draggable element prompt Links that still behave like links "leave clicks with any button other than the main one, and clicks with Ctrl, Cmd, Shift or Alt held, to the browser" Go back prompt Add two general lines to any interactive prompt:
- "Use
<button type="button">for every control that is not a link. Never put a click handler on adivorspan." - "Do not remove the focus outline. If you restyle it, use
:focus-visibleand keep it clearly visible."
The phrase "calling preventDefault only for the arrows" matters more than it looks. A key handler that calls
preventDefault()on every key also swallows Tab, and the user is stuck.Why native elements first
MDN's tabindex reference explains what you get for free: links with an
href, buttons, form fields andsummaryare focusable by default, and developers should not addtabindexto them unless they are changing that behaviour. It also warns against a common shortcut: making adivfocusable and using it as a button. Such components are not listed in the accessibility tree, so assistive technology cannot find or operate them.Two more rules from the same page are worth putting in a rules file:
- Only use
tabindex="0"ortabindex="-1". Positive values change the Tab order and make the page hard to navigate. - Never put
tabindexon a<dialog>.
Keep focus visible
Success criterion 2.4.7 asks that keyboard focus is visible in at least one mode of operation. The W3C's Understanding 2.4.7: Focus Visible lists styling outlines and borders so that the indicator disappears as a failure (F78), and lists CSS
:focus-visibleas a sufficient technique (C45). In generated CSS, look foroutline: noneoroutline: 0with nothing put back in its place.Where a prompt cannot fix it alone
Some patterns need more than keys. WCAG 2.5.7 says dragging must also be possible with a single pointer without dragging, and a keyboard equivalent alone does not meet it. The CodeLifter draggable element says openly that its code does not meet 2.5.7 by itself. If you need that, ask for it by name: "Add buttons or number inputs that move the element without dragging."
Test it in five minutes
- Click the address bar, then press Tab until focus enters your component. Every control should get a visible outline, in a sensible order.
- Press Shift+Tab to go back. Focus should move backwards through the same stops.
- Press Enter on links, and Enter and Space on buttons. Both keys should activate a button.
- Open any dialog. Focus should land inside it; Escape should close it and put focus back on the control that opened it.
- On custom widgets, try the arrow keys you asked for, with and without Shift.
- Tab past the component. If you cannot leave it with the keyboard, a handler is swallowing Tab.
If any step fails, quote the missing prompt line back to the assistant and ask for that change alone. The innerHTML thread covers the other check worth running on every answer, and the local models thread covers running these prompts on your own machine.
- "Use
Write something first.
Give people something to work with: at least 30 words on what happened and what you tried.
That is too long. Keep it under 6,000 characters.
Write the question as the title, 15 to 140 characters, no links.
Pick a category.
Add a name (2 to 40 characters, no links).
That email address does not look right.
That was quick. Read the thread, then try again.
The form expired. Reload the page and post again.
Something went wrong with the form. Reload and try again.
Please complete the check and post again.
Limit reached for now. Try again later.
This thread is closed to new replies.
This thread no longer accepts replies.
Something went wrong with the form. Reload and try again.
Post a reply or question first (name and email), then this browser can vote, edit and accept answers.
You cannot vote on your own post.
Only the author (within 30 days) or the forum team can do that.
That email already has an account. Use your sign-in link instead.
New accounts are paused for the moment. Try again later.
That was already posted.
2 answers
- CodeLifter editorsStaffStaff, CodeLifter ·
Does a div with role="button" work with the keyboard? Not by itself. MDN's button role page says adding
role="button"tells a screen reader the element is a button but provides none of the usual behaviour. On a native<button>, theclickevent fires for mouse clicks and when the user presses Space or Enter while it has focus. On any other element, the click event fires only for the pointer, even with the role set. To make adivorspanwork you have to addtabindex="0"so it can take focus, then akeydownhandler that runs the action on Enter and Space and ignores every other key. MDN nameskeydownand warns against the deprecatedkeypress. A toggle also needsaria-pressedkept in step by your script. That is three or four separate things an assistant can forget, and a mouse user will never notice any of them missing. MDN's own advice is to use<button>or<input type="button">instead. Put that in the prompt as one line: "Use a real<button type="button">; do not putrole="button"on another element." Then run the Tab, Enter and Space checks from the opening post. - CodeLifter editorsStaffStaff, CodeLifter ·
How do you keep keyboard focus inside a modal dialog? Use the native
<dialog>element opened withshowModal(), and the browser does most of the work. MDN's showModal() page says the dialog is shown in the top layer with a::backdrop, and the rest of the page becomes inert, meaning it cannot be focused or clicked while the dialog is open. You do not need a hand-written trap that cycles Tab between the first and last control. Both<dialog>andshowModal()have worked across browsers since March 2022. Three things are left for your prompt. Putautofocuson the control the user needs first, or on the Close button when nothing else needs immediate interaction, as MDN's dialog reference recommends. Keep a visible Close button in the Tab order, which the W3C's modal dialog pattern strongly recommends. And return focus to the element that opened the dialog when it closes, unless that element no longer exists. Escape closes a modal dialog without any code. If an assistant builds its own overlaydivwith a keydown trap, ask for<dialog>andshowModal()by name.