diff --git a/packages/block-editor/src/components/block-visibility/index.js b/packages/block-editor/src/components/block-visibility/index.js index 69b89e2c9497e6..fc79da9ce01592 100644 --- a/packages/block-editor/src/components/block-visibility/index.js +++ b/packages/block-editor/src/components/block-visibility/index.js @@ -3,3 +3,4 @@ export { default as useBlockVisibility } from './use-block-visibility'; export { default as ViewportVisibilityToolbar } from './viewport-toolbar'; export { default as BlockVisibilityViewportMenuItem } from './viewport-menu-item'; export { default as ViewportVisibilityInfo } from './viewport-visibility-info'; +export { getBlockVisibilityLabel } from './utils'; diff --git a/packages/block-editor/src/components/block-visibility/utils.js b/packages/block-editor/src/components/block-visibility/utils.js index 460283ea291e0b..c026a22f47893e 100644 --- a/packages/block-editor/src/components/block-visibility/utils.js +++ b/packages/block-editor/src/components/block-visibility/utils.js @@ -1,3 +1,8 @@ +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; + /** * Internal dependencies */ @@ -101,3 +106,38 @@ export function getHideEverywhereCheckboxState( blocks ) { return null; // Indeterminate: some but not all } + +/** + * Get a human-readable label describing which viewports a block is hidden on. + * + * @param {boolean|Object} blockVisibility The block's visibility metadata. + * @return {string|null} A descriptive label, or null if the block is not hidden. + */ +export function getBlockVisibilityLabel( blockVisibility ) { + // Not hidden at all + if ( ! blockVisibility && blockVisibility !== false ) { + return null; + } + + if ( blockVisibility === false ) { + // Hidden on all viewports + return __( 'Block is hidden' ); + } + + if ( blockVisibility?.viewport ) { + // Hidden on specific viewports - list them + const hiddenViewports = BLOCK_VISIBILITY_VIEWPORT_ENTRIES.filter( + ( [ key ] ) => blockVisibility.viewport?.[ key ] === false + ).map( ( [ , viewport ] ) => viewport.label ); + + if ( hiddenViewports.length > 0 ) { + return sprintf( + /* translators: %s: comma-separated list of viewport names (Desktop, Tablet, Mobile) */ + __( 'Block is hidden on %s' ), + hiddenViewports.join( ', ' ) + ); + } + } + + return null; +} diff --git a/packages/block-editor/src/components/list-view/block-select-button.js b/packages/block-editor/src/components/list-view/block-select-button.js index baa349f879ea75..32df3b7458e4ee 100644 --- a/packages/block-editor/src/components/list-view/block-select-button.js +++ b/packages/block-editor/src/components/list-view/block-select-button.js @@ -9,6 +9,7 @@ import clsx from 'clsx'; import { __experimentalHStack as HStack, __experimentalTruncate as Truncate, + Tooltip, privateApis as componentsPrivateApis, } from '@wordpress/components'; import { forwardRef } from '@wordpress/element'; @@ -33,6 +34,7 @@ import { useBlockLock } from '../block-lock'; import useListViewImages from './use-list-view-images'; import { store as blockEditorStore } from '../../store'; import { unlock } from '../../lock-unlock'; +import { getBlockVisibilityLabel } from '../block-visibility'; const { Badge } = unlock( componentsPrivateApis ); @@ -60,16 +62,13 @@ function ListViewBlockSelectButton( context: 'list-view', } ); const { isLocked } = useBlockLock( clientId ); - const { isBlockHidden, hasPatternName } = useSelect( + const { hasPatternName, blockVisibility } = useSelect( ( select ) => { - const { - isBlockHiddenAnywhere: _isBlockHidden, - getBlockAttributes, - } = unlock( select( blockEditorStore ) ); + const { getBlockAttributes } = unlock( select( blockEditorStore ) ); + const attributes = getBlockAttributes( clientId ); return { - isBlockHidden: _isBlockHidden( clientId ), - hasPatternName: - !! getBlockAttributes( clientId )?.metadata?.patternName, + hasPatternName: !! attributes?.metadata?.patternName, + blockVisibility: attributes?.metadata?.blockVisibility, }; }, [ clientId ] @@ -79,6 +78,9 @@ function ListViewBlockSelectButton( const isSticky = blockInformation?.positionType === 'sticky'; const images = useListViewImages( { clientId, isExpanded } ); + // Determine visibility label from blockVisibility metadata + const visibilityLabel = getBlockVisibilityLabel( blockVisibility ); + // The `href` attribute triggers the browser's native HTML drag operations. // When the link is dragged, the element's outerHTML is set in DataTransfer object as text/html. // We need to clear any HTML drag data to prevent `pasteHandler` from firing @@ -161,10 +163,15 @@ function ListViewBlockSelectButton( ) ) } ) : null } - { isBlockHidden && ( - - - + { !! visibilityLabel && ( + + + ) } { shouldShowLockIcon && ( diff --git a/packages/block-editor/src/components/list-view/block.js b/packages/block-editor/src/components/list-view/block.js index e05036e6e07aa7..0df5b3a57aac5a 100644 --- a/packages/block-editor/src/components/list-view/block.js +++ b/packages/block-editor/src/components/list-view/block.js @@ -25,7 +25,7 @@ import { memo, } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; -import { __, sprintf } from '@wordpress/i18n'; +import { __ } from '@wordpress/i18n'; import { BACKSPACE, DELETE } from '@wordpress/keycodes'; import { isShallowEqual } from '@wordpress/is-shallow-equal'; import { __unstableUseShortcutEventMatch as useShortcutEventMatch } from '@wordpress/keyboard-shortcuts'; @@ -54,9 +54,7 @@ import { useBlockRename, BlockRenameModal } from '../block-rename'; import AriaReferencedText from './aria-referenced-text'; import { unlock } from '../../lock-unlock'; import usePasteStyles from '../use-paste-styles'; -import { useBlockVisibility } from '../block-visibility'; -import { deviceTypeKey } from '../../store/private-keys'; -import { BLOCK_VISIBILITY_VIEWPORTS } from '../block-visibility/constants'; +import { getBlockVisibilityLabel } from '../block-visibility'; function ListViewBlock( { block: { clientId }, @@ -127,51 +125,22 @@ function ListViewBlock( { const pasteStyles = usePasteStyles(); - const { block, blockName, allowRightClickOverrides, selectedDeviceType } = - useSelect( - ( select ) => { - const { getBlock, getBlockName, getSettings } = unlock( - select( blockEditorStore ) - ); + const { block, blockName, allowRightClickOverrides } = useSelect( + ( select ) => { + const { getBlock, getBlockName, getSettings } = unlock( + select( blockEditorStore ) + ); - return { - block: getBlock( clientId ), - blockName: getBlockName( clientId ), - allowRightClickOverrides: - getSettings().allowRightClickOverrides, - selectedDeviceType: - getSettings()?.[ deviceTypeKey ]?.toLowerCase() || - BLOCK_VISIBILITY_VIEWPORTS.desktop.value, - }; - }, - [ clientId ] - ); + return { + block: getBlock( clientId ), + blockName: getBlockName( clientId ), + allowRightClickOverrides: + getSettings().allowRightClickOverrides, + }; + }, + [ clientId ] + ); const { canRename } = useBlockRename( blockName ); - // Use hook to get current viewport and if block is currently hidden (accurate viewport detection) - const { isBlockCurrentlyHidden, currentViewport } = useBlockVisibility( { - blockVisibility: block?.attributes?.metadata?.blockVisibility, - deviceType: selectedDeviceType, - } ); - - // Determine label based on whether block or parent is hidden - const blockVisibilityDescription = useMemo( () => { - if ( isBlockCurrentlyHidden ) { - if ( block?.attributes?.metadata?.blockVisibility === false ) { - return __( 'Block is hidden' ); - } - return sprintf( - /* translators: %s: viewport name (Desktop, Tablet, Mobile) */ - __( 'Block is hidden on %s' ), - BLOCK_VISIBILITY_VIEWPORTS[ currentViewport ]?.label || - currentViewport - ); - } - return null; - }, [ - isBlockCurrentlyHidden, - block?.attributes?.metadata?.blockVisibility, - currentViewport, - ] ); const showBlockActions = // When a block hides its toolbar it also hides the block settings menu, @@ -559,6 +528,11 @@ function ListViewBlock( { isLocked ); + // Determine label based on where block is hidden (not when/current viewport) + const blockVisibilityDescription = getBlockVisibilityLabel( + block?.attributes?.metadata?.blockVisibility + ); + const hasSiblings = siblingBlockCount > 0; const hasRenderedMovers = showBlockMovers && hasSiblings; const moverCellClassName = clsx(