Generating shortcode and HTML on button click

I think this would a job for Ajax. I’ve done a similar thing to load more posts, which is basically, onclick, load content, append content (to existing element).

I haven’t finalized it entirely but I think this will give you a good nudge in the desired direction.

First we need a function which does what you want, when you click it.
Explanation is shown on this page. Make sure you also add the nopriv if you want it to work for visitors.

function sd_get_more_posts() {
    // Handle request then generate response using WP_Ajax_Response

    // get posts
    $post_args = array(
        // your arguments
    );
    $more_posts = get_posts($post_args);

    // echo the output, in my case I use Timber, hence why the Timber::render
    Timber::render( 'partials/overview.twig',
        array(
            'modifier' => $modifier,
            'posts'    => $more_posts
        )
    );

    // Don't forget to stop execution afterward.
    wp_die();

}
add_action( 'wp_ajax_more_load', 'sd_get_more_posts' );
add_action( 'wp_ajax_nopriv_more_load', 'sd_get_more_posts' );

Using my example you need a link with the class ‘load-more-posts’.
You need to add this somewhere and enqueue it.

jQuery(function($){

    jQuery(".load_more_posts").click(function(e) {
        e.preventDefault();
        // jQuery(this).addClass('hidden'); // uncomment this to hide the trigger on click.

        // you might not need them, but they show a bit of what is possible.
        offset = jQuery(this).data('offset');
        amount = jQuery(this).data('amount');

        var data = {
            'action': 'more_posts',
            'offset': offset,
            'amount': amount
        };
        jQuery.post(
            ajaxurl,
            data,
            function(response) {
                if (jQuery(response).find('.class-of-element')){
                    var newElems = jQuery(response).find('.class-of-element').html();
                    jQuery('.class-of-element').append(newElems);
                }
            }
        );
    });

});

Hope this helps.