Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

Commit faeef51

Browse files
authored
fix(FocusZone): Respect defaultTabbable element when FocusZone container gets focus (#637)
* fix(FocusZone): Respect defaultTabbable element when FZ container receives focus * update FZ changelog * Update changelog
1 parent 7893354 commit faeef51

File tree

8 files changed

+29
-12
lines changed

8 files changed

+29
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
2323
### Fixes
2424
- Ensure `Popup` properly flips values of `offset` prop in RTL @kuzhelov ([#612](https://github.com/stardust-ui/react/pull/612))
2525
- Fix `List` - items should be selectable @sophieH29 ([#566](https://github.com/stardust-ui/react/pull/566))
26+
- Respect `defaultTabbable` element when `FocusZone` container gets focus ([#637](https://github.com/stardust-ui/react/pull/637))
2627

2728
### Features
2829
- Add `color` prop to `Text` component @Bugaa92 ([#597](https://github.com/stardust-ui/react/pull/597))

src/lib/accessibility/Behaviors/Menu/menuBehavior.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const menuBehavior: Accessibility = (props: any) => ({
2121
props: {
2222
isCircularNavigation: true,
2323
preventDefaultWhenHandled: true,
24-
shouldFocusFirstElementWhenReceivedFocus: true,
24+
shouldFocusInnerElementWhenReceivedFocus: true,
2525
direction: props.vertical ? FocusZoneDirection.vertical : FocusZoneDirection.horizontal,
2626
},
2727
},

src/lib/accessibility/Behaviors/Tab/tabListBehavior.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const tabListBehavior: Accessibility = (props: any) => ({
1616
props: {
1717
isCircularNavigation: false,
1818
preventDefaultWhenHandled: true,
19-
shouldFocusFirstElementWhenReceivedFocus: true,
19+
shouldFocusInnerElementWhenReceivedFocus: true,
2020
},
2121
},
2222
})

src/lib/accessibility/Behaviors/Toolbar/toolbarBehavior.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const toolbarBehavior: Accessibility = (props: any) => ({
1616
props: {
1717
isCircularNavigation: false,
1818
preventDefaultWhenHandled: true,
19-
shouldFocusFirstElementWhenReceivedFocus: true,
19+
shouldFocusInnerElementWhenReceivedFocus: true,
2020
},
2121
},
2222
})

src/lib/accessibility/FocusZone/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This is a list of changes made to this Stardust copy of FocusZone in comparison
77
- Remove unused prop `componentRef` ([#397](https://github.com/stardust-ui/react/pull/397))
88
- Fix `defaultTabbableElement` prop to be as a function ([#450](https://github.com/stardust-ui/react/pull/450))
99
- Remove role="presentation" @sophieH29 ([#530](https://github.com/stardust-ui/react/pull/530))
10+
- Respect `defaultTabbable` element when FocusZone container receives focus @sophieH29 ([#637](https://github.com/stardust-ui/react/pull/637))
1011

1112
### Features
1213
- Add embed mode for FocusZone and new Chat behavior ([#233](https://github.com/stardust-ui/react/pull/233))

src/lib/accessibility/FocusZone/FocusZone.tsx

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export class FocusZone extends React.Component<FocusZoneProps> implements IFocus
4747
direction: PropTypes.number,
4848
defaultTabbableElement: PropTypes.func,
4949
shouldFocusOnMount: PropTypes.bool,
50-
shouldFocusFirstElementWhenReceivedFocus: PropTypes.bool,
50+
shouldFocusInnerElementWhenReceivedFocus: PropTypes.bool,
5151
shouldHandleKeyDownCapture: PropTypes.bool,
5252
disabled: PropTypes.bool,
5353
as: customPropTypes.as,
@@ -262,7 +262,12 @@ export class FocusZone extends React.Component<FocusZoneProps> implements IFocus
262262
}
263263

264264
private _onFocus = (ev: React.FocusEvent<HTMLElement>): void => {
265-
const { onActiveElementChanged, stopFocusPropagation } = this.props
265+
const {
266+
onActiveElementChanged,
267+
stopFocusPropagation,
268+
shouldFocusInnerElementWhenReceivedFocus,
269+
defaultTabbableElement,
270+
} = this.props
266271

267272
if (this.isImmediateDescendantOfZone(ev.target as HTMLElement)) {
268273
this._activeElement = ev.target as HTMLElement
@@ -283,9 +288,18 @@ export class FocusZone extends React.Component<FocusZoneProps> implements IFocus
283288
onActiveElementChanged(this._activeElement as HTMLElement, ev)
284289
}
285290

286-
// If a first focusable element should be force focused when FocusZone container receives focus
287-
if (this.props.shouldFocusFirstElementWhenReceivedFocus && ev.target === this._root.current) {
288-
this.focus(true)
291+
// If an inner focusable element should be focused when FocusZone container receives focus
292+
if (shouldFocusInnerElementWhenReceivedFocus && ev.target === this._root.current) {
293+
const maybeElementToFocus =
294+
defaultTabbableElement && defaultTabbableElement(this._root.current)
295+
296+
// try to focus defaultTabbable element
297+
if (maybeElementToFocus && isElementTabbable(maybeElementToFocus)) {
298+
maybeElementToFocus.focus()
299+
} else {
300+
// force focus on first focusable element
301+
this.focus(true)
302+
}
289303
}
290304

291305
if (stopFocusPropagation) {

src/lib/accessibility/FocusZone/FocusZone.types.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,10 @@ export interface FocusZoneProps extends React.HTMLAttributes<HTMLElement | Focus
5454
shouldFocusOnMount?: boolean
5555

5656
/**
57-
* If a first focusable element should be force focused when FocusZone container receives focus.
57+
* If true, focus will go either to defaultTabbableElement if set or first focusable element inside FocusZone,
58+
* when FocusZone container receives focus.
5859
*/
59-
shouldFocusFirstElementWhenReceivedFocus?: boolean
60+
shouldFocusInnerElementWhenReceivedFocus?: boolean
6061

6162
/**
6263
* If global onKeyDownCapture should be handled and updating tab indexes.

test/specs/lib/FocusZone-test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,7 +1107,7 @@ describe('FocusZone', () => {
11071107
expect(buttonB.tabIndex).toBe(0)
11081108
})
11091109

1110-
it('should force focus to first focusable element when FocusZone container receives focus and shouldFocusFirstElementWhenReceivedFocus is set to "true"', () => {
1110+
it('should force focus to first focusable element when FocusZone container receives focus and shouldFocusInnerElementWhenReceivedFocus is set to "true"', () => {
11111111
const isInnerZoneKeystroke = (e: React.KeyboardEvent<HTMLElement>): boolean =>
11121112
keyboardKey.getCode(e) === keyboardKey.Enter
11131113
const isFocusableProperty = { [IS_FOCUSABLE_ATTRIBUTE]: true }
@@ -1122,7 +1122,7 @@ describe('FocusZone', () => {
11221122
<FocusZone
11231123
direction={FocusZoneDirection.horizontal}
11241124
id="b"
1125-
shouldFocusFirstElementWhenReceivedFocus={true}
1125+
shouldFocusInnerElementWhenReceivedFocus={true}
11261126
{...isFocusableProperty}
11271127
>
11281128
<button id="bsub">bsub</button>

0 commit comments

Comments
 (0)