Skip to content

feat: #10121 Implemented the Table Column Header Focus - #10369

Open
jsmitrah wants to merge 32 commits into
adobe:mainfrom
jsmitrah:feature/10121/table-column-header-focus-using-keyboard
Open

feat: #10121 Implemented the Table Column Header Focus#10369
jsmitrah wants to merge 32 commits into
adobe:mainfrom
jsmitrah:feature/10121/table-column-header-focus-using-keyboard

Conversation

@jsmitrah

Copy link
Copy Markdown

Closes #10121

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

  • Pass the props as initialFocus="columnheader" to the table.
  • Press the Tab button to focus the table column header.

🧢 Your Project:

@jsmitrah jsmitrah changed the title implemented the table column header focus. fix:#10121 Implemented the Table Column Header Focus Jul 28, 2026
@jsmitrah jsmitrah changed the title fix:#10121 Implemented the Table Column Header Focus Feature - Fix:#10121 Implemented the Table Column Header Focus Jul 28, 2026
Comment thread packages/react-aria/src/grid/useGrid.ts Outdated
Comment thread packages/react-aria/src/table/TableKeyboardDelegate.ts Outdated
Comment thread packages/@adobe/react-spectrum/test/table/TableTests.js Outdated
@jsmitrah
jsmitrah requested a review from snowystinger July 29, 2026 13:43
snowystinger
snowystinger previously approved these changes Jul 30, 2026

@snowystinger snowystinger left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, this looks pretty good. Will bring it to the team and see how we feel about the prop/name etc

@snowystinger snowystinger changed the title Feature - Fix:#10121 Implemented the Table Column Header Focus feat: #10121 Implemented the Table Column Header Focus Jul 30, 2026
@jsmitrah

Copy link
Copy Markdown
Author

Thanks @snowystinger, I'll wait for the team feedback

Comment thread packages/@adobe/react-spectrum/src/table/TableView.tsx
Comment thread packages/react-aria/src/table/TableKeyboardDelegate.ts
@snowystinger snowystinger added the waiting Waiting on Issue Author label Aug 10, 2026
@jsmitrah

Copy link
Copy Markdown
Author

@LFDanLu Thanks for the feedback. I have removed the prop and moved those tests into RAC.

@jsmitrah
jsmitrah requested a review from LFDanLu August 13, 2026 07:30

@snowystinger snowystinger left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

some minor cleanup

Comment thread packages/@adobe/react-spectrum/test/table/TableTests.js Outdated
Comment thread packages/@adobe/react-spectrum/test/table/TableTests.js Outdated
Comment thread packages/react-aria-components/test/Table.test.js Outdated
Comment thread packages/react-aria-components/test/Table.test.js Outdated
Comment thread packages/react-aria-components/test/Table.test.js Outdated
Comment thread packages/react-aria-components/test/Table.test.js Outdated
@jsmitrah

Copy link
Copy Markdown
Author

@snowystinger Cleaned up the code and made the suggested changes

@jsmitrah
jsmitrah requested a review from snowystinger August 17, 2026 07:11
@snowystinger snowystinger added ready for review and removed waiting Waiting on Issue Author labels Aug 17, 2026
Comment thread packages/react-aria/src/table/TableKeyboardDelegate.ts Outdated
@jsmitrah
jsmitrah requested a review from LFDanLu August 24, 2026 07:45
} else {
// If on the root, go to the item a page below the top. Otherwise a page below the current item.
let targetKey = keyboardDelegate.getFirstKey?.();
let targetKey = getFirstItemKey(keyboardDelegate, localState.state.collection);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is starting to worry me that we're making a breaking change

@jsmitrah jsmitrah Aug 25, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for the feedback. I looked into both points a bit more

I agree that we should avoid a breaking change! The reason I added getFirstItemKey is to make the DnD code use an actual item key. DnD expects drop target to be either item or root, so the column header returned by getFirstKey() shouldn't be passed to it, and this helper function will skip non-item nodes and find the first valid item instead.

So this supports columnheader as the initial focus for Tables without changing the shared APIs or passing an invalid key into the DnD logic.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Right, but the fact that this helper is needed means that we broke an assumption on how the function worked. So even though we didn't break the api contract, there was an implicit requirement. And it's one that typescript has trouble representing, so hard to see.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I have handled different approaches without breaking. This keeps the existing getFirstKey() behavior unchanged while allowing it to return the columnheader when explicitly requested during focus entry.

Comment thread packages/react-aria/src/table/TableKeyboardDelegate.ts Outdated
@jsmitrah
jsmitrah requested a review from snowystinger August 25, 2026 07:02
return node.type === 'cell' || node.type === 'rowheader' || node.type === 'column';
}

getFirstKey(fromKey?: Key, global?: boolean, initialFocus?: 'row' | 'columnheader'): Key | null {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@snowystinger and I have been discussing this a bit and would like to explore some different options. IMO, I think the "initialFocus" option is a bit unclear (just like how global is pretty unclear), maybe it would be good to either have the option declare intent (aka "interaction" where only the first drag and droppable table row key would be returned if "interaction=drag", and the first column would be returned for "interaction=navigation", naming TBD), or to borrow from

protected findPreviousKey(
fromKey?: Key,
pred?: (item: Node<T>) => boolean,
where the caller of this function can pass in a filter function so they can determine what kind nodes are "valid" for their use case. Open to other options, but ideally we'd make it generic AND non-breaking for other call sites that were assuming this would only return item type nodes

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Table: support configuring initial Tab focus target (e.g. first column header)

3 participants