icolumbro
icolumbro

Reputation: 123

Building a custom element using shadow dom for CSS and Bootstrap 4

I'm trying to develop a custom component that uses the Bootstrap 4 popover. Basically I want to create a floating button with custom CSS that is not influenced by the CSS of the page and make sure that when you click on the button the Bootstrap popover is shown (also customized). I read this previous discussion, it has been useful to me up to a certain point ... How can I proceed?

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.1/css/all.min.css">
    <title>fwa-button</title>
</head>
<body>

    <div class="container-fluid">
        <fwa-button></fwa-button>
    </div>


    <script src="fwa-button.js"></script>
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
    <script>
        $(function () {
            $('[data-toggle="popover"]').popover({
                container: 'body',
                html: true,
                placement: 'top',
                title: '',
                content: function() {
                    let message = '<p class="h5">Ciao, come posso esserti d\'aiuto?<p>';
                    let checkbox = '<div class="custom-control custom-checkbox"><input type="checkbox" class="custom-control-input" id="customCheck1"><label class="custom-control-label" for="customCheck1">Confermi di aver preso visione della normativa vigente sul trattamento dei dati personali.</label></div>';

                    return message + checkbox;
                },
                template: '<div class="popover chatbox-popup" role="tooltip"><header class="chatbox-popup__header"><aside style="flex:3"><i class="fa fa-user-circle fa-4x chatbox-popup__avatar" aria-hidden="true"></i></aside><aside class="ml-3" style="flex:8"><h1 class="live-chat">Pinco Pallino</h1> <em>Venditore (Online)</em></aside><h3 class="popover-header"></h3></header><div class="popover-body chatbox-popup__main"></div><div class="chatbox-popup__footer"><aside style="flex:10"><textarea type="text" placeholder="Scrivi qui il tuo messaggio..." rows="3" autofocus></textarea></aside><aside style="flex:1;color:#888;text-align:center;"><i class="fa fa-paper-plane ml-3" aria-hidden="true"></i></aside></div></div>',
                sanitize: false,
            })
        })
    </script>
</body>
</html>

fwa-button.js

class FloatingWhatsAppButton extends HTMLElement {
    #container;

    constructor() {
        super();

        var shadow = this.attachShadow( { mode: 'open' } );

        this.#container = document.createElement( 'div' );
        this.#container.setAttribute( 'slot', 'bootstrap' );

        var button = document.createElement( 'button' );
        button.setAttribute( 'type', 'button' );
        button.setAttribute( 'class', 'ccwhatsapp-starter' );
        button.setAttribute( 'data-toggle', 'popover' );

        var icon = document.createElement( 'i' );
        icon.setAttribute( 'class', 'fab fa-whatsapp fa-2x' );
        icon.setAttribute( 'aria-hidden', 'true' );

        button.appendChild( icon );
        this.#container.appendChild( button );

        var slot = document.createElement( 'slot' );
        slot.setAttribute( 'name', 'bootstrap' );
        var style = document.createElement( 'style' );
        style.textContent = '.ccwhatsapp-starter {' +
                                'position: fixed; ' +
                                'bottom: 16px;' +
                                'right: 16px;' +
                                'width: 58px; ' +
                                'height: 58px; ' +
                                'color: white; ' +
                                'background-color: green; ' +
                                'background-position: center center; ' +
                                'background-repeat: no-repeat; ' + 
                                'box-shadow: 12px 15px 20px 0 rgba(46, 61, 73, 0.2); ' +
                                'border: 0; ' +
                                'border-radius: 50%; ' +
                                'cursor: pointer;' +
                            '} ';

        shadow.appendChild( style );
        shadow.appendChild( slot );
    }

    connectedCallback() {
        this.appendChild( this.#container );
    }
}

// Define the new element
customElements.define( 'fwa-button', FloatingWhatsAppButton )

;

Upvotes: 1

Views: 2608

Answers (1)

moefinley
moefinley

Reputation: 1329

If you're asking how do you use Bootstrap in your component the answer is to just repeat the link to the styles and scripts of Bootstrap in your custom element's shadow DOM. The calls will be cached so there is no extra loading and your shadow DOM will now have access to Bootstrap.

If you don't want the parent to influence the custom element you will also have to change the shadow DOM mode to closed var shadow = this.attachShadow( { mode: 'closed' } );

Upvotes: 3

Related Questions