Skip to content

Commit

Permalink
feat: add pointer-arrow theme variant to vaadin-popover
Browse files Browse the repository at this point in the history
  • Loading branch information
web-padawan committed Jul 15, 2024
1 parent 01919cf commit 6c1453a
Show file tree
Hide file tree
Showing 32 changed files with 222 additions and 8 deletions.
6 changes: 6 additions & 0 deletions packages/popover/src/vaadin-popover-overlay-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ export const PopoverOverlayMixin = (superClass) =>
return;
}

this.removeAttribute('arrow-centered');

// Center the overlay horizontally
if (this.position === 'bottom' || this.position === 'top') {
const targetRect = this.positionTarget.getBoundingClientRect();
Expand All @@ -70,13 +72,17 @@ export const PopoverOverlayMixin = (superClass) =>
const left = overlayRect.left + offset;
if (left > 0) {
this.style.left = `${left}px`;
// Center the pointer arrow horizontally
this.setAttribute('arrow-centered', '');
}
}

if (this.style.right) {
const right = parseFloat(this.style.right) + offset;
if (right > 0) {
this.style.right = `${right}px`;
// Center the pointer arrow horizontally
this.setAttribute('arrow-centered', '');
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions packages/popover/src/vaadin-popover-overlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,17 @@ class PopoverOverlay extends PopoverOverlayMixin(DirMixin(ThemableMixin(PolylitM
:host([position^='end'][end-aligned]) [part='overlay'] {
margin-inline-end: var(--vaadin-popover-offset-end, 0);
}
[part='arrow'] {
display: none;
position: absolute;
height: 0;
width: 0;
}
:host([theme~='pointer-arrow']) [part='arrow'] {
display: block;
}
`,
];
}
Expand All @@ -91,6 +102,7 @@ class PopoverOverlay extends PopoverOverlayMixin(DirMixin(ThemableMixin(PolylitM
return html`
<div id="backdrop" part="backdrop" hidden ?hidden="${!this.withBackdrop}"></div>
<div part="overlay" id="overlay" tabindex="0">
<div part="arrow"></div>
<div part="content" id="content"><slot></slot></div>
</div>
`;
Expand Down
6 changes: 6 additions & 0 deletions packages/popover/src/vaadin-popover.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ export type PopoverEventMap = HTMLElementEventMap & PopoverCustomEventMap;
* See [`<vaadin-overlay>`](#/elements/vaadin-overlay) documentation
* for `<vaadin-popover-overlay>` parts.
*
* In addition to `<vaadin-overlay>` parts, the following parts are available for styling:
*
* Part name | Description
* -----------------|-------------------------------------------
* `arrow` | Optional arrow pointing to the target when using `theme="pointer-arrow"`
*
* The following state attributes are available for styling:
*
* Attribute | Description
Expand Down
6 changes: 6 additions & 0 deletions packages/popover/src/vaadin-popover.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ class PopoverOpenedStateController {
* See [`<vaadin-overlay>`](#/elements/vaadin-overlay) documentation
* for `<vaadin-popover-overlay>` parts.
*
* In addition to `<vaadin-overlay>` parts, the following parts are available for styling:
*
* Part name | Description
* -----------------|-------------------------------------------
* `arrow` | Optional arrow pointing to the target when using `theme="pointer-arrow"`
*
* The following state attributes are available for styling:
*
* Attribute | Description
Expand Down
9 changes: 9 additions & 0 deletions packages/popover/test/visual/lumo/popover.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,14 @@ describe('popover', () => {
await nextRender();
await visualDiff(div, position);
});

it(`${position} pointer arrow`, async () => {
element.setAttribute('theme', 'pointer-arrow');
element.position = position;
await nextUpdate(element);
target.click();
await nextRender();
await visualDiff(div, `${position}-pointer-arrow`);
});
});
});
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.
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.
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.
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.
9 changes: 9 additions & 0 deletions packages/popover/test/visual/material/popover.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,14 @@ describe('popover', () => {
await nextRender();
await visualDiff(div, position);
});

it(`${position} pointer arrow`, async () => {
element.setAttribute('theme', 'pointer-arrow');
element.position = position;
await nextUpdate(element);
target.click();
await nextRender();
await visualDiff(div, `${position}-pointer-arrow`);
});
});
});
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.
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.
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.
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.
91 changes: 87 additions & 4 deletions packages/popover/theme/lumo/vaadin-popover-styles.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,103 @@
import '@vaadin/vaadin-lumo-styles/color.js';
import '@vaadin/vaadin-lumo-styles/spacing.js';
import '@vaadin/vaadin-lumo-styles/style.js';
import '@vaadin/vaadin-lumo-styles/typography.js';
import { overlay } from '@vaadin/vaadin-lumo-styles/mixins/overlay.js';
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';

const popoverOverlay = css`
:host {
--vaadin-popover-offset-top: var(--lumo-space-xs);
--vaadin-popover-offset-bottom: var(--lumo-space-xs);
--vaadin-popover-offset-start: var(--lumo-space-xs);
--vaadin-popover-offset-end: var(--lumo-space-xs);
--vaadin-popover-offset-top: var(--_vaadin-popover-default-offset);
--vaadin-popover-offset-bottom: var(--_vaadin-popover-default-offset);
--vaadin-popover-offset-start: var(--_vaadin-popover-default-offset);
--vaadin-popover-offset-end: var(--_vaadin-popover-default-offset);
--vaadin-popover-arrow-size: 0.5rem;
--_vaadin-popover-default-offset: var(--lumo-space-xs);
}
[part='content'] {
padding: var(--lumo-space-xs) var(--lumo-space-s);
}
:host([theme~='pointer-arrow']) {
--_vaadin-popover-default-offset: calc(var(--lumo-space-s) + var(--vaadin-popover-arrow-size) / 2);
}
/* top / bottom position */
:host([theme~='pointer-arrow'][position^='top']) [part='arrow'],
:host([theme~='pointer-arrow'][position^='bottom']) [part='arrow'] {
border-left: var(--vaadin-popover-arrow-size) solid transparent;
border-right: var(--vaadin-popover-arrow-size) solid transparent;
}
:host([theme~='pointer-arrow'][position^='bottom'][bottom-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='top'][bottom-aligned]) [part='arrow'] {
bottom: calc(var(--vaadin-popover-arrow-size) * -1);
border-top: var(--vaadin-popover-arrow-size) solid var(--lumo-base-color);
filter: drop-shadow(0px 2px 1px var(--lumo-shade-10pct));
}
:host([theme~='pointer-arrow'][position^='bottom'][top-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='top'][top-aligned]) [part='arrow'] {
top: calc(var(--vaadin-popover-arrow-size) * -1);
border-bottom: var(--vaadin-popover-arrow-size) solid var(--lumo-base-color);
filter: drop-shadow(0px -2px 1px var(--lumo-shade-10pct));
}
:host([theme~='pointer-arrow'][position^='bottom'][start-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='top'][start-aligned]) [part='arrow'] {
transform: translateX(-50%);
inset-inline-start: 1.5rem;
}
:host([theme~='pointer-arrow'][position^='bottom'][end-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='top'][end-aligned]) [part='arrow'] {
transform: translateX(50%);
inset-inline-end: 1.5rem;
}
:host([theme~='pointer-arrow'][position^='bottom'][arrow-centered]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='top'][arrow-centered]) [part='arrow'] {
transform: translateX(-50%);
inset-inline-start: 50%;
}
/* start / end position */
:host([theme~='pointer-arrow'][position^='start']) [part='arrow'],
:host([theme~='pointer-arrow'][position^='end']) [part='arrow'] {
border-top: var(--vaadin-popover-arrow-size) solid transparent;
border-bottom: var(--vaadin-popover-arrow-size) solid transparent;
}
:host([theme~='pointer-arrow'][position^='start'][start-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='end'][start-aligned]) [part='arrow'] {
inset-inline-start: calc(var(--vaadin-popover-arrow-size) * -1);
border-right: var(--vaadin-popover-arrow-size) solid var(--lumo-base-color);
filter: drop-shadow(-2px 0 1px var(--lumo-shade-10pct));
}
:host([theme~='pointer-arrow'][position^='start'][end-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='end'][end-aligned]) [part='arrow'] {
inset-inline-end: calc(var(--vaadin-popover-arrow-size) * -1);
border-left: var(--vaadin-popover-arrow-size) solid var(--lumo-base-color);
filter: drop-shadow(2px 0 1px var(--lumo-shade-10pct));
}
:host([theme~='pointer-arrow'][position^='start'][top-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='end'][top-aligned]) [part='arrow'] {
top: 0.5rem;
}
:host([theme~='pointer-arrow'][position='start'][top-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position='end'][top-aligned]) [part='arrow'] {
top: 50%;
transform: translateY(-50%);
}
:host([theme~='pointer-arrow'][position^='start'][bottom-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='end'][bottom-aligned]) [part='arrow'] {
bottom: 0.5rem;
}
`;

registerStyles('vaadin-popover-overlay', [overlay, popoverOverlay], { moduleId: 'lumo-popover-overlay' });
91 changes: 87 additions & 4 deletions packages/popover/theme/material/vaadin-popover-styles.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,100 @@
import '@vaadin/vaadin-material-styles/color.js';
import { overlay } from '@vaadin/vaadin-material-styles/mixins/overlay.js';
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';

const popoverOverlay = css`
:host {
--vaadin-popover-offset-top: 0.25rem;
--vaadin-popover-offset-bottom: 0.25rem;
--vaadin-popover-offset-start: 0.25rem;
--vaadin-popover-offset-end: 0.25rem;
--vaadin-popover-offset-top: var(--_vaadin-popover-default-offset);
--vaadin-popover-offset-bottom: var(--_vaadin-popover-default-offset);
--vaadin-popover-offset-start: var(--_vaadin-popover-default-offset);
--vaadin-popover-offset-end: var(--_vaadin-popover-default-offset);
--vaadin-popover-arrow-size: 0.5rem;
--_vaadin-popover-default-offset: 0.25rem;
}
[part='content'] {
padding: 0.25rem 0.5rem;
}
:host([theme~='pointer-arrow']) {
--_vaadin-popover-default-offset: calc(0.25rem + var(--vaadin-popover-arrow-size) / 1.25);
}
/* top / bottom position */
:host([theme~='pointer-arrow'][position^='top']) [part='arrow'],
:host([theme~='pointer-arrow'][position^='bottom']) [part='arrow'] {
border-left: var(--vaadin-popover-arrow-size) solid transparent;
border-right: var(--vaadin-popover-arrow-size) solid transparent;
}
:host([theme~='pointer-arrow'][position^='bottom'][bottom-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='top'][bottom-aligned]) [part='arrow'] {
bottom: calc(var(--vaadin-popover-arrow-size) * -1);
border-top: var(--vaadin-popover-arrow-size) solid var(--material-background-color);
filter: drop-shadow(0px 2px 1px rgba(0, 0, 0, 0.14));
}
:host([theme~='pointer-arrow'][position^='bottom'][top-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='top'][top-aligned]) [part='arrow'] {
top: calc(var(--vaadin-popover-arrow-size) * -1);
border-bottom: var(--vaadin-popover-arrow-size) solid var(--material-background-color);
filter: drop-shadow(0px -2px 1px rgba(0, 0, 0, 0.14));
}
:host([theme~='pointer-arrow'][position^='bottom'][start-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='top'][start-aligned]) [part='arrow'] {
transform: translateX(-50%);
inset-inline-start: 1.5rem;
}
:host([theme~='pointer-arrow'][position^='bottom'][end-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='top'][end-aligned]) [part='arrow'] {
transform: translateX(50%);
inset-inline-end: 1.5rem;
}
:host([theme~='pointer-arrow'][position^='bottom'][arrow-centered]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='top'][arrow-centered]) [part='arrow'] {
transform: translateX(-50%);
inset-inline-start: 50%;
}
/* start / end position */
:host([theme~='pointer-arrow'][position^='start']) [part='arrow'],
:host([theme~='pointer-arrow'][position^='end']) [part='arrow'] {
border-top: var(--vaadin-popover-arrow-size) solid transparent;
border-bottom: var(--vaadin-popover-arrow-size) solid transparent;
}
:host([theme~='pointer-arrow'][position^='start'][start-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='end'][start-aligned]) [part='arrow'] {
inset-inline-start: calc(var(--vaadin-popover-arrow-size) * -1);
border-right: var(--vaadin-popover-arrow-size) solid var(--material-background-color);
filter: drop-shadow(-2px 0 1px rgba(0, 0, 0, 0.14));
}
:host([theme~='pointer-arrow'][position^='start'][end-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='end'][end-aligned]) [part='arrow'] {
inset-inline-end: calc(var(--vaadin-popover-arrow-size) * -1);
border-left: var(--vaadin-popover-arrow-size) solid var(--material-background-color);
filter: drop-shadow(2px 0 1px rgba(0, 0, 0, 0.14));
}
:host([theme~='pointer-arrow'][position^='start'][top-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='end'][top-aligned]) [part='arrow'] {
top: 0.5rem;
}
:host([theme~='pointer-arrow'][position='start'][top-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position='end'][top-aligned]) [part='arrow'] {
top: 50%;
transform: translateY(-50%);
}
:host([theme~='pointer-arrow'][position^='start'][bottom-aligned]) [part='arrow'],
:host([theme~='pointer-arrow'][position^='end'][bottom-aligned]) [part='arrow'] {
bottom: 0.5rem;
}
`;

registerStyles('vaadin-popover-overlay', [overlay, popoverOverlay], { moduleId: 'material-popover-overlay' });

0 comments on commit 6c1453a

Please sign in to comment.