diff --git a/packages/block-library/src/columns/editor.scss b/packages/block-library/src/columns/editor.scss index 4e8905f9bbca18..c795dab3085583 100644 --- a/packages/block-library/src/columns/editor.scss +++ b/packages/block-library/src/columns/editor.scss @@ -21,15 +21,13 @@ // Fullwide: show margin left/right to ensure there's room for the side UI. // This is not a 1:1 preview with the front-end where these margins would presumably be zero. -// @todo This could be revisited, by for example showing this margin only when the parent block was selected first. -// Then at least an unselected columns block would be an accurate preview. -.editor-block-list__block[data-align="full"] .wp-block-columns > .editor-inner-blocks { +.editor-block-list__block[data-align="full"] [data-type="core/columns"][data-align="full"] .wp-block-columns > .editor-inner-blocks { padding-left: $block-padding; padding-right: $block-padding; @include break-small() { - padding-left: $block-padding + $block-padding + $block-side-ui-width + $block-side-ui-clearance + $block-side-ui-clearance; - padding-right: $block-padding + $block-padding + $block-side-ui-width + $block-side-ui-clearance + $block-side-ui-clearance; + padding-left: $block-container-side-padding; + padding-right: $block-container-side-padding; } } diff --git a/packages/block-library/src/editor.scss b/packages/block-library/src/editor.scss index 8422d2c82571de..bc8bbd83911ade 100644 --- a/packages/block-library/src/editor.scss +++ b/packages/block-library/src/editor.scss @@ -25,6 +25,7 @@ @import "./quote/editor.scss"; @import "./rss/editor.scss"; @import "./search/editor.scss"; +@import "./section/editor.scss"; @import "./shortcode/editor.scss"; @import "./spacer/editor.scss"; @import "./subhead/editor.scss"; diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index 81a0e9bec632b4..23b8bb52d33f45 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -44,6 +44,7 @@ import * as pullquote from './pullquote'; import * as reusableBlock from './block'; import * as rss from './rss'; import * as search from './search'; +import * as section from './section'; import * as separator from './separator'; import * as shortcode from './shortcode'; import * as spacer from './spacer'; @@ -106,6 +107,7 @@ export const registerCoreBlocks = () => { pullquote, rss, search, + section, separator, reusableBlock, spacer, diff --git a/packages/block-library/src/section/edit.js b/packages/block-library/src/section/edit.js new file mode 100644 index 00000000000000..fcf17c40c48bce --- /dev/null +++ b/packages/block-library/src/section/edit.js @@ -0,0 +1,48 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { Fragment } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import { + InspectorControls, + InnerBlocks, + PanelColorSettings, + withColors, +} from '@wordpress/block-editor'; + +function SectionEdit( { className, setBackgroundColor, backgroundColor } ) { + const styles = { + backgroundColor: backgroundColor.color, + }; + + const classes = classnames( className, backgroundColor.class, { + 'has-background': !! backgroundColor.color, + } ); + + return ( + + + + +
+ +
+
+ ); +} + +export default withColors( 'backgroundColor' )( SectionEdit ); diff --git a/packages/block-library/src/section/editor.scss b/packages/block-library/src/section/editor.scss new file mode 100644 index 00000000000000..f8cb11319ca0b0 --- /dev/null +++ b/packages/block-library/src/section/editor.scss @@ -0,0 +1,87 @@ +/** + * Section: All Alignment Settings + */ +.wp-block[data-type="core/section"] { + + // Ensure not rendering outside the element + // as -1px causes overflow-x scrollbars + .editor-block-list__insertion-point { + left: 0; + right: 0; + } + + // Only applied when background is added to cancel out padding + > .editor-block-list__block-edit > div > .wp-block-section.has-background > .editor-inner-blocks { + margin-top: -#{$block-padding*2 + $block-spacing}; + margin-bottom: -#{$block-padding*2 + $block-spacing}; + } + + // Full Width Blocks + // specificity required to only target immediate child Blocks of Section + > .editor-block-list__block-edit > div > .wp-block-section > .editor-inner-blocks > .editor-block-list__layout > .wp-block[data-align="full"] { + margin-left: auto; + margin-right: auto; + padding-left: $block-padding*2; + padding-right: $block-padding*2; + + @include break-small() { + padding-left: $block-padding*4 + $block-spacing/2; // 58px + padding-right: $block-padding*4 + $block-spacing/2; // 58px + } + } + + // Full Width Blocks with a background (ie: has padding) + > .editor-block-list__block-edit > div > .wp-block-section.has-background > .editor-inner-blocks > .editor-block-list__layout > .wp-block[data-align="full"] { + // note: using position `left` causes hoz scrollbars so + // we opt to use margin instead + // the 30px matches the hoz padding applied in `theme.scss` + // added when the Block has a background set + margin-left: -30px; + + // 60px here is x2 the hoz padding from `theme.scss` added when + // the Block has a background set + // note: also duplicated below for full width Sections + width: calc(100% + 60px); + } +} + +/** + * Section: Full Width Alignment + */ +.wp-block[data-type="core/section"][data-align="full"] { + + // First tier of InnerBlocks must act like the container of the standard canvas + > .editor-block-list__block-edit > div > .wp-block-section > .editor-inner-blocks { + margin-left: auto; + margin-right: auto; + padding-left: 0; + padding-right: 0; + + > .editor-block-list__layout { + margin-left: 0; + margin-right: 0; + } + } + + // Full Width Blocks + // specificity required to only target immediate child Blocks of Section + > .editor-block-list__block-edit > div > .wp-block-section > .editor-inner-blocks > .editor-block-list__layout > .wp-block[data-align="full"] { + padding-right: 0; + padding-left: 0; + left: 0; + width: 100%; + max-width: none; + + // Allow to be flush with the edges of the canvas + > .editor-block-list__block-edit { + margin-left: 0; + margin-right: 0; + } + } + + // Full Width Blocks with a background (ie: has padding) + // note: also duplicated above for all Section widths + > .editor-block-list__block-edit > div > .wp-block-section.has-background > .editor-inner-blocks > .editor-block-list__layout > .wp-block[data-align="full"] { + width: calc(100% + 60px); + } +} diff --git a/packages/block-library/src/section/index.js b/packages/block-library/src/section/index.js new file mode 100644 index 00000000000000..d119bfa324a4d6 --- /dev/null +++ b/packages/block-library/src/section/index.js @@ -0,0 +1,66 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { Path, SVG } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { InnerBlocks, getColorClassName } from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ +import edit from './edit'; + +export const name = 'core/section'; + +export const settings = { + title: __( 'Section' ), + + icon: , + + category: 'layout', + + description: __( 'A wrapping section acting as a container for other blocks.' ), + + keywords: [ __( 'container' ), __( 'wrapper' ), __( 'row' ) ], + + supports: { + align: [ 'wide', 'full' ], + anchor: true, + html: false, + }, + + attributes: { + backgroundColor: { + type: 'string', + }, + customBackgroundColor: { + type: 'string', + }, + }, + + edit, + + save( { attributes } ) { + const { backgroundColor, customBackgroundColor } = attributes; + + const backgroundClass = getColorClassName( 'background-color', backgroundColor ); + const className = classnames( backgroundClass, { + 'has-background': backgroundColor || customBackgroundColor, + } ); + + const styles = { + backgroundColor: backgroundClass ? undefined : customBackgroundColor, + }; + + return ( +
+ +
+ ); + }, +}; diff --git a/packages/block-library/src/section/theme.scss b/packages/block-library/src/section/theme.scss new file mode 100644 index 00000000000000..fc3a7edd3bbcd3 --- /dev/null +++ b/packages/block-library/src/section/theme.scss @@ -0,0 +1,10 @@ +.wp-block-section { + + &.has-background { + // Matches paragraph Block padding + // Todo: normalise with variables + padding: 20px 30px; + margin-top: 0; + margin-bottom: 0; + } +} diff --git a/packages/block-library/src/theme.scss b/packages/block-library/src/theme.scss index 5aa1b7281537cf..501240a4a9bbdc 100644 --- a/packages/block-library/src/theme.scss +++ b/packages/block-library/src/theme.scss @@ -6,6 +6,7 @@ @import "./pullquote/theme.scss"; @import "./quote/theme.scss"; @import "./search/theme.scss"; +@import "./section/theme.scss"; @import "./separator/theme.scss"; @import "./table/theme.scss"; @import "./video/theme.scss"; diff --git a/packages/e2e-tests/fixtures/block-transforms.js b/packages/e2e-tests/fixtures/block-transforms.js index bf1e218958c41a..57687da9444f80 100644 --- a/packages/e2e-tests/fixtures/block-transforms.js +++ b/packages/e2e-tests/fixtures/block-transforms.js @@ -144,6 +144,10 @@ export const EXPECTED_TRANSFORMS = { originalBlock: 'Search', availableTransforms: [], }, + core__section: { + originalBlock: 'Section', + availableTransforms: [], + }, core__separator: { originalBlock: 'Separator', availableTransforms: [], diff --git a/packages/e2e-tests/fixtures/blocks/core__section.html b/packages/e2e-tests/fixtures/blocks/core__section.html new file mode 100644 index 00000000000000..cf21a46b87991f --- /dev/null +++ b/packages/e2e-tests/fixtures/blocks/core__section.html @@ -0,0 +1,10 @@ + +
+ +

This is a section block.

+ + + +

Section block content.

+
+ diff --git a/packages/e2e-tests/fixtures/blocks/core__section.json b/packages/e2e-tests/fixtures/blocks/core__section.json new file mode 100644 index 00000000000000..7f27655f472cd4 --- /dev/null +++ b/packages/e2e-tests/fixtures/blocks/core__section.json @@ -0,0 +1,36 @@ +[ + { + "clientId": "_clientId_0", + "name": "core/section", + "isValid": true, + "attributes": { + "backgroundColor": "secondary", + "align": "full" + }, + "innerBlocks": [ + { + "clientId": "_clientId_0", + "name": "core/paragraph", + "isValid": true, + "attributes": { + "content": "This is a section block.", + "dropCap": false + }, + "innerBlocks": [], + "originalContent": "

This is a section block.

" + }, + { + "clientId": "_clientId_1", + "name": "core/paragraph", + "isValid": true, + "attributes": { + "content": "Section block content.", + "dropCap": false + }, + "innerBlocks": [], + "originalContent": "

Section block content.

" + } + ], + "originalContent": "
\n\t\n\n\t
" + } +] diff --git a/packages/e2e-tests/fixtures/blocks/core__section.parsed.json b/packages/e2e-tests/fixtures/blocks/core__section.parsed.json new file mode 100644 index 00000000000000..7cdcbf0c9c6eca --- /dev/null +++ b/packages/e2e-tests/fixtures/blocks/core__section.parsed.json @@ -0,0 +1,46 @@ +[ + { + "blockName": "core/section", + "attrs": { + "backgroundColor": "secondary", + "align": "full" + }, + "innerBlocks": [ + { + "blockName": "core/paragraph", + "attrs": {}, + "innerBlocks": [], + "innerHTML": "\n\t

This is a section block.

\n\t", + "innerContent": [ + "\n\t

This is a section block.

\n\t" + ] + }, + { + "blockName": "core/paragraph", + "attrs": {}, + "innerBlocks": [], + "innerHTML": "\n\t

Section block content.

\n\t", + "innerContent": [ + "\n\t

Section block content.

\n\t" + ] + } + ], + "innerHTML": "\n
\n\t\n\n\t
\n", + "innerContent": [ + "\n
\n\t", + null, + "\n\n\t", + null, + "
\n" + ] + }, + { + "blockName": null, + "attrs": {}, + "innerBlocks": [], + "innerHTML": "\n", + "innerContent": [ + "\n" + ] + } +] diff --git a/packages/e2e-tests/fixtures/blocks/core__section.serialized.html b/packages/e2e-tests/fixtures/blocks/core__section.serialized.html new file mode 100644 index 00000000000000..79f0c5eb54cc12 --- /dev/null +++ b/packages/e2e-tests/fixtures/blocks/core__section.serialized.html @@ -0,0 +1,9 @@ + +
+

This is a section block.

+ + + +

Section block content.

+
+ diff --git a/packages/e2e-tests/specs/blocks/__snapshots__/section.test.js.snap b/packages/e2e-tests/specs/blocks/__snapshots__/section.test.js.snap new file mode 100644 index 00000000000000..1e36e894ba4693 --- /dev/null +++ b/packages/e2e-tests/specs/blocks/__snapshots__/section.test.js.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Section can be created using the block inserter 1`] = ` +" +
+

Section block

+
+" +`; + +exports[`Section can be created using the slash inserter 1`] = ` +" +
+

Section block

+
+" +`; diff --git a/packages/e2e-tests/specs/blocks/section.test.js b/packages/e2e-tests/specs/blocks/section.test.js new file mode 100644 index 00000000000000..90ae574d0fcbe7 --- /dev/null +++ b/packages/e2e-tests/specs/blocks/section.test.js @@ -0,0 +1,32 @@ +/** + * WordPress dependencies + */ +import { + clickBlockAppender, + searchForBlock, + getEditedPostContent, + createNewPost, +} from '@wordpress/e2e-test-utils'; + +describe( 'Section', () => { + beforeEach( async () => { + await createNewPost(); + } ); + + it( 'can be created using the block inserter', async () => { + await searchForBlock( 'Section' ); + await page.click( '.editor-block-list-item-section' ); + await page.keyboard.type( 'Section block' ); + + expect( await getEditedPostContent() ).toMatchSnapshot(); + } ); + + it( 'can be created using the slash inserter', async () => { + await clickBlockAppender(); + await page.keyboard.type( '/section' ); + await page.keyboard.press( 'Enter' ); + await page.keyboard.type( 'Section block' ); + + expect( await getEditedPostContent() ).toMatchSnapshot(); + } ); +} ); diff --git a/packages/edit-post/src/components/visual-editor/style.scss b/packages/edit-post/src/components/visual-editor/style.scss index 1ba9ce38e01139..d0ec876d553152 100644 --- a/packages/edit-post/src/components/visual-editor/style.scss +++ b/packages/edit-post/src/components/visual-editor/style.scss @@ -31,11 +31,10 @@ // Use specific selector to not affect nested block toolbars. &[data-align="full"] > .block-editor-block-list__block-edit > .block-editor-block-contextual-toolbar { height: 0; // This collapses the container to an invisible element without margin. - width: 100%; + width: calc(100% - 1px); // -1px to account for inner element left: 1px value causing overflow-x scrollbars margin-left: 0; margin-right: 0; text-align: center; - // This float rule takes the toolbar out of the flow, without it having to be absolute positioned. // This is necessary because otherwise the mere presence of the toolbar can push down content. // Pairs with relative rule on line 49.