Skip to content

Commit

Permalink
Modal: add __experimentalHideHeader prop, wrap in forwardref (#…
Browse files Browse the repository at this point in the history
…36831)

* Destructure props inside function body

* Include Modal and its dependencies in the TS config

* Wrap `Modal` in `forwardRef`

* Add `__experimentalHideHeader` prop

* Add __experimentalHideHeader to Storybook knobs

* Add `__experimentalHideHeader` unit test

* CHANGELOG

* Update snapshots

* Update packages/components/CHANGELOG.md

Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com>

* Update packages/components/src/modal/test/index.js

Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com>

Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com>
  • Loading branch information
ciampo and tyxla authored Nov 25, 2021
1 parent 8648ce3 commit 4a23beb
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 61 deletions.
5 changes: 5 additions & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@
- Fixed inconsistent padding in `UnitControl` ([#35646](https://github.com/WordPress/gutenberg/pull/35646)).
- Added support for RTL behavior for the `ZStack`'s `offset` prop ([#36769](https://github.com/WordPress/gutenberg/pull/36769))
- Fixed race conditions causing conditionally displayed `ToolsPanelItem` components to be erroneously deregistered ([36588](https://github.com/WordPress/gutenberg/pull/36588)).
- Added `__experimentalHideHeader` prop to `Modal` component ([#36831](https://github.com/WordPress/gutenberg/pull/36831)).

### Bug Fix

- Fixed spacing between `BaseControl` fields and help text within the `ToolsPanel` ([36334](https://github.com/WordPress/gutenberg/pull/36334))

### Enhancements

- Wrapped `Modal` in a `forwardRef` call ([#36831](https://github.com/WordPress/gutenberg/pull/36831)).

## 19.0.2 (2021-11-15)

- Remove erroneous use of `??=` syntax from `build-module`.
Expand Down
10 changes: 10 additions & 0 deletions packages/components/src/modal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,16 @@ This property when set to `true` will render a full screen modal.
- Required: No
- Default: `false`

#### __experimentalHideHeader

When set to `true`, the Modal's header (including the icon, title and close button) will not be rendered.

*Warning*: This property is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.

- Type: `boolean`
- Required: No
- Default: `false`

## Related components

- To notify a user with a message of medium importance, use `Notice`.
2 changes: 2 additions & 0 deletions packages/components/src/modal/aria-helper.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//@ts-nocheck

/**
* External dependencies
*/
Expand Down
127 changes: 72 additions & 55 deletions packages/components/src/modal/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//@ts-nocheck

/**
* External dependencies
*/
Expand All @@ -6,7 +8,12 @@ import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { createPortal, useEffect, useRef } from '@wordpress/element';
import {
createPortal,
useEffect,
useRef,
forwardRef,
} from '@wordpress/element';
import {
useInstanceId,
useFocusReturn,
Expand All @@ -30,31 +37,34 @@ import StyleProvider from '../style-provider';
// Used to count the number of open modals.
let openModalCount = 0;

export default function Modal( {
bodyOpenClassName = 'modal-open',
role = 'dialog',
title = null,
focusOnMount = true,
shouldCloseOnEsc = true,
shouldCloseOnClickOutside = true,
isDismissable, // Deprecated
isDismissible = isDismissable || true,
/* accessibility */
aria = {
labelledby: null,
describedby: null,
},
onRequestClose,
icon,
closeButtonLabel,
children,
style,
overlayClassName,
className,
contentLabel,
onKeyDown,
isFullScreen = false,
} ) {
function Modal( props, forwardedRef ) {
const {
bodyOpenClassName = 'modal-open',
role = 'dialog',
title = null,
focusOnMount = true,
shouldCloseOnEsc = true,
shouldCloseOnClickOutside = true,
isDismissable, // Deprecated
isDismissible = isDismissable || true,
/* accessibility */
aria = {
labelledby: null,
describedby: null,
},
onRequestClose,
icon,
closeButtonLabel,
children,
style,
overlayClassName,
className,
contentLabel,
onKeyDown,
isFullScreen = false,
__experimentalHideHeader = false,
} = props;

const ref = useRef();
const instanceId = useInstanceId( Modal );
const headingId = title
Expand Down Expand Up @@ -106,7 +116,7 @@ export default function Modal( {
return createPortal(
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
<div
ref={ ref }
ref={ useMergeRefs( [ ref, forwardedRef ] ) }
className={ classnames(
'components-modal__screen-overlay',
overlayClassName
Expand Down Expand Up @@ -139,38 +149,43 @@ export default function Modal( {
onKeyDown={ onKeyDown }
>
<div
className={ 'components-modal__content' }
className={ classnames( 'components-modal__content', {
'hide-header': __experimentalHideHeader,
} ) }
role="document"
>
<div className="components-modal__header">
<div className="components-modal__header-heading-container">
{ icon && (
<span
className="components-modal__icon-container"
aria-hidden
>
{ icon }
</span>
) }
{ title && (
<h1
id={ headingId }
className="components-modal__header-heading"
>
{ title }
</h1>
{ ! __experimentalHideHeader && (
<div className="components-modal__header">
<div className="components-modal__header-heading-container">
{ icon && (
<span
className="components-modal__icon-container"
aria-hidden
>
{ icon }
</span>
) }
{ title && (
<h1
id={ headingId }
className="components-modal__header-heading"
>
{ title }
</h1>
) }
</div>
{ isDismissible && (
<Button
onClick={ onRequestClose }
icon={ closeSmall }
label={
closeButtonLabel ||
__( 'Close dialog' )
}
/>
) }
</div>
{ isDismissible && (
<Button
onClick={ onRequestClose }
icon={ closeSmall }
label={
closeButtonLabel || __( 'Close dialog' )
}
/>
) }
</div>
) }
{ children }
</div>
</div>
Expand All @@ -179,3 +194,5 @@ export default function Modal( {
document.body
);
}

export default forwardRef( Modal );
5 changes: 5 additions & 0 deletions packages/components/src/modal/stories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ export const _default = () => {
'shouldCloseOnClickOutside',
true
);
const __experimentalHideHeader = boolean(
'__experimentalHideHeader',
false
);

const iconComponent = showIcon ? <Icon icon={ wordpress } /> : null;

Expand All @@ -65,6 +69,7 @@ export const _default = () => {
shouldCloseOnEsc,
shouldCloseOnClickOutside,
title,
__experimentalHideHeader,
};

return <ModalExample { ...modalProps } />;
Expand Down
9 changes: 9 additions & 0 deletions packages/components/src/modal/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,13 @@
display: block;
margin-bottom: $grid-unit-30;
}

&.hide-header {
margin-top: 0;
padding-top: $grid-unit-30;

&::before {
content: none;
}
}
}
11 changes: 11 additions & 0 deletions packages/components/src/modal/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,15 @@ describe( 'Modal', () => {
const titleId = within( dialog ).getByText( 'Test Title' ).id;
expect( dialog ).toHaveAttribute( 'aria-labelledby', titleId );
} );

it( 'hides the header when the `__experimentalHideHeader` prop is used', () => {
render(
<Modal title="Test Title" __experimentalHideHeader>
<p>Modal content</p>
</Modal>
);
const dialog = screen.getByRole( 'dialog' );
const title = within( dialog ).queryByText( 'Test Title' );
expect( title ).not.toBeInTheDocument();
} );
} );
2 changes: 2 additions & 0 deletions packages/components/src/style-provider/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//@ts-nocheck

/**
* External dependencies
*/
Expand Down
2 changes: 2 additions & 0 deletions packages/components/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"src/icon/**/*",
"src/menu-item/**/*",
"src/menu-group/**/*",
"src/modal/**/*",
"src/navigable-container/**/*",
"src/navigator/**/*",
"src/number-control/**/*",
Expand All @@ -57,6 +58,7 @@
"src/select-control/**/*",
"src/shortcut/**/*",
"src/slot-fill/**/*",
"src/style-provider/**/*",
"src/spacer/**/*",
"src/spinner/**/*",
"src/surface/**/*",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`KeyboardShortcutHelpModal should match snapshot when the modal is active 1`] = `
<Modal
<ForwardRef(Modal)
className="edit-post-keyboard-shortcut-help-modal"
closeLabel="Close"
onRequestClose={[Function]}
Expand Down Expand Up @@ -80,7 +80,7 @@ exports[`KeyboardShortcutHelpModal should match snapshot when the modal is activ
}
title="Text formatting"
/>
</Modal>
</ForwardRef(Modal)>
`;

exports[`KeyboardShortcutHelpModal should match snapshot when the modal is not active 1`] = `""`;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`PreferencesModal should match snapshot when the modal is active large viewports 1`] = `
<Modal
<ForwardRef(Modal)
className="edit-post-preferences-modal"
closeLabel="Close"
onRequestClose={[Function]}
Expand Down Expand Up @@ -30,11 +30,11 @@ exports[`PreferencesModal should match snapshot when the modal is active large v
>
<Component />
</TabPanel>
</Modal>
</ForwardRef(Modal)>
`;

exports[`PreferencesModal should match snapshot when the modal is active small viewports 1`] = `
<Modal
<ForwardRef(Modal)
className="edit-post-preferences-modal"
closeLabel="Close"
onRequestClose={[Function]}
Expand Down Expand Up @@ -386,5 +386,5 @@ exports[`PreferencesModal should match snapshot when the modal is active small v
</Card>
</NavigatorScreen>
</NavigatorProvider>
</Modal>
</ForwardRef(Modal)>
`;

0 comments on commit 4a23beb

Please sign in to comment.