Compare commits

...

16 Commits

29 changed files with 336 additions and 264 deletions

View File

@@ -72,7 +72,8 @@
},
"require-dev": {
"roave/security-advisories": "dev-latest",
"laravel/pint": "^1.18"
"laravel/pint": "^1.18",
"wpackagist-plugin/ajax-thumbnail-rebuild": "^1.14"
},
"config": {
"optimize-autoloader": true,

20
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "45d0a582ae7850e497fe7f2b3d7752a7",
"content-hash": "7666943446e3342a3e30a48917611260",
"packages": [
{
"name": "badegguk/bad-egg-digital-login-page",
@@ -2846,6 +2846,24 @@
}
],
"time": "2025-12-12T23:06:01+00:00"
},
{
"name": "wpackagist-plugin/ajax-thumbnail-rebuild",
"version": "1.14",
"source": {
"type": "svn",
"url": "https://plugins.svn.wordpress.org/ajax-thumbnail-rebuild/",
"reference": "tags/1.14"
},
"dist": {
"type": "zip",
"url": "https://downloads.wordpress.org/plugin/ajax-thumbnail-rebuild.1.14.zip"
},
"require": {
"composer/installers": "^1.0 || ^2.0"
},
"type": "wordpress-plugin",
"homepage": "https://wordpress.org/plugins/ajax-thumbnail-rebuild/"
}
],
"aliases": [],

View File

@@ -10,6 +10,8 @@ class Colour
if($colour == 'black'):
$hex = '#000000';
elseif($colour == 'grey'):
$hex = '#808080';
elseif($colour == 'white'):
$hex = '#FFFFFF';
else:
@@ -27,10 +29,11 @@ class Colour
public function values()
{
$colours = get_field('badegg_colours', 'option');
$values = [];
if(function_exists('get_field')):
$colours = get_field('badegg_colours', 'option');
if($colours):
foreach($colours as $index => $props):
$index = $index + 1;
@@ -39,8 +42,10 @@ class Colour
if($hex) $values[$this->latinate($index)] = $hex;
endforeach;
endif;
endif;
$values['white'] = '#FFFFFF';
$values['grey'] = '#808080';
$values['black'] = '#000000';
return $values;
@@ -49,13 +54,13 @@ class Colour
public function tints()
{
return [
'lightest' => 100,
'lighter' => 66,
'light' => 33,
'lightest' => 40,
'lighter' => 25,
'light' => 10,
'0' => 0,
'dark' => -33,
'darker' => -66,
'darkest' => -100,
'dark' => -10,
'darker' => -25,
'darkest' => -40,
];
}

View File

@@ -30,17 +30,17 @@ class CssClasses {
'tint' => $props['bg_tint'],
]);
if(($knockout && $Colour->is_dark($hex) || $props['contrast'] == 'light'))
if(($props['contrast'] && $knockout))
$classes[] = 'knockout';
if($props['padding_top'])
if(!$props['padding_top'])
$classes[] = 'section-zero-top';
if($props['padding_bottom'])
if(!$props['padding_bottom'])
$classes[] = 'section-zero-bottom';
if($props['bg_image'])
$classes[] = "bg-watermarked";
$classes[] = "has-bg-image";
return $classes;
}
@@ -89,7 +89,7 @@ class CssClasses {
if($args['align'])
$classes[] = 'align-' . $args['align'];
if(($Colour->is_dark($hex) || $bg_props['contrast'] == 'light'))
if(($bg_props['contrast']))
$classes[] = 'knockout';
return $classes;

View File

@@ -103,59 +103,7 @@ add_action('init', function () {
'style' => "{$slug}-style",
'script' => "{$slug}-script",
'view_script' => "{$slug}-view-script",
'attributes' => [
'container_width' => [
'type' => 'string',
'default' => '',
],
'alignment' => [
'type' => 'string',
],
'padding_top' => [
'type' => 'boolean',
'default' => true
],
'padding_bottom' => [
'type' => 'boolean',
'default' => true
],
'background_colour' => [
'type' => 'string',
'default' => '',
],
'background_hex' => [
'type' => 'string',
'default' => '',
],
'background_tint' => [
'type' => 'string',
'default' => '0',
],
'background_image' => [
'type' => 'integer',
'default' => 0,
],
'background_url' => [
'type' => 'string',
'default' => '',
],
'background_opacity' => [
'type' => 'integer',
'default' => 30
],
'background_position' => [
'type' => 'string',
'default' => '',
],
'background_fixed' => [
'type' => 'boolean',
'default' => false,
],
'background_contrast' => [
'type' => 'boolean',
'default' => false,
],
],
'attributes' => attributes(),
];
if(!property_exists($json, 'acf') && \Roots\view()->exists("blocks.{$slug}.render")) {
@@ -176,12 +124,20 @@ add_action('init', function () {
function list_inner()
{
$file = file_get_contents(get_theme_file_path("resources/json/core-block-whitelist.json"));
$file = file_get_contents(get_theme_file_path("resources/json/block-core-whitelist.json"));
$json = json_decode($file);
return $json;
}
function attributes()
{
$file = file_get_contents(get_theme_file_path("resources/json/block-attributes.json"));
$json = json_decode($file, true);
return $json;
}
function list_all()
{
$blocks = array_map(function($block) {

View File

@@ -17,9 +17,12 @@
"id": ""
},
"choices": {
"0": "auto",
"0": "None",
"primary": "<i class=\"fas fa-circle\" style=\"color: #dd3333\"><\/i> Punch",
"secondary": "<i class=\"fas fa-circle\" style=\"color: #81d742\"><\/i> Atlantis",
"tertiary": "<i class=\"fas fa-circle\" style=\"color: #8224e3\"><\/i> Purple Heart",
"white": "<i class=\"fas fa-circle\" style=\"color: #FFFFFF\"><\/i> White",
"grey": "<i class=\"fas fa-circle\" style=\"color: #808080\"><\/i> Gray",
"black": "<i class=\"fas fa-circle\" style=\"color: #000000\"><\/i> Black"
},
"default_value": 0,
@@ -91,10 +94,10 @@
},
{
"key": "field_67350f526abf1",
"label": "Text Contrast",
"label": "",
"name": "contrast",
"aria-label": "",
"type": "select",
"type": "true_false",
"instructions": "",
"required": 0,
"conditional_logic": 0,
@@ -103,20 +106,12 @@
"class": "",
"id": ""
},
"choices": {
"0": "Auto",
"dark": "Force dark text",
"light": "Force light text"
},
"message": "Text Contrast",
"default_value": 0,
"return_format": "value",
"multiple": 0,
"allow_null": 0,
"ui": 0,
"ajax": 0,
"placeholder": "",
"create_options": 0,
"save_options": 0
"allow_in_bindings": 0,
"ui_on_text": "Light",
"ui_off_text": "Dark",
"ui": 1
}
],
"location": [
@@ -137,5 +132,6 @@
"active": true,
"description": "",
"show_in_rest": 0,
"modified": 1765746167
"display_title": "",
"modified": 1767548180
}

View File

@@ -36,56 +36,6 @@
},
"layout": "block",
"sub_fields": [
{
"key": "field_67350eb62cdf9",
"label": "Top Padding",
"name": "padding_top",
"aria-label": "",
"type": "radio",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "50",
"class": "",
"id": ""
},
"choices": [
"On",
"Off"
],
"default_value": "",
"return_format": "value",
"allow_null": 0,
"other_choice": 0,
"layout": "horizontal",
"save_other_choice": 0
},
{
"key": "field_673510c1dc830",
"label": "Bottom Padding",
"name": "padding_bottom",
"aria-label": "",
"type": "radio",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "50",
"class": "",
"id": ""
},
"choices": [
"On",
"Off"
],
"default_value": "",
"return_format": "value",
"allow_null": 0,
"other_choice": 0,
"layout": "horizontal",
"save_other_choice": 0
},
{
"key": "field_6800097e61765",
"label": "Container Width",
@@ -119,6 +69,66 @@
"create_options": 0,
"save_options": 0
},
{
"key": "field_67350eb62cdf9",
"label": "",
"name": "padding_top",
"aria-label": "",
"type": "true_false",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"message": "Top Padding",
"default_value": 1,
"allow_in_bindings": 0,
"ui_on_text": "On",
"ui_off_text": "Off",
"ui": 1
},
{
"key": "field_673510c1dc830",
"label": "",
"name": "padding_bottom",
"aria-label": "",
"type": "true_false",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"message": "Bottom Padding",
"default_value": 1,
"allow_in_bindings": 0,
"ui_on_text": "On",
"ui_off_text": "Off",
"ui": 1
},
{
"key": "field_695aa550e16d4",
"label": "Background",
"name": "",
"aria-label": "",
"type": "message",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"message": "",
"new_lines": "wpautop",
"esc_html": 0
},
{
"key": "field_67350aeb146ca",
"label": "Background",
@@ -181,5 +191,5 @@
"description": "",
"show_in_rest": 0,
"display_title": "",
"modified": 1765815052
"modified": 1767548583
}

View File

@@ -63,7 +63,7 @@ p,
li,
td,
label {
color: colours.$grey-dark;
color: colours.$grey-darker;
font-family: fonts.$font;
font-weight: 400;
line-height: 1.5em;

View File

@@ -24,7 +24,7 @@
}
}
#{$button}.#{$name}.inverted {
#{$button}.#{$name}.outline {
color: $hex;
background: transparent;
border-color: $hex;

View File

@@ -13,48 +13,50 @@ $secondary: #5bc0de;
$tertiary: color.invert($primary);
$quaternary: color.invert($secondary);
//== Shades
$white: #FFFFFF;
$grey: #808080;
$black: #000000;
//== Primary Tints
$primary-darkest: color.adjust($primary, $lightness: -30%);
$primary-darker: color.adjust($primary, $lightness: -20%);
$primary-dark: color.adjust($primary, $lightness: -10%);
$primary-light: color.adjust($primary, $lightness: 10%);
$primary-lighter: color.adjust($primary, $lightness: 20%);
$primary-lightest: color.adjust($primary, $lightness: 30%);
$primary-darkest: color.adjust($primary, $lightness: -45%);
$primary-darker: color.adjust($primary, $lightness: -30%);
$primary-dark: color.adjust($primary, $lightness: -15%);
$primary-light: color.adjust($primary, $lightness: 15%);
$primary-lighter: color.adjust($primary, $lightness: 30%);
$primary-lightest: color.adjust($primary, $lightness: 45%);
//== Secondary Tints
$secondary-darkest: color.adjust($secondary, $lightness: -30%);
$secondary-darker: color.adjust($secondary, $lightness: -20%);
$secondary-dark: color.adjust($secondary, $lightness: -10%);
$secondary-light: color.adjust($secondary, $lightness: 10%);
$secondary-lighter: color.adjust($secondary, $lightness: 20%);
$secondary-lightest: color.adjust($secondary, $lightness: 30%);
$secondary-darkest: color.adjust($secondary, $lightness: -45%);
$secondary-darker: color.adjust($secondary, $lightness: -30%);
$secondary-dark: color.adjust($secondary, $lightness: -15%);
$secondary-light: color.adjust($secondary, $lightness: 15%);
$secondary-lighter: color.adjust($secondary, $lightness: 30%);
$secondary-lightest: color.adjust($secondary, $lightness: 45%);
//== Tertiary Tints
$tertiary-darkest: color.adjust($tertiary, $lightness: -30%);
$tertiary-darker: color.adjust($tertiary, $lightness: -20%);
$tertiary-dark: color.adjust($tertiary, $lightness: -10%);
$tertiary-light: color.adjust($tertiary, $lightness: 10%);
$tertiary-lighter: color.adjust($tertiary, $lightness: 20%);
$tertiary-lightest: color.adjust($tertiary, $lightness: 30%);
$tertiary-darkest: color.adjust($tertiary, $lightness: -45%);
$tertiary-darker: color.adjust($tertiary, $lightness: -30%);
$tertiary-dark: color.adjust($tertiary, $lightness: -15%);
$tertiary-light: color.adjust($tertiary, $lightness: 15%);
$tertiary-lighter: color.adjust($tertiary, $lightness: 30%);
$tertiary-lightest: color.adjust($tertiary, $lightness: 45%);
//== quaternary Tints
$quaternary-darkest: color.adjust($quaternary, $lightness: -30%);
$quaternary-darker: color.adjust($quaternary, $lightness: -20%);
$quaternary-dark: color.adjust($quaternary, $lightness: -10%);
$quaternary-light: color.adjust($quaternary, $lightness: 10%);
$quaternary-lighter: color.adjust($quaternary, $lightness: 20%);
$quaternary-lightest: color.adjust($quaternary, $lightness: 30%);
$quaternary-darkest: color.adjust($quaternary, $lightness: -45%);
$quaternary-darker: color.adjust($quaternary, $lightness: -30%);
$quaternary-dark: color.adjust($quaternary, $lightness: -15%);
$quaternary-light: color.adjust($quaternary, $lightness: 15%);
$quaternary-lighter: color.adjust($quaternary, $lightness: 30%);
$quaternary-lightest: color.adjust($quaternary, $lightness: 45%);
//== Shades
$white: white;
$grey-lightest: color.adjust(black, $lightness: 95%);
$grey-lighter: color.adjust(black, $lightness: 80%);
$grey-light: color.adjust(black, $lightness: 70%);
$grey: color.adjust(black, $lightness: 50%);
$grey-dark: color.adjust(black, $lightness: 40%);
$grey-darker: color.adjust(black, $lightness: 20%);
$grey-darkest: color.adjust(black, $lightness: 05%);
$black: black;
//== six shades of grey
$grey-darkest: color.adjust(grey, $lightness: -40%);
$grey-darker: color.adjust(grey, $lightness: -25%);
$grey-dark: color.adjust(grey, $lightness: -10%);
$grey-light: color.adjust(grey, $lightness: 10%);
$grey-lighter: color.adjust(grey, $lightness: 25%);
$grey-lightest: color.adjust(grey, $lightness: 40%);
//## Colour Array (used in generating colour classes).
$colors: (

View File

@@ -85,6 +85,7 @@ export default function BlockSettings({ attributes, setAttributes }) {
background_hex,
background_tint,
background_image,
background_url,
background_opacity,
background_contrast,
background_fixed,
@@ -156,6 +157,7 @@ export default function BlockSettings({ attributes, setAttributes }) {
/>
{ 'background_colour' in attributes && attributes.background_colour && ![0, '0', 'white', 'black'].includes(attributes.background_colour) ? (
<>
<SelectControl
label={ __("Background Tint", "badegg") }
value={ background_tint }
@@ -164,16 +166,17 @@ export default function BlockSettings({ attributes, setAttributes }) {
__next40pxDefaultSize={ true }
__nextHasNoMarginBottom={ true }
/>
) : null }
{ background_image != 0 && (
<>
<ToggleControl
label={ __('Text Contrast', 'badegg') }
checked={ background_contrast }
onChange={(value) => setAttributes({ background_contrast: value }) }
__nextHasNoMarginBottom
/>
</>
) : null }
{ background_image != 0 && (
<>
<ToggleControl
label={ __('Fixed Position', 'badegg') }
checked={ background_fixed }
@@ -216,7 +219,7 @@ export default function BlockSettings({ attributes, setAttributes }) {
{ background_image != 0 && (
<Button
onClick={ () => setAttributes({ background_image: 0 }) }
onClick={ () => setAttributes({ background_image: 0, background_url: '' }) }
isDestructive
variant="secondary"
>

View File

@@ -1,4 +1,4 @@
export function containerClassNames(attributes, bgProps)
export function containerClassNames(attributes, extraClasses = [])
{
let classNames = [
@@ -11,6 +11,9 @@ export function containerClassNames(attributes, bgProps)
if('alignment' in attributes)
classNames.push(`align-${attributes.alignment}`);
// combine arrays
classNames = classNames.concat(extraClasses);
return classNames;
}

View File

@@ -1,44 +1,12 @@
import domReady from '@wordpress/dom-ready';
import blockWhitelist from '../json/core-block-whitelist.json';
import blockParents from '../json/block-parents.json';
import blockWhitelist from '../json/block-core-whitelist.json';
import.meta.glob('../views/blocks/**/{index.jsx,index.js}', { eager: true })
domReady(() => {
const TEXT_EDITOR_BLOCKS = [
// Design
'core/separator',
'core/spacer',
// Media
'core/cover',
'core/file',
'core/gallery',
'core/image',
'core/media-text',
'core/audio',
'core/video',
// Text
'core/footnotes',
'core/heading',
'core/list',
'core/code',
'core/details',
'core/list-item',
'core/missing',
'core/paragraph',
'core/preformatted',
'core/pullquote',
'core/quote',
'core/table',
'core/verse',
];
const restrictEditorParentBlocks = (settings, name) => {
if (TEXT_EDITOR_BLOCKS.includes(name)) {
settings.parent = [
'acf/badegg-editor',
'badegg/article',
];
if (blockWhitelist.includes(name)) {
settings.parent = blockParents;
}
return settings
@@ -46,8 +14,7 @@ domReady(() => {
wp.hooks.addFilter(
'blocks.registerBlockType',
'your-project-name/restrict-parent-blocks',
'badegg/restrict-parent-blocks',
restrictEditorParentBlocks
);
});

View File

@@ -1,12 +0,0 @@
export default function isInsideMyACFBlock(blockName)
{
const editor = wp.data.select('core/block-editor');
const selectedId = editor.getSelectedBlockClientId();
if (!selectedId) return false;
const parents = editor.getBlockParents(selectedId);
const parentNames = parents.map(id => editor.getBlockName(id));
return parentNames.includes(blockName);
}

View File

@@ -0,0 +1,53 @@
{
"container_width": {
"type": "string",
"default": ""
},
"alignment": {
"type": "string"
},
"padding_top": {
"type": "boolean",
"default": true
},
"padding_bottom": {
"type": "boolean",
"default": true
},
"background_colour": {
"type": "string",
"default": ""
},
"background_hex": {
"type": "string",
"default": ""
},
"background_tint": {
"type": "string",
"default": "0"
},
"background_image": {
"type": "integer",
"default": 0
},
"background_url": {
"type": "string",
"default": ""
},
"background_opacity": {
"type": "integer",
"default": 30
},
"background_position": {
"type": "string",
"default": ""
},
"background_fixed": {
"type": "boolean",
"default": false
},
"background_contrast": {
"type": "boolean",
"default": false
}
}

View File

@@ -0,0 +1,4 @@
[
"acf/badegg-editor",
"badegg/article"
]

View File

@@ -0,0 +1,25 @@
# Bad Egg's Article Builder
Designed as a full width component, Article Builder bundles core wordpress blocks commonly used in articles into a classic editor like experience.
## Features
- Uses the `<InnerBlocks/>` component with a whitelist defined in `resources/json/core-block-whitelist.json`
- Provides spacing and background configuration options
- Default block attributes are defined in `resources/json/block-attributes.json` so that they are not needed in duplicate in `block.json`
- A reusable customisation UI is defined in `resources/js/blocks/components/BlockSettings.jsx` so that multiple blocks can rely on the same controls
## Theme-level changes
- All core wordpress blocks are disabled at the top level to prevent them from being used alongside full-width blocks designed to craft page layouts
- Blocks that can use core whitelisted inner blocks are defined in `resources/json/block-parents.json`
## Attributes
- Top Padding
- Bottom Padding
- Container width
- Background
- Colour
- Tint
- Image
- Image opacity
- Text contrast toggle
- Fixed position toggle

View File

@@ -1,4 +0,0 @@
// block.json's editorStyle, applied in block editor and front end
.wp-block-badegg-article.block-editor-block-list__block {
display: block;
}

View File

@@ -9,7 +9,7 @@ import {
InnerBlocks,
} from '@wordpress/block-editor';
import allowedBlocks from '../../../json/core-block-whitelist.json';
import allowedBlocks from '../../../json/block-core-whitelist.json';
import { containerClassNames, sectionClassNames } from '../../../js/blocks/lib/classNames';
import BackgroundImage from '../../../js/blocks/components/BackgroundImage';
import BlockSettings from '../../../js/blocks/components/BlockSettings';
@@ -17,7 +17,7 @@ import BlockSettings from '../../../js/blocks/components/BlockSettings';
registerBlockType(metadata.name, {
edit({ attributes, setAttributes }) {
const blockProps = useBlockProps();
blockProps.className = sectionClassNames(attributes, blockProps.className, [ 'wysiwyg' ]).join(' ');
blockProps.className = sectionClassNames(attributes, blockProps.className).join(' ');
return (
<div { ...blockProps }>
@@ -26,7 +26,7 @@ registerBlockType(metadata.name, {
setAttributes={ setAttributes }
/>
<div className={ containerClassNames(attributes).join(' ') }>
<div className={ containerClassNames(attributes, [ 'wysiwyg' ]).join(' ') }>
<InnerBlocks
allowedBlocks={ allowedBlocks }
defaultBlock={
@@ -51,7 +51,7 @@ registerBlockType(metadata.name, {
return (
<div { ...blockProps }>
<div className={ containerClassNames(attributes).join(' ') }>
<div className={ containerClassNames(attributes, [ 'wysiwyg' ]).join(' ') }>
<InnerBlocks.Content />
</div>

View File

@@ -1 +0,0 @@
// block.json's script, loaded in block editor and front end

View File

@@ -1,4 +0,0 @@
// block.json's style, applied in block editor and front end
.wp-block-badegg-article {
display: block;
}

View File

@@ -1 +0,0 @@
// block.json's viewScript, applied on front end only

View File

@@ -0,0 +1,40 @@
# Bad Egg's Native Wordpress Block Example
This block serves as a placeholder that can be copied and extended to build native Wordpress blocks.
## Features
- Automatic registration and asset building through the theme's `app/blocks.php` file and `vite.config.js`
- Automatic enqueueing of block scripts and styles if the correct files are included in the block's directory
- Supports Laravel Blade templates if the `render.blade.php` file is present, with access to the `$attributes`, `$block`, and `$content` variables.
- Default block attributes are defined in `resources/json/block-attributes.json` so that they are not needed in duplicate in `block.json`
- A reusable customisation UI is defined in `resources/js/blocks/components/BlockSettings.jsx` so that multiple blocks can rely on the same controls
## Directory Structure
```
app
│ ...
│ blocks.php -> this is where the auto registration functions live
resources
│ ...
└── js
│ └── editor.js
└── views
│ ...
└── blocks
│ ...
└── example
│ README.md -> this file
│ block.json -> (required) the block's metadata
│ index.jsx -> (required) EditorScript
│ script.js -> (optional) Editor & Front end
│ view.js -> (optional) Front end
│ editor.scss -> (optional) Editor
│ style.scss -> (optional) Editor & Front end
│ render.blade.php -> (optional) falls back to index.jsx save
```

View File

@@ -1,17 +1,22 @@
// block.json's editorScript, loaded only in the block editor
import metadata from './block.json';
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps } from '@wordpress/block-editor';
import metadata from './block.json';
import { containerClassNames, sectionClassNames } from '../../../js/blocks/lib/classNames';
registerBlockType(metadata.name, {
edit() {
edit({ attributes }) {
const blockProps = useBlockProps();
blockProps.className = sectionClassNames(attributes, blockProps.className, ['bg-success', 'knockout']).join(' ');
return (
<section { ...blockProps }>
<div { ...blockProps }>
<div className="container align-center wysiwyg">
<h2>Bad Egg Block Example</h2>
</section>
</div>
</div>
);
}
});

View File

@@ -1,3 +1,7 @@
<div class="block-badegg-example">
<div {!! get_block_wrapper_attributes([
'class' => 'section bg-success knockout',
]) !!}>
<div class="container wysiwyg align-center">
<h2>Bad Egg Example Block (Blade)</h2>
</div>
</div>

View File

@@ -1 +1,2 @@
// block.json's script, loaded in block editor and front end
console.log('bad egg example block script.js loaded.');

View File

@@ -1 +1,2 @@
// block.json's viewScript, applied on front end only
console.log('bad egg example block view.js loaded.');

View File

@@ -1,4 +1,4 @@
@if($props['blurb'])
@if($props['blurb'] || $props['links'])
@php
$containerProps = [
'width' => $props['container_width'],