Skip to content

Commit

Permalink
Add horizontalAlignment to Menu.open() options (#732)
Browse files Browse the repository at this point in the history
* add align to menu.IOpenOptions

* add align

* add test

* adds tests and default direction

* add docstring

* lint

* try making test more reliable

* lint and update api

* use floor instead of round

* change align to horizontalAlignment

* lint

* update docstrings

* update api
  • Loading branch information
andrewfulton9 authored Dec 19, 2024
1 parent 2361102 commit 53f937e
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 1 deletion.
27 changes: 26 additions & 1 deletion packages/widgets/src/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -465,9 +465,21 @@ export class Menu extends Widget {
let forceY = options.forceY || false;
const host = options.host ?? null;
const ref = options.ref ?? null;
const horizontalAlignment =
options.horizontalAlignment ??
(document.documentElement.dir === 'rtl' ? 'right' : 'left');

// Open the menu as a root menu.
Private.openRootMenu(this, x, y, forceX, forceY, host, ref);
Private.openRootMenu(
this,
x,
y,
forceX,
forceY,
horizontalAlignment,
host,
ref
);

// Activate the menu to accept keyboard input.
this.activate();
Expand Down Expand Up @@ -1009,6 +1021,13 @@ export namespace Menu {
* menu to be added as the last child of the host.
*/
ref?: HTMLElement;

/**
* The alignment of the menu.
*
* The default is `'left'` unless the document `dir` attribute is `'rtl'`
*/
horizontalAlignment?: 'left' | 'right';
}

/**
Expand Down Expand Up @@ -1559,6 +1578,7 @@ namespace Private {
y: number,
forceX: boolean,
forceY: boolean,
horizontalAlignment: 'left' | 'right',
host: HTMLElement | null,
ref: HTMLElement | null
): void {
Expand Down Expand Up @@ -1589,6 +1609,11 @@ namespace Private {
// Measure the size of the menu.
let { width, height } = node.getBoundingClientRect();

// align the menu to the right of the target if requested or language is RTL
if (horizontalAlignment === 'right') {
x -= width;
}

// Adjust the X position of the menu to fit on-screen.
if (!forceX && x + width > px + cw) {
x = px + cw - width;
Expand Down
24 changes: 24 additions & 0 deletions packages/widgets/tests/src/menu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,30 @@ describe('@lumino/widgets', () => {
);
});

it('should accept horizontalAlignment menu flags', () => {
menu.addItem({ command: 'test' });
menu.open(300, 300, { horizontalAlignment: 'right' });
let { width } = menu.node.getBoundingClientRect();
const expectedX = Math.floor(300 - width);
expect(
menu.node.style.transform.startsWith(`translate(${expectedX}`)
).to.equal(true);
expect(menu.node.style.transform.endsWith('px, 300px)')).to.equal(true);
});

it.only('horizontalAlignment should default to `right` if language direction is `rtl`', () => {
document.documentElement.setAttribute('dir', 'rtl');
menu.addItem({ command: 'test' });
menu.open(300, 300);
let { width } = menu.node.getBoundingClientRect();
const expectedX = Math.floor(300 - width);
expect(
menu.node.style.transform.startsWith(`translate(${expectedX}`)
).to.equal(true);
expect(menu.node.style.transform.endsWith('px, 300px)')).to.equal(true);
document.documentElement.removeAttribute('dir'); // Reset the direction
});

it('should bail if already attached', () => {
menu.addItem({ command: 'test' });
menu.open(10, 10);
Expand Down
1 change: 1 addition & 0 deletions review/api/widgets.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,7 @@ export namespace Menu {
export interface IOpenOptions {
forceX?: boolean;
forceY?: boolean;
horizontalAlignment?: 'left' | 'right';
host?: HTMLElement;
ref?: HTMLElement;
}
Expand Down

0 comments on commit 53f937e

Please sign in to comment.