Skip to content

Latest commit

 

History

History
219 lines (164 loc) · 7.2 KB

File metadata and controls

219 lines (164 loc) · 7.2 KB

ResponsiveBlockControl

ResponsiveBlockControl provides a standardised interface for the creation of Block controls that require different settings per viewport (ie: "responsive" settings).

For example, imagine your Block provides a control which affords the ability to change a "padding" value used in the Block display. Consider that whilst this setting may work well on "large" screens, the same value may not work well on smaller screens (it may be too large for example). As a result, you now need to provide a padding control per viewport/screen size.

ResponsiveBlockControl provides a standardised component for the creation of such interfaces within Gutenberg.

Complete control over rendering the controls is provided and the viewport sizes used are entirely customisable.

Note that ResponsiveBlockControl does not handle any persistence of your control values. The control you provide to ResponsiveBlockControl as the renderDefaultControl prop should take care of this.

Usage

In a block's edit implementation, render a <ResponsiveBlockControl /> component passing the required props plus:

  1. a renderDefaultControl function which renders an interface control.
  2. an boolean state for isResponsive (see "Props" below).
  3. a handler function for onIsResponsiveChange (see "Props" below).

By default the default control will be used to render the default (ie: "All") setting as well as the per-viewport responsive settings.

import { useState } from 'react';
import { registerBlockType } from '@wordpress/blocks';
import {
	InspectorControls,
	__experimentalResponsiveBlockControl as ResponsiveBlockControl,
} from '@wordpress/block-editor';

registerBlockType( 'my-plugin/my-block', {
	// ...

	edit( { attributes, setAttributes } ) {

		const [ isResponsive, setIsResponsive ] = useState( false );
		const { paddingSize } = attributes;

		// Your custom control can be anything you'd like to use.
		const paddingControl = ( labelComponent, viewport ) => {
			return (
				<input
					type="number"
					label={ viewport.label }
					onChange={ // handle update to padding value here  }
					value={ paddingSize }
				/>
			);
		};

		return (
			<>
				<InspectorControls>
					<ResponsiveBlockControl
						title='Block Padding'
						property='padding'
						renderDefaultControl={paddingControl}
						isResponsive={ isResponsive }
						onIsResponsiveChange={ () => {
							setIsResponsive( ! isResponsive );
						} }
					/>
				</InspectorControls>
				<div>
					// your Block here
				</div>
			</>
		);
	}
} );

Props

title

  • Type: String
  • Default: undefined
  • Required: true

The title of the control group used in the fieldset's legend element to label the entire set of controls.

property

  • Type: String
  • Default: undefined
  • Required: true

Used to build accessible labels and ARIA roles for the control group. Should represent the layout property which the component controls (eg: padding, margin...etc).

isResponsive

  • Type: Boolean
  • Default: false )
  • Required: false

Determines whether the component displays the default or responsive controls. Updates the state of the toggle control. See also onIsResponsiveChange below.

onIsResponsiveChange

  • Type: Function
  • Default: undefined
  • Required: true

A callback function invoked when the component's toggle value is changed between responsive and non-responsive mode. Should be used to update the value of the isResponsive prop to reflect the current state of the toggle control.

renderDefaultControl

  • Type: Function
  • Default: undefined
  • Required: true
  • Args:
    • labelComponent: (Function) - a rendered ResponsiveBlockControlLabel component for your control.
    • viewport: (Object) - an object representing viewport attributes for your control.

A render function (prop) used to render the control for which you would like to display per viewport settings.

For example, if you have a SelectControl which controls padding size, then pass this component as renderDefaultControl and it will be used to render both default and "responsive" controls for "padding".

The component you return from this function will be used to render the control displayed for the (default) "All" state and (if the renderResponsiveControls is not provided) the individual responsive controls when in "responsive" mode.

It is passed a pre-created, accessible <label>. Your control may also use the contextual information provided by the viewport argument to ensure your component renders appropriately depending on the viewport setting currently being rendered (eg: All or one of the responsive variants).

Note: you are required to handle persisting any state produced by the component you pass as renderDefaultControl. ResponsiveBlockControl is "controlled" and does not persist state in any form.

const renderDefaultControl = ( labelComponent, viewport ) => {
	const { id, label } = viewport;
	// eg:
	// {
	// 	id: 'small',
	// 	label: 'All'
	// }
	return <SelectControl label={ labelComponent } />;
};

renderResponsiveControls

  • Type: Function
  • Default: undefined
  • Required: false
  • Args:
    • viewports: (Array) - an array of viewport Objects, each with an id and label property.

An optional render function (prop) used to render the controls for the responsive settings. If not provided, by default, responsive controls will be automatically rendered using the component returned by the renderDefaultControl prop. For complete control over the output of the responsive controls, you may return a component here and it will be rendered when the control group is in "responsive" mode.

let uniqueId = 0;

const renderResponsiveControls = ( viewports ) => {
	const inputId = ++uniqueId;

	return viewports.map( ( { id, label } ) => {
		return (
			<Fragment key={ `${ inputId }-${ id }` }>
				<label htmlFor={ `${ inputId }-${ id }` }>
					Custom Viewport { label }
				</label>
				<input
					id={ `${ inputId }-${ id }` }
					defaultValue={ label }
					type="range"
				/>
			</Fragment>
		);
	} );
};

toggleLabel

  • Type: String
  • Default: Use the same %s on all screen sizes. (where "%s" is the property prop - see above )
  • Required: false

Optional label used for the toggle control which switches the interface between showing responsive controls or not.

defaultLabel

  • Type: Object
  • Default:
{
	id: 'all',
	label: 'All',
}
  • Required: false

Optional object describing the attributes of the default value. By default this is All which indicates the control will affect "all viewports/screen sizes".

viewports

  • Type: Array
  • Default:
[
	{
		id: 'small',
		label: 'Small screens',
	},
	{
		id: 'medium',
		label: 'Medium screens',
	},
	{
		id: 'large',
		label: 'Large screens',
	},
];
  • Required: false

An array of viewport objects, each describing a configuration for a particular viewport size. These are used to determine the number of responsive controls to display and the configuration of each.