From f4cc3bfb4fd751dbd7e711868088ef33f710ff11 Mon Sep 17 00:00:00 2001 From: Matias Ventura Date: Tue, 20 Mar 2018 16:12:03 +0100 Subject: [PATCH] Predefined set of font sizes (#5269) * Add ButtonGroup UI component. This component renders a row of button controls. * Add predefined sets of font size values paired with classes. When font size control is used and the value matches one of the predefined values, the editor would output a special class instead of an inline fontSize number. * Load default font-sizes in the front. * Use button-group for font-size buttons. * Use a more sensible max value for the slider. * Group reset button with predefined sizes. * Add aria-pressed attr and display afterIcon in range slider. * Refactored to the two attributes approach customFontSize and fontSize. * Implemented deprecation logic to convert existing paragraph blocks. --- blocks/library/paragraph/editor.scss | 10 ++ blocks/library/paragraph/index.js | 141 ++++++++++++++++++++++++--- blocks/library/paragraph/style.scss | 38 ++++++-- components/button-group/index.js | 19 ++++ components/button-group/style.scss | 19 ++++ components/index.js | 1 + 6 files changed, 205 insertions(+), 23 deletions(-) create mode 100644 components/button-group/index.js create mode 100644 components/button-group/style.scss diff --git a/blocks/library/paragraph/editor.scss b/blocks/library/paragraph/editor.scss index a50c04177658f..e5fe10296b7f1 100644 --- a/blocks/library/paragraph/editor.scss +++ b/blocks/library/paragraph/editor.scss @@ -1,3 +1,13 @@ .editor-block-list__block:not( .is-multi-selected ) .wp-block-paragraph { background: white; } + +.blocks-font-size__main { + display: flex; + justify-content: space-between; +} + +.blocks-font-size .blocks-range-control__slider + .dashicon { + width: 30px; + height: 30px; +} diff --git a/blocks/library/paragraph/index.js b/blocks/library/paragraph/index.js index 93ab1c019c68b..d7cefb196a329 100644 --- a/blocks/library/paragraph/index.js +++ b/blocks/library/paragraph/index.js @@ -2,6 +2,7 @@ * External dependencies */ import classnames from 'classnames'; +import { findKey, isFinite, map, omit } from 'lodash'; /** * WordPress dependencies @@ -14,6 +15,8 @@ import { PanelColor, RangeControl, ToggleControl, + Button, + ButtonGroup, withFallbackStyles, } from '@wordpress/components'; @@ -46,6 +49,13 @@ const ContrastCheckerWithFallbackStyles = withFallbackStyles( ( node, ownProps ) }; } )( ContrastChecker ); +const FONT_SIZES = { + small: 14, + regular: 16, + large: 36, + larger: 48, +}; + class ParagraphBlock extends Component { constructor() { super( ...arguments ); @@ -53,6 +63,8 @@ class ParagraphBlock extends Component { this.bindRef = this.bindRef.bind( this ); this.onReplace = this.onReplace.bind( this ); this.toggleDropCap = this.toggleDropCap.bind( this ); + this.getFontSize = this.getFontSize.bind( this ); + this.setFontSize = this.setFontSize.bind( this ); } onReplace( blocks ) { @@ -81,6 +93,33 @@ class ParagraphBlock extends Component { this.nodeRef = node; } + getFontSize() { + const { customFontSize, fontSize } = this.props.attributes; + if ( fontSize ) { + return FONT_SIZES[ fontSize ]; + } + + if ( customFontSize ) { + return customFontSize; + } + } + + setFontSize( fontSizeValue ) { + const { setAttributes } = this.props; + const thresholdFontSize = findKey( FONT_SIZES, ( size ) => size === fontSizeValue ); + if ( thresholdFontSize ) { + setAttributes( { + fontSize: thresholdFontSize, + customFontSize: undefined, + } ); + return; + } + setAttributes( { + fontSize: undefined, + customFontSize: fontSizeValue, + } ); + } + render() { const { attributes, @@ -97,12 +136,13 @@ class ParagraphBlock extends Component { content, dropCap, placeholder, - fontSize, backgroundColor, textColor, width, } = attributes; + const fontSize = this.getFontSize(); + return [ isSelected && ( @@ -116,21 +156,47 @@ class ParagraphBlock extends Component { ), isSelected && ( - + +
+ + { map( { + S: 'small', + M: 'regular', + L: 'large', + XL: 'larger', + }, ( size, label ) => ( + + ) ) } + + +
+ this.setFontSize( value ) } + min={ 12 } + max={ 100 } + beforeIcon="editor-textcolor" + afterIcon="editor-textcolor" + /> - setAttributes( { fontSize: value } ) } - min={ 10 } - max={ 200 } - beforeIcon="editor-textcolor" - allowReset - />
{ content }

; + }, + migrate( attributes ) { + if ( isFinite( attributes.fontSize ) ) { + return omit( { + ...attributes, + customFontSize: attributes.fontSize, + }, 'fontSize' ); + } + return attributes; + }, + }, { supports, attributes: { @@ -314,16 +417,28 @@ export const settings = { edit: ParagraphBlock, save( { attributes } ) { - const { width, align, content, dropCap, backgroundColor, textColor, fontSize } = attributes; + const { + width, + align, + content, + dropCap, + backgroundColor, + textColor, + fontSize, + customFontSize, + } = attributes; + const className = classnames( { [ `align${ width }` ]: width, 'has-background': backgroundColor, 'has-drop-cap': dropCap, + [ `is-${ fontSize }-text` ]: fontSize && FONT_SIZES[ fontSize ], } ); + const styles = { backgroundColor: backgroundColor, color: textColor, - fontSize: fontSize, + fontSize: ! fontSize && customFontSize ? customFontSize : undefined, textAlign: align, }; diff --git a/blocks/library/paragraph/style.scss b/blocks/library/paragraph/style.scss index ba590421b23b9..7d8da4883876f 100644 --- a/blocks/library/paragraph/style.scss +++ b/blocks/library/paragraph/style.scss @@ -1,13 +1,31 @@ -p.has-drop-cap { - &:first-letter { - float: left; - font-size: 4.1em; - line-height: 0.7; - font-family: serif; - font-weight: bold; - margin: .07em .23em 0 0; - text-transform: uppercase; - font-style: normal; +p { + &.is-small-text { + font-size: 14px; + } + + &.is-regular-text { + font-size: 16px; + } + + &.is-large-text { + font-size: 36px; + } + + &.is-larger-text { + font-size: 48px; + } + + &.has-drop-cap { + &:first-letter { + float: left; + font-size: 4.1em; + line-height: 0.7; + font-family: serif; + font-weight: bold; + margin: .07em .23em 0 0; + text-transform: uppercase; + font-style: normal; + } } } diff --git a/components/button-group/index.js b/components/button-group/index.js new file mode 100644 index 0000000000000..df65e99cb8068 --- /dev/null +++ b/components/button-group/index.js @@ -0,0 +1,19 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * Internal dependencies + */ +import './style.scss'; + +function ButtonGroup( { className, ...props } ) { + const classes = classnames( 'components-button-group', className ); + + return ( +
+ ); +} + +export default ButtonGroup; diff --git a/components/button-group/style.scss b/components/button-group/style.scss new file mode 100644 index 0000000000000..5be7e700ac197 --- /dev/null +++ b/components/button-group/style.scss @@ -0,0 +1,19 @@ +.components-button-group { + display: inline-block; + margin-bottom: 20px; + + .components-button { + border-radius: 0; + & + .components-button { + margin-left: -1px; + } + + &:first-child { + border-radius: 3px 0 0 3px; + } + + &:last-child { + border-radius: 0 3px 3px 0; + } + } +} diff --git a/components/index.js b/components/index.js index 512e2b8babb18..f720220639972 100644 --- a/components/index.js +++ b/components/index.js @@ -3,6 +3,7 @@ export { default as APIProvider } from './higher-order/with-api-data/provider'; export { default as Autocomplete } from './autocomplete'; export { default as BaseControl } from './base-control'; export { default as Button } from './button'; +export { default as ButtonGroup } from './button-group'; export { default as CheckboxControl } from './checkbox-control'; export { default as ClipboardButton } from './clipboard-button'; export { default as CodeEditor } from './code-editor';