Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

[terra-slide-panel] Disclosing node capturing method update #2095

Merged
merged 11 commits into from
Mar 26, 2024
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion packages/terra-framework-docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
* Changed
* Updated `terra-navigation-side-menu` example.

* Added
* Added test example for `terra-slide-panel` with no `mainContent` prop.

## 1.75.0 - (March 19, 2024)

* Changed
Expand All @@ -13,7 +16,7 @@
## 1.74.0 - (March 14, 2024)

* Added
* Added an example of a `compact-interactive-list` with no borders.
* Added an example for `terra-compact-interactive-list` with no borders.

* Changed
* Updated `terra-compact-interactive-list` documentation for `terra-menu` support.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import './PlaceholderList.module.scss';
/* eslint-disable */
const List = ({ children, isPadded }) => (
<ul aria-label="Placeholder List" role="listbox" className={isPadded ? 'placeholder-list is-padded' : 'placeholder-list '}>
<ul aria-label="Placeholder List" role="tablist" className={isPadded ? 'placeholder-list is-padded' : 'placeholder-list '}>
{children}
</ul>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const PlaceholderListItem = ({
className={classNames}
onClick={onSelect}
onKeyDown={keyDown}
role="option"
role="tab"
>
{children}
</li>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import React, { useState } from 'react';
import SlidePanel, { SlidePanelPositions } from 'terra-slide-panel';
import classNames from 'classnames/bind';
import styles from './SlidePanelNoMainContent.test.module.scss';

const cx = classNames.bind(styles);

const mainContentForSlidePanel = (togglePanelHandler) => (
<div>
<header className={cx('header-content')}>
<h3>Main Content</h3>
<button id="mainToggleBtn" type="button" onClick={togglePanelHandler} className={cx('custom-button')}>Toggle Panel 1</button>
{/* eslint-disable-next-line jsx-a11y/no-interactive-element-to-noninteractive-role */}
<button id="mainToggleBtnWithWrongRole" type="button" role="presentation" onClick={togglePanelHandler} className={cx('extension-button')}>Toggle Panel 2</button>
{ /* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions */}
<p id="mainToggleParagraph" onClick={togglePanelHandler} className={cx('extension-button')}>Toggle Panel 3</p>
</header>
<div className={cx('content-wrapper')}>
<p>
This is the main content area of the slide panel.
The overall height of the SlidePanel is determined by
the intrinsic height of the content in this container.
</p>
<p>
{'Focus is moved to the toggle button in the panel container when the panel is opened via the componentDidUpdate lifecycle hook in '}
<a href="https://github.com/cerner/terra-framework/blob/main/packages/terra-slide-panel/src/terra-dev-site/doc/example/DefaultSlidePanel.jsx">the example code</a>
.
</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
</ul>
</div>
</div>
);

const panelContentForSlidePanel = (togglePanelHandler) => (
<div>
<header className={cx('header-content')}>
<h3 className={cx('heading')}>Panel Content</h3>
<button id="panelToggleBtn" type="button" onClick={togglePanelHandler} className={cx('extension-button')}>Toggle Panel</button>
</header>
<div className={cx('content-wrapper')}>
<p>This is the panel content area of the slide panel.</p>
<p>
{'Focus is moved to the toggle button in the main container when the panel is closed via the componentDidUpdate lifecycle hook in '}
<a href="https://github.com/cerner/terra-framework/blob/main/packages/terra-slide-panel/src/terra-dev-site/doc/example/DefaultSlidePanel.jsx">the example code</a>
.
</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
<li>Item 13</li>
<li>Item 14</li>
<li>Item 15</li>
</ul>
</div>
</div>
);

const SlidePanelNoMainContent = () => {
const [isOpen, setIsOpen] = useState(false);

const handlePanelToggle = () => {
setIsOpen(!isOpen);
};

return (
<div className={cx('example-container')}>
{mainContentForSlidePanel(handlePanelToggle)}
<div className={isOpen ? cx('panel-container') : null}>
<SlidePanel
id="test-slide"
panelContent={panelContentForSlidePanel(handlePanelToggle)}
panelAriaLabel="Panel content area"
panelSize="small"
panelBehavior="overlay"
panelPosition={SlidePanelPositions.END}
isOpen={isOpen}
/>
</div>
</div>
);
};

export default SlidePanelNoMainContent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
:local {
.example-container {
position: relative;
}

.panel-container > div:first-child {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
}

.header-content {
background-color: #d3d3d3;

p {
width: auto;
display: inline-block;
margin: 0 !important;
}
}

.header-content > :not(:last-child){
margin-right: 5px;
}

.header-content h3 {
display: inline-block;
margin: 0;
padding: 5px;
}

.content-wrapper {
margin: 5px;
}

.custom-button {
display: inline-block;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -364,8 +364,6 @@ exports[`SlidePanelManager should disclose content in SlidePanel 1`] = `
aria-hidden="false"
className="main"
key="main"
onClick={[Function]}
onKeyUp={[Function]}
role="main"
tabIndex="-1"
>
Expand Down Expand Up @@ -863,8 +861,6 @@ exports[`SlidePanelManager should render a SlidePanelManager with level three he
aria-hidden="false"
className="main"
key="main"
onClick={[Function]}
onKeyUp={[Function]}
role="main"
tabIndex="-1"
>
Expand Down Expand Up @@ -1130,8 +1126,6 @@ exports[`SlidePanelManager should render the SlidePanelManager with custom props
aria-hidden="false"
className="main"
key="main"
onClick={[Function]}
onKeyUp={[Function]}
role="main"
tabIndex="-1"
>
Expand Down Expand Up @@ -1390,8 +1384,6 @@ exports[`SlidePanelManager should render the SlidePanelManager with defaults 1`]
aria-hidden="false"
className="main"
key="main"
onClick={[Function]}
onKeyUp={[Function]}
role="main"
tabIndex="-1"
>
Expand Down Expand Up @@ -1650,8 +1642,6 @@ exports[`SlidePanelManager should render the SlidePanelManager with squish overr
aria-hidden="false"
className="main"
key="main"
onClick={[Function]}
onKeyUp={[Function]}
role="main"
tabIndex="-1"
>
Expand Down
3 changes: 3 additions & 0 deletions packages/terra-slide-panel/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Changed
* Updated capturing the disclosing node to accommodate for cases with no `mainContent`.

## 3.47.0 - (December 18, 2023)

* Changed
Expand Down
21 changes: 9 additions & 12 deletions packages/terra-slide-panel/src/SlidePanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,14 @@ class SlidePanel extends React.Component {
super(props);
this.setPanelNode = this.setPanelNode.bind(this);
this.mainNode = React.createRef();
this.setLastClicked = this.setLastClicked.bind(this);
this.setDisclosingNode = this.setDisclosingNode.bind(this);
this.mainAriaDescribedByID = `detail-panel-warning-${uuidv4()}`;
}

componentDidUpdate(prevProps) {
if (this.props.isOpen && this.props.isOpen !== prevProps.isOpen) {
// Save the disclosing node for returning focus when panel is closed
this.setDisclosingNode(this.lastClicked);
this.setDisclosingNode(document.activeElement);
this.panelNode.focus();
return;
}
Expand All @@ -110,8 +109,12 @@ class SlidePanel extends React.Component {
this.disclosingNode.focus();
return;
}
// The disclosing element doesn't exist or isn't focusable, return focus to the main div
this.mainNode.current.focus();
// The disclosing element doesn't exist or isn't focusable, return focus to the main div or body
if (this.mainNode?.current) {
this.mainNode.current.focus();
} else {
document.body.focus();
}
}
}

Expand All @@ -122,10 +125,6 @@ class SlidePanel extends React.Component {
this.panelNode = node;
}

setLastClicked(event) {
this.lastClicked = event.target;
}

setDisclosingNode(node) {
if (node) {
node.setAttribute('aria-expanded', 'true');
Expand Down Expand Up @@ -189,8 +188,6 @@ class SlidePanel extends React.Component {
aria-hidden={isOpen && isFullscreen ? 'true' : 'false'}
ref={this.mainNode}
role="main"
onClick={this.setLastClicked}
onKeyUp={this.setLastClicked}
>
<VisuallyHiddenText
tabIndex="-1"
Expand All @@ -204,11 +201,11 @@ class SlidePanel extends React.Component {
const content = (panelPosition === SlidePanelPositions.START) ? (
<React.Fragment>
{panelDiv}
{mainDiv}
{mainContent && mainDiv}
</React.Fragment>
) : (
<React.Fragment>
{mainDiv}
{mainContent && mainDiv}
{panelDiv}
</React.Fragment>
);
Expand Down
17 changes: 13 additions & 4 deletions packages/terra-slide-panel/tests/jest/SlidePanel.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ describe('When a SlidePanel is rendered', () => {
expect(wrapper).toMatchSnapshot();
});

it('should render a SlidePanel without main content if mainContent prop was not provided', () => {
const slidePanel = (
<SlidePanel />
);
const wrapper = enzymeIntl.shallowWithIntl(slidePanel).dive();
const mainContent = wrapper.find('.main');
expect(mainContent.length).toBe(0);
});

it('should render a SlidePanel with panel content', () => {
const slidePanel = (
<SlidePanel
Expand Down Expand Up @@ -138,7 +147,7 @@ describe('When a SlidePanel is rendered', () => {
});

it('should render a SlidePanel with panelAriaLabel and mainAriaLabel specified', () => {
const slidePanel = <SlidePanel panelAriaLabel="Panel content area" mainAriaLabel="Main content area" />;
const slidePanel = <SlidePanel panelAriaLabel="Panel content area" mainContent={<p>Main Content</p>} mainAriaLabel="Main content area" />;
const wrapper = enzymeIntl.shallowWithIntl(slidePanel).dive();

const panelDiv = wrapper.find('.panel');
Expand All @@ -163,15 +172,15 @@ describe('When a SlidePanel is rendered', () => {
});

it('should contain a Visually Hidden Text as the aria-describedby target', () => {
const slidePanel = <SlidePanel />;
const slidePanel = <SlidePanel mainContent={<p>Main Content</p>} />;
const wrapper = enzymeIntl.shallowWithIntl(slidePanel).dive();

const mainDiv = wrapper.find('#detail-panel-warning-00000000-0000-0000-0000-000000000000').prop('text');
expect(mainDiv).toEqual('Terra.slidePanel.discloseWarning');
});

it('should set the text property of Visually Hidden Text from ./translations', () => {
const slidePanel = <IntlProvider locale="en" messages={translationsFile}><SlidePanel /></IntlProvider>;
const slidePanel = <IntlProvider locale="en" messages={translationsFile}><SlidePanel mainContent={<p>Main Content</p>} /></IntlProvider>;
const wrapper = enzymeIntl.shallowWithIntl(slidePanel).dive().dive();

const mainDiv = wrapper.find('#detail-panel-warning-00000000-0000-0000-0000-000000000000').prop('text');
Expand Down Expand Up @@ -202,7 +211,7 @@ describe('When custom props are used', () => {
});

it('sets aria-hidden to true on main content div when isOpen and isFullscreen props are both true', () => {
const slidePanel = <SlidePanel isOpen isFullscreen />;
const slidePanel = <SlidePanel mainContent={<p>Main Content</p>} isOpen isFullscreen />;
const wrapper = enzymeIntl.shallowWithIntl(slidePanel).dive();

const mainDiv = wrapper.find('.main');
Expand Down
Loading
Loading