Skip to content

Commit

Permalink
feat(menu): add position-strategy to allow positioning menu absolute …
Browse files Browse the repository at this point in the history
…rather then fixed (VIV-2135) (#1918)
  • Loading branch information
rachelbt authored Oct 2, 2024
1 parent 1249285 commit 55d2b87
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 1 deletion.
34 changes: 34 additions & 0 deletions libs/components/src/lib/menu/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,40 @@ Use the `placement` attribute to control the position of the menu relative to it
</div>
```

### Position Strategy

Add the `position-strategy` attribute to set the menu to be positioned `absolute` instead of `fixed`.

- Type: `fixed` | `absolute`
- Default: `fixed`

<vwc-note connotation="information" icon="info-solid" headline="when to use position-strategy=absolute">
When the menu is within a container that has properties such as `transform`, `perspective`, or `container-type`, which modify its containing block, it's best to use `position-strategy=absolute`.

<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block">read more about Layout and the containing block</a>

</vwc-note>

```html preview 200px
<div style="position: absolute; container-type: inline-size;">
<vwc-menu
position-strategy="absolute"
trigger="auto"
aria-label="Menu example"
placement="bottom-end"
>
<vwc-button
slot="anchor"
icon="more-vertical-line"
aria-label="Open menu"
appearance="outlined"
></vwc-button>
<vwc-menu-item text="Menu item 1"></vwc-menu-item>
<vwc-menu-item text="Menu item 2"></vwc-menu-item>
</vwc-menu>
</div>
```

### Anchor

It's best to use the [`anchor` slot](#anchor-1) to set the anchor, but you can also use the `anchor` member.
Expand Down
16 changes: 16 additions & 0 deletions libs/components/src/lib/menu/menu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ describe('vwc-menu', () => {
expect(element.open).toEqual(false);
expect(element.anchor).toEqual(undefined);
expect(element.placement).toEqual('bottom');
expect(element.positionStrategy).toEqual('fixed');
});
});

Expand Down Expand Up @@ -413,6 +414,21 @@ describe('vwc-menu', () => {
});
});

describe('position-strategy', () => {
it('should reflect position-strategy attribute to property', async function () {
element.setAttribute('position-strategy', 'absolute');
await elementUpdated(element);
expect(element.positionStrategy).toEqual('absolute');
});

it('should reflect its value to popup class', async function () {
element.positionStrategy = 'absolute';
await elementUpdated(element);

expect(popup.strategy).toBe('absolute');
});
});

describe('open', () => {
it('should remain open when clicked inside', async () => {
element.anchor = 'anchorButton';
Expand Down
1 change: 1 addition & 0 deletions libs/components/src/lib/menu/menu.template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export const MenuTemplate: (
:placement=${(x) => x.placement}
:open=${(x) => x.open}
:anchor=${(x) => x._anchorEl}
:strategy="${(x) => x.positionStrategy}"
@keydown="${(x, c) => handleEscapeKey(x, c.event as KeyboardEvent)}"
@vwc-popup:open="${(x, c) => handlePopupEvents(x, c.event, true)}"
@vwc-popup:close="${(x, c) => handlePopupEvents(x, c.event, false)}"
Expand Down
10 changes: 9 additions & 1 deletion libs/components/src/lib/menu/menu.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { attr, DOM, observable } from '@microsoft/fast-element';
import { Menu as FastMenu } from '@microsoft/fast-foundation';
import type { Placement } from '@floating-ui/dom';
import type { Placement, Strategy } from '@floating-ui/dom';
import { type Anchored, anchored } from '../../shared/patterns/anchored';

/**
Expand Down Expand Up @@ -44,6 +44,14 @@ export class Menu extends FastMenu {
*/
@attr({ mode: 'boolean', attribute: 'auto-dismiss' }) autoDismiss = false;

/**
* The strategy-absolute attribute.
*
* @public
* HTML Attribute: strategy
*/
@attr({ mode: 'fromView', attribute: 'position-strategy' })
positionStrategy?: Strategy = 'fixed';
/**
* indicates whether the menu is open
*
Expand Down
41 changes: 41 additions & 0 deletions libs/components/src/lib/menu/ui.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,45 @@ import {

const components = ['menu', 'menu-item', 'button', 'text-field'];

async function testAbsolutStrategy({ page }: { page: Page }) {
const template = `
<style>
.wrapper {
width: 100%;
height: 700px;
position: relative;
}
</style>
<div class="wrapper"><div style="container-type: inline-size">
<vwc-menu id="menu-1" placement="right-start" open strategy-absolute>
<vwc-button slot="anchor" label="Toggle Menu" appearance="outlined"></vwc-button>
<vwc-menu-item text="Menu item 1"></vwc-menu-item>
<vwc-menu-item text="Menu item 2"></vwc-menu-item>
<vwc-menu-item text="Menu item 3"></vwc-menu-item>
</vwc-menu>
</div></div>`;

page.setViewportSize({ width: 500, height: 400 });

await loadComponents({
page,
components,
});
await loadTemplate({
page,
template,
});

const testWrapper = await page.$('#wrapper');

await page.waitForLoadState('networkidle');

expect(await testWrapper?.screenshot()).toMatchSnapshot(
'./snapshots/absolute-menu.png',
{ maxDiffPixelRatio: 0.01 }
);
}

test('should show the component', async ({ page }: { page: Page }) => {
const template = `
<style>
Expand Down Expand Up @@ -50,3 +89,5 @@ test('should show the component', async ({ page }: { page: Page }) => {
'./snapshots/menu.png'
);
});

test('menu with absolute strategy', testAbsolutStrategy);
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 55d2b87

Please sign in to comment.