Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(Modal): CO-6277: add accessibility attributes #722

Merged
merged 1 commit into from
Mar 21, 2022
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
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