Skip to content

Commit 3e62bae

Browse files
authored
feat: port popover Lumo styles to CSS files (#9352)
1 parent 83c2fc1 commit 3e62bae

File tree

7 files changed

+182
-4
lines changed

7 files changed

+182
-4
lines changed

dev/popover.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import '@vaadin/horizontal-layout';
1313
import '@vaadin/popover';
1414
import '@vaadin/text-field';
15+
import '@vaadin/vaadin-lumo-styles/lumo.css';
1516
</script>
1617
</head>
1718

packages/popover/src/vaadin-popover-overlay.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { defineCustomElement } from '@vaadin/component-base/src/define.js';
88
import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
99
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
1010
import { overlayStyles } from '@vaadin/overlay/src/vaadin-overlay-styles.js';
11+
import { CSSInjectionMixin } from '@vaadin/vaadin-themable-mixin/css-injection-mixin.js';
1112
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
1213
import { PopoverOverlayMixin } from './vaadin-popover-overlay-mixin.js';
1314

@@ -21,7 +22,7 @@ import { PopoverOverlayMixin } from './vaadin-popover-overlay-mixin.js';
2122
* @mixes ThemableMixin
2223
* @private
2324
*/
24-
class PopoverOverlay extends PopoverOverlayMixin(DirMixin(ThemableMixin(PolylitMixin(LitElement)))) {
25+
class PopoverOverlay extends PopoverOverlayMixin(DirMixin(ThemableMixin(CSSInjectionMixin(PolylitMixin(LitElement))))) {
2526
static get is() {
2627
return 'vaadin-popover-overlay';
2728
}

packages/popover/src/vaadin-popover.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixi
1818
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
1919
import { generateUniqueId } from '@vaadin/component-base/src/unique-id-utils.js';
2020
import { isLastOverlay } from '@vaadin/overlay/src/vaadin-overlay-stack-mixin.js';
21+
import { CSSInjectionMixin } from '@vaadin/vaadin-themable-mixin/css-injection-mixin.js';
2122
import { ThemePropertyMixin } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
2223
import { PopoverPositionMixin } from './vaadin-popover-position-mixin.js';
2324
import { PopoverTargetMixin } from './vaadin-popover-target-mixin.js';
@@ -203,7 +204,7 @@ class PopoverOpenedStateController {
203204
* @mixes ThemePropertyMixin
204205
*/
205206
class Popover extends PopoverPositionMixin(
206-
PopoverTargetMixin(OverlayClassMixin(ThemePropertyMixin(ElementMixin(PolylitMixin(LitElement))))),
207+
PopoverTargetMixin(OverlayClassMixin(ThemePropertyMixin(ElementMixin(CSSInjectionMixin(PolylitMixin(LitElement)))))),
207208
) {
208209
static get is() {
209210
return 'vaadin-popover';

packages/popover/test/visual/lumo/popover.test.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { fixtureSync, nextRender, nextUpdate } from '@vaadin/testing-helpers';
22
import { visualDiff } from '@web/test-runner-visual-regression';
3-
import '@vaadin/vaadin-lumo-styles/test/autoload.js';
3+
import '@vaadin/vaadin-lumo-styles/global.css';
4+
import '@vaadin/vaadin-lumo-styles/props.css';
5+
import '@vaadin/vaadin-lumo-styles/components/popover.css';
46
import '../../not-animated-styles.js';
5-
import '../../../theme/lumo/vaadin-popover.js';
7+
import '../../../vaadin-popover.js';
68

79
describe('popover', () => {
810
let div, target, element;

packages/vaadin-lumo-styles/components.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
@import './components/multi-select-combo-box.css';
2525
@import './components/number-field.css';
2626
@import './components/password-field.css';
27+
@import './components/popover.css';
2728
@import './components/radio-button.css';
2829
@import './components/radio-group.css';
2930
@import './components/select.css';
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* @license
3+
* Copyright (c) 2017 - 2025 Vaadin Ltd.
4+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5+
*/
6+
@import '../src/mixins/base-layer-reset.css' vaadin-popover-overlay;
7+
@import '../src/mixins/overlay.css' vaadin-popover-overlay;
8+
@import '../src/components/popover-overlay.css' vaadin-popover-overlay;
9+
10+
html {
11+
--vaadin-popover-overlay-css-inject: 1;
12+
}
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/**
2+
* @license
3+
* Copyright (c) 2017 - 2025 Vaadin Ltd.
4+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5+
*/
6+
:host {
7+
--_vaadin-popover-content-width: auto;
8+
--_vaadin-popover-content-height: auto;
9+
--vaadin-popover-offset-top: var(--_vaadin-popover-default-offset);
10+
--vaadin-popover-offset-bottom: var(--_vaadin-popover-default-offset);
11+
--vaadin-popover-offset-start: var(--_vaadin-popover-default-offset);
12+
--vaadin-popover-offset-end: var(--_vaadin-popover-default-offset);
13+
--vaadin-popover-arrow-size: 0.5rem;
14+
--_vaadin-popover-default-offset: var(--lumo-space-xs);
15+
}
16+
17+
[part='overlay'] {
18+
position: relative;
19+
overflow: visible;
20+
max-height: 100%;
21+
outline: none;
22+
}
23+
24+
[part='content'] {
25+
overflow: auto;
26+
box-sizing: border-box;
27+
max-height: 100%;
28+
width: var(--_vaadin-popover-content-width);
29+
height: var(--_vaadin-popover-content-height);
30+
padding: var(--lumo-space-xs) var(--lumo-space-s);
31+
}
32+
33+
/* Increase the area of the popover so the pointer can go from the target directly to it. */
34+
[part='overlay']::before {
35+
position: absolute;
36+
content: '';
37+
inset-block: calc(var(--vaadin-popover-offset-top, 0) * -1) calc(var(--vaadin-popover-offset-bottom, 0) * -1);
38+
inset-inline: calc(var(--vaadin-popover-offset-start, 0) * -1) calc(var(--vaadin-popover-offset-end, 0) * -1);
39+
z-index: -1;
40+
pointer-events: auto;
41+
}
42+
43+
:host([theme~='no-padding']) [part='content'] {
44+
padding: 0;
45+
}
46+
47+
[part='arrow'] {
48+
display: none;
49+
position: absolute;
50+
height: 0;
51+
width: 0;
52+
}
53+
54+
:host([theme~='arrow']) {
55+
--_vaadin-popover-default-offset: calc(var(--lumo-space-s) + var(--vaadin-popover-arrow-size) / 2);
56+
}
57+
58+
:host([theme~='arrow']) [part='arrow'] {
59+
display: block;
60+
}
61+
62+
:host([modeless][with-backdrop]) [part='backdrop'] {
63+
pointer-events: none;
64+
}
65+
66+
:host([position^='top'][top-aligned]) [part='overlay'],
67+
:host([position^='bottom'][top-aligned]) [part='overlay'] {
68+
margin-top: var(--vaadin-popover-offset-top, 0);
69+
}
70+
71+
:host([position^='top'][bottom-aligned]) [part='overlay'],
72+
:host([position^='bottom'][bottom-aligned]) [part='overlay'] {
73+
margin-bottom: var(--vaadin-popover-offset-bottom, 0);
74+
}
75+
76+
:host([position^='start'][start-aligned]) [part='overlay'],
77+
:host([position^='end'][start-aligned]) [part='overlay'] {
78+
margin-inline-start: var(--vaadin-popover-offset-start, 0);
79+
}
80+
81+
:host([position^='start'][end-aligned]) [part='overlay'],
82+
:host([position^='end'][end-aligned]) [part='overlay'] {
83+
margin-inline-end: var(--vaadin-popover-offset-end, 0);
84+
}
85+
86+
/* top / bottom position */
87+
:host([theme~='arrow'][position^='top']) [part='arrow'],
88+
:host([theme~='arrow'][position^='bottom']) [part='arrow'] {
89+
border-left: var(--vaadin-popover-arrow-size) solid transparent;
90+
border-right: var(--vaadin-popover-arrow-size) solid transparent;
91+
}
92+
93+
:host([theme~='arrow'][position^='bottom'][bottom-aligned]) [part='arrow'],
94+
:host([theme~='arrow'][position^='top'][bottom-aligned]) [part='arrow'] {
95+
bottom: calc(var(--vaadin-popover-arrow-size) * -1);
96+
border-top: var(--vaadin-popover-arrow-size) solid var(--lumo-base-color);
97+
filter: drop-shadow(0 2px 1px var(--lumo-shade-10pct));
98+
}
99+
100+
:host([theme~='arrow'][position^='bottom'][top-aligned]) [part='arrow'],
101+
:host([theme~='arrow'][position^='top'][top-aligned]) [part='arrow'] {
102+
top: calc(var(--vaadin-popover-arrow-size) * -1);
103+
border-bottom: var(--vaadin-popover-arrow-size) solid var(--lumo-base-color);
104+
filter: drop-shadow(0 -2px 1px var(--lumo-shade-10pct));
105+
}
106+
107+
:host([theme~='arrow'][position^='bottom'][start-aligned]) [part='arrow'],
108+
:host([theme~='arrow'][position^='top'][start-aligned]) [part='arrow'] {
109+
transform: translateX(-50%);
110+
inset-inline-start: 1.5rem;
111+
}
112+
113+
:host([theme~='arrow'][position^='bottom'][end-aligned]) [part='arrow'],
114+
:host([theme~='arrow'][position^='top'][end-aligned]) [part='arrow'] {
115+
transform: translateX(50%);
116+
inset-inline-end: 1.5rem;
117+
}
118+
119+
:host([theme~='arrow'][position^='bottom'][arrow-centered]) [part='arrow'],
120+
:host([theme~='arrow'][position^='top'][arrow-centered]) [part='arrow'] {
121+
transform: translateX(-50%);
122+
inset-inline-start: 50%;
123+
}
124+
125+
/* start / end position */
126+
:host([theme~='arrow'][position^='start']) [part='arrow'],
127+
:host([theme~='arrow'][position^='end']) [part='arrow'] {
128+
border-top: var(--vaadin-popover-arrow-size) solid transparent;
129+
border-bottom: var(--vaadin-popover-arrow-size) solid transparent;
130+
}
131+
132+
:host([theme~='arrow'][position^='start'][start-aligned]) [part='arrow'],
133+
:host([theme~='arrow'][position^='end'][start-aligned]) [part='arrow'] {
134+
inset-inline-start: calc(var(--vaadin-popover-arrow-size) * -1);
135+
border-right: var(--vaadin-popover-arrow-size) solid var(--lumo-base-color);
136+
filter: drop-shadow(-2px 0 1px var(--lumo-shade-10pct));
137+
}
138+
139+
:host([theme~='arrow'][position^='start'][end-aligned]) [part='arrow'],
140+
:host([theme~='arrow'][position^='end'][end-aligned]) [part='arrow'] {
141+
inset-inline-end: calc(var(--vaadin-popover-arrow-size) * -1);
142+
border-left: var(--vaadin-popover-arrow-size) solid var(--lumo-base-color);
143+
filter: drop-shadow(2px 0 1px var(--lumo-shade-10pct));
144+
}
145+
146+
:host([theme~='arrow'][position^='start'][top-aligned]) [part='arrow'],
147+
:host([theme~='arrow'][position^='end'][top-aligned]) [part='arrow'] {
148+
top: 0.5rem;
149+
}
150+
151+
:host([theme~='arrow'][position='start'][top-aligned]) [part='arrow'],
152+
:host([theme~='arrow'][position='end'][top-aligned]) [part='arrow'] {
153+
top: 50%;
154+
transform: translateY(-50%);
155+
}
156+
157+
:host([theme~='arrow'][position^='start'][bottom-aligned]) [part='arrow'],
158+
:host([theme~='arrow'][position^='end'][bottom-aligned]) [part='arrow'] {
159+
bottom: 0.5rem;
160+
}

0 commit comments

Comments
 (0)