Tutorial WordPress: Cómo dar estilo a los mensajes del sistema (notices) del admin-bar en front

·

·

Introducción

En WordPress, la barra de administración (admin-bar) en el front permite mostrar accesos rápidos y avisos puntuales a usuarios con sesión activa. Este artículo explica en detalle varias técnicas para mostrar y dar estilo a los mensajes del sistema (notices) dentro de la admin-bar en el front: desde una implementación básica hasta una versión avanzada con mensajes descartables (dismissible), accesibilidad y buenas prácticas de seguridad.

Qué cubriremos

Requisitos y consideraciones previas

Antes de añadir notices visibles en el front dentro de la admin-bar conviene tener en cuenta:

  1. Solo los usuarios con sesión y la barra activa (is_admin_bar_showing()) verán los mensajes. Filtra por capacidades (current_user_can) si son avisos de administración.
  2. Escapa todo el HTML que muestres (esc_html, wp_kses_post) y aplica nonces si haces peticiones AJAX.
  3. Carga CSS/JS únicamente en el front y solo para usuarios con la barra (optimización).
  4. Considera la usabilidad: evita sobrecargar la barra con contenido demasiado grande.

1) Agregar un mensaje simple en la admin-bar

La forma más directa es usar la API del WP_Admin_Bar para añadir un nodo. Ejemplo mínimo que añade un aviso informativo:

lt?php
// functions.php o plugin
add_action( admin_bar_menu, mi_adminbar_notice_simple, 100 )
function mi_adminbar_notice_simple( wp_admin_bar ) {
    // Solo para usuarios con barra visible y permiso específico
    if ( ! is_user_logged_in()  ! is_admin_bar_showing()  ! current_user_can( edit_posts ) ) {
        return
    }

    title = ltspan class=ab-notice ab-infogt . esc_html__( Recordatorio: Revisar comentarios pendientes, mi-textdomain ) . lt/spangt
    args = array(
        id    => mi-admin-notice,
        title => title,
        meta  => array(
            class => mi-admin-notice-class,
            html  => true, // marcaremos HTML en title
        ),
        href  => admin_url( edit-comments.php ),
    )
    wp_admin_bar->add_node( args )
}
?gt

En este ejemplo se añade un enlace en la parte superior que puede recibir estilo CSS. Observa que incluimos clases propias para dirigirte después en CSS.

2) Estilizar el notice usando CSS

La admin-bar tiene su propio DOM y estilos para integrar un aviso visualmente coherente hay que apuntar a las clases que genera WP. Ejemplo CSS que añade apariencia tipo notice (info/actualizado/error) y un contador opcional:

/ Cargar solo en front cuando is_admin_bar_showing() /
#wp-admin-bar-mi-admin-notice > .ab-item .ab-notice {
    display: inline-block
    padding: 6px 10px
    border-radius: 3px
    font-size: 13px
    line-height: 1
    vertical-align: middle
    margin-left: 6px
}

/ Tipos /
#wp-admin-bar-mi-admin-notice .ab-notice.ab-info {
    background: #d9edf7
    color: #31708f
    border: 1px solid rgba(49,112,143,0.15)
}

#wp-admin-bar-mi-admin-notice .ab-notice.ab-success {
    background: #dff0d8
    color: #3c763d
    border: 1px solid rgba(60,118,61,0.15)
}

#wp-admin-bar-mi-admin-notice .ab-notice.ab-error {
    background: #f2dede
    color: #a94442
    border: 1px solid rgba(169,68,66,0.15)
}

/ Un pequeño contador rojo en caso de mensajes pendientes /
#wp-admin-bar-mi-admin-notice .ab-count {
    background: #dc3232
    color: #fff
    font-weight: 600
    padding: 2px 6px
    border-radius: 999px
    margin-left: 8px
    font-size: 11px
    vertical-align: middle
}

En la práctica deberás encolar este CSS con wp_enqueue_style y condicionar su carga con is_admin_bar_showing() y is_user_logged_in().

3) Notice descartable (dismissible) por usuario — enfoque completo

Si el aviso debe poder ocultarse por el usuario y mantenerse oculto en futuras cargas, usa AJAX y user meta para recordar el estado. Flujo:

  1. Al generar el notice, añade un botón Cerrar con data-attribute que contiene el id del notice.
  2. Un pequeño script captura el click y hace una petición AJAX con nonce.
  3. PHP guarda en user meta la clave que indica que ese usuario lo descarta.
  4. Al renderizar la admin-bar, compruebas user meta y no añades el nodo si el usuario lo descartó.

Ejemplo completo (PHP JS CSS). Primero el PHP:

lt?php
add_action( wp_enqueue_scripts, mi_notice_enqueue_assets )
function mi_notice_enqueue_assets() {
    if ( ! is_user_logged_in()  ! is_admin_bar_showing() ) {
        return
    }

    // CSS y JS deben ir en tu tema/plugin
    wp_enqueue_style( mi-adminbar-notice-style, get_stylesheet_directory_uri() . /css/mi-adminbar-notice.css, array(), 1.0 )
    wp_enqueue_script( mi-adminbar-notice-js, get_stylesheet_directory_uri() . /js/mi-adminbar-notice.js, array( jquery ), 1.0, true )

    // Localiza datos para AJAX
    wp_localize_script( mi-adminbar-notice-js, miAdminNotice, array(
        ajax_url => admin_url( admin-ajax.php ),
        nonce    => wp_create_nonce( mi_admin_notice_nonce ),
    ))
}

add_action( admin_bar_menu, mi_adminbar_notice_dismissible, 100 )
function mi_adminbar_notice_dismissible( wp_admin_bar ) {
    user_id = get_current_user_id()
    notice_id = actualizacion-plugin-x // identificador único para este aviso

    // Si el usuario ya lo descartó, no mostrar
    if ( get_user_meta( user_id, mi_notice_dismissed_ . notice_id, true ) ) {
        return
    }

    title = ltspan class=ab-notice ab-infogt . esc_html__( Actualización disponible para Plugin X, mi-textdomain ) . lt/spangt
    title .= ltspan class=ab-close data-notice-id= . esc_attr( notice_id ) .  role=button aria-label= . esc_attr__( Descartar aviso, mi-textdomain ) . gttimeslt/spangt

    args = array(
        id    => mi-admin-notice,
        title => title,
        meta  => array( html => true ),
        href  => admin_url( update-core.php ),
    )
    wp_admin_bar->add_node( args )
}

// AJAX handler que marca el notice como descartado para el usuario actual
add_action( wp_ajax_mi_dismiss_admin_notice, mi_dismiss_admin_notice_ajax )
function mi_dismiss_admin_notice_ajax() {
    check_ajax_referer( mi_admin_notice_nonce, nonce )

    notice_id = isset( _POST[notice_id] ) ? sanitize_text_field( wp_unslash( _POST[notice_id] ) ) : 
    if ( empty( notice_id ) ) {
        wp_send_json_error( array( message => __( Identificador inválido, mi-textdomain ) ) )
    }

    user_id = get_current_user_id()
    if ( ! user_id ) {
        wp_send_json_error()
    }

    update_user_meta( user_id, mi_notice_dismissed_ . notice_id, 1 )
    wp_send_json_success()
}
?gt

Ahora el JavaScript que enviará la petición AJAX (archivo mi-adminbar-notice.js):

jQuery( function(  ) {
    ( document ).on( click, #wp-admin-bar-mi-admin-notice .ab-close, function( e ) {
        e.preventDefault()
        var button = ( this )
        var noticeId = button.data( notice-id )

        // Petición AJAX
        .post( miAdminNotice.ajax_url, {
            action: mi_dismiss_admin_notice,
            notice_id: noticeId,
            nonce: miAdminNotice.nonce
        }, function( response ) {
            if ( response.success ) {
                // Opciones de UX: esconder el nodo o mostrar un pequeño feedback
                button.closest( #wp-admin-bar-mi-admin-notice ).fadeOut( 200, function() {
                    ( this ).remove()
                })
            } else {
                // Fail silencioso o consola
                window.console  console.log( response )
            }
        })
    })
})

Y el CSS mínimo para mostrar el botón de cerrar:

#wp-admin-bar-mi-admin-notice .ab-close {
    display: inline-block
    margin-left: 8px
    color: rgba(0,0,0,0.6)
    cursor: pointer
    font-weight: 700
    padding: 0 6px
}
#wp-admin-bar-mi-admin-notice .ab-close:hover {
    color: rgba(0,0,0,0.85)
}

Notas sobre seguridad y rendimiento

4) Detectar y mostrar avisos del core o plugins (ejemplo avanzado)

En algunos casos querrás reflejar el número de actualizaciones o avisos del core en la admin-bar con estilo propio. Un ejemplo: mostrar el contador de actualizaciones con estilo personalizado:

lt?php
add_action( admin_bar_menu, mi_adminbar_updates_counter, 60 )
function mi_adminbar_updates_counter( wp_admin_bar ) {
    if ( ! is_user_logged_in()  ! is_admin_bar_showing()  ! current_user_can( update_core ) ) {
        return
    }

    // Obtener contador de actualizaciones (core, plugins, themes)
    update_count = 0
    if ( function_exists( get_site_transient ) ) {
        updates = get_site_transient( update_core )
        if ( ! empty( updates-gtupdates ) ) {
            update_count  = count( updates-gtupdates )
        }
        plugin_updates = get_site_transient( update_plugins )
        if ( ! empty( plugin_updates-gtresponse ) ) {
            update_count  = count( plugin_updates-gtresponse )
        }
        theme_updates = get_site_transient( update_themes )
        if ( ! empty( theme_updates-gtresponse ) ) {
            update_count  = count( theme_updates-gtresponse )
        }
    }

    if ( update_count ) {
        title = ltspan class=ab-notice ab-errorgt . esc_html__( Actualizaciones pendientes, mi-textdomain ) . lt/spangt
        title .= ltspan class=ab-countgt . intval( update_count ) . lt/spangt
        wp_admin_bar->add_node( array(
            id    => mi-updates-notice,
            title => title,
            href  => admin_url( update-core.php ),
            meta  => array( html => true ),
        ) )
    }
}
?gt

Este código combina datos del core con el mismo patrón de estilo que definimos antes, y muestra un contador de color rojo si hay actualizaciones.

5) Accesibilidad y consideraciones finales

Al añadir contenidos interactivos en la admin-bar asegúrate de:

Resumen de buenas prácticas

Conclusión

La admin-bar es un lugar útil para mostrar avisos rápidos a administradores o editores en el front. Con la API de WP_Admin_Bar puedes insertar mensajes y estilarlos con CSS para que parezcan notices del sistema. Si necesitas que sean descartables, añade un pequeño handler AJAX y guarda el estado por usuario. Siempre protege con nonces, escapa el contenido y carga los assets condicionalmente.

Enlaces útiles



Leave a Reply

Your email address will not be published. Required fields are marked *