In diesem Beitrag zeige ich, wie sich unterschiedliche Farbpaletten in Gutenberg einsetzen lassen, sodass beispielsweise für die Textfarbe andere Farben gewählt werden können als für die Hintergrundfarbe.
Update vom 18. November 2018: Mit einem der letzten Gutenberg-Updates wurde PanelColor
entfernt. Ich habe den Code mit der stattdessen zu verwendenden PanelColorSettings
-Komponenten angepasst. Damit ist die Lösung auch einfacher geworden, da diese Komponente direkt vorsieht, dass die globalen Farben überschrieben werden können.
Update vom 11. Juli 2018: Damit die Markierung der gewählten Farbe nach dem Neuladen des Editors funktioniert, müssen im letzten Code-Block noch die beiden Farb-Attribute als attributes
angegeben werden.
Die Zielsetzung
Ziel war, quasi die Farbwähler nachzubauen, die bei dem Absatz-Block vorhanden sind:
Dabei befinden sich die Farben innerhalb eines auf- und zuklappbaren Bereichs und die ausgewählte Farbe wird neben dem Titel dieses Bereichs angezeigt. Wird eine Farbe ausgewählt, wird für das Absatz-Element eine entsprechende Klasse eingefügt und ein Inline-Style gesetzt.
Die Lösung
In der ersten Version meiner Lösung habe ich die PanelColor
-Komponente genutzt, der keine eigenen Farben mitgegeben werden konnten, weshalb hier der Aufwand noch etwas größer war als mit PanelColorSettings
. Dieser können eigene Farben übergeben werden – es muss aber darauf geachtet werden, dass alle genutzten Farben über add_theme_support()
angelegt sind, weil Gutenberg diese Farben zur Erstellung der Farb-Klassennamen nutzt.
Die Lösung besteht damit quasi aus zwei Teilen:
- Gutenberg die gewünschten Farben über
add_theme_support( 'editor-color-palette' )
beibringen. - Den Farb-Teil aus dem Absatz-Block nachbauen.
Ich gehe davon aus, dass ihr Gutenberg installiert und eine JavaScript-Datei im Editor eingebunden habt und bereits eine package.json
nutzt. Ich nutze hier moderne JavaScript-Syntax, die mit Babel in ES5 konvertiert wird.
Farbpalette definieren
Zunächst definieren wir unsere Farben, die wir später nutzen wollen:
add_action( 'after_setup_theme', 'setup_theme_supported_features' );
function setup_theme_supported_features() {
add_theme_support( 'editor-color-palette',
[
[
'name' => 'Puerto Rico',
'slug' => 'puerto-rico',
'color' => '#53c4ab',
],
[
'name' => 'Tundora',
'slug' => 'tundora',
'color' => '#454545',
],
[
'name' => 'Butterfly Bush',
'slug' => 'butterfly-bush',
'color' => '#5151a0',
],
[
'name' => 'White',
'slug' => 'white',
'color' => '#ffffff',
],
]
);
add_theme_support( 'disable-custom-colors' );
}
Code-Sprache: PHP (php)
Der JavaScript-Part
Neben Komponenten von Gutenberg brauchen wir noch die classnames
-Bibliothek. Um die zu installieren, führen wir folgenden Befehl in der Kommandozeile aus:
Code-Sprache: JavaScript (javascript)npm install classnames
Kommen wir jetzt zunächst zu den ganzen externen Dingen, die wir in unsere JavaScript-Datei importieren müssen.
import classnames from 'classnames';
const {
registerBlockType,
} = wp.blocks;
const {
InspectorControls,
InnerBlocks,
withColors,
getColorClass
} = wp.editor;
const {
PanelBody,
withFallbackStyles,
PanelColor,
ColorPalette,
} = wp.components;
const {
compose,
Component,
} = wp.element;
const {getComputedStyle} = window;
const FallbackStyles = withFallbackStyles((node, ownProps) => {
const {textColor, backgroundColor} = ownProps.attributes;
const editableNode = node.querySelector('[contenteditable="true"]');
//verify if editableNode is available, before using getComputedStyle.
const computedStyles = editableNode ? getComputedStyle(editableNode) : null;
return {
fallbackBackgroundColor: backgroundColor || !computedStyles ? undefined : computedStyles.backgroundColor,
fallbackTextColor: textColor || !computedStyles ? undefined : computedStyles.color,
};
});
Code-Sprache: JavaScript (javascript)
Wie bereits geschrieben, ist die Lösung ja aus bestehenden Gutenberg-Komponenten zusammengesucht – dementsprechend lassen sich diese Definitionen und die withFallbackStyles()
-Funktion im Absatz-Block und der PanelColor
-Komponente finden.
Wie im Absatz-Block zu sehen, werden wir den Edit-Teil unseres Blocks als Unterklasse von Component
anlegen:
class OneColumnBlock extends Component {
constructor() {
super(...arguments);
}
render() {
const {
attributes,
setAttributes,
mergeBlocks,
onReplace,
className,
backgroundColor,
textColor,
setBackgroundColor,
setTextColor,
fallbackBackgroundColor,
fallbackTextColor,
fallbackFontSize,
} = this.props;
const textColors = [
{
name: 'Tundora',
slug: 'tundora',
color: '#454545'
},
];
const backgroundColors = [
{
name: 'Puerto Rico',
slug: 'puerto-rico',
color: '#53c4ab'
},
{
name: 'Butterfly Bush',
slug: 'butterfly-bush',
color: '#5151a0'
},
{
name: 'White',
slug: 'white',
color: '#ffffff'
}
];
return (
<div
className={classnames(className, {
'has-background': backgroundColor.value,
[backgroundColor.class]: backgroundColor.class,
[textColor.class]: textColor.class,
})}
style={{
backgroundColor: backgroundColor.value,
color: textColor.value,
}}
>
<InnerBlocks/>
<InspectorControls>
<PanelColorSettings
title="'Farbschema"
colorSettings={[
{
colors: textColors,
label: 'Textfarbe',
onChange: setTextColor,
value: textColor.color,
disableCustomColors: true,
},
{
colors: backgroundColors,
label: 'Hintergrundfarbe',
onChange: setBackgroundColor,
value: backgroundColor.color,
disableCustomColors: true,
}
]}
/>
</InspectorControls>
</div>
);
}
}
Code-Sprache: JavaScript (javascript)
Interessant ist der render
-Part. Die Konstanten vom Anfang sind aus dem Absatz-Block übernommen – textColors
und backgroundColors
sind unsere Untermengen der über add_theme_support( 'editor-color-palette' )
definierten Farben.
Im return
-Teil wird zunächst ein div
geöffnet, in dem die Klassennamen und die Inline-Styles ausgegeben werden. Auch das ist aus der Absatz-Komponente übernommen. InnerBlocks
ist eine Komponente, die es ermöglicht, andere Blöcke in diesem Block zu verwenden, und danach geht es innerhalb von InspectorControls
an unsere Farbwähler, die wir über eine PanelColorSettings
-Komponente erstellen.
Hier geben wir zunächst mit title
den Titel an und übergeben mit colorSettings
ein Array von Objekten, wobei jedes Objekt einen Farbwähler erzeugt. Mit colors
definieren wir die verfügbaren Farben (Standard wären die, die über add_theme_support( 'editor-color-palette' )
angegeben wurden) – für den ersten Farbwähler mit textColors
die Textfarbe und mit backgroundColors
für den zweiten die Hintergrundfarben.
Über label
bekommt jeder Farbwähler eine Beschriftung und an onChange
über geben wir die Funktionen zum Speichern der Farbe (aus dem Absatz-Block entnommen). Als Wert wird der Hexadezimal-Wert genutzt und wir möchten deaktivieren, dass der Nutzer eine eigene Farbe definieren kann.
Ein letztes Stück Code haben wir jetzt noch – ebenfalls wieder an die Absatz-Komponente angelehnt:
export default registerBlockType('slug/one-column', {
title: 'Eine Spalte',
icon: 'admin-post',
category: 'layout',
attributes: {
backgroundColor: {
type: 'string',
},
textColor: {
type: 'string',
},
},
edit: compose([
withColors('backgroundColor', {textColor: 'color'}),
FallbackStyles,
])(OneColumnBlock),
save: props => {
const {
backgroundColor,
textColor,
customBackgroundColor,
customTextColor,
} = props.attributes;
const textClass = getColorClass( 'color', textColor );
const backgroundClass = getColorClass( 'background-color', backgroundColor );
const className = classnames( {
'has-background': backgroundColor || customBackgroundColor,
[ textClass ]: textClass,
[ backgroundClass ]: backgroundClass,
} );
return (
<div className={className}>
<InnerBlocks.Content/>
</div>
);
},
});
Code-Sprache: JavaScript (javascript)
Hier registrieren wir jetzt unseren konkreten Block slug/one-column
und geben ein paar Metadaten an. Als edit
legen wir mit compose
den Teil aus OneColumnBlock
fest und in save
bilden wir die eventuell notwendigen Farbklassen und weisen sie dem div
zu, das den Inhalt von unserem InnerBlocks
-Block umschließt.
Und so sieht das Ergebnis aus (ich habe bei dem Projekt ein paar Farben mehr als im Beispiel):
Den kompletten Code aus dem Beispiel könnt ihr als Gist anschauen.