From f6ca65d8bdfb63cff9d786c1440535b306d629cf Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Thu, 1 Dec 2022 17:13:37 +1100 Subject: [PATCH] Try a CustomSelectControl for the position input --- packages/block-editor/src/hooks/position.js | 143 +++++++++++++----- packages/block-editor/src/hooks/position.scss | 18 +++ packages/block-editor/src/style.scss | 1 + 3 files changed, 121 insertions(+), 41 deletions(-) create mode 100644 packages/block-editor/src/hooks/position.scss diff --git a/packages/block-editor/src/hooks/position.js b/packages/block-editor/src/hooks/position.js index 6e8e7bb12abf02..c4d6eb65f2f629 100644 --- a/packages/block-editor/src/hooks/position.js +++ b/packages/block-editor/src/hooks/position.js @@ -6,14 +6,16 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; import { getBlockSupport, hasBlockSupport } from '@wordpress/blocks'; -import { - __experimentalToggleGroupControl as ToggleGroupControl, - __experimentalToggleGroupControlOption as ToggleGroupControlOption, -} from '@wordpress/components'; +import { BaseControl, CustomSelectControl } from '@wordpress/components'; import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose'; -import { useContext, createPortal, Platform } from '@wordpress/element'; +import { + useContext, + useMemo, + createPortal, + Platform, +} from '@wordpress/element'; import { addFilter } from '@wordpress/hooks'; /** @@ -26,20 +28,36 @@ import { cleanEmptyObject } from './utils'; const POSITION_SUPPORT_KEY = 'position'; -const POSITION_OPTIONS = [ - { - key: 'default', - label: __( 'Default' ), - value: '', - name: __( 'Default' ), - }, - { - key: 'sticky', - label: __( 'Sticky' ), - value: 'sticky', - name: __( 'Sticky' ), - }, -]; +const OPTION_CLASSNAME = + 'block-editor-hooks__position-selection__select-control__option'; + +const DEFAULT_OPTION = { + key: 'static', + value: '', + name: __( 'Static' ), + className: OPTION_CLASSNAME, + __experimentalHint: __( 'The default position' ), +}; + +const STICKY_OPTION = { + key: 'sticky', + value: 'sticky', + name: __( 'Sticky' ), + className: OPTION_CLASSNAME, + __experimentalHint: __( + 'The block will scroll with the document but stick instead of exiting the viewport' + ), +}; + +const FIXED_OPTION = { + key: 'fixed', + value: 'fixed', + name: __( 'Fixed' ), + className: OPTION_CLASSNAME, + __experimentalHint: __( + 'The block will not move when the page is scrolled' + ), +}; const POSITION_SIDES = [ 'top', 'right', 'bottom', 'left' ]; const VALID_POSITION_TYPES = [ 'sticky', 'fixed' ]; @@ -79,6 +97,30 @@ export function getPositionCSS( { selector, style } ) { return output; } +/** + * Determines if there is sticky position support. + * + * @param {string|Object} blockType Block name or Block Type object. + * + * @return {boolean} Whether there is support. + */ +export function hasStickyPositionSupport( blockType ) { + const support = getBlockSupport( blockType, POSITION_SUPPORT_KEY ); + return !! ( true === support || support?.sticky ); +} + +/** + * Determines if there is fixed position support. + * + * @param {string|Object} blockType Block name or Block Type object. + * + * @return {boolean} Whether there is support. + */ +export function hasFixedPositionSupport( blockType ) { + const support = getBlockSupport( blockType, POSITION_SUPPORT_KEY ); + return !! ( true === support || support?.fixed ); +} + /** * Determines if there is position support. * @@ -152,9 +194,24 @@ export function useIsPositionDisabled( { name: blockName } = {} ) { export function PositionEdit( props ) { const { attributes: { style = {} }, + name: blockName, setAttributes, } = props; + const allowFixed = hasFixedPositionSupport( blockName ); + const allowSticky = hasStickyPositionSupport( blockName ); + + const options = useMemo( () => { + const availableOptions = [ DEFAULT_OPTION ]; + if ( allowSticky ) { + availableOptions.push( STICKY_OPTION ); + } + if ( allowFixed ) { + availableOptions.push( FIXED_OPTION ); + } + return availableOptions; + }, [ allowFixed, allowSticky ] ); + if ( useIsPositionDisabled( props ) ) { return null; } @@ -182,30 +239,34 @@ export function PositionEdit( props ) { } ); }; + const value = style?.position?.type; + const selectedOption = value + ? options.find( ( option ) => option.value === value ) + : DEFAULT_OPTION; + return Platform.select( { web: ( <> - { - onChangeType( newValue ); - } } - isBlock - > - { POSITION_OPTIONS.map( ( option ) => ( - - ) ) } - + + { + onChangeType( selectedItem.value ); + } } + size={ '__unstable-large' } + /> + ), native: null, diff --git a/packages/block-editor/src/hooks/position.scss b/packages/block-editor/src/hooks/position.scss new file mode 100644 index 00000000000000..b3bd6b1b9ef041 --- /dev/null +++ b/packages/block-editor/src/hooks/position.scss @@ -0,0 +1,18 @@ +.block-editor-hooks__position-selection__select-control { + .components-custom-select-control__hint { + display: none; + } +} + +.block-editor-hooks__position-selection__select-control__option { + &.has-hint { + grid-template-columns: auto 30px; + line-height: $default-line-height; + margin-bottom: 0; + } + + .components-custom-select-control__item-hint { + grid-row: 2; + text-align: left; + } +} diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index 8237e715e2cc30..8554a5bece5cb5 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -49,6 +49,7 @@ @import "./hooks/layout.scss"; @import "./hooks/border.scss"; @import "./hooks/dimensions.scss"; +@import "./hooks/position.scss"; @import "./hooks/typography.scss"; @import "./hooks/color.scss"; @import "./hooks/padding.scss";