-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New block: Modal block using the Interactivity API (#675)
* Add a Modal block * Add editor UI * Add color controls * Modal style: Use default content width * Remove editor CSS The frontend style is loaded in the editor iframe, so this is not used * Dry the color code, explain how values are set * Render button as a div in the editor to prevent keyboard events * Fix or ignore eslint issues * Add button style options * Add `is-small` style options * Fix linter
- Loading branch information
Showing
7 changed files
with
597 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
<?php | ||
/** | ||
* Block Name: Modal | ||
* Description: Display content in a modal, hidden behind a button click. | ||
* | ||
* @package wporg | ||
*/ | ||
|
||
namespace WordPressdotorg\MU_Plugins\Modal; | ||
|
||
add_action( 'init', __NAMESPACE__ . '\init' ); | ||
|
||
/** | ||
* Registers the block using the metadata loaded from the `block.json` file. | ||
* Behind the scenes, it registers also all assets so they can be enqueued | ||
* through the block editor in the corresponding context. | ||
* | ||
* @see https://developer.wordpress.org/reference/functions/register_block_type/ | ||
*/ | ||
function init() { | ||
register_block_type( __DIR__ . '/build' ); | ||
} | ||
|
||
/** | ||
* Get the style declaration for a color attribute. | ||
* | ||
* The base color attribute (e.g. `backgroundColor`) is the preset color name, | ||
* and needs to be converted into a CSS variable. | ||
* The custom* color attribute (e.g. `customBackgroundColor`) is a hex value. | ||
* | ||
* In most cases, the base color attribute has a default value (see block.json), | ||
* so there will always be a value for that attribute. This means we can pick | ||
* up the custom* color attribute first, and fall back to the preset color if | ||
* it's not found. Also, when picked in the color picker, the custom color | ||
* will be prefilled with the hex value of the preset color. | ||
* | ||
* The overlayColor is a special case, it sets a default on `customOverlayColor`. | ||
* If only `overlayColor` is set, the custom default will be used. If coding a | ||
* modal by hand, make sure to set both `overlayColor` and `customColorOverlay` | ||
* when needed (or only `customColorOverlay`). | ||
* | ||
* @param array $attributes The block attributes. | ||
* @param string $name The name of the base attribute. | ||
* | ||
* @return string The style declaration (or empty if no colors set). | ||
*/ | ||
function get_style_decl_from_attr( $attributes, $name ) { | ||
$value = false; | ||
if ( ! empty( $attributes[ 'custom' . ucfirst( $name ) ] ) ) { | ||
$value = $attributes[ 'custom' . ucfirst( $name ) ]; | ||
} elseif ( ! empty( $attributes[ $name ] ) ) { | ||
$value = "var(--wp--preset--color--{$attributes[$name]})"; | ||
} | ||
|
||
if ( $value ) { | ||
// Get the custom property name. | ||
$slug = _wp_to_kebab_case( str_replace( 'Color', '', $name ) ); | ||
return "--wp--custom--wporg-modal--color--{$slug}: {$value};"; | ||
} | ||
|
||
return ''; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
<?php | ||
/** | ||
* Render the modal. | ||
*/ | ||
|
||
use function WordPressdotorg\MU_Plugins\Modal\get_style_decl_from_attr; | ||
|
||
$attributes['label'] = $attributes['label'] ?: __( 'Open modal', 'wporg' ); | ||
|
||
$style = ''; | ||
$style .= get_style_decl_from_attr( $attributes, 'backgroundColor' ); | ||
$style .= get_style_decl_from_attr( $attributes, 'textColor' ); | ||
$style .= get_style_decl_from_attr( $attributes, 'overlayColor' ); | ||
$style .= get_style_decl_from_attr( $attributes, 'closeButtonColor' ); | ||
|
||
$button_class = 'wp-block-button'; | ||
if ( ! empty( $attributes['buttonStyle'] ) ) { | ||
$button_class .= ' is-style-' . $attributes['buttonStyle']; | ||
} | ||
|
||
// Initial state to pass to Interactivity API. | ||
$init_state = [ | ||
'isOpen' => false, | ||
]; | ||
|
||
// Set up a unique ID for this modal. | ||
$html_id = wp_unique_id( 'modal-' ); | ||
|
||
?> | ||
<div | ||
<?php echo get_block_wrapper_attributes( [ 'style' => $style ]); // phpcs:ignore ?> | ||
data-wp-interactive="wporg/modal" | ||
data-wp-watch="callbacks.init" | ||
data-wp-on--keydown="actions.handleKeydown" | ||
data-wp-class--is-modal-open="context.isOpen" | ||
<?php echo wp_interactivity_data_wp_context( $init_state ); // phpcs:ignore ?> | ||
> | ||
<div class="wp-block-buttons"> | ||
<div class="<?php echo esc_attr( $button_class ); ?>"> | ||
<?php if ( ! empty( $attributes['href'] ) ) : ?> | ||
<a | ||
href="<?php echo esc_attr( $attributes['href'] ); ?>" | ||
download | ||
class="wporg-modal__toggle wp-block-button__link" | ||
data-wp-on--click="actions.toggle" | ||
data-wp-bind--aria-expanded="context.isOpen" | ||
aria-controls="<?php echo esc_attr( $html_id ); ?>" | ||
><?php echo wp_kses_post( $attributes['label'] ); ?></a> | ||
<?php else : ?> | ||
<button | ||
class="wporg-modal__toggle wp-block-button__link" | ||
data-wp-on--click="actions.toggle" | ||
data-wp-bind--aria-expanded="context.isOpen" | ||
aria-controls="<?php echo esc_attr( $html_id ); ?>" | ||
><?php echo wp_kses_post( $attributes['label'] ); ?></button> | ||
<?php endif; ?> | ||
</div> | ||
</div> | ||
|
||
<div | ||
class="wporg-modal__modal-backdrop" | ||
data-wp-bind--hidden="!context.isOpen" | ||
data-wp-on--click="actions.clickBackdrop" | ||
> | ||
<div | ||
class="wporg-modal__modal" | ||
id="<?php echo esc_attr( $html_id ); ?>" | ||
data-wp-bind--hidden="!context.isOpen" | ||
> | ||
<button | ||
class="wporg-modal__modal-close" | ||
data-wp-on--click="actions.close" | ||
aria-label="<?php esc_attr_e( 'Close', 'wporg' ); ?>" | ||
></button> | ||
|
||
<div class="wporg-modal__modal-content"> | ||
<?php echo wp_kses_post( $content ); ?> | ||
</div> | ||
</div> <!-- /.wporg-modal__modal --> | ||
</div> <!-- /.wporg-modal__modal-backdrop --> | ||
</div> <!-- /.wporg-modal --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
{ | ||
"$schema": "https://schemas.wp.org/trunk/block.json", | ||
"apiVersion": 3, | ||
"name": "wporg/modal", | ||
"title": "Modal", | ||
"icon": "location", | ||
"category": "layout", | ||
"description": "A modal dialog.", | ||
"textdomain": "wporg", | ||
"attributes": { | ||
"backgroundColor": { | ||
"type": "string", | ||
"default": "white" | ||
}, | ||
"customBackgroundColor": { | ||
"type": "string" | ||
}, | ||
"textColor": { | ||
"type": "string", | ||
"default": "charcoal-1" | ||
}, | ||
"customTextColor": { | ||
"type": "string" | ||
}, | ||
"closeButtonColor": { | ||
"type": "string", | ||
"default": "charcoal-1" | ||
}, | ||
"customCloseButtonColor": { | ||
"type": "string" | ||
}, | ||
"overlayColor": { | ||
"type": "string" | ||
}, | ||
"customOverlayColor": { | ||
"type": "string", | ||
"default": "#1e1e1ecc" | ||
}, | ||
"href": { | ||
"type": "string" | ||
}, | ||
"label": { | ||
"type": "string", | ||
"default": "Open modal" | ||
}, | ||
"buttonStyle": { | ||
"type": "string", | ||
"default": "" | ||
} | ||
}, | ||
"supports": { | ||
"align": false, | ||
"layout": false, | ||
"interactivity": true | ||
}, | ||
"editorScript": "file:./index.js", | ||
"style": "file:./style-index.css", | ||
"viewScriptModule": "file:./view.js", | ||
"render": "file:../render.php" | ||
} |
Oops, something went wrong.