Skip to content

Commit 122d0c8

Browse files
authored
feat(RAC Breadcrumbs): add autoFocusCurrent to RAC Breadcrumbs (#6325)
1 parent 800f9a0 commit 122d0c8

File tree

3 files changed

+71
-12
lines changed

3 files changed

+71
-12
lines changed

packages/react-aria-components/src/Breadcrumbs.tsx

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ export interface BreadcrumbsProps<T> extends Omit<CollectionProps<T>, 'disabledK
2222
/** Whether the breadcrumbs are disabled. */
2323
isDisabled?: boolean,
2424
/** Handler that is called when a breadcrumb is clicked. */
25-
onAction?: (key: Key) => void
25+
onAction?: (key: Key) => void,
26+
/** Whether to autoFocus the last Breadcrumb item when the Breadcrumbs render. */
27+
autoFocusCurrent?: boolean
2628
}
2729

2830
export const BreadcrumbsContext = createContext<ContextValue<BreadcrumbsProps<any>, HTMLOListElement>>(null);
@@ -54,14 +56,18 @@ function BreadcrumbsInner<T extends object>({props, collection, breadcrumbsRef:
5456
slot={props.slot || undefined}
5557
style={props.style}
5658
className={props.className ?? 'react-aria-Breadcrumbs'}>
57-
{[...collection].map((node, i) => (
58-
<BreadcrumbItem
59-
key={node.key}
60-
node={node}
61-
isCurrent={i === collection.size - 1}
62-
isDisabled={props.isDisabled}
63-
onAction={props.onAction} />
64-
))}
59+
{[...collection].map((node, i) => {
60+
let isCurrent = i === collection.size - 1;
61+
return (
62+
<BreadcrumbItem
63+
key={node.key}
64+
node={node}
65+
isCurrent={isCurrent}
66+
isDisabled={props.isDisabled}
67+
onAction={props.onAction}
68+
autoFocus={props.autoFocusCurrent && isCurrent} />
69+
);
70+
})}
6571
</ol>
6672
);
6773
}
@@ -93,15 +99,17 @@ interface BreadcrumbItemProps {
9399
node: Node<object>,
94100
isCurrent: boolean,
95101
isDisabled?: boolean,
96-
onAction?: (key: Key) => void
102+
onAction?: (key: Key) => void,
103+
autoFocus?: boolean
97104
}
98105

99-
function BreadcrumbItem({node, isCurrent, isDisabled, onAction}: BreadcrumbItemProps) {
106+
function BreadcrumbItem({node, isCurrent, isDisabled, onAction, autoFocus}: BreadcrumbItemProps) {
100107
// Recreating useBreadcrumbItem because we want to use composition instead of having the link builtin.
101108
let linkProps = {
102109
'aria-current': isCurrent ? 'page' : null,
103110
isDisabled: isDisabled || isCurrent,
104-
onPress: () => onAction?.(node.key)
111+
onPress: () => onAction?.(node.key),
112+
autoFocus: autoFocus
105113
};
106114

107115
return (
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2022 Adobe. All rights reserved.
3+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License. You may obtain a copy
5+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under
8+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
* OF ANY KIND, either express or implied. See the License for the specific language
10+
* governing permissions and limitations under the License.
11+
*/
12+
13+
import {Breadcrumb, Breadcrumbs, Link} from 'react-aria-components';
14+
import React from 'react';
15+
16+
export default {
17+
title: 'React Aria Components',
18+
component: Breadcrumbs,
19+
argTypes: {
20+
autoFocusCurrent: {
21+
control: {type: 'boolean'}
22+
}
23+
}
24+
};
25+
26+
export const BreadcrumbsExample = (args: any) => (
27+
<Breadcrumbs {...args}>
28+
<Breadcrumb>
29+
<Link href="/">Home</Link>
30+
</Breadcrumb>
31+
<Breadcrumb>
32+
<Link href="/react-aria">React Aria</Link>
33+
</Breadcrumb>
34+
<Breadcrumb>
35+
<Link href="/react-aria">Breadcrumbs</Link>
36+
</Breadcrumb>
37+
</Breadcrumbs>
38+
);

packages/react-aria-components/test/Breadcrumbs.test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,17 @@ describe('Breadcrumbs', () => {
103103
let item = getByRole('listitem');
104104
expect(breadcrumbRef.current).toBe(item);
105105
});
106+
107+
it('should support autoFocusCurrent', () => {
108+
let {getAllByRole} = render(
109+
<Breadcrumbs autoFocusCurrent>
110+
<Breadcrumb><Link href="/">Home</Link></Breadcrumb>
111+
<Breadcrumb><Link href="/react-aria">React Aria</Link></Breadcrumb>
112+
<Breadcrumb><Link href="/react-aria">useBreadcrumbs</Link></Breadcrumb>
113+
</Breadcrumbs>
114+
);
115+
116+
let links = getAllByRole('link');
117+
expect(links[2]).toHaveFocus();
118+
});
106119
});

0 commit comments

Comments
 (0)