JavaScript for WordPress Forums Gutenberg Development How to get a color class name

Viewing 12 posts - 1 through 12 (of 12 total)
  • Author
    Posts
  • #47916
    ericvalois
    Participant

    Hi, Gutenberg 2.8 introduced a new way to handle colors. In order to reduce inline styles. Which is a good thing!

    However, I’m having a hard time figure out how to get the color name instead of the color value.

    // give has-ffffff-background-color instead of has-white-background-color
    const backgroundClass = getColorClass( 'background-color', blockBackgroundColor );

    I took a look at the paragraph block source code for inspiration but it was too complicated for me.

    Any ideas?

    #47927
    Zac Gordon
    Keymaster

    Few things:

    1. Make sure you’ve added custom colors to your theme or plugin
    2. Make sure to import getColorClass from editor
    3. Setup your attributes all the same way as before (I believe)
    4. Save getColorClass( ‘color’, colorName ) to a variable
    5. Wherever you want to use that custom CSS name, call that variable

    Hope this helps!

    I don’t have any examples of this at the moment, but I will make a note for the next course update 🙂

    #47935
    ericvalois
    Participant

    Thanks for the fast answer, but it doesn’t work.

    My block is already set like you explained. My question is how to get the color name? Because the color attribute returns the color value, not the color’s name.
    https://github.com/time-to-first-byte/ttfb-blocks/blob/dev/blocks/section/index.js#L120

    #47952
    Zac Gordon
    Keymaster

    Hmmm, gotcha.

    I haven’t played with this enough, but maybe some of there other functions can help?

    https://github.com/WordPress/gutenberg/blob/f95b2d5b952e7a495128d6cb5ca90cc42cf4e169/editor/components/colors/utils.js

    Wonder if it’s setting in a color picker to return name if available instead of hex but you may still be able to get yourself.

    #51740
    mengland
    Participant

    @ericvalois

    Ironically I’m working on the same thing and having some struggles getting the color classes to work. Were you able to get a working example?

    #51745
    ericvalois
    Participant

    No sorry, I have never been able to make it work.

    #51754
    Zac Gordon
    Keymaster

    @mengland this is probably a good question for the core editor Slack channel 👍

    #51758
    mengland
    Participant

    I hopped on there and presented the question. I’ll post back if they share anything helpful. However, in the meantime I believe I stumbled upon something that provides a solution and I hope it helps someone else.

    Florian created a remake of the paragraph block which has a working Color Palette with color class names.
    Create different color palettes with Gutenberg

    #51761
    ericvalois
    Participant

    Thanks for the link!

    #51769
    mengland
    Participant

    I have one final follow up and I wanted to share this because it was a lot of work to get here. I have a working example of a block that pulls in custom colors that have been defined in theme support. The original link I shared showed how to utilize your own custom color sets defined at the block level.

    /**
    * Based on a block by Florian Brinkmann
    */
    
    import classnames from 'classnames';
    
    const {
    	registerBlockType,
    } = wp.blocks;
    const {
    	InspectorControls,
    	InnerBlocks,
    	PanelColor,
    	withColors,
    	getColorClass
    } = wp.editor;
    const {
    	PanelBody,
    	withFallbackStyles,
    	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,
    	};
    });
    
    class OneColumnBlock extends Component {
    	constructor() {
    		super(...arguments);
    	}
    
    	render() {
    		const {
    			attributes,
    			setAttributes,
    			mergeBlocks,
    			onReplace,
    			className,
    			backgroundColor,
    			textColor,
    			setBackgroundColor,
    			setTextColor,
    			fallbackBackgroundColor,
    			fallbackTextColor,
    			fallbackFontSize,
    		} = this.props;
    
    		const {
    			align,
    			content,
    			dropCap,
    			placeholder,
    		} = attributes;
    
    		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
            layouts={ [
              { name: 'inner-content', label: 'Story Container', icon: 'columns' },
            ] }
    
            template={
              [
                [ 'core/heading', { layout:'inner-content', placeholder:'Example Title...' } ],
                [ 'core/paragraph', { layout:'inner-content', placeholder:'Example Heading...' } ],
              ]
            }
            />
    				<InspectorControls>
    						<PanelColor
                  {...{
                    title: 'Background Color',
                    colorName: backgroundColor.name,
                    colorValue: backgroundColor.value,
                    initialOpen: false,
                    onChange: setBackgroundColor
                  } }
                />
    
                <PanelColor
                  {...{
                    title: 'Text Color',
                    colorName: textColor.name,
                    colorValue: textColor.value,
                    initialOpen: false,
                    onChange: setTextColor
                  } }
                />
    
    				</InspectorControls>
    			</div>
    		);
    	}
    }
    
    export default registerBlockType('slug/one-column', {
    	title: 'ColorPanel Example Column',
    	icon: 'admin-appearance',
    	category: 'common',
    	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>
    		);
    	},
    });
    
    #84683
    Tomas Mulder
    Participant

    If you make select available to dig into WordPress’s data and a few color helper functions

    const { select } = wp.data;
    const {
        getColorClassName,
        getColorObjectByColorValue,
    } = wp.editor;

    then you can grab the class name or style (in case they select a custom color)

    if( color ) {
        const settings = select( 'core/editor' ).getEditorSettings();
        const colorObject = getColorObjectByColorValue( settings.colors, color );
        if( colorObject ) {
            console.log( 'add a class of', getColorClassName( 'background-color', colorObject.slug ) );
        } else {
            console.log( 'add a style of', { backgroundColor: color } );
        }
    }

    pretty easily.

    #106793
    chiefalchemist
    Participant

    Did anyone ever find a final / current answer on this? My JS is basic so this might not be the best way to do this, but it’s working now (which is better than inlining the style colors.

            function colorObject(colors, color, prop){
    
                var colorObj = getColorObjectByColorValue(colors, color)
    
                if (typeof colorObj === 'undefined'){
                    return color.slice(1);
                }
    
                switch(prop) {
                    case 'color':
                    if ( colorObj.color ){
                        return colorObj.color
                    }
                    return '';
    
                    case 'name':
                    if ( colorObj.name ){
                        return colorObj.name
                    }
                    return '';
                      case 'slug':
                      if ( colorObj.slug ){
                        return colorObj.slug
                    }
                    return '';
    
                    default:
                     return ''
                  }
            }

    Then for classnames I have something like this:

            const classes = classnames(
                className,
                {
                [ <code>block-color-${colorObject(myObj.blockColors, blockColor, &quot;slug&quot;) }</code>]: blockColor,
             });

    Where myObj is an object of settings / values that I pass in via the WP PHP function localize script. This is allowing me to set the colors at the color pallet level, instead of a global one size fits all list of colors (via theme suppprts()). That same obj + property is also used then I configure the various pallets in the inspector.

    Maybe there’s a better way to do this? If so, some one please let me know. TIA

Viewing 12 posts - 1 through 12 (of 12 total)
  • You must be logged in to reply to this topic.