Premium support for our pure JavaScript UI components


Post by gbrdhvndi »

When a Bryntum widget is rendered inside of the lightning-modal component, the menus are shifted by several pixels to the right from the expected position. This is due to the CSS class slds-modal__container on the modal's body element defining transform: translate(0, 0) rule.

To replicate the issue, create three Lightning web components: bryntumGrid, modalWithGrid, and modalPreview as follows.

bryntumGrid

HTML:

<template>
	<div
		id="b"
		data-role="bryntum-host"
		class="slds-grid slds-grid_vertical"
		style="height: 100%"
		lwc:dom="manual"
	></div>
</template>

JS:

import { LightningElement } from 'lwc';
import { loadScript, loadStyle } from 'lightning/platformResourceLoader';

import RESOURCE_URL from '@salesforce/resourceUrl/bryntum';

const getBundle = () => {
    /* global bryntum */
    try {
        return bryntum?.grid;
    } catch (e) {
        return undefined;
    }
};

const loadBundle = async (cmp) => {
    if (!getBundle()) {
        await Promise.all([
            loadStyle(cmp, `${RESOURCE_URL}/grid.stockholm.css`),
            loadScript(cmp, `${RESOURCE_URL}/grid.lwc.module.js`),
        ]);
    }

    return getBundle();
};

export default class BryntumGrid extends LightningElement {
    gridId = null;

    async renderedCallback() {
        this.createGrid(await loadBundle(this));
    }

    disconnectedCallback() {
        const { gridId } = this;

        if (gridId) {
            const { Widget } = getBundle();

            const grid = Widget.getById(gridId);
            grid.destroy();
            this.gridId = null;
        }
    }

    createGrid({ Grid }) {
        const { appendTo } = this;

        const grid = new Grid({
            appendTo,
            columns: [
                {
                    type: 'rownumber',
                },
                {
                    text: 'Name',
                    flex: 1,
                },
            ],
        });

        this.gridId = grid.id;
    }

    get appendTo() {
        // An element with lwc:dom="manual"
        return this.template.querySelector('[data-role="bryntum-host"]');
    }
}

modalWithGrid

HTML:

<template>
	<lightning-modal-header
		label="Grid in Modal"
	></lightning-modal-header>
	<lightning-modal-body>
		<c-bryntum-grid
			class="slds-card slds-card_boundary"
			style="display: block; height: 50vh"
		></c-bryntum-grid>
	</lightning-modal-body>
</template>

JS:

import LightningModal from 'lightning/modal';

export default class ModalWithGrid extends LightningModal {}

modalPreview

HTML:

<template>
	<lightning-button
		variant="brand"
		label="Show the Modal Dialog"
		onclick={handleButtonClick}
	></lightning-button>
</template>

JS:

import { LightningElement } from 'lwc';
import ModalWithGrid from 'c/modalWithGrid';

export default class ModalPreview extends LightningElement {
    async handleButtonClick() {
        await ModalWithGrid.open({
            size: 'large',
        });
    }
}

Observed result

Add the modalPreview component to an App page or a Tab, open it and click the button. Once the modal dialog opens and the grid loads, right-click on a column header. The menu is displayed at a distance from the mouse pointer. Now hover over an expandable menu option. The submenu will display at the same distance away from the main menu.

menu-alignment-broken.gif
menu-alignment-broken.gif (394.58 KiB) Viewed 277 times

The fix

A simple override of the Rectangle.alignTo() method resolves this issue:

class RectangleOverride {
    static get target() {
        return {
            class: Rectangle,
        };
    }

    alignTo(spec) {
        const result = this._overridden.alignTo.call(this, spec);

        const { source, constrainTo } = spec;

        if (constrainTo === window || constrainTo === document) {
            const rootEl = DomHelper.getRootElement(source.element);
            const floatRoot = rootEl.querySelector('.b-float-root');

            if (floatRoot) {
                const { x } = Rectangle.from(floatRoot);

                // Compensate for the position shift
                // caused by slds-modal__container's
                // CSS transform: translate(0, 0);
                result.translate(-x, 0);
            }
        }

        return result;
    }
}

Override.apply(RectangleOverride);

Expected result

Follow the same steps as before to launch the modal dialog and open the header context menu.

menu-alignment-fixed.gif
menu-alignment-fixed.gif (398.01 KiB) Viewed 277 times

🙂

Aleksei


Post by Maxim Gorkovsky »

Hello.
It appears we already have a ticket for this problem: https://github.com/bryntum/support/issues/2307 We will bring it up the queue


Post Reply