diff --git a/assets/stylesheets/_z-index.scss b/assets/stylesheets/_z-index.scss
index b8f00482e84af..462824c88c578 100644
--- a/assets/stylesheets/_z-index.scss
+++ b/assets/stylesheets/_z-index.scss
@@ -67,9 +67,9 @@ $z-layers: (
// but bellow #adminmenuback { z-index: 100 }
".edit-post-sidebar {greater than small}": 90,
- // Show notices below expanded wp-admin submenus:
- // #adminmenuwrap { z-index: 9990 }
- ".components-notice-list": 9989,
+ // Show notices below expanded editor bar
+ // .edit-post-header { z-index: 30 }
+ ".components-notice-list": 29,
// Show modal under the wp-admin menus and the popover
".components-modal__screen-overlay": 100000,
diff --git a/packages/components/src/notice/list.js b/packages/components/src/notice/list.js
index 4ff12e2a45118..dcb39dc49b582 100644
--- a/packages/components/src/notice/list.js
+++ b/packages/components/src/notice/list.js
@@ -1,6 +1,7 @@
/**
* External dependencies
*/
+import classnames from 'classnames';
import { noop, omit } from 'lodash';
/**
@@ -18,9 +19,11 @@ import Notice from './';
* @param {Object} $0.children Array of children to be rendered inside the notice list.
* @return {Object} The rendered notices list.
*/
-function NoticeList( { notices, onRemove = noop, className = 'components-notice-list', children } ) {
+function NoticeList( { notices, onRemove = noop, className, children } ) {
const removeNotice = ( id ) => () => onRemove( id );
+ className = classnames( 'components-notice-list', className );
+
return (
{ children }
diff --git a/packages/components/src/notice/test/list.js b/packages/components/src/notice/test/list.js
new file mode 100644
index 0000000000000..034ff9b7dfd82
--- /dev/null
+++ b/packages/components/src/notice/test/list.js
@@ -0,0 +1,26 @@
+/**
+ * External dependencies
+ */
+import ShallowRenderer from 'react-test-renderer/shallow';
+
+/**
+ * WordPress dependencies
+ */
+import TokenList from '@wordpress/token-list';
+
+/**
+ * Internal dependencies
+ */
+import NoticeList from '../list';
+
+describe( 'NoticeList', () => {
+ it( 'should merge className', () => {
+ const renderer = new ShallowRenderer();
+
+ renderer.render(
);
+
+ const classes = new TokenList( renderer.getRenderOutput().props.className );
+ expect( classes.contains( 'is-ok' ) ).toBe( true );
+ expect( classes.contains( 'components-notice-list' ) ).toBe( true );
+ } );
+} );
diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js
index 1c67baed29d22..f0876f4672287 100644
--- a/packages/edit-post/src/components/layout/index.js
+++ b/packages/edit-post/src/components/layout/index.js
@@ -78,7 +78,8 @@ function Layout( {
aria-label={ __( 'Editor content' ) }
tabIndex="-1"
>
-
+
+
diff --git a/packages/edit-post/src/components/layout/style.scss b/packages/edit-post/src/components/layout/style.scss
index f848a8cfd7ccd..dfbfaf77dd356 100644
--- a/packages/edit-post/src/components/layout/style.scss
+++ b/packages/edit-post/src/components/layout/style.scss
@@ -13,49 +13,36 @@
color: $dark-gray-900;
@include break-small {
- position: fixed;
- top: inherit;
+ top: 0;
+ }
+
+ // Non-dismissible notices.
+ &.is-pinned {
+ position: relative;
+ left: 0;
+ top: 0;
}
+ }
- .components-notice {
- margin: 0 0 5px;
- padding: 6px 12px;
- min-height: $panel-header-height;
+ .components-notice {
+ margin: 0 0 5px;
+ padding: 6px 12px;
+ min-height: $panel-header-height;
- .components-notice__dismiss {
- margin: 10px 5px;
- }
+ .components-notice__dismiss {
+ margin: 10px 5px;
}
}
- // On mobile, toolbars behave differently.
+ // Beyond the mobile breakpoint, the editor bar is fixed, so make room for it eabove the layout content.
@include break-small {
padding-top: $header-height;
}
- &.has-fixed-toolbar {
- .edit-post-layout__content {
- padding-top: $block-controls-height;
- }
-
- // On mobile, toolbars behave differently.
- @include break-small {
- padding-top: $header-height + $block-toolbar-height;
-
- .edit-post-layout__content {
- padding-top: 0;
- }
- }
-
- @include break-large {
- padding-top: $header-height;
- }
- }
+ // Beyond the medium breakpoint, the main scrolling area itself becomes fixed so the padding then becomes
+ // unnecessary, but until then it's still needed.
}
-@include editor-left(".components-notice-list");
-@include editor-right(".components-notice-list");
-
.edit-post-layout__metaboxes:not(:empty) {
border-top: $border-width solid $light-gray-500;
margin-top: 10px;
@@ -121,16 +108,33 @@
}
}
+ // For users with the Top Toolbar option enabled, special rules apply to the height of the content area.
+ .has-fixed-toolbar & {
+ // From the medium breakpoint it sits below the editor bar.
+ @include break-medium() {
+ top: $header-height + $admin-bar-height + $block-controls-height;
+ }
+
+ // From the xlarge breakpoint it sits in the editor bar.
+ @include break-xlarge() {
+ top: $header-height + $admin-bar-height;
+ }
+ }
+
// Pad the scroll box so content on the bottom can be scrolled up.
padding-bottom: 50vh;
@include break-small {
padding-bottom: 0;
}
- // On mobile the main content area has to scroll otherwise you can invoke
- // the overscroll bounce on the non-scrolling container, causing
- // (ノಠ益ಠ)ノ彡┻━┻
- overflow-y: auto;
+ // On mobile the main content (html or body) area has to scroll.
+ // If, like we do on the desktop, scroll an element (.edit-post-layout__content) you can invoke
+ // the overscroll bounce on the non-scrolling container, causing for a frustrating scrolling experience.
+ // The following rule enables this scrolling beyond the mobile breakpoint, because on the desktop
+ // breakpoints scrolling an isolated element helps avoid scroll bleed.
+ @include break-small() {
+ overflow-y: auto;
+ }
-webkit-overflow-scrolling: touch;
// This rule ensures that if you've scrolled to the end of a container,
diff --git a/packages/editor/src/components/block-list/style.scss b/packages/editor/src/components/block-list/style.scss
index a024bb2198d06..043ddd2613607 100644
--- a/packages/editor/src/components/block-list/style.scss
+++ b/packages/editor/src/components/block-list/style.scss
@@ -784,7 +784,6 @@
.editor-block-list__block {
.editor-block-contextual-toolbar {
- position: sticky;
z-index: z-index(".editor-block-contextual-toolbar");
white-space: nowrap;
text-align: left;
diff --git a/packages/editor/src/components/editor-notices/index.js b/packages/editor/src/components/editor-notices/index.js
index f11c76181cbb5..f899f4a61e0ff 100644
--- a/packages/editor/src/components/editor-notices/index.js
+++ b/packages/editor/src/components/editor-notices/index.js
@@ -1,3 +1,8 @@
+/**
+ * External dependencies
+ */
+import { filter } from 'lodash';
+
/**
* WordPress dependencies
*/
@@ -10,10 +15,16 @@ import { compose } from '@wordpress/compose';
*/
import TemplateValidationNotice from '../template-validation-notice';
-function EditorNotices( props ) {
+export function EditorNotices( { dismissible, notices, ...props } ) {
+ if ( dismissible !== undefined ) {
+ notices = filter( notices, { isDismissible: dismissible } );
+ }
+
return (
-
-
+
+ { dismissible !== false && (
+
+ ) }
);
}
diff --git a/packages/editor/src/components/editor-notices/test/index.js b/packages/editor/src/components/editor-notices/test/index.js
new file mode 100644
index 0000000000000..655a990aa174f
--- /dev/null
+++ b/packages/editor/src/components/editor-notices/test/index.js
@@ -0,0 +1,35 @@
+/**
+ * External dependencies
+ */
+import { shallow } from 'enzyme';
+
+/**
+ * Internal dependencies
+ */
+import { EditorNotices } from '../';
+
+describe( 'EditorNotices', () => {
+ const notices = [
+ { content: 'Eat your vegetables!', isDismissible: true },
+ { content: 'Brush your teeth!', isDismissible: true },
+ { content: 'Existence is fleeting!', isDismissible: false },
+ ];
+
+ it( 'renders all notices', () => {
+ const wrapper = shallow( );
+ expect( wrapper.prop( 'notices' ) ).toHaveLength( 3 );
+ expect( wrapper.children() ).toHaveLength( 1 );
+ } );
+
+ it( 'renders only dismissible notices', () => {
+ const wrapper = shallow( );
+ expect( wrapper.prop( 'notices' ) ).toHaveLength( 2 );
+ expect( wrapper.children() ).toHaveLength( 1 );
+ } );
+
+ it( 'renders only non-dismissible notices', () => {
+ const wrapper = shallow( );
+ expect( wrapper.prop( 'notices' ) ).toHaveLength( 1 );
+ expect( wrapper.children() ).toHaveLength( 0 );
+ } );
+} );