Modal

<div class="modal " aria-hidden="true" id="modal-id">
    <div class="modal__inner">
        <div class="modal__box">
            <div class="modal__header">
                <button aria-controls="modal-id" aria-label="Stäng" class="modal__close-button">
                    <svg class="icon modal__close-button-icon" focusable="false">
                        <use xlink:href="#icon-close"></use>
                    </svg>
                </button>
            </div>

            <div class="modal__content">
                <h2>Example content</h2>
                <p>EXAMPLE CONTENT: Pellentesque dapibus suscipit ligula. Donec posuere augue in quam. Etiam vel tortor
                    sodales tellus
                    ultricies commodo. Suspendisse potenti. Aenean in sem ac leo mollis blandit. Donec neque quam,
                    dignissim in, mollis
                    nec, sagittis eu, wisi. Phasellus lacus. Etiam laoreet quam sed arcu. Phasellus at dui in ligula
                    mollis ultricies.
                    Integer placerat tristique nisl. Praesent augue. Fusce commodo. Vestibulum convallis, lorem a tempus
                    semper, dui dui
                    euismod elit, vitae placerat urna tortor vitae lacus. Nullam libero mauris, consequat quis, varius
                    et, dictum id,
                    arcu. Mauris mollis tincidunt felis. Aliquam feugiat tellus ut neque. Nulla facilisis, risus a
                    rhoncus fermentum,
                    tellus tellus lacinia purus.</p>
            </div>
        </div>
    </div>
</div>
<div class="modal {{getmodifiers modifiers "modal"}}" aria-hidden="true" id="{{ id }}">
    <div class="modal__inner">
        <div class="modal__box">
            <div class="modal__header">
                <button aria-controls="{{ id }}" aria-label="{{closeLabel}}" class="modal__close-button">
                    {{> @icon id="close" additionalClasses="modal__close-button-icon"}}
                </button>
            </div>

            <div class="modal__content">
                {{#>@partial-block}}
                <h2>Example content</h2>
                <p>EXAMPLE CONTENT: Pellentesque dapibus suscipit ligula. Donec posuere augue in quam. Etiam vel tortor
                    sodales tellus
                    ultricies commodo. Suspendisse potenti. Aenean in sem ac leo mollis blandit. Donec neque quam,
                    dignissim in, mollis
                    nec, sagittis eu, wisi. Phasellus lacus. Etiam laoreet quam sed arcu. Phasellus at dui in ligula
                    mollis ultricies.
                    Integer placerat tristique nisl. Praesent augue. Fusce commodo. Vestibulum convallis, lorem a tempus
                    semper, dui dui
                    euismod elit, vitae placerat urna tortor vitae lacus. Nullam libero mauris, consequat quis, varius
                    et, dictum id,
                    arcu. Mauris mollis tincidunt felis. Aliquam feugiat tellus ut neque. Nulla facilisis, risus a
                    rhoncus fermentum,
                    tellus tellus lacinia purus.</p>
                {{/@partial-block}}
            </div>
        </div>
    </div>
</div>
{
  "modal": true,
  "id": "modal-id",
  "closeLabel": "Stäng"
}
  • Content:
    import TabLoop from '../../functions/TabLoop';
    
    class Modal {
        constructor(modal) {
            this.modal = modal;
            this.state = 'hidden';
            this.id = modal.getAttribute('id');
            this.lastFocusedElement = undefined;
            this.tabLoop = new TabLoop(this.modal);
            this.ESCKEY = 27;
            this.keyUpHandler = e => this.keyUp(e);
            this.clickOutsideHandler = e => this.clickOutside(e);
            this.setModalStateHandler = e => this.setModalState(e);
    
            this.modal.modal = this;
            this.publicOpen = (tabLoop) => this.open(tabLoop);
            this.publicClose = () => this.close();
    
            this.init();
        }
    
        init() {
            this.attachTriggers();
        }
    
        attachTriggers() {
            const triggers = document.querySelectorAll(`[aria-controls="${this.id}"]`);
    
            for (let i = 0; i < triggers.length; i++) {
                const trigger = triggers[i];
    
                trigger.addEventListener('click', this.setModalStateHandler);
            }
        }
    
        setModalState(e) {
            e.preventDefault();
    
            if (this.state === 'hidden') {
                this.lastFocusedElement = e.target;
            }
    
            this.toggle();
        }
    
        addEventListeners() {
            document.addEventListener('keyup', this.keyUpHandler);
            document.addEventListener('click', this.clickOutsideHandler);
        }
    
        removeEventListeners() {
            document.removeEventListener('keyup', this.keyUpHandler);
            document.removeEventListener('click', this.clickOutsideHandler);
        }
    
        keyUp(e) {
            if (e.which === this.ESCKEY) {
                e.preventDefault();
                this.close();
            }
        }
    
        clickOutside(e) {
            const target = e.target;
    
            if (target === this.modal.children[0]) {
                this.close();
            }
        }
    
        open() {
            this.modal.style.display = 'block';
            this.modal.style.overflowX = 'hidden';
    
            setTimeout(() => {
                this.modal.setAttribute('aria-hidden', false);
                this.state = 'visible';
    
                document.body.style.overflow = 'hidden';
                document.body.style.height = '100%';
                this.tabLoop.start();
                this.addEventListeners();
            }, 30);
        }
    
        close() {
            this.modal.setAttribute('aria-hidden', true);
            this.state = 'hidden';
    
            document.body.style.height = 'auto';
    
            this.lastFocusedElement.focus();
            this.tabLoop.stop();
            this.removeEventListeners();
    
            setTimeout(() => {
                this.modal.style.display = 'none';
                this.modal.style.overflowX = '';
                document.body.style.overflow = '';
            }, 250);
        }
    
        toggle() {
            if (this.state === 'hidden') {
                this.open();
            } else {
                this.close();
            }
        }
    }
    
    export default Modal;
    
  • URL: /components/raw/modal/Modal.js
  • Filesystem Path: src/components/modal/Modal.js
  • Size: 2.8 KB
  • Content:
    import Modal from './Modal';
    
    const els = document.querySelectorAll('.modal');
    
    for (let el of els) {
        new Modal(el);
    }
    
  • URL: /components/raw/modal/index.js
  • Filesystem Path: src/components/modal/index.js
  • Size: 123 Bytes
  • Content:
    .modal {
        display: none;
        position: fixed;
        left: -9999px;
        top: 0px;
        width: 100%;
        height: 100%;
        background: rgba($color-black, 0);
        overflow: scroll;
        text-align: left;
        -webkit-overflow-scrolling: touch;
        transition-property: left, background-color;
        transition-duration: 0ms, 200ms;
        transition-delay: 200ms, 0ms;
        z-index: $z-modal;
    }
    
    .modal__inner {
        @include breakpoint($s) {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            text-align: center;
    
            &:before {
                content: '';
                display: inline-block;
                height: 100%;
                vertical-align: middle;
                margin-right: -0.25em;
            }
        }
    }
    
    .modal[aria-hidden='false'] {
        left: 0;
        transition-delay: 0ms, 0ms;
        background-color: rgba($color-black, 0.5);
    }
    
    .modal__box {
        position: relative;
        width: 100%;
        min-height: calc(100vh + size(10));
        background: $color-white;
        transform: translate3d(0, 400px, 0);
        opacity: 0;
        transition: all 200ms;
        transition-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1);
    
        @include breakpoint($s) {
            width: percentage(10 / 12);
            min-height: 0;
            display: inline-block;
            vertical-align: middle;
            text-align: left;
        }
    
        @include breakpoint($m) {
            max-width: $site-content-width;
        }
    
        @include breakpoint($l) {
            max-width: $l;
        }
    
        .modal--form & {
            width: auto;
            margin: 40px 16px;
            overflow: hidden;
    
            @include breakpoint($s) {
                width: percentage(10 / 12);
            }
    
            @include breakpoint($m) {
                max-width: 764px;
                margin: 40px 0;
            }
    
            h2 {
                padding: 0 0 20px;
                margin: 0 0 14px;
                position: relative;
    
                @include breakpoint($m) {
                    padding: 0 0 30px;
                    margin: 0 0 37px;
                }
    
                &:after {
                    position: absolute;
                    content: '';
                    left: -100px;
                    right: -100px;
                    top: -100px;
                    background: #E9F2E5;
                    z-index: -1;
                    bottom: 0;
                }
            }
        }
    }
    
    .modal[aria-hidden='false'] .modal__box {
        transform: translate3d(0, 0, 0);
        opacity: 1;
    }
    
    .modal__header {
        display: flex;
        justify-content: center;
        align-items: center;
        padding: size(3) size(2);
        padding-right: size(7);
        color: $color-white;
        position: relative;
        min-height: size(8);
    
        @include breakpoint($s) {
            padding: size(2);
        }
    }
    
    .modal__close-button {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        background: transparent;
        border: none;
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        right: size(2);
        padding: 0;
        color: $color-black;
    
        @include breakpoint($s) {
            right: size(3);
        }
    }
    
    .modal__close-button-icon {
        width: size(4);
        height: size(4);
        fill: currentColor;
    }
    
    .modal__content {
        padding: 0 size(2) size(2);
        padding-top: 0;
        width: 100%;
        vertical-align: top;
        text-align: left;
        min-height: calc(100vh - size(15));
    
        @include breakpoint($s) {
            min-height: 0;
            padding: 0 size(4) size(4);
        }
    }
    
  • URL: /components/raw/modal/modal.scss
  • Filesystem Path: src/components/modal/modal.scss
  • Size: 3.4 KB

No notes defined.