Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DimensionControl component #16791

Merged
merged 27 commits into from
Oct 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2fcb86f
Adds initial component
getdave Jul 29, 2019
56e0670
Remove redunant files. Refactors tests.
getdave Jul 29, 2019
3f2bade
Updates docs
getdave Jul 29, 2019
1acb0a3
Checks callbacks are functions prior to calling
getdave Jul 29, 2019
51d5575
Adds temp testing example usage of component to Group Block
getdave Jul 29, 2019
61d25ee
Updates to allow sizes as an (optionaly) prop dependency
getdave Jul 29, 2019
09a54ec
Update default value label
getdave Sep 12, 2019
0a6864e
Removes unnecessary InstanceId HOC usage
getdave Sep 14, 2019
591979c
Remove unused abbreviation in size table
getdave Sep 14, 2019
46aeac6
Revert "Adds temp testing example usage of component to Group Block"
getdave Sep 14, 2019
4d21bb7
Remove arbitrary size value from sizes list
getdave Sep 14, 2019
3feb767
Remove icon label for a11y reasons
getdave Sep 14, 2019
da1c0ff
Update component docs for consistency, spelling and grammar
getdave Sep 14, 2019
93f5dd1
Tweak docblock formats
getdave Sep 14, 2019
93a2929
Update test snapshots to match new default value
getdave Sep 14, 2019
d3a8924
Update API from onSpacingChange to more agnostic onChange
getdave Oct 7, 2019
196a8ae
Update tests to cover onChange handler renamed
getdave Oct 7, 2019
fc8f003
Update currentSize prop to value for consistency with other components
getdave Oct 7, 2019
dbe7a4f
Removes onReset in favour of onChange with undefined for consistency
getdave Oct 7, 2019
d36ac83
Move component to @wordpress/components package
getdave Oct 7, 2019
4cea8ad
Remove invalid font sizes style import
getdave Oct 7, 2019
70bc609
Deps update due to rebase
getdave Oct 7, 2019
1a4f6af
Remove unneeded doc blocks
getdave Oct 28, 2019
f1d67fc
Remove usage suggestion which was not helpful
getdave Oct 28, 2019
387a993
Update readme docs to match current API
getdave Oct 28, 2019
a0b2dca
Export as experimental component
getdave Oct 28, 2019
d2d8816
Revert "Deps update due to rebase"
getdave Oct 28, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/manifest-devhub.json
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,12 @@
"markdown_source": "../packages/components/src/date-time/README.md",
"parent": "components"
},
{
"title": "DimensionControl",
"slug": "dimension-control",
"markdown_source": "../packages/components/src/dimension-control/README.md",
"parent": "components"
},
{
"title": "Disabled",
"slug": "disabled",
Expand Down
120 changes: 120 additions & 0 deletions packages/components/src/dimension-control/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
DimensionControl
=============================

`DimensionControl` is a component designed to provide a UI to control spacing and/or dimensions.

## Usage

In a block's `edit` implementation, render a `<DimensionControl />` component.


```jsx
import { registerBlockType } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import {
DimensionControl,
} from '@wordpress/block-editor';

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

attributes: {
// other attributes here
// ...

paddingSize: {
type: 'string',
},
},

edit( { attributes, setAttributes, clientId } ) {

const { paddingSize } = attributes;


const updateSpacing = ( dimension, size, device = '' ) => {
setAttributes( {
[ `${ dimension }${ device }` ]: size,
} );
};

return (
<DimensionControl
label={ __( 'Padding' ) }
icon={ 'desktop' }
onChange={ partialRight( updateSpacing, 'paddingSize' ) }
value={ paddingSize }
/>
);
}
} );
```

_Note:_ it is recommended to partially apply the value of the Block attribute to be updated (eg: `paddingSize`, `marginSize`...etc) to your callback functions. This avoids the need to unnecessarily couple the component to the Block attribute schema.

_Note:_ by default, if you do not provide an initial `value` prop for the current dimension value, then no value will be selected (ie: there is no default dimension set).

## Props

### `label`
* **Type:** `String`
* **Default:** `undefined`
* **Required:** Yes

The human readable label for the control.

### `value`
* **Type:** `String`
* **Default:** `''`
* **Required:** No

The current value of the dimension UI control. If provided the UI with automatically select the value.

### `sizes`
* **Type:** `Array`
* **Default:** See `packages/block-editor/src/components/dimension-control/sizes.js`
* **Required:** No

An optional array of size objects in the following shape:

```
[
{
name: __( 'Small' ),
slug: 'small',
},
{
name: __( 'Medium' ),
slug: 'small',
},
// ...etc
]
```

By default a set of relative sizes (`small`, `medium`...etc) are provided. See `packages/block-editor/src/components/dimension-control/sizes.js`.

### `icon`
* **Type:** `String`
* **Default:** `undefined`
* **Required:** No

An optional dashicon to display before to the control label.

### `onChange`
* **Type:** `Function`
* **Default:** `undefined`
* **Required:** No
* **Arguments:**:
- `size` - a string representing the selected size (eg: `medium`)

A callback which is triggered when a spacing size value changes (is selected/clicked).


### `className`
* **Type:** `String`
* **Default:** `''`
* **Required:** No

A string of classes to be added to the control component.


76 changes: 76 additions & 0 deletions packages/components/src/dimension-control/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* External dependencies
*/
import classnames from 'classnames';
import { isFunction } from 'lodash';

/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
import {
Icon,
SelectControl,
} from '../';
import { __ } from '@wordpress/i18n';

import {
Fragment,
} from '@wordpress/element';

/**
* Internal dependencies
*/
import sizesTable, { findSizeBySlug } from './sizes';

export function DimensionControl( props ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm personally a bit hesitant on making this a public component in @wordpress/components.

The @wordpress/components package is basically the design system while this is more something for the editor, maybe something for the block-editor package?

What do you all think about moving this to the block-editor package or making it experimental?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nvm, I just saw that it's already experimental :) I wonder if we should move it to the block-editor and stabilize it once we use it a block.

const { label, value, sizes = sizesTable, icon, onChange, className = '' } = props;

const onChangeSpacingSize = ( val ) => {
const theSize = findSizeBySlug( sizes, val );

if ( ! theSize || value === theSize.slug ) {
onChange( undefined );
} else if ( isFunction( onChange ) ) {
onChange( theSize.slug );
}
};

const formatSizesAsOptions = ( theSizes ) => {
const options = theSizes.map( ( { name, slug } ) => ( {
label: name,
value: slug,
} ) );

return [ {
label: __( 'Default' ),
value: '',
} ].concat( options );
};

const selectLabel = (
<Fragment>
{ icon && (
<Icon
icon={ icon }
/>
) }
{ label }
</Fragment>
);

return (
<SelectControl
className={ classnames( className, 'block-editor-dimension-control' ) }
label={ selectLabel }
hideLabelFromVision={ false }
value={ value }
onChange={ onChangeSpacingSize }
options={ formatSizesAsOptions( sizes ) }
/>
);
}

export default DimensionControl;
45 changes: 45 additions & 0 deletions packages/components/src/dimension-control/sizes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* Sizes
*
* defines the sizes used in dimension controls
* all hardcoded `size` values are based on the value of
* the Sass variable `$block-padding` from
* `packages/block-editor/src/components/dimension-control/sizes.js`.
*/

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';

/**
* Finds the correct size object from the provided sizes
* table by size slug (eg: `medium`)
*
* @param {Array} sizes containing objects for each size definition
* @param {string} slug a string representation of the size (eg: `medium`)
* @return {Object} the matching size definition
*/
export const findSizeBySlug = ( sizes, slug ) => sizes.find( ( size ) => slug === size.slug );

export default [
{
name: __( 'None' ),
slug: 'none',
},
{
name: __( 'Small' ),
slug: 'small',
},
{
name: __( 'Medium' ),
slug: 'medium',
},
{
name: __( 'Large' ),
slug: 'large',
}, {
name: __( 'Extra Large' ),
slug: 'xlarge',
},
];
22 changes: 22 additions & 0 deletions packages/components/src/dimension-control/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.block-editor-dimension-control {

.components-base-control__field {
display: flex;
align-items: center;
}

.components-base-control__label {
display: flex;
align-items: center;
margin-right: 1em;
margin-bottom: 0;

.dashicon {
margin-right: 0.5em;
}
}

&.is-manual .components-base-control__label {
width: 10em;
}
}
Loading