Skip to content

chore: Revert "feat: focus loading indicator in rac tree (#8270)" #8336

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/@react-aria/selection/src/ListKeyboardDelegate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class ListKeyboardDelegate<T> implements KeyboardDelegate {
let nextKey = key;
while (nextKey != null) {
let item = this.collection.getItem(nextKey);
if (item?.type === 'loader' || (item?.type === 'item' && !this.isDisabled(item))) {
if (item?.type === 'item' && !this.isDisabled(item)) {
return nextKey;
}

Expand Down
1 change: 0 additions & 1 deletion packages/react-aria-components/example/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ html {
}
}

.tree-loader,
.tree-item {
padding: 4px 5px;
outline: none;
Expand Down
26 changes: 9 additions & 17 deletions packages/react-aria-components/src/Tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@ export const TreeItem = /*#__PURE__*/ createBranchComponent('item', <T extends o
);
});

export interface UNSTABLE_TreeLoadingIndicatorRenderProps extends Pick<TreeItemRenderProps, 'isFocused' | 'isFocusVisible'> {
export interface UNSTABLE_TreeLoadingIndicatorRenderProps {
/**
* What level the tree item has within the tree.
* @selector [data-level]
Expand All @@ -711,44 +711,36 @@ export interface TreeLoaderProps extends RenderProps<UNSTABLE_TreeLoadingIndicat

export const UNSTABLE_TreeLoadingIndicator = createLeafComponent('loader', function TreeLoader<T extends object>(props: TreeLoaderProps, ref: ForwardedRef<HTMLDivElement>, item: Node<T>) {
let state = useContext(TreeStateContext)!;
ref = useObjectRef<HTMLDivElement>(ref);
let {rowProps, gridCellProps, ...states} = useTreeItem({node: item}, state, ref);
// This loader row is is non-interactable, but we want the same aria props calculated as a typical row
// @ts-ignore
let {rowProps} = useTreeItem({node: item}, state, ref);
let level = rowProps['aria-level'] || 1;

let ariaProps = {
role: 'row',
'aria-level': rowProps['aria-level'],
'aria-posinset': rowProps['aria-posinset'],
'aria-setsize': rowProps['aria-setsize'],
tabIndex: rowProps.tabIndex
'aria-setsize': rowProps['aria-setsize']
};

let {isFocusVisible, focusProps} = useFocusRing();

let renderProps = useRenderProps({
...props,
id: undefined,
children: item.rendered,
defaultClassName: 'react-aria-TreeLoader',
values: {
level,
isFocused: states.isFocused,
isFocusVisible
level
}
});

return (
<>
<div
role="row"
ref={ref}
{...mergeProps(filterDOMProps(props as any), ariaProps, focusProps)}
{...mergeProps(filterDOMProps(props as any), ariaProps)}
{...renderProps}
data-key={rowProps['data-key']}
data-collection={rowProps['data-collection']}
data-focused={states.isFocused || undefined}
data-focus-visible={isFocusVisible || undefined}
data-level={level}>
<div {...gridCellProps}>
<div role="gridcell" aria-colindex={1}>
{renderProps.children}
</div>
</div>
Expand Down
6 changes: 1 addition & 5 deletions packages/react-aria-components/stories/Tree.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,7 @@ let rows = [

const MyTreeLoader = () => {
return (
<UNSTABLE_TreeLoadingIndicator
className={({isFocused, isFocusVisible}) => classNames(styles, 'tree-loader', {
focused: isFocused,
'focus-visible': isFocusVisible
})}>
<UNSTABLE_TreeLoadingIndicator>
{({level}) => {
let message = `Level ${level} loading spinner`;
if (level === 1) {
Expand Down
27 changes: 14 additions & 13 deletions packages/react-aria-components/test/Tree.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,7 @@ describe('Tree', () => {
expect(cell).toHaveAttribute('aria-colindex', '1');
});

it('should focus the load more row when using ArrowDown/ArrowUp', async () => {
it('should not focus the load more row when using ArrowDown/ArrowUp', async () => {
let {getAllByRole} = render(<LoadingMoreTree isLoading />);

let rows = getAllByRole('row');
Expand All @@ -1133,18 +1133,19 @@ describe('Tree', () => {

await user.tab();
expect(document.activeElement).toBe(rows[0]);
for (let i = 1; i < 8; i++) {
for (let i = 0; i < 5; i++) {
await user.keyboard('{ArrowDown}');
expect(document.activeElement).toBe(rows[i]);
}
expect(document.activeElement).toBe(rows[5]);

for (let i = 6; i >= 0; i--) {
await user.keyboard('{ArrowUp}');
expect(document.activeElement).toBe(rows[i]);
}
await user.keyboard('{ArrowDown}');
expect(document.activeElement).toBe(rows[7]);

await user.keyboard('{ArrowUp}');
expect(document.activeElement).toBe(rows[5]);
});

it('should focus the load more row when using End', async () => {
it('should not focus the load more row when using End', async () => {
let {getAllByRole} = render(<LoadingMoreTree isLoading />);

let rows = getAllByRole('row');
Expand All @@ -1154,14 +1155,14 @@ describe('Tree', () => {
await user.tab();
expect(document.activeElement).toBe(rows[0]);
await user.keyboard('{End}');
expect(document.activeElement).toBe(rows[21]);
expect(document.activeElement).toBe(rows[20]);

// Check that it didn't shift the focusedkey to the loader key even if DOM focus didn't shift to the loader
await user.keyboard('{ArrowUp}');
expect(document.activeElement).toBe(rows[20]);
expect(document.activeElement).toBe(rows[19]);
});

it('should focus the load more row when using PageDown', async () => {
it('should not focus the load more row when using PageDown', async () => {
let {getAllByRole} = render(<LoadingMoreTree isLoading />);

let rows = getAllByRole('row');
Expand All @@ -1171,11 +1172,11 @@ describe('Tree', () => {
await user.tab();
expect(document.activeElement).toBe(rows[0]);
await user.keyboard('{PageDown}');
expect(document.activeElement).toBe(rows[21]);
expect(document.activeElement).toBe(rows[20]);

// Check that it didn't shift the focusedkey to the loader key even if DOM focus didn't shift to the loader
await user.keyboard('{ArrowUp}');
expect(document.activeElement).toBe(rows[20]);
expect(document.activeElement).toBe(rows[19]);
});

it('should not render no results state and the loader at the same time', () => {
Expand Down