Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try to solve the stacking context issue using either <dialog> or popover #23

Merged
merged 8 commits into from
Apr 10, 2024
Merged
52 changes: 40 additions & 12 deletions src/cosmoz-dropdown.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { component, useCallback } from '@pionjs/pion';
import { html, nothing, TemplateResult } from 'lit-html';
import { when } from 'lit-html/directives/when.js';
import { ref } from 'lit-html/directives/ref.js';
import { usePosition, Placement } from './use-position';
import { useHostFocus, UseFocusOpts } from './use-focus';

Expand All @@ -12,9 +13,25 @@ interface ContentProps {
render?: () => TemplateResult;
}

const supportsPopover = () => {
// eslint-disable-next-line no-prototype-builtins
return HTMLElement.prototype.hasOwnProperty('popover');
};

const showPopover = (popover?: Element) => {
const popoverElement = popover as HTMLElement;

if (supportsPopover()) {
requestAnimationFrame(() => {
popoverElement?.showPopover();
});
}
};

const Content = (host: HTMLElement & ContentProps) => {
const { anchor, placement, render } = host;
usePosition({ anchor, placement, host });

return html` <style>
:host {
position: fixed;
Expand All @@ -24,6 +41,12 @@ const Content = (host: HTMLElement & ContentProps) => {
padding: var(--cosmoz-dropdown-spacing, 0px);
z-index: var(--cosmoz-dropdown-z-index, 2);
}
:host(:popover-open) {
margin: 0;
border: 0;
/* The padding is needed to show the box shadow in Chrome */
padding: 4px;
}
.wrap {
background: var(--cosmoz-dropdown-bg-color, #fff);
box-shadow: var(
Expand Down Expand Up @@ -104,7 +127,9 @@ const Dropdown = (host: HTMLElement & DropdownProps) => {
${when(
active,
() =>
html` <cosmoz-dropdown-content
html`<cosmoz-dropdown-content
${ref(showPopover)}
popover
id="content"
part="content"
exportparts="wrap, content"
Expand All @@ -113,7 +138,7 @@ const Dropdown = (host: HTMLElement & DropdownProps) => {
.render=${render}
>
<slot></slot>
</cosmoz-dropdown-content>`
</cosmoz-dropdown-content>`,
)}`;
};

Expand All @@ -131,7 +156,9 @@ const List = () => html`
padding: 10px 24px;
background: transparent;
color: var(--cosmoz-dropdown-menu-color, #101010);
transition: background 0.25s, color 0.25s;
transition:
background 0.25s,
color 0.25s;
border: none;
cursor: pointer;
font-size: 14px;
Expand All @@ -158,18 +185,19 @@ const List = () => html`

type MenuProps = Pick<DropdownProps, 'placement'>;

const Menu = ({ placement }: MenuProps) => html` <cosmoz-dropdown
.placement=${placement}
part="dropdown"
exportparts="anchor, button, content, wrap, dropdown"
>
<slot name="button" slot="button"></slot>
<cosmoz-dropdown-list><slot></slot></cosmoz-dropdown-list>
</cosmoz-dropdown>`;
const Menu = ({ placement }: MenuProps) =>
html` <cosmoz-dropdown
.placement=${placement}
part="dropdown"
exportparts="anchor, button, content, wrap, dropdown"
>
<slot name="button" slot="button"></slot>
<cosmoz-dropdown-list><slot></slot></cosmoz-dropdown-list>
</cosmoz-dropdown>`;

customElements.define(
'cosmoz-dropdown-content',
component<ContentProps>(Content)
component<ContentProps>(Content),
);
customElements.define('cosmoz-dropdown', component<DropdownProps>(Dropdown));
customElements.define('cosmoz-dropdown-list', component(List));
Expand Down
15 changes: 13 additions & 2 deletions stories/cosmoz-dropdown.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const DropdownMenu: Story = {
};

export const DropdownWithBug: Story = {
name: 'Dropdown with Bug - fixed on Chrome',
render: () => {
return html`<style>
.wrapper-with-bug {
Expand All @@ -47,10 +48,19 @@ export const DropdownWithBug: Story = {
height: 300px;
top: 100px;
left: 100px;
margin: 0 auto;
background-color: blueviolet;
transform: translate3d(0, 0, 0);
}
.overlay {
width: 350px;
height: 350px;
background-color: green;
transform: translate3d(0, 0, 0);
position: absolute;
top: 150px;
left: 100px;
z-index: 3;
}
</style>
<div class="wrapper-with-bug">
<cosmoz-dropdown>
Expand All @@ -60,6 +70,7 @@ export const DropdownWithBug: Story = {
<div>Item 4</div>
<div>Item 5</div>
</cosmoz-dropdown>
</div>`;
</div>
<div class="overlay"></div>`;
},
};