Help Center

Help Center Popup

Make a help center popup on your website using a categorie and lots of “help” post. It’s under 200 lines of code and looks great!

By ♟ Maggew.comUpdated   30 Views
wordpress help center popup

Updated! I added a v2 that includes lightbox modal support for video and images. Scroll to very bottom to get it!

Inspiration

Goal

  • Create a custom Help Center that pops up in the bottom right of the viewport on WordPress sites. Triggered by menu item with .open-help-center class.

Functionality

  • AJAX-powered Help Center loads posts from “help” category
  • Clicking a post title loads full content into the popup
  • Includes search box (appears only when popup is open or user clicks “Go Back”)
  • Two action buttons per article: “Go Back” and “Open support page”

Frontend Features

  • Responsive popup (400×700 desktop, full width mobile)
  • Injected via wp_footer
  • Uses jQuery, wp_localize_script, AJAX and nonce verification
  • Minimal CSS for layout only — theme styles inherit everything else
  • Autofocus search input when opening popup
  • Add “Back to top” at bottom off every article that is loaded

Integration

  • All PHP goes in a single Snippets plugin block
  • CSS goes in Customizer → Additional CSS

Version 1

So far so good… v1 is looking good…

Copy/Paste this PHP Function Snippet:

// Help Center Popup - Optimized with ESC key and accessibility
add_action('wp_enqueue_scripts', function () {
    wp_enqueue_script('jquery');

    $js = <<<EOT
    jQuery(document).ready(function($) {
        const popup = $('#help-center-popup');
        const searchWrap = $('#help-center-search');
        const searchInput = $('#help-center-search-input');
        const resultsWrap = $('#help-center-results');
        let lastFocusedElement;
        let searchTimeout;

        function loadArticles(search = '') {
            $.ajax({
                url: helpCenter.ajax_url,
                method: 'POST',
                data: {
                    action: search ? 'search_help_articles' : 'get_popular_help_articles',
                    nonce: helpCenter.nonce,
                    search
                },
                success: (res) => {
                    if (res.success) {
                        resultsWrap.html(res.data);
                        searchWrap.show();
                        searchInput.focus();
                    }
                }
            });
        }

        function loadArticle(postId) {
            $.ajax({
                url: helpCenter.ajax_url,
                method: 'POST',
                data: {
                    action: 'load_help_article',
                    nonce: helpCenter.nonce,
                    post_id: postId
                },
                success: (res) => {
                    if (res.success) {
                        resultsWrap.html(res.data);
                        searchWrap.hide();
                    }
                }
            });
        }

        $(document).on('click', '.open-help-center a', (e) => {
            e.preventDefault();
            lastFocusedElement = $(document.activeElement); // Store last focused element
            popup.fadeIn(200).attr('aria-hidden', 'false');
            loadArticles();
        });

        searchInput.on('input', function() {
            clearTimeout(searchTimeout);
            searchTimeout = setTimeout(() => {
                const val = $(this).val().trim();
                val.length >= 3 ? loadArticles(val) : loadArticles();
            }, 300);
        });

        popup.on('click', '.help-article-title', function() {
            loadArticle($(this).data('post-id'));
        });

        popup.on('click', '#help-go-back', () => loadArticles());

        popup.on('click', '#help-center-close', () => {
            popup.fadeOut(200).attr('aria-hidden', 'true');
            lastFocusedElement.focus(); // Return focus to last element
        });

        popup.on('click', '.back-to-top', (e) => {
            e.preventDefault();
            popup.animate({ scrollTop: 0 }, 400);
        });

        // Close popup with ESC key
        $(document).on('keydown', (e) => {
            if (e.keyCode === 27 && popup.is(':visible')) { // ESC key
                popup.fadeOut(200).attr('aria-hidden', 'true');
                lastFocusedElement.focus(); // Return focus to last element
            }
        });
    });
EOT;

    wp_add_inline_script('jquery', $js);

    wp_localize_script('jquery', 'helpCenter', [
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce'    => wp_create_nonce('help_center_nonce')
    ]);
});

add_action('wp_footer', function () {
    ?>
    <div id="help-center-popup" class="help-center-popup" role="dialog" aria-modal="true" aria-labelledby="help-center-title" aria-hidden="true">
        <div class="help-center-header">
            <strong id="help-center-title">Help Center</strong>
            <button id="help-center-close" class="help-center-close" aria-label="Close Help Center">×</button>
        </div>
        <div id="help-center-search" class="help-center-search">
            <input type="text" id="help-center-search-input" placeholder="Search for help" aria-label="Search help articles">
        </div>
        <div id="help-center-results" class="help-center-results" tabindex="0"></div>
    </div>
    <?php
});

add_filter('nav_menu_css_class', function ($classes) {
    if (in_array('open-help-center', $classes)) {
        $classes[] = 'open-help-center';
    }
    return $classes;
}, 10, 1);

function render_help_articles($query) {
    if (!$query->have_posts()) {
        return '<p>No help articles found.</p>';
    }

    ob_start();
    while ($query->have_posts()) {
        $query->the_post();
        printf(
            '<div class="help-article"><h3 class="help-article-title" data-post-id="%d">%s</h3></div>',
            get_the_ID(),
            esc_html(get_the_title())
        );
    }
    wp_reset_postdata();
    return ob_get_clean();
}

add_action('wp_ajax_get_popular_help_articles', 'load_help_articles');
add_action('wp_ajax_nopriv_get_popular_help_articles', 'load_help_articles');
function load_help_articles() {
    check_ajax_referer('help_center_nonce', 'nonce');

    $query = new WP_Query([
        'post_type'      => 'post',
        'category_name'  => 'help',
        'posts_per_page' => 6,
        'orderby'        => 'date',
        'order'          => 'DESC'
    ]);

    wp_send_json_success(render_help_articles($query));
}

add_action('wp_ajax_search_help_articles', 'search_help_articles');
add_action('wp_ajax_nopriv_search_help_articles', 'search_help_articles');
function search_help_articles() {
    check_ajax_referer('help_center_nonce', 'nonce');
    $search = sanitize_text_field($_POST['search'] ?? '');

    $query = new WP_Query([
        'post_type'      => 'post', // Fixed typo from 'content' to 'post'
        'category_name'  => 'help',
        'posts_per_page' => 6,
        's'              => $search
    ]);

    wp_send_json_success(render_help_articles($query));
}

add_action('wp_ajax_load_help_article', 'load_help_article');
add_action('wp_ajax_nopriv_load_help_article', 'load_help_article');
function load_help_article() {
    check_ajax_referer('help_center_nonce', 'nonce');
    $post_id = intval($_POST['post_id']);
    $post = get_post($post_id);

    if (!$post || !has_category('help', $post)) {
        wp_send_json_error('Invalid article');
    }

    ob_start();
    ?>
    <div class="help-article-controls">
        <button id="help-go-back" class="help-go-back" aria-label="Go back to article list">Go Back</button>
        <a href="<?php echo esc_url(get_permalink($post)); ?>" target="_blank" class="help-open-page" aria-label="Open support page in new tab">Open Support Page</a>
    </div>
    <h2><?php echo esc_html(get_the_title($post)); ?></h2>
    <?php echo apply_filters('the_content', $post->post_content); ?>
    <div id="sticky-back-to-top">
        <a class="back-to-top" href="#help-center-popup" role="button" aria-label="Scroll back to top">Back to top ↑</a>
    </div>
    <?php
    wp_send_json_success(ob_get_clean());
}

Copy / Paste this CSS:

#help-center-popup {
    position: fixed;
    bottom: 0;
    right: 0;
    width: 400px;
    max-width: 100%;
    height: 55vh;
    max-height: 90vh;
    border: 1px solid;
    box-shadow: 0 0 6px rgba(0,0,0,0.1);
    z-index: 10000;
    display: none;
    flex-direction: column;
    overflow-y: auto;
    padding: 0 15px 0 15px;
    background: inherit;
    transition: opacity 0.2s ease;
}

.help-center-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    z-index: 10;
    background: inherit;
}

.help-center-close {
    background: none;
    border: none;
    font-size: 1.5em;
    cursor: pointer;
    line-height: 1;
}

#help-center-search {
    display: none;
    position: sticky;
    top: 40px;
    z-index: 9;
    background: inherit;
    padding-bottom: 10px;
}

#help-center-search-input {
    width: 100%;
    border: 1px solid;
    font-size: inherit;
    background: inherit;
    color: inherit;
    padding: 3px;
}

.help-center-results {
    display: flex;
    flex-direction: column;
/*     gap: 1em; */
}

.help-article-title {
    cursor: pointer;
    margin: 0;
    padding: 0;
    scroll-margin-top: 60px;
}

.help-article-controls {
    display: flex;
    gap: 10px;
    margin-bottom: 15px;
}

.help-go-back,
.help-open-page {
    flex: 1;
    text-align: center;
    border: 1px solid;
    background: inherit;
    color: inherit;
    font-size: small;
    padding: 8px;
    text-decoration: none;
    cursor: pointer;
}

#sticky-back-to-top {
    position: sticky;
    bottom: 0;
    z-index: 8;
    text-align: center;
	  padding: 10px;
	  background: #000;
}

.back-to-top {
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}

@media (max-width: 600px) {
    #help-center-popup {
        width: 100%;
        right: 0;
        bottom: 0;
        border-radius: 0;
    }
}

Updated v2

This is version 2 with image and video lightbox support

~266 lines of code PHP Function:

add_action('wp_enqueue_scripts', function () {
    wp_enqueue_script('jquery');

    $js = <<<EOT
    jQuery(document).ready(function($) {
        const popup = $('#help-center-popup');
        const lightbox = $('#help-center-lightbox');
        const lightboxContent = $('.lightbox-content');
        const searchWrap = $('#help-center-search');
        const searchInput = $('#help-center-search-input');
        const resultsWrap = $('#help-center-results');
        let lastFocusedElement;
        let searchTimeout;

        function loadArticles(search = '') {
            $.ajax({
                url: helpCenter.ajax_url,
                method: 'POST',
                data: {
                    action: search ? 'search_help_articles' : 'get_popular_help_articles',
                    nonce: helpCenter.nonce,
                    search
                },
                success: (res) => {
                    if (res.success) {
                        resultsWrap.html(res.data);
                        searchWrap.show();
                        searchInput.focus();
                    }
                }
            });
        }

        function loadArticle(postId) {
            $.ajax({
                url: helpCenter.ajax_url,
                method: 'POST',
                data: {
                    action: 'load_help_article',
                    nonce: helpCenter.nonce,
                    post_id: postId
                },
                success: (res) => {
                    if (res.success) {
                        resultsWrap.html(res.data);
                        searchWrap.hide();
                    }
                }
            });
        }

        // Open help center popup
        $(document).on('click', '.open-help-center a', (e) => {
            e.preventDefault();
            lastFocusedElement = $(document.activeElement);
            popup.fadeIn(200).attr('aria-hidden', 'false');
            loadArticles();
        });

        // Search input handling
        searchInput.on('input', function() {
            clearTimeout(searchTimeout);
            searchTimeout = setTimeout(() => {
                const val = $(this).val().trim();
                val.length >= 3 ? loadArticles(val) : loadArticles();
            }, 300);
        });

        // Load single article
        popup.on('click', '.help-article-title', function() {
            loadArticle($(this).data('post-id'));
        });

        // Go back to article list
        popup.on('click', '#help-go-back', () => loadArticles());

        // Close help center popup
        popup.on('click', '#help-center-close', () => {
            popup.fadeOut(200).attr('aria-hidden', 'true');
            lastFocusedElement.focus();
        });

        // Scroll to top
        popup.on('click', '.back-to-top', (e) => {
            e.preventDefault();
            popup.animate({ scrollTop: 0 }, 400);
        });

        // Open lightbox when clicking images or videos
        resultsWrap.on('click', 'img, video', function(e) {
            e.preventDefault();
            const src = $(this).attr('src');
            const tag = $(this).prop('tagName').toLowerCase();
            let content;

            if (tag === 'img') {
                content = $('<img>').attr('src', src);
            } else if (tag === 'video') {
                content = $('<video>').attr({
                    src: src,
                    controls: true,
                    autoplay: true
                });
            }

            lightboxContent.empty().append(content);
            lightbox.fadeIn(200).attr('aria-hidden', 'false');
            $('#lightbox-close').focus();
        });

        // Close lightbox
        lightbox.on('click', '#lightbox-close', () => {
            lightbox.fadeOut(200).attr('aria-hidden', 'true');
            lightboxContent.empty();
            resultsWrap.focus();
        });

        // Close lightbox or popup with ESC key
        $(document).on('keydown', (e) => {
            if (e.keyCode === 27) { // ESC key
                if (lightbox.is(':visible')) {
                    lightbox.fadeOut(200).attr('aria-hidden', 'true');
                    lightboxContent.empty();
                    resultsWrap.focus();
                } else if (popup.is(':visible')) {
                    popup.fadeOut(200).attr('aria-hidden', 'true');
                    lastFocusedElement.focus();
                }
            }
        });

        // Close lightbox when clicking outside content
        lightbox.on('click', (e) => {
            if ($(e.target).hasClass('help-center-lightbox')) {
                lightbox.fadeOut(200).attr('aria-hidden', 'true');
                lightboxContent.empty();
                resultsWrap.focus();
            }
        });
    });
EOT;

    wp_add_inline_script('jquery', $js);

    wp_localize_script('jquery', 'helpCenter', [
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce'    => wp_create_nonce('help_center_nonce')
    ]);
});

add_action('wp_footer', function () {
    ?>
    <div id="help-center-popup" class="help-center-popup" role="dialog" aria-modal="true" aria-labelledby="help-center-title" aria-hidden="true">
        <div class="help-center-header">
            <strong id="help-center-title">Help Center</strong>
            <button id="help-center-close" class="help-center-close" aria-label="Close Help Center">×</button>
        </div>
        <div id="help-center-search" class="help-center-search">
            <input type="text" id="help-center-search-input" placeholder="Search for help" aria-label="Search help articles">
        </div>
        <div id="help-center-results" class="help-center-results" tabindex="0"></div>
    </div>
    <?php
});

add_filter('nav_menu_css_class', function ($classes) {
    if (in_array('open-help-center', $classes)) {
        $classes[] = 'open-help-center';
    }
    return $classes;
}, 10, 1);

function render_help_articles($query) {
    if (!$query->have_posts()) {
        return '<p>No help articles found.</p>';
    }

    ob_start();
    while ($query->have_posts()) {
        $query->the_post();
        printf(
            '<div class="help-article"><h5 class="help-article-title" data-post-id="%d">%s</h5></div>',
            get_the_ID(),
            esc_html(get_the_title())
        );
    }
    wp_reset_postdata();
    return ob_get_clean();
}

add_action('wp_ajax_get_popular_help_articles', 'load_help_articles');
add_action('wp_ajax_nopriv_get_popular_help_articles', 'load_help_articles');
function load_help_articles() {
    check_ajax_referer('help_center_nonce', 'nonce');

    $query = new WP_Query([
        'post_type'      => 'post',
        'category_name'  => 'help',
        'posts_per_page' => 6,
        'orderby'        => 'date',
        'order'          => 'DESC'
    ]);

    wp_send_json_success(render_help_articles($query));
}

add_action('wp_ajax_search_help_articles', 'search_help_articles');
add_action('wp_ajax_nopriv_search_help_articles', 'search_help_articles');
function search_help_articles() {
    check_ajax_referer('help_center_nonce', 'nonce');
    $search = sanitize_text_field($_POST['search'] ?? '');

    $query = new WP_Query([
        'post_type'      => 'post', // Fixed typo from 'content' to 'post'
        'category_name'  => 'help',
        'posts_per_page' => 6,
        's'              => $search
    ]);

    wp_send_json_success(render_help_articles($query));
}

add_action('wp_ajax_load_help_article', 'load_help_article');
add_action('wp_ajax_nopriv_load_help_article', 'load_help_article');
function load_help_article() {
    check_ajax_referer('help_center_nonce', 'nonce');
    $post_id = intval($_POST['post_id']);
    $post = get_post($post_id);

    if (!$post || !has_category('help', $post)) {
        wp_send_json_error('Invalid article');
    }

    ob_start();
    ?>
    <div class="help-article-controls">
        <button id="help-go-back" class="help-go-back" aria-label="Go back to article list">Go Back</button>
        <a href="<?php echo esc_url(get_permalink($post)); ?>" target="_self" class="help-open-page" aria-label="Open support page in new tab">Open Support Page</a>
    </div>
    <h3><?php echo esc_html(get_the_title($post)); ?></h3>
    <?php echo apply_filters('the_content', $post->post_content); ?>
    <div id="sticky-back-to-top">
        <a class="back-to-top" href="#help-center-popup" role="button" aria-label="Scroll back to top">Back to top ↑</a>
    </div>
    <?php
    wp_send_json_success(ob_get_clean());
}

add_action('wp_footer', function () {
    ?>
    <div id="help-center-popup" class="help-center-popup" role="dialog" aria-modal="true" aria-labelledby="help-center-title" aria-hidden="true">
        <div class="help-center-header">
            <strong id="help-center-title">Help Center</strong>
            <button id="help-center-close" class="help-center-close" aria-label="Close Help Center">×</button>
        </div>
        <div id="help-center-search" class="help-center-search">
            <input type="text" id="help-center-search-input" placeholder="Search for help" aria-label="Search help articles">
        </div>
        <div id="help-center-results" class="help-center-results" tabindex="0"></div>
    </div>
    <div id="help-center-lightbox" class="help-center-lightbox" role="dialog" aria-modal="true" aria-hidden="true">
        <button id="lightbox-close" class="lightbox-close" aria-label="Close Lightbox">×</button>
        <div class="lightbox-content"></div>
    </div>
    <?php
});

~170 lines of CSS:

#help-center-popup {
    background: inherit;
    border: 1px solid;
    bottom: 0;
    box-shadow: 0 0 6px rgba(0, 0, 0, 0.1);
    display: none;
    flex-direction: column;
    height: 55vh;
    max-height: 90vh;
    max-width: 100%;
    overflow-x: hidden;
    overflow-y: auto;
    padding: 0 15px;
    position: fixed;
    right: 0;
    transition: opacity 0.2s ease;
    width: 400px;
    z-index: 10000;
}

.help-center-header {
    align-items: center;
    background: inherit;
    display: flex;
    justify-content: space-between;
    z-index: 10;
}

.help-center-close {
    background: none;
    border: none;
    cursor: pointer;
    line-height: 1;
}

#help-center-search {
    background: inherit;
    display: none;
    padding-bottom: 10px;
    position: sticky;
    top: 40px;
    z-index: 9;
}

#help-center-search-input {
    background: inherit;
    border: 1px solid;
    color: inherit;
    font-size: inherit;
    padding: 3px;
    width: 100%;
}

.help-center-results {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.help-article-title {
    cursor: pointer;
    margin: 0;
    padding: 0;
    scroll-margin-top: 60px;
}

.help-article:hover {
    border-right: 4px solid;
}

.help-article-controls {
    display: flex;
    gap: 10px;
    margin-bottom: 10px;
}

.help-center-results video {
    width: 100%;
}

.help-center-results video:hover,
.help-center-results img:hover {
    cursor: pointer;
}

.help-go-back,
.help-open-page {
    background: inherit;
    border: 1px solid;
    color: inherit;
    cursor: pointer;
    flex: 1;
    font-size: small;
    padding: 8px;
    text-align: center;
    text-decoration: none;
}

#sticky-back-to-top {
    background: var(--contrast);
    bottom: 0;
    position: sticky;
    text-align: center;
    z-index: 8;
}

.back-to-top {
    color: inherit;
    cursor: pointer;
    display: block;
    font-size: initial;
    padding: 10px;
    text-decoration: none;
}

.help-center-lightbox {
    align-items: center;
    background: rgba(0, 0, 0, 0.9);
    display: none;
    height: 100vh;
    justify-content: center;
    left: 0;
    opacity: 0;
    position: fixed;
    top: 0;
    transition: opacity 0.2s ease;
    width: 100vw;
    z-index: 10001;
}

.help-center-lightbox[aria-hidden="false"] {
    display: flex !important;
    opacity: 1;
}

.lightbox-close {
    background: none;
    border: none;
    color: #fff;
    cursor: pointer;
    font-size: 2em;
    line-height: 1;
    position: absolute;
    right: 15px;
    top: 15px;
}

.lightbox-content {
    align-items: center;
    display: flex;
    flex-shrink: 0;
    justify-content: center;
    max-height: 90vh;
    max-width: 90vw;
}

.lightbox-content img,
.lightbox-content video {
    max-height: 100%;
    max-width: 100%;
    object-fit: contain;
    vertical-align: middle;
}

@media (max-width: 600px) {
    #help-center-popup {
        border-radius: 0;
        bottom: 0;
        right: 0;
        width: 100%;
    }
}

Updated! I added a v2 that includes lightbox modal support for video and images. Scroll to very bottom to get it!

Inspiration

Goal

  • Create a custom Help Center that pops up in the bottom right of the viewport on WordPress sites. Triggered by menu item with .open-help-center class.

Functionality

  • AJAX-powered Help Center loads posts from “help” category
  • Clicking a post title loads full content into the popup
  • Includes search box (appears only when popup is open or user clicks “Go Back”)
  • Two action buttons per article: “Go Back” and “Open support page”

Frontend Features

  • Responsive popup (400×700 desktop, full width mobile)
  • Injected via wp_footer
  • Uses jQuery, wp_localize_script, AJAX and nonce verification
  • Minimal CSS for layout only — theme styles inherit everything else
  • Autofocus search input when opening popup
  • Add “Back to top” at bottom off every article that is loaded

Integration

  • All PHP goes in a single Snippets plugin block
  • CSS goes in Customizer → Additional CSS

Version 1

So far so good… v1 is looking good…

Copy/Paste this PHP Function Snippet:

// Help Center Popup - Optimized with ESC key and accessibility
add_action('wp_enqueue_scripts', function () {
    wp_enqueue_script('jquery');

    $js = <<<EOT
    jQuery(document).ready(function($) {
        const popup = $('#help-center-popup');
        const searchWrap = $('#help-center-search');
        const searchInput = $('#help-center-search-input');
        const resultsWrap = $('#help-center-results');
        let lastFocusedElement;
        let searchTimeout;

        function loadArticles(search = '') {
            $.ajax({
                url: helpCenter.ajax_url,
                method: 'POST',
                data: {
                    action: search ? 'search_help_articles' : 'get_popular_help_articles',
                    nonce: helpCenter.nonce,
                    search
                },
                success: (res) => {
                    if (res.success) {
                        resultsWrap.html(res.data);
                        searchWrap.show();
                        searchInput.focus();
                    }
                }
            });
        }

        function loadArticle(postId) {
            $.ajax({
                url: helpCenter.ajax_url,
                method: 'POST',
                data: {
                    action: 'load_help_article',
                    nonce: helpCenter.nonce,
                    post_id: postId
                },
                success: (res) => {
                    if (res.success) {
                        resultsWrap.html(res.data);
                        searchWrap.hide();
                    }
                }
            });
        }

        $(document).on('click', '.open-help-center a', (e) => {
            e.preventDefault();
            lastFocusedElement = $(document.activeElement); // Store last focused element
            popup.fadeIn(200).attr('aria-hidden', 'false');
            loadArticles();
        });

        searchInput.on('input', function() {
            clearTimeout(searchTimeout);
            searchTimeout = setTimeout(() => {
                const val = $(this).val().trim();
                val.length >= 3 ? loadArticles(val) : loadArticles();
            }, 300);
        });

        popup.on('click', '.help-article-title', function() {
            loadArticle($(this).data('post-id'));
        });

        popup.on('click', '#help-go-back', () => loadArticles());

        popup.on('click', '#help-center-close', () => {
            popup.fadeOut(200).attr('aria-hidden', 'true');
            lastFocusedElement.focus(); // Return focus to last element
        });

        popup.on('click', '.back-to-top', (e) => {
            e.preventDefault();
            popup.animate({ scrollTop: 0 }, 400);
        });

        // Close popup with ESC key
        $(document).on('keydown', (e) => {
            if (e.keyCode === 27 && popup.is(':visible')) { // ESC key
                popup.fadeOut(200).attr('aria-hidden', 'true');
                lastFocusedElement.focus(); // Return focus to last element
            }
        });
    });
EOT;

    wp_add_inline_script('jquery', $js);

    wp_localize_script('jquery', 'helpCenter', [
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce'    => wp_create_nonce('help_center_nonce')
    ]);
});

add_action('wp_footer', function () {
    ?>
    <div id="help-center-popup" class="help-center-popup" role="dialog" aria-modal="true" aria-labelledby="help-center-title" aria-hidden="true">
        <div class="help-center-header">
            <strong id="help-center-title">Help Center</strong>
            <button id="help-center-close" class="help-center-close" aria-label="Close Help Center">×</button>
        </div>
        <div id="help-center-search" class="help-center-search">
            <input type="text" id="help-center-search-input" placeholder="Search for help" aria-label="Search help articles">
        </div>
        <div id="help-center-results" class="help-center-results" tabindex="0"></div>
    </div>
    <?php
});

add_filter('nav_menu_css_class', function ($classes) {
    if (in_array('open-help-center', $classes)) {
        $classes[] = 'open-help-center';
    }
    return $classes;
}, 10, 1);

function render_help_articles($query) {
    if (!$query->have_posts()) {
        return '<p>No help articles found.</p>';
    }

    ob_start();
    while ($query->have_posts()) {
        $query->the_post();
        printf(
            '<div class="help-article"><h3 class="help-article-title" data-post-id="%d">%s</h3></div>',
            get_the_ID(),
            esc_html(get_the_title())
        );
    }
    wp_reset_postdata();
    return ob_get_clean();
}

add_action('wp_ajax_get_popular_help_articles', 'load_help_articles');
add_action('wp_ajax_nopriv_get_popular_help_articles', 'load_help_articles');
function load_help_articles() {
    check_ajax_referer('help_center_nonce', 'nonce');

    $query = new WP_Query([
        'post_type'      => 'post',
        'category_name'  => 'help',
        'posts_per_page' => 6,
        'orderby'        => 'date',
        'order'          => 'DESC'
    ]);

    wp_send_json_success(render_help_articles($query));
}

add_action('wp_ajax_search_help_articles', 'search_help_articles');
add_action('wp_ajax_nopriv_search_help_articles', 'search_help_articles');
function search_help_articles() {
    check_ajax_referer('help_center_nonce', 'nonce');
    $search = sanitize_text_field($_POST['search'] ?? '');

    $query = new WP_Query([
        'post_type'      => 'post', // Fixed typo from 'content' to 'post'
        'category_name'  => 'help',
        'posts_per_page' => 6,
        's'              => $search
    ]);

    wp_send_json_success(render_help_articles($query));
}

add_action('wp_ajax_load_help_article', 'load_help_article');
add_action('wp_ajax_nopriv_load_help_article', 'load_help_article');
function load_help_article() {
    check_ajax_referer('help_center_nonce', 'nonce');
    $post_id = intval($_POST['post_id']);
    $post = get_post($post_id);

    if (!$post || !has_category('help', $post)) {
        wp_send_json_error('Invalid article');
    }

    ob_start();
    ?>
    <div class="help-article-controls">
        <button id="help-go-back" class="help-go-back" aria-label="Go back to article list">Go Back</button>
        <a href="<?php echo esc_url(get_permalink($post)); ?>" target="_blank" class="help-open-page" aria-label="Open support page in new tab">Open Support Page</a>
    </div>
    <h2><?php echo esc_html(get_the_title($post)); ?></h2>
    <?php echo apply_filters('the_content', $post->post_content); ?>
    <div id="sticky-back-to-top">
        <a class="back-to-top" href="#help-center-popup" role="button" aria-label="Scroll back to top">Back to top ↑</a>
    </div>
    <?php
    wp_send_json_success(ob_get_clean());
}

Copy / Paste this CSS:

#help-center-popup {
    position: fixed;
    bottom: 0;
    right: 0;
    width: 400px;
    max-width: 100%;
    height: 55vh;
    max-height: 90vh;
    border: 1px solid;
    box-shadow: 0 0 6px rgba(0,0,0,0.1);
    z-index: 10000;
    display: none;
    flex-direction: column;
    overflow-y: auto;
    padding: 0 15px 0 15px;
    background: inherit;
    transition: opacity 0.2s ease;
}

.help-center-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    z-index: 10;
    background: inherit;
}

.help-center-close {
    background: none;
    border: none;
    font-size: 1.5em;
    cursor: pointer;
    line-height: 1;
}

#help-center-search {
    display: none;
    position: sticky;
    top: 40px;
    z-index: 9;
    background: inherit;
    padding-bottom: 10px;
}

#help-center-search-input {
    width: 100%;
    border: 1px solid;
    font-size: inherit;
    background: inherit;
    color: inherit;
    padding: 3px;
}

.help-center-results {
    display: flex;
    flex-direction: column;
/*     gap: 1em; */
}

.help-article-title {
    cursor: pointer;
    margin: 0;
    padding: 0;
    scroll-margin-top: 60px;
}

.help-article-controls {
    display: flex;
    gap: 10px;
    margin-bottom: 15px;
}

.help-go-back,
.help-open-page {
    flex: 1;
    text-align: center;
    border: 1px solid;
    background: inherit;
    color: inherit;
    font-size: small;
    padding: 8px;
    text-decoration: none;
    cursor: pointer;
}

#sticky-back-to-top {
    position: sticky;
    bottom: 0;
    z-index: 8;
    text-align: center;
	  padding: 10px;
	  background: #000;
}

.back-to-top {
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}

@media (max-width: 600px) {
    #help-center-popup {
        width: 100%;
        right: 0;
        bottom: 0;
        border-radius: 0;
    }
}

Updated v2

This is version 2 with image and video lightbox support

~266 lines of code PHP Function:

add_action('wp_enqueue_scripts', function () {
    wp_enqueue_script('jquery');

    $js = <<<EOT
    jQuery(document).ready(function($) {
        const popup = $('#help-center-popup');
        const lightbox = $('#help-center-lightbox');
        const lightboxContent = $('.lightbox-content');
        const searchWrap = $('#help-center-search');
        const searchInput = $('#help-center-search-input');
        const resultsWrap = $('#help-center-results');
        let lastFocusedElement;
        let searchTimeout;

        function loadArticles(search = '') {
            $.ajax({
                url: helpCenter.ajax_url,
                method: 'POST',
                data: {
                    action: search ? 'search_help_articles' : 'get_popular_help_articles',
                    nonce: helpCenter.nonce,
                    search
                },
                success: (res) => {
                    if (res.success) {
                        resultsWrap.html(res.data);
                        searchWrap.show();
                        searchInput.focus();
                    }
                }
            });
        }

        function loadArticle(postId) {
            $.ajax({
                url: helpCenter.ajax_url,
                method: 'POST',
                data: {
                    action: 'load_help_article',
                    nonce: helpCenter.nonce,
                    post_id: postId
                },
                success: (res) => {
                    if (res.success) {
                        resultsWrap.html(res.data);
                        searchWrap.hide();
                    }
                }
            });
        }

        // Open help center popup
        $(document).on('click', '.open-help-center a', (e) => {
            e.preventDefault();
            lastFocusedElement = $(document.activeElement);
            popup.fadeIn(200).attr('aria-hidden', 'false');
            loadArticles();
        });

        // Search input handling
        searchInput.on('input', function() {
            clearTimeout(searchTimeout);
            searchTimeout = setTimeout(() => {
                const val = $(this).val().trim();
                val.length >= 3 ? loadArticles(val) : loadArticles();
            }, 300);
        });

        // Load single article
        popup.on('click', '.help-article-title', function() {
            loadArticle($(this).data('post-id'));
        });

        // Go back to article list
        popup.on('click', '#help-go-back', () => loadArticles());

        // Close help center popup
        popup.on('click', '#help-center-close', () => {
            popup.fadeOut(200).attr('aria-hidden', 'true');
            lastFocusedElement.focus();
        });

        // Scroll to top
        popup.on('click', '.back-to-top', (e) => {
            e.preventDefault();
            popup.animate({ scrollTop: 0 }, 400);
        });

        // Open lightbox when clicking images or videos
        resultsWrap.on('click', 'img, video', function(e) {
            e.preventDefault();
            const src = $(this).attr('src');
            const tag = $(this).prop('tagName').toLowerCase();
            let content;

            if (tag === 'img') {
                content = $('<img>').attr('src', src);
            } else if (tag === 'video') {
                content = $('<video>').attr({
                    src: src,
                    controls: true,
                    autoplay: true
                });
            }

            lightboxContent.empty().append(content);
            lightbox.fadeIn(200).attr('aria-hidden', 'false');
            $('#lightbox-close').focus();
        });

        // Close lightbox
        lightbox.on('click', '#lightbox-close', () => {
            lightbox.fadeOut(200).attr('aria-hidden', 'true');
            lightboxContent.empty();
            resultsWrap.focus();
        });

        // Close lightbox or popup with ESC key
        $(document).on('keydown', (e) => {
            if (e.keyCode === 27) { // ESC key
                if (lightbox.is(':visible')) {
                    lightbox.fadeOut(200).attr('aria-hidden', 'true');
                    lightboxContent.empty();
                    resultsWrap.focus();
                } else if (popup.is(':visible')) {
                    popup.fadeOut(200).attr('aria-hidden', 'true');
                    lastFocusedElement.focus();
                }
            }
        });

        // Close lightbox when clicking outside content
        lightbox.on('click', (e) => {
            if ($(e.target).hasClass('help-center-lightbox')) {
                lightbox.fadeOut(200).attr('aria-hidden', 'true');
                lightboxContent.empty();
                resultsWrap.focus();
            }
        });
    });
EOT;

    wp_add_inline_script('jquery', $js);

    wp_localize_script('jquery', 'helpCenter', [
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce'    => wp_create_nonce('help_center_nonce')
    ]);
});

add_action('wp_footer', function () {
    ?>
    <div id="help-center-popup" class="help-center-popup" role="dialog" aria-modal="true" aria-labelledby="help-center-title" aria-hidden="true">
        <div class="help-center-header">
            <strong id="help-center-title">Help Center</strong>
            <button id="help-center-close" class="help-center-close" aria-label="Close Help Center">×</button>
        </div>
        <div id="help-center-search" class="help-center-search">
            <input type="text" id="help-center-search-input" placeholder="Search for help" aria-label="Search help articles">
        </div>
        <div id="help-center-results" class="help-center-results" tabindex="0"></div>
    </div>
    <?php
});

add_filter('nav_menu_css_class', function ($classes) {
    if (in_array('open-help-center', $classes)) {
        $classes[] = 'open-help-center';
    }
    return $classes;
}, 10, 1);

function render_help_articles($query) {
    if (!$query->have_posts()) {
        return '<p>No help articles found.</p>';
    }

    ob_start();
    while ($query->have_posts()) {
        $query->the_post();
        printf(
            '<div class="help-article"><h5 class="help-article-title" data-post-id="%d">%s</h5></div>',
            get_the_ID(),
            esc_html(get_the_title())
        );
    }
    wp_reset_postdata();
    return ob_get_clean();
}

add_action('wp_ajax_get_popular_help_articles', 'load_help_articles');
add_action('wp_ajax_nopriv_get_popular_help_articles', 'load_help_articles');
function load_help_articles() {
    check_ajax_referer('help_center_nonce', 'nonce');

    $query = new WP_Query([
        'post_type'      => 'post',
        'category_name'  => 'help',
        'posts_per_page' => 6,
        'orderby'        => 'date',
        'order'          => 'DESC'
    ]);

    wp_send_json_success(render_help_articles($query));
}

add_action('wp_ajax_search_help_articles', 'search_help_articles');
add_action('wp_ajax_nopriv_search_help_articles', 'search_help_articles');
function search_help_articles() {
    check_ajax_referer('help_center_nonce', 'nonce');
    $search = sanitize_text_field($_POST['search'] ?? '');

    $query = new WP_Query([
        'post_type'      => 'post', // Fixed typo from 'content' to 'post'
        'category_name'  => 'help',
        'posts_per_page' => 6,
        's'              => $search
    ]);

    wp_send_json_success(render_help_articles($query));
}

add_action('wp_ajax_load_help_article', 'load_help_article');
add_action('wp_ajax_nopriv_load_help_article', 'load_help_article');
function load_help_article() {
    check_ajax_referer('help_center_nonce', 'nonce');
    $post_id = intval($_POST['post_id']);
    $post = get_post($post_id);

    if (!$post || !has_category('help', $post)) {
        wp_send_json_error('Invalid article');
    }

    ob_start();
    ?>
    <div class="help-article-controls">
        <button id="help-go-back" class="help-go-back" aria-label="Go back to article list">Go Back</button>
        <a href="<?php echo esc_url(get_permalink($post)); ?>" target="_self" class="help-open-page" aria-label="Open support page in new tab">Open Support Page</a>
    </div>
    <h3><?php echo esc_html(get_the_title($post)); ?></h3>
    <?php echo apply_filters('the_content', $post->post_content); ?>
    <div id="sticky-back-to-top">
        <a class="back-to-top" href="#help-center-popup" role="button" aria-label="Scroll back to top">Back to top ↑</a>
    </div>
    <?php
    wp_send_json_success(ob_get_clean());
}

add_action('wp_footer', function () {
    ?>
    <div id="help-center-popup" class="help-center-popup" role="dialog" aria-modal="true" aria-labelledby="help-center-title" aria-hidden="true">
        <div class="help-center-header">
            <strong id="help-center-title">Help Center</strong>
            <button id="help-center-close" class="help-center-close" aria-label="Close Help Center">×</button>
        </div>
        <div id="help-center-search" class="help-center-search">
            <input type="text" id="help-center-search-input" placeholder="Search for help" aria-label="Search help articles">
        </div>
        <div id="help-center-results" class="help-center-results" tabindex="0"></div>
    </div>
    <div id="help-center-lightbox" class="help-center-lightbox" role="dialog" aria-modal="true" aria-hidden="true">
        <button id="lightbox-close" class="lightbox-close" aria-label="Close Lightbox">×</button>
        <div class="lightbox-content"></div>
    </div>
    <?php
});

~170 lines of CSS:

#help-center-popup {
    background: inherit;
    border: 1px solid;
    bottom: 0;
    box-shadow: 0 0 6px rgba(0, 0, 0, 0.1);
    display: none;
    flex-direction: column;
    height: 55vh;
    max-height: 90vh;
    max-width: 100%;
    overflow-x: hidden;
    overflow-y: auto;
    padding: 0 15px;
    position: fixed;
    right: 0;
    transition: opacity 0.2s ease;
    width: 400px;
    z-index: 10000;
}

.help-center-header {
    align-items: center;
    background: inherit;
    display: flex;
    justify-content: space-between;
    z-index: 10;
}

.help-center-close {
    background: none;
    border: none;
    cursor: pointer;
    line-height: 1;
}

#help-center-search {
    background: inherit;
    display: none;
    padding-bottom: 10px;
    position: sticky;
    top: 40px;
    z-index: 9;
}

#help-center-search-input {
    background: inherit;
    border: 1px solid;
    color: inherit;
    font-size: inherit;
    padding: 3px;
    width: 100%;
}

.help-center-results {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.help-article-title {
    cursor: pointer;
    margin: 0;
    padding: 0;
    scroll-margin-top: 60px;
}

.help-article:hover {
    border-right: 4px solid;
}

.help-article-controls {
    display: flex;
    gap: 10px;
    margin-bottom: 10px;
}

.help-center-results video {
    width: 100%;
}

.help-center-results video:hover,
.help-center-results img:hover {
    cursor: pointer;
}

.help-go-back,
.help-open-page {
    background: inherit;
    border: 1px solid;
    color: inherit;
    cursor: pointer;
    flex: 1;
    font-size: small;
    padding: 8px;
    text-align: center;
    text-decoration: none;
}

#sticky-back-to-top {
    background: var(--contrast);
    bottom: 0;
    position: sticky;
    text-align: center;
    z-index: 8;
}

.back-to-top {
    color: inherit;
    cursor: pointer;
    display: block;
    font-size: initial;
    padding: 10px;
    text-decoration: none;
}

.help-center-lightbox {
    align-items: center;
    background: rgba(0, 0, 0, 0.9);
    display: none;
    height: 100vh;
    justify-content: center;
    left: 0;
    opacity: 0;
    position: fixed;
    top: 0;
    transition: opacity 0.2s ease;
    width: 100vw;
    z-index: 10001;
}

.help-center-lightbox[aria-hidden="false"] {
    display: flex !important;
    opacity: 1;
}

.lightbox-close {
    background: none;
    border: none;
    color: #fff;
    cursor: pointer;
    font-size: 2em;
    line-height: 1;
    position: absolute;
    right: 15px;
    top: 15px;
}

.lightbox-content {
    align-items: center;
    display: flex;
    flex-shrink: 0;
    justify-content: center;
    max-height: 90vh;
    max-width: 90vw;
}

.lightbox-content img,
.lightbox-content video {
    max-height: 100%;
    max-width: 100%;
    object-fit: contain;
    vertical-align: middle;
}

@media (max-width: 600px) {
    #help-center-popup {
        border-radius: 0;
        bottom: 0;
        right: 0;
        width: 100%;
    }
}

Was this helpful?

Yes! 🎉 No! 😑

Not quite what you're looking for? Get Help

1 thought on “Help Center Popup”

Leave a Comment

Item added to cart.
0 items - $0