Skip to content

Commit 7feff31

Browse files
t-hamanotyxlaMamadukaramonjdtalldan
authored
Block API: Add block visibility control support and UI (#71203)
* Block API: Add block visibility control support and UI * Render hidden block block * Remove unused code * Always hide block when it's not selected * Extend existing isBlockVisible selector and use it * Revert "Extend existing isBlockVisible selector and use it" This reverts commit c3f7135. * Remove SCSS import statement * Use "isBlockHidden" * Remove useBlockVisibility hook * useBlockDropZone: Filter out blocks that are hidden * Remove useBlockVisibility hook * Update doc * Show hidden block placeholder when dragging * Revert "Show hidden block placeholder when dragging" This reverts commit 2bfa54e. * Show block toolbar button only when editing mode is default * Process metadata updates for multiple blocks at once * Preserve block visibility metadata in block transforms * Remove support from schema and docs * Add experiments setting * Make Block Visibility as experiment feature * Rename __experimentalBlockVisibility to blockVisibility * Fix: other metadata attributes get stripped when toggling via the toolbar * Show block toolbar button when multiple blocks are selected * Fix incorrect block.json definition * Apply opacity to hidden and selected blocks * Revert "Apply opacity to hidden and selected blocks" This reverts commit 5596f83. * Provide blockVilibility metadata to preview context * Accordion Header, Accordion Panel: disable blockVisibility support * Visually hide block * Stabilize feature * Add backport changelog * Update server side function * Use "visibility:hidden" to visually hide blocks * Combine multiple useSelect call into one * Reset styles from hidden blocks * Update lib/block-supports/block-visibility.php Co-authored-by: Mukesh Panchal <[email protected]> * Better behavior for hidden blocks --------- Co-authored-by: t-hamano <[email protected]> Co-authored-by: tyxla <[email protected]> Co-authored-by: Mamaduka <[email protected]> Co-authored-by: ramonjd <[email protected]> Co-authored-by: talldan <[email protected]> Co-authored-by: sunyatasattva <[email protected]> Co-authored-by: mukeshpanchal27 <[email protected]> Co-authored-by: jasmussen <[email protected]> Co-authored-by: annezazu <[email protected]> Co-authored-by: supernovia <[email protected]> Co-authored-by: andrewserong <[email protected]> Co-authored-by: jameskoster <[email protected]>
1 parent 98386bd commit 7feff31

File tree

23 files changed

+354
-33
lines changed

23 files changed

+354
-33
lines changed

backport-changelog/6.9/10110.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
https://github.com/WordPress/wordpress-develop/pull/10110
2+
3+
* https://github.com/WordPress/gutenberg/pull/71203

docs/reference-guides/core-blocks.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Displays an accordion header. ([Source](https://github.com/WordPress/gutenberg/t
3939
- **Experimental:** true
4040
- **Category:** design
4141
- **Parent:** core/accordion-content
42-
- **Supports:** anchor, color (background, gradients, text), interactivity, shadow, spacing (padding), typography (fontSize), ~~align~~
42+
- **Supports:** anchor, color (background, gradients, text), interactivity, shadow, spacing (padding), typography (fontSize), ~~align~~, ~~blockVisibility~~
4343
- **Attributes:** iconPosition, level, levelOptions, openByDefault, showIcon, title
4444

4545
## Accordion Panel
@@ -50,7 +50,7 @@ Displays an accordion panel. ([Source](https://github.com/WordPress/gutenberg/tr
5050
- **Experimental:** true
5151
- **Category:** design
5252
- **Parent:** core/accordion-content
53-
- **Supports:** color (background, gradients, text), interactivity, layout, shadow, spacing (blockGap, padding), typography (fontSize, lineHeight)
53+
- **Supports:** color (background, gradients, text), interactivity, layout, shadow, spacing (blockGap, padding), typography (fontSize, lineHeight), ~~blockVisibility~~
5454
- **Attributes:** allowedBlocks, isSelected, openByDefault, templateLock
5555

5656
## Archives
@@ -86,7 +86,7 @@ Reuse this design across your site. ([Source](https://github.com/WordPress/guten
8686

8787
- **Name:** core/block
8888
- **Category:** reusable
89-
- **Supports:** interactivity (clientNavigation), ~~customClassName~~, ~~html~~, ~~inserter~~, ~~renaming~~
89+
- **Supports:** interactivity (clientNavigation), ~~blockVisibility~~, ~~customClassName~~, ~~html~~, ~~inserter~~, ~~renaming~~
9090
- **Attributes:** content, ref
9191

9292
## Button
@@ -585,7 +585,7 @@ Show a block pattern. ([Source](https://github.com/WordPress/gutenberg/tree/trun
585585

586586
- **Name:** core/pattern
587587
- **Category:** theme
588-
- **Supports:** interactivity (clientNavigation), ~~html~~, ~~inserter~~, ~~renaming~~
588+
- **Supports:** interactivity (clientNavigation), ~~blockVisibility~~, ~~html~~, ~~inserter~~, ~~renaming~~
589589
- **Attributes:** slug
590590

591591
## Author
@@ -975,7 +975,7 @@ Edit the different global regions of your site, like the header, footer, sidebar
975975

976976
- **Name:** core/template-part
977977
- **Category:** theme
978-
- **Supports:** align, interactivity (clientNavigation), ~~html~~, ~~renaming~~, ~~reusable~~
978+
- **Supports:** align, interactivity (clientNavigation), ~~blockVisibility~~, ~~html~~, ~~renaming~~, ~~reusable~~
979979
- **Attributes:** area, slug, tagName, theme
980980

981981
## Term Description
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
/**
3+
* Block visibility block support flag.
4+
*
5+
* @package gutenberg
6+
*/
7+
8+
/**
9+
* Render nothing if the block is hidden.
10+
*
11+
* @param string $block_content Rendered block content.
12+
* @param array $block Block object.
13+
* @return string Filtered block content.
14+
*/
15+
function gutenberg_render_block_visibility_support( $block_content, $block ) {
16+
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
17+
18+
if ( ! $block_type || ! block_has_support( $block_type, 'blockVisibility', true ) ) {
19+
return $block_content;
20+
}
21+
22+
if ( isset( $block['attrs']['metadata']['blockVisibility'] ) && false === $block['attrs']['metadata']['blockVisibility'] ) {
23+
return '';
24+
}
25+
26+
return $block_content;
27+
}
28+
29+
if ( function_exists( 'wp_render_block_visibility_support' ) ) {
30+
remove_filter( 'render_block', 'wp_render_block_visibility_support' );
31+
}
32+
add_filter( 'render_block', 'gutenberg_render_block_visibility_support', 10, 2 );

lib/load.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ function gutenberg_is_experiment_enabled( $name ) {
162162
require __DIR__ . '/block-supports/background.php';
163163
require __DIR__ . '/block-supports/block-style-variations.php';
164164
require __DIR__ . '/block-supports/aria-label.php';
165+
require __DIR__ . '/block-supports/block-visibility.php';
165166

166167
// Data views.
167168
require_once __DIR__ . '/experimental/data-views.php';

packages/block-editor/src/components/block-list/block.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,7 @@ function BlockListBlockProvider( props ) {
624624
? getBlockDefaultClassName( blockName )
625625
: undefined,
626626
blockTitle: blockType?.title,
627+
isBlockHidden: attributes?.metadata?.blockVisibility === false,
627628
};
628629

629630
// When in preview mode, we can avoid a lot of selection and
@@ -632,6 +633,9 @@ function BlockListBlockProvider( props ) {
632633
return previewContext;
633634
}
634635

636+
const { isBlockHidden: _isBlockHidden } = unlock(
637+
select( blockEditorStore )
638+
);
635639
const _isSelected = isBlockSelected( clientId );
636640
const canRemove = canRemoveBlock( clientId );
637641
const canMove = canMoveBlock( clientId );
@@ -705,6 +709,7 @@ function BlockListBlockProvider( props ) {
705709
originalBlockClientId: isInvalid
706710
? blocksWithSameName[ 0 ]
707711
: false,
712+
isBlockHidden: _isBlockHidden( clientId ),
708713
};
709714
},
710715
[ clientId, rootClientId ]
@@ -747,6 +752,7 @@ function BlockListBlockProvider( props ) {
747752
className,
748753
defaultClassName,
749754
originalBlockClientId,
755+
isBlockHidden,
750756
} = selectedProps;
751757

752758
// Users of the editor.BlockListBlock filter used to be able to
@@ -795,8 +801,18 @@ function BlockListBlockProvider( props ) {
795801
originalBlockClientId,
796802
themeSupportsLayout,
797803
canMove,
804+
isBlockHidden,
798805
};
799806

807+
if (
808+
isBlockHidden &&
809+
! isSelected &&
810+
! isMultiSelected &&
811+
! hasChildSelected
812+
) {
813+
return null;
814+
}
815+
800816
// Here we separate between the props passed to BlockListBlock and any other
801817
// information we selected for internal use. BlockListBlock is a filtered
802818
// component and thus ALL the props are PUBLIC API.

packages/block-editor/src/components/block-list/content.scss

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,25 @@ _::-webkit-full-page-media, _:future, :root [data-has-multi-selection="true"] .b
9393
}
9494
}
9595

96+
97+
// Hidden blocks.
98+
// In order for the block toolbar to render correctly, blocks cannot be hidden.
99+
// Instead, use styles to visually hide blocks.
100+
.block-editor-block-list__block.is-block-hidden {
101+
visibility: hidden;
102+
overflow: hidden;
103+
height: 0;
104+
border: none !important;
105+
padding: 0 !important;
106+
}
107+
108+
&.is-layout-flex:not(.is-vertical) > .is-block-hidden {
109+
width: 0;
110+
height: auto;
111+
align-self: stretch;
112+
white-space: nowrap !important;
113+
}
114+
96115
// Re-enable it on components inside.
97116
[class^="components-"] {
98117
user-select: text;

packages/block-editor/src/components/block-list/use-block-props/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
101101
defaultClassName,
102102
isSectionBlock,
103103
canMove,
104+
isBlockHidden,
104105
} = useContext( PrivateBlockContext );
105106

106107
// translators: %s: Type of block (i.e. Text, Image etc)
@@ -183,6 +184,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
183184
'has-negative-margin': hasNegativeMargin,
184185
'is-content-locked-temporarily-editing-as-blocks':
185186
isTemporarilyEditingAsBlocks,
187+
'is-block-hidden': isBlockHidden,
186188
},
187189
className,
188190
props.className,

packages/block-editor/src/components/block-settings-menu-controls/index.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
MenuGroup,
77
__experimentalStyleProvider as StyleProvider,
88
} from '@wordpress/components';
9+
import { hasBlockSupport } from '@wordpress/blocks';
910
import { useSelect } from '@wordpress/data';
1011

1112
/**
@@ -20,13 +21,20 @@ import { store as blockEditorStore } from '../../store';
2021
import BlockModeToggle from '../block-settings-menu/block-mode-toggle';
2122
import { ModifyContentLockMenuItem } from '../content-lock';
2223
import { BlockRenameControl, useBlockRename } from '../block-rename';
24+
import { BlockVisibilityMenuItem } from '../block-visibility';
2325

2426
const { Fill, Slot } = createSlotFill( 'BlockSettingsMenuControls' );
2527

2628
const BlockSettingsMenuControlsSlot = ( { fillProps, clientIds = null } ) => {
27-
const { selectedBlocks, selectedClientIds, isContentOnly } = useSelect(
29+
const {
30+
selectedBlocks,
31+
selectedClientIds,
32+
isContentOnly,
33+
canToggleSelectedBlocksVisibility,
34+
} = useSelect(
2835
( select ) => {
2936
const {
37+
getBlocksByClientId,
3038
getBlockNamesByClientId,
3139
getSelectedBlockClientIds,
3240
getBlockEditingMode,
@@ -38,6 +46,11 @@ const BlockSettingsMenuControlsSlot = ( { fillProps, clientIds = null } ) => {
3846
selectedClientIds: ids,
3947
isContentOnly:
4048
getBlockEditingMode( ids[ 0 ] ) === 'contentOnly',
49+
canToggleSelectedBlocksVisibility: getBlocksByClientId(
50+
ids
51+
).every( ( block ) =>
52+
hasBlockSupport( block.name, 'blockVisibility', true )
53+
),
4154
};
4255
},
4356
[ clientIds ]
@@ -49,6 +62,8 @@ const BlockSettingsMenuControlsSlot = ( { fillProps, clientIds = null } ) => {
4962
selectedClientIds.length === 1 && canLock && ! isContentOnly;
5063
const showRenameButton =
5164
selectedClientIds.length === 1 && canRename && ! isContentOnly;
65+
const showVisibilityButton =
66+
canToggleSelectedBlocksVisibility && ! isContentOnly;
5267

5368
// Check if current selection of blocks is Groupable or Ungroupable
5469
// and pass this props down to ConvertToGroupButton.
@@ -93,6 +108,11 @@ const BlockSettingsMenuControlsSlot = ( { fillProps, clientIds = null } ) => {
93108
clientId={ selectedClientIds[ 0 ] }
94109
/>
95110
) }
111+
{ showVisibilityButton && (
112+
<BlockVisibilityMenuItem
113+
clientIds={ selectedClientIds }
114+
/>
115+
) }
96116
{ fills }
97117
{ selectedClientIds.length === 1 && (
98118
<ModifyContentLockMenuItem

packages/block-editor/src/components/block-toolbar/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import BlockControls from '../block-controls';
2828
import __unstableBlockToolbarLastItem from './block-toolbar-last-item';
2929
import BlockSettingsMenu from '../block-settings-menu';
3030
import { BlockLockToolbar } from '../block-lock';
31+
import { BlockVisibilityToolbar } from '../block-visibility';
3132
import { BlockGroupToolbar } from '../convert-to-group-buttons';
3233
import BlockEditVisuallyButton from '../block-edit-visually-button';
3334
import { useShowHoveredOrFocusedGestures } from './utils';
@@ -73,6 +74,7 @@ export function PrivateBlockToolbar( {
7374
showSlots,
7475
showGroupButtons,
7576
showLockButtons,
77+
showBlockVisibilityButton,
7678
showSwitchSectionStyleButton,
7779
hasFixedToolbar,
7880
isNavigationMode,
@@ -163,6 +165,7 @@ export function PrivateBlockToolbar( {
163165
showSlots: ! _isZoomOut,
164166
showGroupButtons: ! _isZoomOut,
165167
showLockButtons: ! _isZoomOut,
168+
showBlockVisibilityButton: ! _isZoomOut,
166169
showSwitchSectionStyleButton: _showSwitchSectionStyleButton,
167170
hasFixedToolbar: getSettings().hasFixedToolbar,
168171
isNavigationMode: isNavigationModeEnabled,
@@ -227,6 +230,12 @@ export function PrivateBlockToolbar( {
227230
>
228231
<ToolbarGroup className="block-editor-block-toolbar__block-controls">
229232
<BlockSwitcher clientIds={ blockClientIds } />
233+
{ isDefaultEditingMode &&
234+
showBlockVisibilityButton && (
235+
<BlockVisibilityToolbar
236+
clientIds={ blockClientIds }
237+
/>
238+
) }
230239
{ ! isMultiToolbar &&
231240
isDefaultEditingMode &&
232241
showLockButtons && (
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as BlockVisibilityMenuItem } from './menu-item';
2+
export { default as BlockVisibilityToolbar } from './toolbar';

0 commit comments

Comments
 (0)