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

fix(FocusZone): fix last breaking changes and make improvements when using Chat #614

Merged
merged 16 commits into from
Dec 20, 2018
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Fixes
- Ensure `Popup` properly flips values of `offset` prop in RTL @kuzhelov ([#612](https://github.com/stardust-ui/react/pull/612))
- Fix `List` - items should be selectable @sophieH29 ([#566](https://github.com/stardust-ui/react/pull/566))
- Respect `defaultTabbable` element when `FocusZone` container gets focus ([#637](https://github.com/stardust-ui/react/pull/637))
- Respect `defaultTabbable` element when `FocusZone` container gets focus @sophieH29 ([#637](https://github.com/stardust-ui/react/pull/637))
- Fix `FocusZone` - fix last breaking changes and make improvements for `Chat` usage @sophieH29 ([#614](https://github.com/stardust-ui/react/pull/614))

### Features
- Add `color` prop to `Text` component @Bugaa92 ([#597](https://github.com/stardust-ui/react/pull/597))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ function createMessageContentWithAttachments(content: string, messageId: string)
icon="file word outline"
aria-label={`File attachment ${fileName}. Press tab for more options Press Enter to open the file`}
header={fileName}
action={render => render(actionPopup)}
action={actionPopup}
data-is-focusable={true}
styles={{
'&:focus': {
Expand Down
7 changes: 5 additions & 2 deletions src/lib/accessibility/Behaviors/Chat/chatBehavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const ChatBehavior: Accessibility = (props: any) => ({
props: {
shouldEnterInnerZone: event => keyboardKey.getCode(event) === keyboardKey.Enter,
direction: FocusZoneDirection.vertical,
shouldHandleKeyDownCapture: false,
shouldResetActiveElementWhenTabFromZone: true,
defaultTabbableElement: getLastTabbableElement, // select last chat message by default
[CHAT_FOCUSZONE_ATTRIBUTE]: '', // allows querying the default active element
},
Expand All @@ -36,8 +36,11 @@ const ChatBehavior: Accessibility = (props: any) => ({
})

const getLastTabbableElement = (root: HTMLElement): HTMLElement => {
const lastVisibleMessage = root.querySelector('[data-last-visible="true"]') as HTMLElement
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This behavior will be moved in future

if (lastVisibleMessage) return lastVisibleMessage

const chatItemsElements = root.querySelectorAll(
`[${CHAT_FOCUSZONE_ATTRIBUTE}] .ui-chat__item > [${IS_FOCUSABLE_ATTRIBUTE}]`,
`[${CHAT_FOCUSZONE_ATTRIBUTE}] .ui-chat__message[${IS_FOCUSABLE_ATTRIBUTE}="true"]`,
)
return chatItemsElements.length > 0
? (chatItemsElements[chatItemsElements.length - 1] as HTMLElement)
Expand Down
1 change: 1 addition & 0 deletions src/lib/accessibility/FocusZone/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This is a list of changes made to this Stardust copy of FocusZone in comparison
- Fix `defaultTabbableElement` prop to be as a function ([#450](https://github.com/stardust-ui/react/pull/450))
- Remove role="presentation" @sophieH29 ([#530](https://github.com/stardust-ui/react/pull/530))
- Respect `defaultTabbable` element when FocusZone container receives focus @sophieH29 ([#637](https://github.com/stardust-ui/react/pull/637))
- Fix `FocusZone` - add `shouldResetActiveElementWhenTabFromZone` prop @sophieH29 ([#614](https://github.com/stardust-ui/react/pull/614))

### Features
- Add embed mode for FocusZone and new Chat behavior ([#233](https://github.com/stardust-ui/react/pull/233))
Expand Down
23 changes: 11 additions & 12 deletions src/lib/accessibility/FocusZone/FocusZone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ export class FocusZone extends React.Component<FocusZoneProps> implements IFocus
direction: PropTypes.number,
defaultTabbableElement: PropTypes.func,
shouldFocusOnMount: PropTypes.bool,
shouldResetActiveElementWhenTabFromZone: PropTypes.bool,
shouldFocusInnerElementWhenReceivedFocus: PropTypes.bool,
shouldHandleKeyDownCapture: PropTypes.bool,
disabled: PropTypes.bool,
as: customPropTypes.as,
isCircularNavigation: PropTypes.bool,
Expand All @@ -67,7 +67,6 @@ export class FocusZone extends React.Component<FocusZoneProps> implements IFocus
static defaultProps: FocusZoneProps = {
isCircularNavigation: false,
direction: FocusZoneDirection.bidirectional,
shouldHandleKeyDownCapture: true,
as: 'div',
}

Expand Down Expand Up @@ -105,8 +104,6 @@ export class FocusZone extends React.Component<FocusZoneProps> implements IFocus
public componentDidMount(): void {
_allInstances[this._id] = this

const { shouldHandleKeyDownCapture, defaultTabbableElement, shouldFocusOnMount } = this.props

this.setRef(this) // called here to support functional components, we only need HTMLElement ref anyway
if (this._root.current) {
this.windowElement = getWindow(this._root.current)
Expand All @@ -121,27 +118,22 @@ export class FocusZone extends React.Component<FocusZoneProps> implements IFocus
parentElement = getParent(parentElement)
}

if (!this._isInnerZone && shouldHandleKeyDownCapture) {
if (!this._isInnerZone) {
this.windowElement.addEventListener('keydown', this.onKeyDownCapture, true)
}

// Assign initial tab indexes so that we can set initial focus as appropriate.
this.updateTabIndexes()

if (defaultTabbableElement) {
const initialActiveElement = defaultTabbableElement(this._root.current)
initialActiveElement && this.setActiveElement(initialActiveElement)
}

if (shouldFocusOnMount) {
if (this.props.shouldFocusOnMount) {
this.focus()
}
}
}

public componentWillUnmount() {
delete _allInstances[this._id]
if (this.windowElement && this.props.shouldHandleKeyDownCapture) {
if (this.windowElement) {
this.windowElement.removeEventListener('keydown', this.onKeyDownCapture, true)
}
}
Expand Down Expand Up @@ -490,6 +482,8 @@ export class FocusZone extends React.Component<FocusZoneProps> implements IFocus
if (focusChanged) {
break
}
} else if (this.props.shouldResetActiveElementWhenTabFromZone) {
this._activeElement = null
}
return undefined

Expand Down Expand Up @@ -885,6 +879,11 @@ export class FocusZone extends React.Component<FocusZoneProps> implements IFocus

private updateTabIndexes(onElement?: HTMLElement) {
let element = onElement

if (!this._activeElement && this.props.defaultTabbableElement) {
this._activeElement = this.props.defaultTabbableElement(this._root.current)
}

if (!element && this._root.current) {
this._defaultFocusElement = null
element = this._root.current
Expand Down
4 changes: 2 additions & 2 deletions src/lib/accessibility/FocusZone/FocusZone.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ export interface FocusZoneProps extends React.HTMLAttributes<HTMLElement | Focus
shouldFocusInnerElementWhenReceivedFocus?: boolean

/**
* If global onKeyDownCapture should be handled and updating tab indexes.
* If true and handleTab is false, resets current activeElement to null value.
*/
shouldHandleKeyDownCapture?: boolean
shouldResetActiveElementWhenTabFromZone?: boolean

/**
* If set, the FocusZone will not be tabbable and keyboard navigation will be disabled.
Expand Down