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

fix(FocusZone|FocusTrapZone): correctly define current document object of the components #1820

Merged
merged 5 commits into from
Aug 19, 2019
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Fix bidirectional `FocusZone` to land focus correctly on DOWN key press after series of UP arrow keys @sophieH29 ([#1794](https://github.com/stardust-ui/react/pull/1794))
- Fix `hand` icon in Teams theme @lucivpav ([#1782](https://github.com/stardust-ui/react/pull/1782))
- ESC key should close the last opened `Popup` or `Dialog` if body has focus @sophieH29 ([#1807](https://github.com/stardust-ui/react/pull/1807))
- Correctly define current document object of the `FocusZone` and `FocusTrapZone` @sophieH29 ([#1820](https://github.com/stardust-ui/react/pull/1820))

### Features
- Add `overwrite` prop to `Provider` @layershifter ([#1780](https://github.com/stardust-ui/react/pull/1780))
Expand Down
6 changes: 4 additions & 2 deletions packages/react/src/lib/accessibility/FocusZone/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ This is a list of changes made to this Stardust copy of FocusZone in comparison
- Update tabindexes and focus alignment when item is focused programatically @sophieH29 ([#1098](https://github.com/stardust-ui/react/pull/1098))
- `FocusZone` should respect elements with `contenteditable` attribute on Home/End key press @sophieH29 ([#1749](https://github.com/stardust-ui/react/pull/1749))
- Fix bidirectional `FocusZone` to land focus correctly on DOWN key press after series of UP arrow keys @sophieH29 ([#1794](https://github.com/stardust-ui/react/pull/1794))
- Use always `getDocument` to correctly define current document object @sophieH29 ([#1820](https://github.com/stardust-ui/react/pull/1820))

### Features
- Add embed mode for FocusZone and new Chat behavior ([#233](https://github.com/stardust-ui/react/pull/233))
Expand Down Expand Up @@ -68,12 +69,13 @@ This is a list of changes made to the Stardust copy of FocusTrapZone in comparis
### BREAKING CHANGES
- Allow using `firstFocusableSelector` for all type of selectors, not only class names @sophieH29 ([#1732](https://github.com/stardust-ui/react/pull/1732))

### fixes
### Fixes
- Do not focus trigger on outside click @sophieH29 ([#627](https://github.com/stardust-ui/react/pull/627))
- Do not hide aria-live regions from accessibility tree @sophieH29 ([#917](https://github.com/stardust-ui/react/pull/917))
- Do not propagate any keyboard events @sophieH29 ([#1180](https://github.com/stardust-ui/react/pull/1180))
- Use always `getDocument` to correctly define current document object @sophieH29 ([#1820](https://github.com/stardust-ui/react/pull/1820))

### features
### Features
- Add focus trap zone [#239](https://github.com/stardust-ui/react/pull/239)
- Used Stardust utils instead of Fabric utilities:
- Used `EventListener` [#949](https://github.com/stardust-ui/react/pull/949)
Expand Down
29 changes: 19 additions & 10 deletions packages/react/src/lib/accessibility/FocusZone/FocusTrapZone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
getFirstTabbable,
getLastTabbable,
getWindow,
getDocument,
focusAsync,
HIDDEN_FROM_ACC_TREE,
} from './focusUtilities'
Expand Down Expand Up @@ -74,7 +75,8 @@ export default class FocusTrapZone extends React.Component<FocusTrapZoneProps, {
forceFocusInsideTrapOnOutsideFocus,
disabled,
} = this.props
const activeElement = document.activeElement as HTMLElement
const doc = getDocument(this._root.current)
const activeElement = doc.activeElement as HTMLElement

// if after componentDidUpdate focus is not inside the focus trap, bring it back
if (
Expand Down Expand Up @@ -111,10 +113,11 @@ export default class FocusTrapZone extends React.Component<FocusTrapZoneProps, {

componentWillUnmount(): void {
// don't handle return focus unless forceFocusInsideTrapOnOutsideFocus is true or focus is still within FocusTrapZone
const doc = getDocument(this._root.current)
if (
!this.props.disabled ||
this.props.forceFocusInsideTrapOnOutsideFocus ||
!this._root.current.contains(document.activeElement as HTMLElement)
!this._root.current.contains(doc.activeElement as HTMLElement)
) {
this._releaseFocusTrapZone()
}
Expand Down Expand Up @@ -199,7 +202,8 @@ export default class FocusTrapZone extends React.Component<FocusTrapZoneProps, {
// even when it's not. Using document.activeElement is another way
// for us to be able to get what the relatedTarget without relying
// on the event
relatedTarget = document.activeElement as Element
const doc = getDocument(this._root.current)
relatedTarget = doc.activeElement as Element
}

if (!this._root.current.contains(relatedTarget as HTMLElement)) {
Expand Down Expand Up @@ -282,11 +286,12 @@ export default class FocusTrapZone extends React.Component<FocusTrapZoneProps, {
})

// try to focus element which triggered FocusTrapZone - prviously focused element outside trap zone
const activeElement = document.activeElement as HTMLElement
const doc = getDocument(this._root.current)
const activeElement = doc.activeElement as HTMLElement
if (
!ignoreExternalFocusing &&
this._previouslyFocusedElementOutsideTrapZone &&
(this._root.current.contains(activeElement) || activeElement === document.body)
(this._root.current.contains(activeElement) || activeElement === doc.body)
) {
this._focusAsync(this._previouslyFocusedElementOutsideTrapZone)
}
Expand Down Expand Up @@ -374,7 +379,8 @@ export default class FocusTrapZone extends React.Component<FocusTrapZoneProps, {
}

_handleOutsideFocus = (ev: FocusEvent): void => {
const focusedElement = document.activeElement as HTMLElement
const doc = getDocument(this._root.current)
const focusedElement = doc.activeElement as HTMLElement
focusedElement && this._forceFocusInTrap(ev, focusedElement)
}

Expand Down Expand Up @@ -414,16 +420,18 @@ export default class FocusTrapZone extends React.Component<FocusTrapZoneProps, {
if (elementToFocusOnDismiss && previouslyFocusedElement !== elementToFocusOnDismiss) {
previouslyFocusedElement = elementToFocusOnDismiss
} else if (!previouslyFocusedElement) {
previouslyFocusedElement = document.activeElement as HTMLElement
const doc = getDocument(this._root.current)
previouslyFocusedElement = doc.activeElement as HTMLElement
}

return previouslyFocusedElement
}

_hideContentFromAccessibilityTree = () => {
const bodyChildren = (document.body && document.body.children) || []
const doc = getDocument(this._root.current)
const bodyChildren = (doc.body && doc.body.children) || []

if (bodyChildren.length && !document.body.contains(this._root.current)) {
if (bodyChildren.length && !doc.body.contains(this._root.current)) {
// In case popup render options will change
/* eslint-disable-next-line no-console */
console.warn(
Expand All @@ -449,7 +457,8 @@ export default class FocusTrapZone extends React.Component<FocusTrapZoneProps, {
}

_showContentInAccessibilityTree = () => {
const hiddenElements = document.querySelectorAll(`[${HIDDEN_FROM_ACC_TREE}="true"]`)
const doc = getDocument(this._root.current)
const hiddenElements = doc.querySelectorAll(`[${HIDDEN_FROM_ACC_TREE}="true"]`)
for (let index = 0; index < hiddenElements.length; index++) {
const element = hiddenElements[index]
element.removeAttribute('aria-hidden')
Expand Down
14 changes: 7 additions & 7 deletions packages/react/src/lib/accessibility/FocusZone/FocusZone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,9 @@ export default class FocusZone extends React.Component<FocusZoneProps> implement

this.windowElement = getWindow(this._root.current)
let parentElement = getParent(this._root.current)
const doc = getDocument(this._root.current)

while (parentElement && parentElement !== document.body && parentElement.nodeType === 1) {
while (parentElement && parentElement !== doc.body && parentElement.nodeType === 1) {
if (isElementFocusZone(parentElement)) {
this._isInnerZone = true
break
Expand Down Expand Up @@ -513,7 +514,9 @@ export default class FocusZone extends React.Component<FocusZoneProps> implement
return undefined
}

if (document.activeElement === this._root.current && this._isInnerZone) {
const doc = getDocument(this._root.current)

if (doc.activeElement === this._root.current && this._isInnerZone) {
// If this element has focus, it is being controlled by a parent.
// Ignore the keystroke.
return undefined
Expand Down Expand Up @@ -1004,13 +1007,10 @@ export default class FocusZone extends React.Component<FocusZoneProps> implement
}

getOwnerZone(element?: HTMLElement): HTMLElement | null {
const doc = getDocument(this._root.current)
let parentElement = getParent(element as HTMLElement)

while (
parentElement &&
parentElement !== this._root.current &&
parentElement !== document.body
) {
while (parentElement && parentElement !== this._root.current && parentElement !== doc.body) {
if (isElementFocusZone(parentElement)) {
return parentElement
}
Expand Down