From 1054b89bc3a1971a293f945bfe96822ab1d248d4 Mon Sep 17 00:00:00 2001 From: Ben Worline Date: Wed, 16 May 2018 15:35:59 -0700 Subject: [PATCH 01/11] added support for remembering last focused item in a FTZ and restoring it when the FTZ gets focus. --- .../FocusTrapZone/FocusTrapZone.test.tsx | 97 ++++++++++++++++++- .../FocusTrapZone/FocusTrapZone.tsx | 60 +++++++++--- .../FocusTrapZone/FocusTrapZone.types.ts | 35 +++++-- 3 files changed, 164 insertions(+), 28 deletions(-) diff --git a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.test.tsx b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.test.tsx index ce617e2f6437a..30f894ea4a400 100644 --- a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.test.tsx +++ b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.test.tsx @@ -1,17 +1,18 @@ import * as React from 'react'; - import * as ReactDOM from 'react-dom'; import * as ReactTestUtils from 'react-dom/test-utils'; -import { KeyCodes } from '../../Utilities'; - +import { KeyCodes, createRef } from '../../Utilities'; import { FocusZone, FocusZoneDirection } from '../FocusZone'; import { FocusTrapZone } from './FocusTrapZone'; +import { FocusTransferRule } from './FocusTrapZone.types'; // rAF does not exist in node - let's mock it window.requestAnimationFrame = (callback: FrameRequestCallback) => { - return window.setTimeout(callback, 16); + const r = window.setTimeout(callback, 16); + jest.runAllTimers(); + return r; }; - +const animationFrame = () => new Promise(resolve => window.requestAnimationFrame(resolve)); jest.useFakeTimers(); describe('FocusTrapZone', () => { @@ -260,4 +261,90 @@ describe('FocusTrapZone', () => { jest.runAllTimers(); }); + + describe('Focusing the FTZ', () => { + function setupTest(rule: FocusTransferRule) { + const focusTrapZoneRef = createRef(); + const topLevelDiv = ReactTestUtils.renderIntoDocument( +
+ + + + + + + + +
+ ) as HTMLElement; + + const focusTrapZone = ReactDOM.findDOMNode(focusTrapZoneRef.current!) as Element; + const buttonF = topLevelDiv.querySelector('.f') as HTMLElement; + const buttonA = topLevelDiv.querySelector('.a') as HTMLElement; + const buttonB = topLevelDiv.querySelector('.b') as HTMLElement; + const buttonZ = topLevelDiv.querySelector('.z') as HTMLElement; + + // Assign bounding locations to buttons. + setupElement(buttonF, { clientRect: { top: 0, bottom: 10, left: 0, right: 10 } }); + setupElement(buttonA, { clientRect: { top: 10, bottom: 20, left: 0, right: 10 } }); + setupElement(buttonB, { clientRect: { top: 20, bottom: 30, left: 0, right: 10 } }); + setupElement(buttonZ, { clientRect: { top: 30, bottom: 40, left: 0, right: 10 } }); + + return { focusTrapZone, buttonF, buttonA, buttonB, buttonZ }; + } + + it('goes to previously focused element when focusing the FTZ', async () => { + expect.assertions(4); + + const { focusTrapZone, buttonF, buttonB, buttonZ } = setupTest(FocusTransferRule.previouslyFocusedElement); + + // Manually focusing FTZ when FTZ has never + // had focus within should go to 1st focusable inner element. + ReactTestUtils.Simulate.focus(focusTrapZone); + await animationFrame(); + expect(lastFocusedElement).toBe(buttonF); + + // Focus inside the trap zone, not the first element. + ReactTestUtils.Simulate.focus(buttonB); + await animationFrame(); + expect(lastFocusedElement).toBe(buttonB); + + // Focus outside the trap zone + ReactTestUtils.Simulate.focus(buttonZ); + await animationFrame(); + expect(lastFocusedElement).toBe(buttonZ); + + // Manually focusing FTZ should return to originally focused inner element. + ReactTestUtils.Simulate.focus(focusTrapZone); + await animationFrame(); + expect(lastFocusedElement).toBe(buttonB); + }); + + it('goes to first focusable element when focusing the FTZ', async () => { + expect.assertions(4); + + const { focusTrapZone, buttonF, buttonB, buttonZ } = setupTest(FocusTransferRule.firstFocusable); + + // Manually focusing FTZ when FTZ has never + // had focus within should go to 1st focusable inner element. + ReactTestUtils.Simulate.focus(focusTrapZone); + await animationFrame(); + expect(lastFocusedElement).toBe(buttonF); + + // Focus inside the trap zone, not the first element. + ReactTestUtils.Simulate.focus(buttonB); + await animationFrame(); + expect(lastFocusedElement).toBe(buttonB); + + // Focus outside the trap zone + ReactTestUtils.Simulate.focus(buttonZ); + await animationFrame(); + expect(lastFocusedElement).toBe(buttonZ); + + // Manually focusing FTZ should go to the first focusable element. + ReactTestUtils.Simulate.focus(focusTrapZone); + await animationFrame(); + expect(lastFocusedElement).toBe(buttonF); + }); + }); }); diff --git a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx index debd0e6ae5088..0bf7452043866 100644 --- a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx +++ b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx @@ -11,7 +11,7 @@ import { focusAsync, createRef } from '../../Utilities'; -import { IFocusTrapZone, IFocusTrapZoneProps } from './FocusTrapZone.types'; +import { IFocusTrapZone, IFocusTrapZoneProps, FocusTransferRule } from './FocusTrapZone.types'; export class FocusTrapZone extends BaseComponent implements IFocusTrapZone { @@ -19,7 +19,8 @@ export class FocusTrapZone extends BaseComponent implem private static _clickStack: FocusTrapZone[] = []; private _root = createRef(); - private _previouslyFocusedElement: HTMLElement; + private _previouslyFocusedElementOutsideTrapZone: HTMLElement; + private _previouslyFocusedElementInTrapZone?: HTMLElement; private _isInFocusStack = false; private _isInClickStack = false; @@ -38,8 +39,8 @@ export class FocusTrapZone extends BaseComponent implem public componentDidMount(): void { const { isClickableOutsideFocusTrap = false, forceFocusInsideTrap = true, elementToFocusOnDismiss, disableFirstFocus = false } = this.props; - this._previouslyFocusedElement = elementToFocusOnDismiss ? elementToFocusOnDismiss : document.activeElement as HTMLElement; - if (!elementContains(this._root.current, this._previouslyFocusedElement) && !disableFirstFocus) { + this._previouslyFocusedElementOutsideTrapZone = elementToFocusOnDismiss ? elementToFocusOnDismiss : document.activeElement as HTMLElement; + if (!elementContains(this._root.current, this._previouslyFocusedElementOutsideTrapZone) && !disableFirstFocus) { this.focus(); } @@ -54,8 +55,8 @@ export class FocusTrapZone extends BaseComponent implem public componentWillReceiveProps(nextProps: IFocusTrapZoneProps): void { const { elementToFocusOnDismiss } = nextProps; - if (elementToFocusOnDismiss && this._previouslyFocusedElement !== elementToFocusOnDismiss) { - this._previouslyFocusedElement = elementToFocusOnDismiss; + if (elementToFocusOnDismiss && this._previouslyFocusedElementOutsideTrapZone !== elementToFocusOnDismiss) { + this._previouslyFocusedElementOutsideTrapZone = elementToFocusOnDismiss; } } @@ -77,10 +78,10 @@ export class FocusTrapZone extends BaseComponent implem const activeElement = document.activeElement as HTMLElement; if (!ignoreExternalFocusing && - this._previouslyFocusedElement && - typeof this._previouslyFocusedElement.focus === 'function' && + this._previouslyFocusedElementOutsideTrapZone && + typeof this._previouslyFocusedElementOutsideTrapZone.focus === 'function' && (elementContains(this._root.value, activeElement) || activeElement === document.body)) { - focusAsync(this._previouslyFocusedElement); + focusAsync(this._previouslyFocusedElementOutsideTrapZone); } } @@ -95,20 +96,28 @@ export class FocusTrapZone extends BaseComponent implem ref={ this._root } aria-labelledby={ ariaLabelledBy } onKeyDown={ this._onKeyboardHandler } + onFocusCapture={ this._onFocusCapture } > { this.props.children } ); } - /** - * Need to expose this method in case of popups since focus needs to be set when popup is opened - */ public focus() { - const { firstFocusableSelector } = this.props; - const focusSelector = typeof firstFocusableSelector === 'string' - ? firstFocusableSelector - : firstFocusableSelector && firstFocusableSelector(); + const { focusTransferRule = FocusTransferRule.firstFocusable, firstFocusableSelector } = this.props; + + if ( + focusTransferRule === FocusTransferRule.previouslyFocusedElement && + this._previouslyFocusedElementInTrapZone && + elementContains(this._root.value, this._previouslyFocusedElementInTrapZone) + ) { + // focus on the last item that had focus in the zone before we left the zone + focusAsync(this._previouslyFocusedElementInTrapZone); + return; + } + + const focusSelector = + typeof firstFocusableSelector === 'string' ? firstFocusableSelector : firstFocusableSelector && firstFocusableSelector(); let _firstFocusableChild; @@ -124,6 +133,25 @@ export class FocusTrapZone extends BaseComponent implem } } + private _onFocusCapture = (ev: React.FocusEvent) => { + if (this.props.onFocusCapture) { + this.props.onFocusCapture(ev); + } + + if (ev.target === ev.currentTarget) { + // If the trap zone gets focus, pass on focus to either first focusable + // child element or the last focused element when this zone last had + // a focused child (depending on a prop). + this.focus(); + ev.preventDefault(); + ev.stopPropagation(); + } else { + // every time focus changes within the trap zone, remember the focused element so that + // it can be restored if focus leaves the pane and returns via keystroke (i.e. via a call to this.focus(true)) + this._previouslyFocusedElementInTrapZone = ev.target as HTMLElement; + } + } + private _onKeyboardHandler = (ev: React.KeyboardEvent): void => { if (this.props.onKeyDown) { this.props.onKeyDown(ev); diff --git a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts index 5ef3c478173da..c9cf36f0fd5e3 100644 --- a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts +++ b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts @@ -1,9 +1,22 @@ import * as React from 'react'; +/** + * Algorithm used to determine which descendant element to focus when the FocusTrapZone is focused. + */ +export const enum FocusTransferRule { + /** Locate and focus the first focusable descendant, filtered by the firstFocusableSelector property if present. */ + firstFocusable = 0, + /** + * Go to the element that was focused when this FocusTrapZone last had a focused descendant. + * If it has never had a focused descendant before, behavior falls back to FirstFocusable. + */ + previouslyFocusedElement = 1 +} + export interface IFocusTrapZone { /** - * Sets focus on the first focusable, or configured, child in focus trap zone - */ + * Sets focus on the first focusable, or configured, child in focus trap zone + */ focus: () => void; } @@ -38,14 +51,14 @@ export interface IFocusTrapZoneProps extends React.HTMLAttributes string); /** @@ -54,6 +67,14 @@ export interface IFocusTrapZoneProps extends React.HTMLAttributes Date: Wed, 16 May 2018 15:37:21 -0700 Subject: [PATCH 02/11] rush change --- .../ftz-rememberlastfocused_2018-05-16-22-37.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json diff --git a/common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json b/common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json new file mode 100644 index 0000000000000..def3693e6588d --- /dev/null +++ b/common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "office-ui-fabric-react", + "comment": "Added FocusTrapZone capability: When the FTZ is focused, it will pass focus to a child element. The new prop 'focusTransferRule' controls the child-choosing behavior.", + "type": "minor" + } + ], + "packageName": "office-ui-fabric-react", + "email": "benw@microsoft.com" +} \ No newline at end of file From 43564b9db116645cc99805d7c3ab641168966b25 Mon Sep 17 00:00:00 2001 From: Ben Worline Date: Wed, 16 May 2018 16:59:04 -0700 Subject: [PATCH 03/11] removed onKeyDown from formal api; already present in nativeProps --- .../src/components/FocusTrapZone/FocusTrapZone.types.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts index c9cf36f0fd5e3..f768ca3b44beb 100644 --- a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts +++ b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts @@ -74,9 +74,4 @@ export interface IFocusTrapZoneProps extends React.HTMLAttributes) => void; } From 9da9a9adc3594a1e9c0480bafb5abba1d62e774a Mon Sep 17 00:00:00 2001 From: Ben Worline Date: Wed, 16 May 2018 17:36:21 -0700 Subject: [PATCH 04/11] use defaultProps for focusTransferRule --- .../src/components/FocusTrapZone/FocusTrapZone.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx index 0bf7452043866..f08421423b2c1 100644 --- a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx +++ b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx @@ -14,6 +14,9 @@ import { import { IFocusTrapZone, IFocusTrapZoneProps, FocusTransferRule } from './FocusTrapZone.types'; export class FocusTrapZone extends BaseComponent implements IFocusTrapZone { + public static defaultProps = { + focusTransferRule: FocusTransferRule.firstFocusable + }; private static _focusStack: FocusTrapZone[] = []; private static _clickStack: FocusTrapZone[] = []; @@ -104,7 +107,7 @@ export class FocusTrapZone extends BaseComponent implem } public focus() { - const { focusTransferRule = FocusTransferRule.firstFocusable, firstFocusableSelector } = this.props; + const { focusTransferRule, firstFocusableSelector } = this.props; if ( focusTransferRule === FocusTransferRule.previouslyFocusedElement && From fe25c3aebbaedae998b94c33e8947ff3fda9d705 Mon Sep 17 00:00:00 2001 From: Ben Worline Date: Wed, 16 May 2018 20:32:19 -0700 Subject: [PATCH 05/11] Correct type compile error on keybaord handler params --- .../src/components/FocusTrapZone/FocusTrapZone.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx index f08421423b2c1..3c21891aba5b3 100644 --- a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx +++ b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx @@ -155,7 +155,7 @@ export class FocusTrapZone extends BaseComponent implem } } - private _onKeyboardHandler = (ev: React.KeyboardEvent): void => { + private _onKeyboardHandler = (ev: React.KeyboardEvent): void => { if (this.props.onKeyDown) { this.props.onKeyDown(ev); } From acd945877284448f4e754338e11ef125bb287b64 Mon Sep 17 00:00:00 2001 From: Ben Worline Date: Wed, 16 May 2018 22:15:49 -0700 Subject: [PATCH 06/11] change new prop from enum to bool on CR suggestion --- .../FocusTrapZone/FocusTrapZone.test.tsx | 14 +++++---- .../FocusTrapZone/FocusTrapZone.tsx | 10 ++----- .../FocusTrapZone/FocusTrapZone.types.ts | 29 ++++++------------- 3 files changed, 21 insertions(+), 32 deletions(-) diff --git a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.test.tsx b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.test.tsx index 30f894ea4a400..fa4197afad3ee 100644 --- a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.test.tsx +++ b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.test.tsx @@ -4,7 +4,6 @@ import * as ReactTestUtils from 'react-dom/test-utils'; import { KeyCodes, createRef } from '../../Utilities'; import { FocusZone, FocusZoneDirection } from '../FocusZone'; import { FocusTrapZone } from './FocusTrapZone'; -import { FocusTransferRule } from './FocusTrapZone.types'; // rAF does not exist in node - let's mock it window.requestAnimationFrame = (callback: FrameRequestCallback) => { @@ -263,11 +262,16 @@ describe('FocusTrapZone', () => { }); describe('Focusing the FTZ', () => { - function setupTest(rule: FocusTransferRule) { + function setupTest(focusPreviouslyFocusedInnerElement: boolean) { const focusTrapZoneRef = createRef(); const topLevelDiv = ReactTestUtils.renderIntoDocument(
- + @@ -296,7 +300,7 @@ describe('FocusTrapZone', () => { it('goes to previously focused element when focusing the FTZ', async () => { expect.assertions(4); - const { focusTrapZone, buttonF, buttonB, buttonZ } = setupTest(FocusTransferRule.previouslyFocusedElement); + const { focusTrapZone, buttonF, buttonB, buttonZ } = setupTest(true /*focusPreviouslyFocusedInnerElement*/); // Manually focusing FTZ when FTZ has never // had focus within should go to 1st focusable inner element. @@ -323,7 +327,7 @@ describe('FocusTrapZone', () => { it('goes to first focusable element when focusing the FTZ', async () => { expect.assertions(4); - const { focusTrapZone, buttonF, buttonB, buttonZ } = setupTest(FocusTransferRule.firstFocusable); + const { focusTrapZone, buttonF, buttonB, buttonZ } = setupTest(false /*focusPreviouslyFocusedInnerElement*/); // Manually focusing FTZ when FTZ has never // had focus within should go to 1st focusable inner element. diff --git a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx index 3c21891aba5b3..765dd724b4015 100644 --- a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx +++ b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx @@ -11,13 +11,9 @@ import { focusAsync, createRef } from '../../Utilities'; -import { IFocusTrapZone, IFocusTrapZoneProps, FocusTransferRule } from './FocusTrapZone.types'; +import { IFocusTrapZone, IFocusTrapZoneProps } from './FocusTrapZone.types'; export class FocusTrapZone extends BaseComponent implements IFocusTrapZone { - public static defaultProps = { - focusTransferRule: FocusTransferRule.firstFocusable - }; - private static _focusStack: FocusTrapZone[] = []; private static _clickStack: FocusTrapZone[] = []; @@ -107,10 +103,10 @@ export class FocusTrapZone extends BaseComponent implem } public focus() { - const { focusTransferRule, firstFocusableSelector } = this.props; + const { focusPreviouslyFocusedInnerElement, firstFocusableSelector } = this.props; if ( - focusTransferRule === FocusTransferRule.previouslyFocusedElement && + focusPreviouslyFocusedInnerElement && this._previouslyFocusedElementInTrapZone && elementContains(this._root.value, this._previouslyFocusedElementInTrapZone) ) { diff --git a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts index f768ca3b44beb..05ea1b92ee6db 100644 --- a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts +++ b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts @@ -1,21 +1,9 @@ import * as React from 'react'; -/** - * Algorithm used to determine which descendant element to focus when the FocusTrapZone is focused. - */ -export const enum FocusTransferRule { - /** Locate and focus the first focusable descendant, filtered by the firstFocusableSelector property if present. */ - firstFocusable = 0, - /** - * Go to the element that was focused when this FocusTrapZone last had a focused descendant. - * If it has never had a focused descendant before, behavior falls back to FirstFocusable. - */ - previouslyFocusedElement = 1 -} - export interface IFocusTrapZone { /** - * Sets focus on the first focusable, or configured, child in focus trap zone + * Sets focus to a descendant in the Trap Zone. + * See firstFocusableSelector and focusPreviouslyFocusedInnerElement for details. */ focus: () => void; } @@ -57,7 +45,7 @@ export interface IFocusTrapZoneProps extends React.HTMLAttributes string); @@ -68,10 +56,11 @@ export interface IFocusTrapZoneProps extends React.HTMLAttributes Date: Wed, 16 May 2018 22:28:09 -0700 Subject: [PATCH 07/11] updated rush change msg --- .../ftz-rememberlastfocused_2018-05-16-22-37.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json b/common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json index def3693e6588d..dbb19c31f1654 100644 --- a/common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json +++ b/common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "office-ui-fabric-react", - "comment": "Added FocusTrapZone capability: When the FTZ is focused, it will pass focus to a child element. The new prop 'focusTransferRule' controls the child-choosing behavior.", + "comment": "Added FocusTrapZone capability: When the FTZ is focused, it will pass focus to a descendant element. The new prop 'focusPreviouslyFocusedInnerElement' controls the descendant-choosing behavior.", "type": "minor" } ], From ac562fcf1a235f0895dc45d74806565adbbbe766 Mon Sep 17 00:00:00 2001 From: "REDMOND\\benw" Date: Thu, 24 May 2018 15:25:57 -0700 Subject: [PATCH 08/11] added isDefaultPrevented to FocusCapture handler --- .../src/components/FocusTrapZone/FocusTrapZone.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx index 765dd724b4015..d3f440e03b2d2 100644 --- a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx +++ b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.tsx @@ -136,6 +136,9 @@ export class FocusTrapZone extends BaseComponent implem if (this.props.onFocusCapture) { this.props.onFocusCapture(ev); } + if (ev.isDefaultPrevented()) { + return; + } if (ev.target === ev.currentTarget) { // If the trap zone gets focus, pass on focus to either first focusable From a2a9b898d76aaaad63c0290d2a12f2a10afc6559 Mon Sep 17 00:00:00 2001 From: Ben Worline Date: Tue, 5 Jun 2018 08:45:25 -0700 Subject: [PATCH 09/11] update change comment --- .../ftz-rememberlastfocused_2018-05-16-22-37.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json b/common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json index dbb19c31f1654..c96910bf7491d 100644 --- a/common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json +++ b/common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json @@ -2,10 +2,10 @@ "changes": [ { "packageName": "office-ui-fabric-react", - "comment": "Added FocusTrapZone capability: When the FTZ is focused, it will pass focus to a descendant element. The new prop 'focusPreviouslyFocusedInnerElement' controls the descendant-choosing behavior.", + "comment": "Added FocusTrapZone capability: When FTZ.focus() is called, it will pass focus to a descendant element. The new prop 'focusPreviouslyFocusedInnerElement' controls the descendant-choosing behavior.", "type": "minor" } ], "packageName": "office-ui-fabric-react", "email": "benw@microsoft.com" -} \ No newline at end of file +} From 62dfcff1dc550b2c862e44e3beaf1b549d21541d Mon Sep 17 00:00:00 2001 From: Ben Worline Date: Tue, 5 Jun 2018 08:50:21 -0700 Subject: [PATCH 10/11] update comment --- .../src/components/FocusTrapZone/FocusTrapZone.types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts index 05ea1b92ee6db..d0ab9e81c434e 100644 --- a/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts +++ b/packages/office-ui-fabric-react/src/components/FocusTrapZone/FocusTrapZone.types.ts @@ -56,7 +56,7 @@ export interface IFocusTrapZoneProps extends React.HTMLAttributes Date: Tue, 5 Jun 2018 10:19:25 -0700 Subject: [PATCH 11/11] Update ftz-rememberlastfocused_2018-05-16-22-37.json --- .../ftz-rememberlastfocused_2018-05-16-22-37.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json b/common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json index c96910bf7491d..0741f771aec9f 100644 --- a/common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json +++ b/common/changes/office-ui-fabric-react/ftz-rememberlastfocused_2018-05-16-22-37.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "office-ui-fabric-react", - "comment": "Added FocusTrapZone capability: When FTZ.focus() is called, it will pass focus to a descendant element. The new prop 'focusPreviouslyFocusedInnerElement' controls the descendant-choosing behavior.", + "comment": "FocusTrapZone: Added new capability. When `FTZ.focus()` is called, it will pass focus to a descendant element. The new prop `focusPreviouslyFocusedInnerElement` controls the descendant-choosing behavior.", "type": "minor" } ],