Skip to content

Fix Dataframe whole-table keyboard focus - #13633

Draft
abidlabs wants to merge 1 commit into
mainfrom
fix/issue-11735-focus-is-landing-on-the-whole-table-unnecessaril
Draft

Fix Dataframe whole-table keyboard focus#13633
abidlabs wants to merge 1 commit into
mainfrom
fix/issue-11735-focus-is-landing-on-the-whole-table-unnecessaril

Conversation

@abidlabs

Copy link
Copy Markdown
Member

Description

This removes the Dataframe's whole-table containers from the normal keyboard Tab sequence while preserving programmatic grid focus and individual cell focus. It also prevents the disabled-click upload wrapper used by Dataframe from becoming a separate Tab stop and adds regression coverage for the resulting focus targets.

Closes: #11735

AI Disclosure

  • I used AI to investigate the focus behavior, draft the implementation and test, and prepare this PR description. I reviewed every changed line and ran the verification listed below.
  • I did not use AI

🎯 PRs Should Target Issues

This PR targets #11735. I checked open PRs by issue number and focus-related wording before opening this PR and found no overlapping work.

Testing and Formatting Your Code

  • CI=1 npx vitest run --config .config/vitest.config.ts js/dataframe/Dataframe.test.ts — 51 passed, 2 todo.
  • pnpm build — passed.
  • bash scripts/format_frontend.sh — formatting completed; the repository-wide svelte-check step reported 15 errors outside the touched files (existing utility, Prism declaration, and preview/Rollup typing errors).
  • Rebuilt and manually verified the local demo: Dataframe grid/upload containers have tabIndex = -1, while the individual Alice cell remains at tabIndex = 0.

The reproduction demo was kept untracked and is not part of this PR:

import gradio as gr


def filter_records(records: list[list[str]], gender: str) -> list[list[str]]:
    return [record for record in records if record[2] == gender]


demo = gr.Interface(
    filter_records,
    [
        gr.Dataframe(
            headers=["name", "age", "gender"],
            datatype=["str", "number", "str"],
            value=[
                ["Alice", 30, "F"],
                ["Bob", 25, "M"],
                ["Casey", 28, "O"],
            ],
            row_count=3,
            column_count=(3, "fixed"),
        ),
        gr.Dropdown(["M", "F", "O"], label="Gender"),
    ],
    "dataframe",
    description="Tab through the controls and inspect which Dataframe element receives focus.",
)

if __name__ == "__main__":
    demo.launch()

@gradio-pr-bot

gradio-pr-bot commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator

🪼 branch checks and previews

Name Status URL
Spaces ready! Spaces preview
Storybook ready! Storybook preview
🦄 Changes failed! Workflow log

Install Gradio from this PR

pip install https://huggingface.co/buckets/gradio/pypi-previews/resolve/0dd91c133b4325112e265bb0625be5c11d458f8f/gradio-6.20.0-py3-none-any.whl

Install Gradio Python Client from this PR

pip install "gradio-client @ git+https://github.com/gradio-app/gradio@0dd91c133b4325112e265bb0625be5c11d458f8f#subdirectory=client/python"

Import Gradio JS Client from this PR via CDN

import { Client } from "https://huggingface.co/buckets/gradio/npm-previews/resolve/0dd91c133b4325112e265bb0625be5c11d458f8f/browser.js";

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 improves keyboard accessibility of the Dataframe component by removing whole-table “grid container” elements (and the Dataframe upload wrapper) from the normal Tab sequence, while keeping programmatic focus and individual cell focus intact. It also adds regression coverage to ensure the intended focus targets remain correct.

Changes:

  • Make the Dataframe grid container(s) non-tabbable by changing the grid wrapper’s tabindex to -1.
  • Prevent Upload instances with disable_click from becoming Tab stops by setting tabindex=-1 in that state.
  • Add/extend Dataframe unit tests to assert expected tabIndex/tabindex values for the grid containers, upload drop target, and an individual cell.

Reviewed changes

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

File Description
js/upload/src/Upload.svelte Removes Upload from the Tab sequence when disable_click is enabled.
js/dataframe/shared/Table.svelte Removes the grid wrapper from the Tab sequence (tabindex=-1) to avoid whole-table focus stops.
js/dataframe/Dataframe.test.ts Adds regression assertions for focus/tabIndex targets and shared-prop coverage setup.
.changeset/fuzzy-tables-focus.md Records a patch-level change for the affected packages.

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

describe("Dataframe rendering", () => {
afterEach(() => cleanup());

test("tabbing skips dataframe containers and reaches individual cells", async () => {
@abidlabs

Copy link
Copy Markdown
Member Author

Upon testing on a Windows device, this didn't fix the issue and seems to have broken the UI/ layout

image

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.

Focus is landing on the whole table unnecessarily in Windows.

3 participants