-
Notifications
You must be signed in to change notification settings - Fork 83
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement basic popover logic, move mixins from tooltip (#7409)
- Loading branch information
1 parent
d247e95
commit fe73eed
Showing
19 changed files
with
920 additions
and
176 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Popover</title> | ||
<script type="module" src="./common.js"></script> | ||
|
||
<script type="module"> | ||
import '@vaadin/button'; | ||
import '@vaadin/horizontal-layout'; | ||
import '@vaadin/popover'; | ||
import '@vaadin/text-field'; | ||
</script> | ||
</head> | ||
|
||
<body> | ||
<vaadin-button id="button">Discount</vaadin-button> | ||
|
||
<vaadin-popover for="button" position="bottom-start"></vaadin-popover> | ||
|
||
<script type="module"> | ||
const popover = document.querySelector('vaadin-popover'); | ||
|
||
popover.renderer = (root) => { | ||
if (root.firstChild) { | ||
return; | ||
} | ||
|
||
const layout = document.createElement('vaadin-horizontal-layout'); | ||
layout.setAttribute('theme', 'spacing-s'); | ||
layout.style.alignItems = 'baseline'; | ||
|
||
const field = document.createElement('vaadin-text-field'); | ||
field.label = 'Discount code'; | ||
|
||
const button = document.createElement('vaadin-button'); | ||
button.textContent = 'Apply'; | ||
|
||
layout.append(field, button); | ||
|
||
root.append(layout); | ||
}; | ||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/** | ||
* @license | ||
* Copyright (c) 2024 Vaadin Ltd. | ||
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ | ||
*/ | ||
import { css, html, LitElement } from 'lit'; | ||
import { defineCustomElement } from '@vaadin/component-base/src/define.js'; | ||
import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js'; | ||
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js'; | ||
import { overlayStyles } from '@vaadin/overlay/src/vaadin-overlay-styles.js'; | ||
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; | ||
import { PopoverOverlayMixin } from './vaadin-popover-overlay-mixin.js'; | ||
|
||
/** | ||
* An element used internally by `<vaadin-popover>`. Not intended to be used separately. | ||
* | ||
* @customElement | ||
* @extends HTMLElement | ||
* @mixes DirMixin | ||
* @mixes PopoverOverlayMixin | ||
* @mixes ThemableMixin | ||
* @private | ||
*/ | ||
class PopoverOverlay extends PopoverOverlayMixin(DirMixin(ThemableMixin(PolylitMixin(LitElement)))) { | ||
static get is() { | ||
return 'vaadin-popover-overlay'; | ||
} | ||
|
||
static get styles() { | ||
return [ | ||
overlayStyles, | ||
css` | ||
:host([position^='top'][top-aligned]) [part='overlay'], | ||
:host([position^='bottom'][top-aligned]) [part='overlay'] { | ||
margin-top: var(--vaadin-popover-offset-top, 0); | ||
} | ||
:host([position^='top'][bottom-aligned]) [part='overlay'], | ||
:host([position^='bottom'][bottom-aligned]) [part='overlay'] { | ||
margin-bottom: var(--vaadin-popover-offset-bottom, 0); | ||
} | ||
:host([position^='start'][start-aligned]) [part='overlay'], | ||
:host([position^='end'][start-aligned]) [part='overlay'] { | ||
margin-inline-start: var(--vaadin-popover-offset-start, 0); | ||
} | ||
:host([position^='start'][end-aligned]) [part='overlay'], | ||
:host([position^='end'][end-aligned]) [part='overlay'] { | ||
margin-inline-end: var(--vaadin-popover-offset-end, 0); | ||
} | ||
`, | ||
]; | ||
} | ||
|
||
/** @protected */ | ||
render() { | ||
return html` | ||
<div id="backdrop" part="backdrop" hidden ?hidden="${!this.withBackdrop}"></div> | ||
<div part="overlay" id="overlay"> | ||
<div part="content" id="content"><slot></slot></div> | ||
</div> | ||
`; | ||
} | ||
} | ||
|
||
defineCustomElement(PopoverOverlay); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/** | ||
* @license | ||
* Copyright (c) 2024 Vaadin Ltd. | ||
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ | ||
*/ | ||
import type { Constructor } from '@open-wc/dedupe-mixin'; | ||
|
||
export type PopoverPosition = | ||
| 'bottom-end' | ||
| 'bottom-start' | ||
| 'bottom' | ||
| 'end-bottom' | ||
| 'end-top' | ||
| 'end' | ||
| 'start-bottom' | ||
| 'start-top' | ||
| 'start' | ||
| 'top-end' | ||
| 'top-start' | ||
| 'top'; | ||
|
||
/** | ||
* A mixin providing popover position functionality. | ||
*/ | ||
export declare function PopoverPositionMixin<T extends Constructor<HTMLElement>>( | ||
base: T, | ||
): Constructor<PopoverPositionMixinClass> & T; | ||
|
||
export declare class PopoverPositionMixinClass { | ||
/** | ||
* Position of the overlay with respect to the target. | ||
* Supported values: `top-start`, `top`, `top-end`, | ||
* `bottom-start`, `bottom`, `bottom-end`, `start-top`, | ||
* `start`, `start-bottom`, `end-top`, `end`, `end-bottom`. | ||
*/ | ||
position: PopoverPosition; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/** | ||
* @license | ||
* Copyright (c) 2024 Vaadin Ltd. | ||
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ | ||
*/ | ||
|
||
/** | ||
* A mixin providing popover position functionality. | ||
* | ||
* @polymerMixin | ||
*/ | ||
export const PopoverPositionMixin = (superClass) => | ||
class PopoverPositionMixinClass extends superClass { | ||
static get properties() { | ||
return { | ||
/** | ||
* Position of the overlay with respect to the target. | ||
* Supported values: `top-start`, `top`, `top-end`, | ||
* `bottom-start`, `bottom`, `bottom-end`, `start-top`, | ||
* `start`, `start-bottom`, `end-top`, `end`, `end-bottom`. | ||
*/ | ||
position: { | ||
type: String, | ||
}, | ||
|
||
/** | ||
* Default value used when `position` property is not set. | ||
* @protected | ||
*/ | ||
_position: { | ||
type: String, | ||
value: 'bottom', | ||
}, | ||
|
||
/** @private */ | ||
__effectivePosition: { | ||
type: String, | ||
computed: '__computePosition(position, _position)', | ||
}, | ||
}; | ||
} | ||
|
||
/** @protected */ | ||
__computeHorizontalAlign(position) { | ||
return ['top-end', 'bottom-end', 'start-top', 'start', 'start-bottom'].includes(position) ? 'end' : 'start'; | ||
} | ||
|
||
/** @protected */ | ||
__computeNoHorizontalOverlap(position) { | ||
return ['start-top', 'start', 'start-bottom', 'end-top', 'end', 'end-bottom'].includes(position); | ||
} | ||
|
||
/** @protected */ | ||
__computeNoVerticalOverlap(position) { | ||
return ['top-start', 'top-end', 'top', 'bottom-start', 'bottom', 'bottom-end'].includes(position); | ||
} | ||
|
||
/** @protected */ | ||
__computeVerticalAlign(position) { | ||
return ['top-start', 'top-end', 'top', 'start-bottom', 'end-bottom'].includes(position) ? 'bottom' : 'top'; | ||
} | ||
|
||
/** @private */ | ||
__computePosition(position, defaultPosition) { | ||
return position || defaultPosition; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/** | ||
* @license | ||
* Copyright (c) 2024 Vaadin Ltd. | ||
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ | ||
*/ | ||
import type { Constructor } from '@open-wc/dedupe-mixin'; | ||
|
||
/** | ||
* A mixin providing popover target functionality. | ||
*/ | ||
export declare function PopoverTargetMixin<T extends Constructor<HTMLElement>>( | ||
base: T, | ||
): Constructor<PopoverTargetMixinClass> & T; | ||
|
||
export declare class PopoverTargetMixinClass { | ||
/** | ||
* The id of the element to be used as `target` value. | ||
* The element should be in the DOM by the time when | ||
* the attribute is set, otherwise a warning is shown. | ||
*/ | ||
for: string | undefined; | ||
|
||
/** | ||
* Reference to the DOM element used both to trigger the overlay | ||
* by user interaction and to visually position it on the screen. | ||
* | ||
* Defaults to an element referenced with `for` attribute, in | ||
* which case it must be located in the same shadow scope. | ||
*/ | ||
target: HTMLElement | undefined; | ||
|
||
protected _addTargetListeners(target: HTMLElement): void; | ||
|
||
protected _removeTargetListeners(target: HTMLElement): void; | ||
} |
Oops, something went wrong.