Skip to content

Commit

Permalink
perf(Modal): CO-6277: add accessibility attributes (#722)
Browse files Browse the repository at this point in the history
  • Loading branch information
kat-chen-tm authored and simplynutty committed Mar 23, 2022
1 parent 73a30d6 commit bcb6f09
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 19 deletions.
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v14.7
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ cache:
- node_modules
notifications:
email: false
node_js:
- '12'
script:
- npm run lint
- npm run lint:css
Expand Down
6 changes: 6 additions & 0 deletions catalog/pages/adaptive_modal/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ rows:
- Prop: onScroll
Type: func(Event)
Notes: Optional. Callback is fired when the user scrolls modal's content
- Prop: focusElement
Type: React ref
Notes: Optional. Focuses on referenced element when modal is opened.
- Prop: modalId
Type: string
Notes: Optional. Sets ids of modal's title and content elements as modalId followed by '-title' and '-content' respectively.
```

```react
Expand Down
4 changes: 4 additions & 0 deletions catalog/pages/buttons/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ rows:
Type: any
Default:
Notes: Passes through any other props to underlying button, or in the case of an href prop being passed, anchor, element
- Prop: forwardedRef
Type: any
Default: null
Notes: React ref forwarded to button element.
```

### Standard button
Expand Down
18 changes: 9 additions & 9 deletions src/components/Banner/__tests__/__snapshots__/index.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ exports[`<Banner /> renders correctly when open 1`] = `
This is your primary message text.
</span>
<div
style="max-height: 0px;"
style="transition: max-height 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955) 0s; max-height: 0px;"
>
<div
class="c4 text text--dark text--primary c5"
Expand Down Expand Up @@ -253,7 +253,7 @@ exports[`<Banner /> renders correctly when variant is set 1`] = `
This is your primary message text.
</span>
<div
style="max-height: 0px;"
style="transition: max-height 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955) 0s; max-height: 0px;"
>
<div
class="c4 text text--dark text--primary c5"
Expand Down Expand Up @@ -434,7 +434,7 @@ exports[`<Banner /> renders correctly with close button 1`] = `
This is your primary message text.
</span>
<div
style="max-height: 0px;"
style="transition: max-height 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955) 0s; max-height: 0px;"
>
<div
class="c4 text text--dark text--primary c5"
Expand Down Expand Up @@ -611,7 +611,7 @@ exports[`<Banner /> renders correctly with close button hidden 1`] = `
This is your primary message text.
</span>
<div
style="max-height: 0px;"
style="transition: max-height 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955) 0s; max-height: 0px;"
>
<div
class="c4 text text--dark text--primary c5"
Expand Down Expand Up @@ -729,7 +729,7 @@ exports[`<Banner /> renders correctly with content 1`] = `
This is your primary message text.
</span>
<div
style="max-height: 0px;"
style="transition: max-height 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955) 0s; max-height: 0px;"
>
<div
class="c4 text text--dark text--primary c5"
Expand Down Expand Up @@ -869,7 +869,7 @@ exports[`<Banner /> renders correctly with custom icon 1`] = `
This is your primary message text.
</span>
<div
style="max-height: 0px;"
style="transition: max-height 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955) 0s; max-height: 0px;"
>
<div
class="c4 text text--dark text--primary c5"
Expand Down Expand Up @@ -1061,7 +1061,7 @@ exports[`<Banner /> renders correctly with custom title for the close button 1`]
test link text
</span>
<div
style="max-height: 0px;"
style="transition: max-height 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955) 0s; max-height: 0px;"
>
<div
class="c5 text text--dark text--primary c6"
Expand Down Expand Up @@ -1279,7 +1279,7 @@ exports[`<Banner /> renders correctly with expand/collapse button 1`] = `
collapsedText
</span>
<div
style="max-height: 0px;"
style="transition: max-height 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955) 0s; max-height: 0px;"
>
<div
class="c5 text text--dark text--primary c6"
Expand Down Expand Up @@ -1500,7 +1500,7 @@ exports[`<Banner /> renders correctly with link 1`] = `
test link text
</span>
<div
style="max-height: 0px;"
style="transition: max-height 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955) 0s; max-height: 0px;"
>
<div
class="c5 text text--dark text--primary c6"
Expand Down
9 changes: 6 additions & 3 deletions src/components/Button/Base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface ButtonProps {
readonly icon: any;
disabled?: boolean;
type?: "button" | "submit" | "reset";
forwardedRef?: any;
}

export interface ButtonLinkProps extends ButtonProps {
Expand All @@ -39,13 +40,15 @@ class Button extends Component<ButtonProps> {
variant: PropTypes.oneOf(BUTTON_VARIANTS),
size: PropTypes.oneOf(SIZES),
icon: PropTypes.node,
children: PropTypes.node.isRequired
children: PropTypes.node.isRequired,
forwardedRef: PropTypes.objectOf(PropTypes.any)
};

static defaultProps: ButtonProps = {
size: REGULAR,
variant: STANDARD,
icon: null
icon: null,
forwardedRef: null
};

componentDidMount() {
Expand Down Expand Up @@ -78,7 +81,7 @@ class Button extends Component<ButtonProps> {
}
};

button = React.createRef<HTMLButtonElement>();
button = this.props.forwardedRef || React.createRef<HTMLButtonElement>();

render() {
const { variant, size, icon, children, ...rest } = this.props;
Expand Down
16 changes: 16 additions & 0 deletions src/components/Modal/__tests__/__snapshots__/index.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,9 @@ exports[`<Modal /> closeModal should close the modal when the request was approv
class="c0 container--overlay"
>
<div
aria-modal="true"
class="c1"
role="dialog"
>
<div
class="c2"
Expand Down Expand Up @@ -379,7 +381,9 @@ exports[`<Modal /> closeModal should close the modal when there is no onRequestC
class="c0 container--overlay"
>
<div
aria-modal="true"
class="c1"
role="dialog"
>
<div
class="c2"
Expand Down Expand Up @@ -576,7 +580,9 @@ exports[`<Modal /> render should not render the modal if it is closed 1`] = `
class="c0 container--overlay"
>
<div
aria-modal="true"
class="c1"
role="dialog"
>
<div
class="c2"
Expand Down Expand Up @@ -862,7 +868,9 @@ exports[`<Modal /> render should render fullscreen modal with action bars 1`] =
class="c0 container--overlay"
>
<div
aria-modal="true"
class="c1 fullscreen"
role="dialog"
>
<div
class="c2"
Expand Down Expand Up @@ -1162,7 +1170,9 @@ exports[`<Modal /> render should render with actionBar and bottomActionBar 1`] =
class="c0 container--overlay"
>
<div
aria-modal="true"
class="c1"
role="dialog"
>
<div
class="c2"
Expand Down Expand Up @@ -1372,7 +1382,9 @@ exports[`<Modal /> render should render without errors and pass extra props 1`]
class="c0 container--overlay"
>
<div
aria-modal="true"
class="c1"
role="dialog"
style="width: 210px;"
>
<div
Expand Down Expand Up @@ -1581,7 +1593,9 @@ exports[`<Modal /> should recalculate shadows and content height on props change
class="c0 container--overlay open-enter open-enter-active"
>
<div
aria-modal="true"
class="c1 open-enter open-enter-active"
role="dialog"
>
<div
class="c2"
Expand Down Expand Up @@ -1825,7 +1839,9 @@ exports[`<Modal /> should set bottom action bar shadow when the content was scro
class="c0 container--overlay"
>
<div
aria-modal="true"
class="c1"
role="dialog"
>
<div
class="c2"
Expand Down
40 changes: 35 additions & 5 deletions src/components/Modal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ export class Modal extends React.Component {
containerProps: PropTypes.object,
actionBarProps: PropTypes.object,
contentProps: PropTypes.object,
bottomActionBarProps: PropTypes.object
bottomActionBarProps: PropTypes.object,
/* eslint-enable react/forbid-prop-types */
focusElement: PropTypes.objectOf(PropTypes.any),
modalId: PropTypes.string
};

static defaultProps = {
Expand All @@ -79,7 +81,9 @@ export class Modal extends React.Component {
containerProps: {},
actionBarProps: {},
contentProps: {},
bottomActionBarProps: {}
bottomActionBarProps: {},
focusElement: null,
modalId: null
};

static throttleTimout = 100;
Expand All @@ -101,15 +105,31 @@ export class Modal extends React.Component {
}

componentDidMount() {
if (this.props.isOpened) {
const { focusElement, isOpened } = this.props;
if (isOpened) {
this.updateHeightAndShadows();
if (
focusElement &&
focusElement.current &&
typeof focusElement.current.focus === "function"
) {
focusElement.current.focus();
}
}
window.addEventListener("resize", this.throttledUpdateHeightAndShadows); // eslint-disable-line
}

componentDidUpdate(prevProps) {
if (this.props.isOpened && !prevProps.isOpened) {
const { focusElement, isOpened } = this.props;
if (isOpened && !prevProps.isOpened) {
this.updateHeightAndShadows();
if (
focusElement &&
focusElement.current &&
typeof focusElement.current.focus === "function"
) {
focusElement.current.focus();
}
}
}

Expand Down Expand Up @@ -217,11 +237,15 @@ export class Modal extends React.Component {
contentProps,
bottomActionBarProps,
displayTop,
isFullscreen
isFullscreen,
modalId
} = this.props;
const { isOpened, actionBarShadow, bottomActionBarShadow } = this.state;
const { closeModal } = this;

const contentId = modalId && `${modalId}-content`;
const titleId = modalId && `${modalId}-title`;

return (
<ModalProvider value={{ closeModal }}>
<CSSTransition
Expand All @@ -248,13 +272,18 @@ export class Modal extends React.Component {
size={size}
displayTop={displayTop}
isFullscreen={isFullscreen}
aria-describedby={contentId}
aria-labelledby={titleId}
aria-modal
role="dialog"
{...containerProps}
>
{actionBar && (
<ActionBar
shadow={actionBarShadow}
ref={this.actionBarRef}
gutters={gutters}
id={titleId}
{...actionBarProps}
>
{actionBar}
Expand All @@ -264,6 +293,7 @@ export class Modal extends React.Component {
ref={this.contentRef}
onScroll={this.handleScroll}
gutters={gutters}
id={contentId}
{...contentProps}
>
{children}
Expand Down

0 comments on commit bcb6f09

Please sign in to comment.