Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Next Next commit
Blocks: Adding the quote block
  • Loading branch information
youknowriad committed Apr 13, 2017
commit 3e1e0311b42e054e880a64f8f3f81666cb1e1bc2
1 change: 1 addition & 0 deletions blocks/library/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ import './freeform';
import './image';
import './text';
import './list';
import './quote';
50 changes: 50 additions & 0 deletions blocks/library/quote/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* Internal dependencies
*/
import './style.scss';
import { registerBlock, query as hpq } from 'api';
import Editable from 'components/editable';

const { html, query } = hpq;
Copy link
Member

Choose a reason for hiding this comment

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

Ah yes, the shadow conflict. It's been on my mind lately whether we should rename wp.blocks.query to something else. I thought perhaps parse being the default exported function with other methods as properties available via destructuring, but I'm not sure I like the idea of block implementers thinking of this as a parse action (even if it is 😄 ).

Copy link
Member

Choose a reason for hiding this comment

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

Or we could simply reference hpq as a proper external dependency and expect plugin authors to enqueue it themselves as a preloaded dependency. I quite liked masking the underlying implementation detail and providing a single unified interface for blocks though.


registerBlock( 'core/quote', {
title: wp.i18n.__( 'Quote' ),
icon: 'format-quote',
category: 'common',

attributes: {
value: ( node ) => query( 'blockquote > p', html() )( node ).join(),
Copy link
Member

Choose a reason for hiding this comment

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

Won't this disallow multiple paragraphs in a single quote? Instead maybe we want to retrieve paragraphs as an array of HTML?

Roughly:

attributes: {
	value: html( 'p' )
}

save( { value } ) {
	return <blockquote>{ value.map( ( paragraph ) => <p>{ paragraph }</p> ) }</blockquote>;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The above will retrieve all the paragraphs and join them, so no it won't disallow multiple paragraphs. I wanted to have a unique string to pass to the Editable inside the edit instead of having to duplicate the join logic in edit and save.

Also worth noting that the footer can contain p elements, so that's why I'm using blockquote > p

Copy link
Member

Choose a reason for hiding this comment

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

The above will retrieve all the paragraphs and join them, so no it won't disallow multiple paragraphs.

But html retrieves the innerHTML so it would lose the tag and become a single joined string.

I wanted to have a unique string to pass to the Editable inside the edit instead of having to duplicate the join logic in edit and save.

I guess I'm more on the side of using attributes to get the raw-est data possible even if that's not necessarily the most useful, and assume that edit and save will form it into whatever's most applicable, perhaps sharing logic with common components if need be.

Also worth noting that the footer can contain p elements

Is this "can" as in: technically possible per spec, or something we want to support?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point! What about adding a div wrapper inside the blockquote to separate the footer from the content properly. This will also resolve the dangerouslySetInnerHTML issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is this "can" as in: technically possible per spec, or something we want to support?

I don't know :P. What I know is that TinyMCE (current implementation) adds p automatically around text (we could avoid it passing a tagName, but we create other limits by doing so). Also the current post content sample contains the p

citation: html( 'footer' )
},

edit( { attributes, setAttributes } ) {
const { value, citation } = attributes;

return (
<blockquote className="blocks-quote">
<Editable
value={ value }
onChange={ ( newValue ) => setAttributes( { value: newValue } ) } />
<footer>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to hide this when the citation is empty and we're not focusing the block but it's not possible for now, because the isSelected is not enough for this. We need a distinct isFocused which stays active even if we start typing.

Copy link
Member

Choose a reason for hiding this comment

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

We need a distinct isFocused which stays active even if we start typing.

Should we create an issue to track this, or do you plan to tackle this in the near future?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was planing to take a look at this (but don't know really when) Let's create an issue for this :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

<Editable
value={ citation }
onChange={ ( newValue ) => setAttributes( { citation: newValue } ) } />
</footer>
</blockquote>
);
},

save( attributes ) {
const { value, citation } = attributes;
return (
<blockquote>
Copy link
Member

Choose a reason for hiding this comment

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

I think we'll need some dangerouslySetInnerHTML throughout here.

Copy link
Contributor Author

@youknowriad youknowriad Apr 13, 2017

Choose a reason for hiding this comment

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

🤔 How do we apply the dangerouslySetInnerHTML without a wrapper?

Copy link
Member

Choose a reason for hiding this comment

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

🤔 How do we apply the dangerouslySetInnerHTML without a wrapper?

Yeah, we ought to be thinking about this, because I don't think it's particularly obvious and the "dangerous" terminology is quite off-putting.

Perhaps we can walk the tree returned from the function and manually revise string children as dangerouslySetInnerHTML? 😬

{ value }
{ !! citation &&
<footer>
{ citation }
</footer>
}
</blockquote>
);
}
} );
24 changes: 24 additions & 0 deletions blocks/library/quote/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.blocks-quote {
margin: 0;
box-shadow: inset 0px 0px 0px 0px $light-gray-500;
transition: all .2s ease;
Copy link
Member

Choose a reason for hiding this comment

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

What's the effect we're trying to achieve with the transition? At least in my browser, the border width effect feels a little janky when switching between styles.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree, let's remove that one. Though the idea of "transitioning between styles" is interesting, I think that will get old quickly, and it likely won't scale to other block transformations either.

font-size: 20px;
border-left: 4px solid $black;
padding-left: 1em;
font-style: italic;

footer {
color: $dark-gray-100;
font-size: 0.9em;
font-style: normal;
margin-left: 1.3em;
position: relative;

&:after {
Copy link
Member

Choose a reason for hiding this comment

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

Not that it really matters much here, but if it's shown effectively before the cite, should we apply as :before for semantic's sake?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

content: '— ';
position: absolute;
left: -1.3em;
top: 0;
}
}
}
4 changes: 4 additions & 0 deletions languages/gutenberg.pot
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ msgstr ""
msgid "Justify"
msgstr ""

#: blocks/library/quote/index.js:11
msgid "Quote"
msgstr ""

#: blocks/library/text/index.js:10
msgid "Text"
msgstr ""
Expand Down