Skip to content

Commit

Permalink
Cover Block: Normalize the block toolbar (#29247)
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowriad authored Mar 15, 2021
1 parent 7cf7369 commit e382528
Show file tree
Hide file tree
Showing 31 changed files with 430 additions and 391 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Alignment Matrix Control

The alignment matrix control allows users to quickly adjust inner block alignment; this is in contrast to the alignment toolbar that aligns the frame block.

![Button components](https://i.imgur.com/PxYkgL5.png)

## Table of contents

- [Alignment Matrix Control](#alignment-matrix-control)
- [Table of contents](#table-of-contents)
- [Design guidelines](#design-guidelines)
- [Usage](#usage)
- [Development guidelines](#development-guidelines)
- [Usage](#usage-1)
- [Props](#props)

## Design guidelines

### Usage

The alignment matrix is a specialized tool, and it's used in the cover block.

![Cover](https://i.imgur.com/nJjqen8.png)

As an example, here's the matrix alignment tool in action.

![center](https://i.imgur.com/0Ce1fZm.png)

![rop_right](https://i.imgur.com/yGGf6IP.png)

## Development guidelines

### Usage

```jsx
// This is a paraphrased example from the cover block
import {
BlockControls,
__experimentalBlockAlignmentMatrixControl as BlockAlignmentMatrixControl
} from "@wordpress/block-editor";

const controls = (
<>
<BlockControls>
<BlockAlignmentMatrixControl
label={ __( 'Change content position' ) }
value={ contentPosition }
onChange={ ( nextPosition ) =>
setAttributes( { contentPosition: nextPosition } )
}
/>
</BlockControls>
</>
}
```
### Props
| Name | Type | Default | Description |
| ---------- | ---------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `label` | `string` | `Change matrix alignment` | concise description of tool's functionality. |
| `onChange` | `function` | `noop` | the function to execute upon a user's change of the matrix state |
| `value` | `string` | `center` | describes the content alignment location and can be `top`, `right`, `bottom`, `left`, `topRight`, `bottomRight`, `bottomLeft`, `topLeft` |
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ import { DOWN } from '@wordpress/keycodes';
import {
ToolbarButton,
Dropdown,
ToolbarGroup,
__experimentalAlignmentMatrixControl as AlignmentMatrixControl,
} from '@wordpress/components';

export function BlockAlignmentMatrixToolbar( props ) {
function BlockAlignmentMatrixControl( props ) {
const {
label = __( 'Change matrix alignment' ),
onChange = noop,
Expand All @@ -23,7 +22,7 @@ export function BlockAlignmentMatrixToolbar( props ) {
} = props;

const icon = <AlignmentMatrixControl.Icon value={ value } />;
const className = 'block-editor-block-alignment-matrix-toolbar';
const className = 'block-editor-block-alignment-matrix-control';
const popoverClassName = `${ className }__popover`;
const isAlternate = true;

Expand All @@ -42,18 +41,16 @@ export function BlockAlignmentMatrixToolbar( props ) {
};

return (
<ToolbarGroup>
<ToolbarButton
onClick={ onToggle }
aria-haspopup="true"
aria-expanded={ isOpen }
onKeyDown={ openOnArrowDown }
label={ label }
icon={ icon }
showTooltip
disabled={ isDisabled }
/>
</ToolbarGroup>
<ToolbarButton
onClick={ onToggle }
aria-haspopup="true"
aria-expanded={ isOpen }
onKeyDown={ openOnArrowDown }
label={ label }
icon={ icon }
showTooltip
disabled={ isDisabled }
/>
);
} }
renderContent={ () => (
Expand All @@ -67,4 +64,4 @@ export function BlockAlignmentMatrixToolbar( props ) {
);
}

export default BlockAlignmentMatrixToolbar;
export default BlockAlignmentMatrixControl;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.block-editor-block-alignment-matrix-toolbar__popover {
.block-editor-block-alignment-matrix-control__popover {
.components-popover__content {
min-width: 0;
width: auto;
Expand All @@ -7,5 +7,4 @@
padding: $grid-unit;
}
}

}

This file was deleted.

48 changes: 48 additions & 0 deletions packages/block-editor/src/components/block-controls/fill.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* External dependencies
*/
import { isEmpty } from 'lodash';

/**
* WordPress dependencies
*/
import {
__experimentalToolbarContext as ToolbarContext,
ToolbarGroup,
} from '@wordpress/components';

/**
* Internal dependencies
*/
import useDisplayBlockControls from '../use-display-block-controls';
import groups from './groups';

export default function BlockControlsFill( {
group = 'default',
controls,
children,
} ) {
if ( ! useDisplayBlockControls() ) {
return null;
}
const Fill = groups[ group ].Fill;

return (
<Fill>
{ ( fillProps ) => {
// Children passed to BlockControlsFill will not have access to any
// React Context whose Provider is part of the BlockControlsSlot tree.
// So we re-create the Provider in this subtree.
const value = ! isEmpty( fillProps ) ? fillProps : null;
return (
<ToolbarContext.Provider value={ value }>
{ group === 'default' && (
<ToolbarGroup controls={ controls } />
) }
{ children }
</ToolbarContext.Provider>
);
} }
</Fill>
);
}
18 changes: 18 additions & 0 deletions packages/block-editor/src/components/block-controls/groups.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* WordPress dependencies
*/
import { createSlotFill } from '@wordpress/components';

const BlockControlsDefault = createSlotFill( 'BlockControls' );
const BlockControlsBlock = createSlotFill( 'BlockControlsBlock' );
const BlockControlsInline = createSlotFill( 'BlockFormatControls' );
const BlockControlsOther = createSlotFill( 'BlockControlsOther' );

const groups = {
default: BlockControlsDefault,
block: BlockControlsBlock,
inline: BlockControlsInline,
other: BlockControlsOther,
};

export default groups;
56 changes: 10 additions & 46 deletions packages/block-editor/src/components/block-controls/index.js
Original file line number Diff line number Diff line change
@@ -1,55 +1,19 @@
/**
* External dependencies
*/
import { isEmpty } from 'lodash';

/**
* WordPress dependencies
*/
import { useContext } from '@wordpress/element';
import {
__experimentalToolbarContext as ToolbarContext,
createSlotFill,
ToolbarGroup,
} from '@wordpress/components';

/**
* Internal dependencies
*/
import useDisplayBlockControls from '../use-display-block-controls';

const { Fill, Slot } = createSlotFill( 'BlockControls' );

function BlockControlsSlot( props ) {
const accessibleToolbarState = useContext( ToolbarContext );
return <Slot { ...props } fillProps={ accessibleToolbarState } />;
}

function BlockControlsFill( { controls, children } ) {
if ( ! useDisplayBlockControls() ) {
return null;
}

return (
<Fill>
{ ( fillProps ) => {
// Children passed to BlockControlsFill will not have access to any
// React Context whose Provider is part of the BlockControlsSlot tree.
// So we re-create the Provider in this subtree.
const value = ! isEmpty( fillProps ) ? fillProps : null;
return (
<ToolbarContext.Provider value={ value }>
<ToolbarGroup controls={ controls } />
{ children }
</ToolbarContext.Provider>
);
} }
</Fill>
);
}
import BlockControlsFill from './fill';
import BlockControlsSlot from './slot';

const BlockControls = BlockControlsFill;

BlockControls.Slot = BlockControlsSlot;

// This is just here for backward compatibility
export const BlockFormatControls = ( props ) => {
return <BlockControlsFill group="inline" { ...props } />;
};
BlockFormatControls.Slot = ( props ) => {
return <BlockControlsSlot group="inline" { ...props } />;
};

export default BlockControls;
45 changes: 45 additions & 0 deletions packages/block-editor/src/components/block-controls/slot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* WordPress dependencies
*/
import { useContext } from '@wordpress/element';
import {
__experimentalToolbarContext as ToolbarContext,
ToolbarGroup,
__experimentalUseSlot as useSlot,
} from '@wordpress/components';

/**
* Internal dependencies
*/
import groups from './groups';

export default function BlockControlsSlot( { group = 'default', ...props } ) {
const accessibleToolbarState = useContext( ToolbarContext );
const Slot = groups[ group ].Slot;
const slot = useSlot( Slot.__unstableName );
const hasFills = Boolean( slot.fills && slot.fills.length );

if ( ! hasFills ) {
return null;
}

if ( group === 'default' ) {
return (
<Slot
{ ...props }
bubblesVirtually
fillProps={ accessibleToolbarState }
/>
);
}

return (
<ToolbarGroup>
<Slot
{ ...props }
bubblesVirtually
fillProps={ accessibleToolbarState }
/>
</ToolbarGroup>
);
}
Loading

0 comments on commit e382528

Please sign in to comment.