From db9abb9b9f9cb59947af361d08489d2ce6479894 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Mon, 13 Mar 2017 09:19:59 +0100 Subject: [PATCH] TinyMCE per block: Showing moving block controls on hover (#250) --- .../src/blocks/embed-block/form.js | 8 +++--- .../src/blocks/heading-block/form.js | 6 ++--- .../src/blocks/html-block/form.js | 6 ++--- .../src/blocks/image-block/form.js | 8 +++--- .../src/blocks/quote-block/_style.scss | 6 ++--- .../src/blocks/quote-block/form.js | 6 ++--- .../src/blocks/text-block/form.js | 6 ++--- .../src/controls/block-arrangement/style.scss | 2 +- .../src/renderers/block/_style.scss | 26 ++++++++++++++----- .../src/renderers/block/commands.js | 8 ++++++ .../src/renderers/block/index.js | 4 ++- .../src/renderers/block/updater.js | 14 +++++++++- 12 files changed, 69 insertions(+), 31 deletions(-) diff --git a/tinymce-per-block/src/blocks/embed-block/form.js b/tinymce-per-block/src/blocks/embed-block/form.js index 69c806dd16059..ea7a37dbc8e80 100644 --- a/tinymce-per-block/src/blocks/embed-block/form.js +++ b/tinymce-per-block/src/blocks/embed-block/form.js @@ -19,7 +19,7 @@ export default class EmbedBlockForm extends Component { }; render() { - const { api, block, isSelected, first, last, focusConfig } = this.props; + const { api, block, isSelected, isHovered, first, last, focusConfig } = this.props; const removePrevious = () => { if ( ! block.url ) { @@ -37,8 +37,10 @@ export default class EmbedBlockForm extends Component { const html = getEmbedHtmlFromUrl( block.url ); return ( -
- { isSelected && + { ( isSelected || isHovered ) && } { isSelected &&
diff --git a/tinymce-per-block/src/blocks/heading-block/form.js b/tinymce-per-block/src/blocks/heading-block/form.js index d41739df488b5..05dd30170b452 100644 --- a/tinymce-per-block/src/blocks/heading-block/form.js +++ b/tinymce-per-block/src/blocks/heading-block/form.js @@ -28,12 +28,12 @@ export default class HeadingBlockForm extends Component { }; render() { - const { api, block, isSelected, first, last } = this.props; + const { api, block, isSelected, isHovered, first, last } = this.props; const sizes = [ 'h1', 'h2', 'h3' ]; return ( -
- { isSelected && + { ( isSelected || isHovered ) && } { isSelected && (
diff --git a/tinymce-per-block/src/blocks/html-block/form.js b/tinymce-per-block/src/blocks/html-block/form.js index f33d1872381b0..0a4cb7c06dbbd 100644 --- a/tinymce-per-block/src/blocks/html-block/form.js +++ b/tinymce-per-block/src/blocks/html-block/form.js @@ -26,7 +26,7 @@ export default class HtmlBlockForm extends Component { }; render() { - const { api, block, isSelected, first, last, focusConfig } = this.props; + const { api, block, isSelected, isHovered, first, last, focusConfig } = this.props; const splitValue = ( left, right ) => { api.change( { content: left } ); if ( right ) { @@ -44,8 +44,8 @@ export default class HtmlBlockForm extends Component { }; return ( -
- { isSelected && + { ( isSelected || isHovered ) && } { isSelected && (
diff --git a/tinymce-per-block/src/blocks/image-block/form.js b/tinymce-per-block/src/blocks/image-block/form.js index 2d2f7faedb376..2f6cc5b31fa41 100644 --- a/tinymce-per-block/src/blocks/image-block/form.js +++ b/tinymce-per-block/src/blocks/image-block/form.js @@ -14,7 +14,7 @@ export default class ImageBlockForm extends Component { }; render() { - const { api, block, first, last, isSelected, focusConfig } = this.props; + const { api, block, first, last, isSelected, isHovered, focusConfig } = this.props; const removePrevious = () => { if ( ! block.caption ) { api.remove(); @@ -29,8 +29,10 @@ export default class ImageBlockForm extends Component { }; return ( -
- { isSelected && + { ( isSelected || isHovered ) && } { isSelected &&
diff --git a/tinymce-per-block/src/blocks/quote-block/_style.scss b/tinymce-per-block/src/blocks/quote-block/_style.scss index f5aad5604e11c..2bcb56ad1fda0 100644 --- a/tinymce-per-block/src/blocks/quote-block/_style.scss +++ b/tinymce-per-block/src/blocks/quote-block/_style.scss @@ -23,7 +23,7 @@ color: $gray-dark-300; resize: none; font-style: italic; - padding-left: 20px; + padding-left: 15px; &:before { display: block; @@ -37,8 +37,8 @@ .quote-block__form.quote-style1 { border-left: 4px solid black; - margin-left: -20px; - padding-left: 20px; + margin-left: -15px; + padding-left: 15px; .quote-block__content { font-style: italic; diff --git a/tinymce-per-block/src/blocks/quote-block/form.js b/tinymce-per-block/src/blocks/quote-block/form.js index 4c9c58fbf9734..cb0399a2dfee2 100644 --- a/tinymce-per-block/src/blocks/quote-block/form.js +++ b/tinymce-per-block/src/blocks/quote-block/form.js @@ -43,7 +43,7 @@ export default class QuoteBlockForm extends Component { }; render() { - const { api, block, first, last, isSelected, focusConfig } = this.props; + const { api, block, first, last, isSelected, isHovered, focusConfig } = this.props; const splitValue = ( left, right ) => { api.change( { cite: left } ); api.appendBlock( { @@ -59,8 +59,8 @@ export default class QuoteBlockForm extends Component { const currentStyle = block.style || 'style1'; return ( -
- { isSelected && + { ( isSelected || isHovered ) && } { isSelected &&
diff --git a/tinymce-per-block/src/blocks/text-block/form.js b/tinymce-per-block/src/blocks/text-block/form.js index 2805daf3753b4..506e81d692b4c 100644 --- a/tinymce-per-block/src/blocks/text-block/form.js +++ b/tinymce-per-block/src/blocks/text-block/form.js @@ -28,15 +28,15 @@ export default class TextBlockForm extends Component { }; render() { - const { api, block, isSelected, focusConfig, first, last } = this.props; + const { api, block, isSelected, isHovered, focusConfig, first, last } = this.props; const selectedTextAlign = block.align || 'left'; const style = { textAlign: selectedTextAlign }; return ( -
- { isSelected && + { ( isSelected || isHovered ) && } { isSelected &&
diff --git a/tinymce-per-block/src/controls/block-arrangement/style.scss b/tinymce-per-block/src/controls/block-arrangement/style.scss index c86a5ab03032b..5c3b871e41f61 100644 --- a/tinymce-per-block/src/controls/block-arrangement/style.scss +++ b/tinymce-per-block/src/controls/block-arrangement/style.scss @@ -2,7 +2,7 @@ @include animate_fade; position: absolute; top: 10px; - left: -35px; + left: 0; .block-arrangement__control { display: block; diff --git a/tinymce-per-block/src/renderers/block/_style.scss b/tinymce-per-block/src/renderers/block/_style.scss index 3a36794107135..0f7281816b592 100644 --- a/tinymce-per-block/src/renderers/block/_style.scss +++ b/tinymce-per-block/src/renderers/block/_style.scss @@ -6,21 +6,33 @@ .block-list__block { outline: 0; + position: relative; + margin-left: -35px; + margin-bottom: 15px; > div { position: relative; - border: 2px solid transparent; outline: none; - padding: 0.8rem 1.2rem; - transition: 0.2s border-color; - margin-bottom: 1rem; + padding: 15px 15px 15px 50px; + + &:before { + z-index: -1; + content: ''; + position: absolute; + top: 0; + bottom: 0; + left: 35px; + right: 0; + border: 2px solid transparent; + transition: 0.2s border-color; + } } - &:hover > div { + &:hover > div:before { border-left-color: #e1e6ea; } - &.is-selected > div { + &.is-selected > div:before { border-color: #e1e6ea; } } @@ -28,7 +40,7 @@ .block-list__block-controls { @include animate_fade; position: absolute; - left: 0; + left: 35px; top: -36px; z-index: 1; } diff --git a/tinymce-per-block/src/renderers/block/commands.js b/tinymce-per-block/src/renderers/block/commands.js index 5d3fe0e294646..61d679b86b457 100644 --- a/tinymce-per-block/src/renderers/block/commands.js +++ b/tinymce-per-block/src/renderers/block/commands.js @@ -55,3 +55,11 @@ export const transform = ( id ) => ( { type: 'transform', id } ); + +export const hover = () => ( { + type: 'hover' +} ); + +export const unhover = () => ( { + type: 'unhover' +} ); diff --git a/tinymce-per-block/src/renderers/block/index.js b/tinymce-per-block/src/renderers/block/index.js index af20cc3dc90bd..bed504ad8f370 100644 --- a/tinymce-per-block/src/renderers/block/index.js +++ b/tinymce-per-block/src/renderers/block/index.js @@ -16,6 +16,7 @@ import * as commands from './commands'; class BlockList extends Component { state = { + hovered: null, selected: null, focus: { uid: null }, blocks: [], @@ -85,7 +86,7 @@ class BlockList extends Component { } render() { - const { blocks, focus, selected } = this.state; + const { blocks, focus, selected, hovered } = this.state; return (
@@ -122,6 +123,7 @@ class BlockList extends Component { block={ block } api={ api } isSelected={ selected === block.uid } + isHovered={ hovered === block.uid } focusConfig={ isFocused ? focus.config : null } first={ index === 0 } last={ index === blocks.length - 1 } diff --git a/tinymce-per-block/src/renderers/block/updater.js b/tinymce-per-block/src/renderers/block/updater.js index f18ffda957ac5..08ee38bef7b25 100644 --- a/tinymce-per-block/src/renderers/block/updater.js +++ b/tinymce-per-block/src/renderers/block/updater.js @@ -174,7 +174,19 @@ const blockLevelUpdater = ( state, command ) => { blocks: newBlocks, focus: { uid: newBlockUid, config: {} } } ); - } + }, + + hover: () => { + return mergeStates( { + hovered: currentUID + } ); + }, + + unhover: () => { + return mergeStates( { + hovered: null + } ); + }, }; if ( blockCommandHandlers[ command.type ] ) {