Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -1356,7 +1356,6 @@ private static function add_account_notice( $message, $type = 'success' ) {
$message,
[
'type' => $type,
'corner' => 'top-right',
'autohide' => true,
'active_on_load' => true,
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ public static function sanitize_svgs() {
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false" class="newspack-ui__svg-icon--arrow-right">
<path d="m14.5 6.5-1 1 3.7 3.7H4v1.6h13.2l-3.7 3.7 1 1 5.6-5.5z" />
</svg>',
'caution' =>
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false" class="newspack-ui__svg-icon--caution">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.5 12a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0ZM12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16Zm-.75 12v-1.5h1.5V16h-1.5Zm0-8v5h1.5V8h-1.5Z" />
</svg>',
'check' =>
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false" class="newspack-ui__svg-icon--check">
<path d="M16.5 7.5 10 13.9l-2.5-2.4-1 1 3.5 3.6 7.5-7.6z" />
Expand Down
152 changes: 98 additions & 54 deletions plugins/newspack-plugin/includes/class-newspack-ui.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Newspack_UI {
*
* @var array
*/
private static $notices = [];
private static array $notices = [];

/**
* Initialize hooks.
Expand Down Expand Up @@ -59,34 +59,56 @@ public static function enqueue_assets() {
Newspack::asset_version( 'newspack-ui' ),
true
);

$icons = [];
foreach ( self::get_type_icons() as $type => $icon_name ) {
$icons[ $type ] = wp_kses( Newspack_UI_Icons::get_svg( $icon_name ), Newspack_UI_Icons::sanitize_svgs() );
}
wp_localize_script(
'newspack-ui',
'newspackUIData',
[
'icons' => $icons,
]
);
}

/**
* Map of notice types to their Newspack UI icon name. Types absent from the
* map render no icon.
*
* @return array<string, string> Notice type => icon name.
*/
private static function get_type_icons() {
return [
'error' => 'error',
'warning' => 'caution',
];
}

/**
* Add a snackbar notice.
*
* @param string $message The notice message.
* @param string|array $args Notice arguments array or notice type.
* @param string|array $args Notice arguments array, or a notice type string as shorthand.
*
* @return string The notice ID.
*/
public static function add_notice( $message, $args = [] ) {
public static function add_notice( string $message, string|array $args = [] ): string {
if ( is_string( $args ) ) {
$args = [
'type' => $args,
];
$args = [ 'type' => $args ];
}
$notice = wp_parse_args(
$args,
[
'message' => $message,
'corner' => 'top-right',
'type' => 'success',
'type' => 'success', // Severity; drives the ARIA announcement politeness ('error' assertive, else polite), the type icon, and the [data-type] styling.
'id' => uniqid(),
'autohide' => true, // If false, the notice will have a close button.
'active_on_load' => true, // Whether the notice should be visible on page load.
]
);
self::$notices[ $notice['corner'] ][ $notice['id'] ] = $notice;
self::$notices[ $notice['id'] ] = $notice;
Comment thread
adekbadek marked this conversation as resolved.

return $notice['id'];
}
Expand All @@ -98,36 +120,35 @@ public static function print_notices() {
if ( empty( self::$notices ) ) {
return;
}

foreach ( self::$notices as $corner => $notices ) {
if ( empty( $notices ) ) {
continue;
}
?>
<div class="newspack-ui">
<div class="newspack-ui__snackbar newspack-ui__snackbar--<?php echo esc_attr( $corner ); ?>">
<?php foreach ( $notices as $notice ) : ?>
<div
class="newspack-ui__snackbar__item newspack-ui__snackbar__item--<?php echo esc_attr( $notice['type'] ); ?>"
data-notice-id="<?php echo esc_attr( $notice['id'] ); ?>"
data-nonce="<?php echo esc_attr( wp_create_nonce( 'newspack_ui_notice_dismissed' ) ); ?>"
data-autohide="<?php echo $notice['autohide'] ? 'true' : 'false'; ?>"
data-active-on-load="<?php echo $notice['active_on_load'] ? 'true' : 'false'; ?>"
>
<?php if ( ! $notice['autohide'] ) : ?>
<button class="newspack-ui__snackbar__close" aria-label="<?php esc_attr_e( 'Close', 'newspack-plugin' ); ?>" title="<?php esc_attr_e( 'Close', 'newspack-plugin' ); ?>">
<?php Newspack_UI_Icons::print_svg( 'closeSmall' ); ?>
</button>
<?php endif; ?>
<div class="newspack-ui__snackbar__content">
<?php echo wp_kses_post( $notice['message'] ); ?>
</div>
?>
<div class="newspack-ui">
<div class="newspack-ui__snackbar">
<?php foreach ( self::$notices as $notice ) : ?>
<div
class="newspack-ui__snackbar__item"
Comment thread
adekbadek marked this conversation as resolved.
data-type="<?php echo esc_attr( $notice['type'] ); ?>"
data-notice-id="<?php echo esc_attr( $notice['id'] ); ?>"
data-nonce="<?php echo esc_attr( wp_create_nonce( 'newspack_ui_notice_dismissed' ) ); ?>"
data-autohide="<?php echo $notice['autohide'] ? 'true' : 'false'; ?>"
data-active-on-load="<?php echo $notice['active_on_load'] ? 'true' : 'false'; ?>"
>
<?php $type_icons = self::get_type_icons(); ?>
<?php if ( isset( $type_icons[ $notice['type'] ] ) ) : ?>
<span class="newspack-ui__snackbar__icon"><?php Newspack_UI_Icons::print_svg( $type_icons[ $notice['type'] ] ); ?></span>
<?php endif; ?>
<div class="newspack-ui__snackbar__content">
<?php echo wp_kses_post( $notice['message'] ); ?>
</div>
<?php endforeach; ?>
</div>
<?php if ( ! $notice['autohide'] ) : ?>
<button class="newspack-ui__button newspack-ui__button--icon newspack-ui__button--ghost-dark newspack-ui__snackbar__close" aria-label="<?php esc_attr_e( 'Close', 'newspack-plugin' ); ?>" title="<?php esc_attr_e( 'Close', 'newspack-plugin' ); ?>">
<?php Newspack_UI_Icons::print_svg( 'closeSmall' ); ?>
</button>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php
}
</div>
<?php
}

/**
Expand Down Expand Up @@ -468,69 +489,92 @@ public static function return_demo_content() {

<h2 id="notices">Notices</h2>

<div class="newspack-ui__notice">
<div class="newspack-ui__notice" role="status">
<div>
<p>Default notice style</p>
</div>
</div>

<div class="newspack-ui__notice newspack-ui__notice--success">
<div class="newspack-ui__notice newspack-ui__notice--success" role="status">
<div>
<p>"Success" notice style</p>
</div>
</div>

<div class="newspack-ui__notice newspack-ui__notice--warning">
<div class="newspack-ui__notice newspack-ui__notice--warning" role="status">
<div>
<p>"Warning" notice style</p>
</div>
</div>

<div class="newspack-ui__notice newspack-ui__notice--error">
<div class="newspack-ui__notice newspack-ui__notice--error" role="alert">
<div>
<p>"Error" notice style</p>
</div>
</div>

<div class="newspack-ui__notice">
<div class="newspack-ui__notice" role="status">
<?php Newspack_UI_Icons::print_svg( 'info' ); ?>
<div>
<p>Default notice with icon style</p>
</div>
</div>

<div class="newspack-ui__notice newspack-ui__notice--success">
<div class="newspack-ui__notice newspack-ui__notice--success" role="status">
<?php Newspack_UI_Icons::print_svg( 'check' ); ?>
<div>
<p>"Success" notice with icon style</p>
</div>
</div>

<div class="newspack-ui__notice newspack-ui__notice--warning">
<div class="newspack-ui__notice newspack-ui__notice--warning" role="status">
<?php Newspack_UI_Icons::print_svg( 'info' ); ?>
<div>
<p>"Warning" notice with icon style</p>
</div>
</div>

<div class="newspack-ui__notice newspack-ui__notice--error">
<div class="newspack-ui__notice newspack-ui__notice--error" role="alert">
<?php Newspack_UI_Icons::print_svg( 'error' ); ?>
<div>
<p>"Error" notice with icon style</p>
</div>
</div>
<button id="show-snackbar-example" class="newspack-ui__button newspack-ui__button--primary">Show snackbar</button>
<div class="newspack-ui__snackbar newspack-ui__snackbar--top-right">
<div id="snackbar-example" class="newspack-ui__snackbar__item newspack-ui__snackbar__item--success" data-autohide="true">
<div class="newspack-ui__snackbar__content">This is a snackbar message</div>
</div>
<div class="newspack-ui__stack newspack-ui__stack--horizontal">
<button id="show-snackbar-example" class="newspack-ui__button newspack-ui__button--primary">Show snackbar</button>
<button id="show-snackbar-warning" class="newspack-ui__button newspack-ui__button--secondary">Show warning snackbar</button>
<button id="show-snackbar-persistent" class="newspack-ui__button newspack-ui__button--secondary">Show error snackbar</button>
</div>
<div class="newspack-ui__snackbar"></div>
<template id="snackbar-persistent-template">
<div class="newspack-ui__snackbar__item" data-type="error" data-autohide="false">
<span class="newspack-ui__snackbar__icon"><?php Newspack_UI_Icons::print_svg( 'error' ); ?></span>
<div class="newspack-ui__snackbar__content">This snackbar stays until dismissed. Please <a href="#">take action</a>.</div>
<button class="newspack-ui__button newspack-ui__button--icon newspack-ui__button--ghost-dark newspack-ui__snackbar__close" aria-label="<?php esc_attr_e( 'Close', 'newspack-plugin' ); ?>" title="<?php esc_attr_e( 'Close', 'newspack-plugin' ); ?>">
<?php Newspack_UI_Icons::print_svg( 'closeSmall' ); ?>
</button>
</div>
</template>
<script>
( function() {
const snackbar = document.getElementById( 'snackbar-example' );
const button = document.getElementById( 'show-snackbar-example' );
button.addEventListener( 'click', function() {
newspackUI.notices.openNotice( snackbar, false );
const snackbar = document.querySelector( '.newspack-ui__snackbar' );
document.getElementById( 'show-snackbar-example' ).addEventListener( 'click', function() {
newspackUI.notices.createNotice( 'This is a snackbar message' );
} );
document.getElementById( 'show-snackbar-warning' ).addEventListener( 'click', function() {
newspackUI.notices.createNotice( 'This is a warning snackbar message', 'warning' );
} );
const template = document.getElementById( 'snackbar-persistent-template' );
document.getElementById( 'show-snackbar-persistent' ).addEventListener( 'click', function() {
const item = template.content.firstElementChild.cloneNode( true );
snackbar.appendChild( item );
item.querySelectorAll( 'a, button' ).forEach( function( el ) {
el.addEventListener( 'click', function() {
newspackUI.notices.closeNotice( item );
} );
} );
void item.offsetWidth;
newspackUI.notices.openNotice( item, true );
} );
} )();
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,15 +399,14 @@ public static function handle_result_notice() {
Newspack_UI::add_notice(
$message,
[
'type' => 'success',
'autohide' => true,
]
);
} elseif ( 'failure' === $result ) {
Newspack_UI::add_notice(
__( "We couldn't verify your location. Make sure you're on your organization's network and try again.", 'newspack-plugin' ),
[
'type' => 'warning',
'type' => 'error',
'autohide' => false,
]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -863,49 +863,26 @@ public static function render_invite_notice() {
}

$messages = [
'link_invalid' => [
'message' => __( 'This link is no longer valid. Please contact the group manager.', 'newspack-plugin' ),
'type' => 'error',
],
'link_full' => [
'message' => __( 'This group already has the maximum number of members. Please contact the group manager.', 'newspack-plugin' ),
'type' => 'error',
],
'link_failed' => [
'message' => __( "We couldn't add you to the group. Please contact the group manager.", 'newspack-plugin' ),
'type' => 'error',
],
'login_needed' => [
'message' => __( 'Please log in or register an account to join the group.', 'newspack-plugin' ),
'type' => 'notice',
],
'error_invalid_link' => [
'message' => __( 'Invalid invitation link.', 'newspack-plugin' ),
'type' => 'error',
],
'error_email_mismatch' => [
'message' => __( 'This invitation is for a different email address.', 'newspack-plugin' ),
'type' => 'error',
],
'error_invite_invalid' => [
'message' => __( 'Invalid or expired invitation.', 'newspack-plugin' ),
'type' => 'error',
],
'error_registration_failed' => [
'message' => __( 'Could not create your account. Please try again.', 'newspack-plugin' ),
'type' => 'error',
],
'link_invalid' => __( 'This link is no longer valid. Please contact the group manager.', 'newspack-plugin' ),
'link_full' => __( 'This group already has the maximum number of members. Please contact the group manager.', 'newspack-plugin' ),
'link_failed' => __( "We couldn't add you to the group. Please contact the group manager.", 'newspack-plugin' ),
'login_needed' => __( 'Please log in or register an account to join the group.', 'newspack-plugin' ),
'error_invalid_link' => __( 'Invalid invitation link.', 'newspack-plugin' ),
'error_email_mismatch' => __( 'This invitation is for a different email address.', 'newspack-plugin' ),
'error_invite_invalid' => __( 'Invalid or expired invitation.', 'newspack-plugin' ),
'error_registration_failed' => __( 'Could not create your account. Please try again.', 'newspack-plugin' ),
];

if ( 'success' === $result ) {
$message = __( 'You have successfully joined the group!', 'newspack-plugin' );
$type = 'success';
} else {
$message = ! empty( $messages[ $result ]['message'] ) ? $messages[ $result ]['message'] : __( 'There was a problem with your invitation.', 'newspack-plugin' );
$type = ! empty( $messages[ $result ]['type'] ) ? $messages[ $result ]['type'] : 'error';
$message = ! empty( $messages[ $result ] ) ? $messages[ $result ] : __( 'There was a problem with your invitation.', 'newspack-plugin' );
// 'login_needed' is an informational call to action, not an error, so it announces politely.
$type = 'login_needed' === $result ? 'success' : 'error';
}

Newspack_UI::add_notice( $message, $type );
Newspack_UI::add_notice( $message, [ 'type' => $type ] );
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,6 @@ public static function maybe_add_newspack_notices() {
$notice,
[
'id' => $notice_id,
'type' => 'warning',
'corner' => 'top-right',
'autohide' => false,
]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -572,8 +572,6 @@ public static function add_after_delete_account_notice() {
__( 'Your account has been deleted.', 'newspack-plugin' ),
[
'id' => 'after-delete-account',
'type' => 'success',
'corner' => 'top-right',
'autohide' => true,
]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
$is_completely_empty = empty( $members ) && empty( $all_invites );
?>
<?php if ( ! $is_manageable ) : ?>
<div class="newspack-ui__notice newspack-ui__notice--info newspack-my-account__group_subscription__inactive-notice">
<div class="newspack-ui__notice newspack-ui__notice--info newspack-my-account__group_subscription__inactive-notice" role="status">
<p class="newspack-ui__spacing-top--0 newspack-ui__spacing-bottom--0">
<?php
echo esc_html(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
[
'id' => uniqid( 'newspack-myaccount-error-' ),
'type' => 'error',
'corner' => 'top-right',
'autohide' => ! apply_filters( 'newspack_ui_notice_is_urgent', false, $notice['notice'] ),
'active_on_load' => true,
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
[
'id' => uniqid( 'newspack-myaccount-notice-' ),
'type' => 'warning',
'corner' => 'top-right',
'autohide' => ! apply_filters( 'newspack_ui_notice_is_urgent', false, $notice['notice'] ),
'active_on_load' => true,
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
$notice['notice'],
[
'id' => uniqid( 'newspack-myaccount-success-' ),
'type' => 'success',
'corner' => 'top-right',
'autohide' => ! apply_filters( 'newspack_ui_notice_is_urgent', false, $notice['notice'] ),
'active_on_load' => true,
]
Expand Down
Loading
Loading