From 9c4fd06452849235f2f7933b27b03fe66693aa9a Mon Sep 17 00:00:00 2001 From: Diego Cardoso Date: Wed, 19 Jun 2024 10:04:49 +0300 Subject: [PATCH] feat: add no-vertical-overlap prop to vaadin-select (#7492) Add a property to `vaadin-select` called `noVerticalOverlap` which forwards its value to the same property present in the Overlay, to allow users to configure whether they want the overlay to overlap the input container (default) or not. Part of #5101 --- packages/select/src/vaadin-lit-select.js | 1 + .../select/src/vaadin-select-base-mixin.d.ts | 8 +++++ .../select/src/vaadin-select-base-mixin.js | 11 +++++++ packages/select/src/vaadin-select.js | 1 + packages/select/test/select.common.js | 29 +++++++++++++++++++ .../select/theme/lumo/vaadin-select-styles.js | 8 +++++ 6 files changed, 58 insertions(+) diff --git a/packages/select/src/vaadin-lit-select.js b/packages/select/src/vaadin-lit-select.js index 8407eeccc4..43556bfdde 100644 --- a/packages/select/src/vaadin-lit-select.js +++ b/packages/select/src/vaadin-lit-select.js @@ -90,6 +90,7 @@ class Select extends SelectBaseMixin(ElementMixin(ThemableMixin(PolylitMixin(Lit .renderer="${this.renderer || this.__defaultRenderer}" ?phone="${this._phone}" theme="${this._theme}" + ?no-vertical-overlap="${this.noVerticalOverlap}" @opened-changed="${this._onOpenedChanged}" @vaadin-overlay-open="${this._onOverlayOpen}" > diff --git a/packages/select/src/vaadin-select-base-mixin.d.ts b/packages/select/src/vaadin-select-base-mixin.d.ts index 135a5919e7..f8250ba8ca 100644 --- a/packages/select/src/vaadin-select-base-mixin.d.ts +++ b/packages/select/src/vaadin-select-base-mixin.d.ts @@ -102,6 +102,14 @@ export declare class SelectBaseMixinClass { */ readonly: boolean; + /** + * Defines whether the overlay should overlap the target element + * in the y-axis, or be positioned right above/below it. + * + * @attr {boolean} no-vertical-overlap + */ + noVerticalOverlap: boolean; + /** * Requests an update for the content of the select. * While performing the update, it invokes the renderer passed in the `renderer` property. diff --git a/packages/select/src/vaadin-select-base-mixin.js b/packages/select/src/vaadin-select-base-mixin.js index 4a033635b1..73a3411536 100644 --- a/packages/select/src/vaadin-select-base-mixin.js +++ b/packages/select/src/vaadin-select-base-mixin.js @@ -127,6 +127,17 @@ export const SelectBaseMixin = (superClass) => reflectToAttribute: true, }, + /** + * Defines whether the overlay should overlap the target element + * in the y-axis, or be positioned right above/below it. + * + * @attr {boolean} no-vertical-overlap + */ + noVerticalOverlap: { + type: Boolean, + value: false, + }, + /** @private */ _phone: Boolean, diff --git a/packages/select/src/vaadin-select.js b/packages/select/src/vaadin-select.js index b2f868e3a5..352ed54327 100644 --- a/packages/select/src/vaadin-select.js +++ b/packages/select/src/vaadin-select.js @@ -184,6 +184,7 @@ class Select extends SelectBaseMixin(ElementMixin(ThemableMixin(PolymerElement)) with-backdrop="[[_phone]]" phone$="[[_phone]]" theme$="[[_theme]]" + no-vertical-overlap$="[[noVerticalOverlap]]" on-vaadin-overlay-open="_onOverlayOpen" > diff --git a/packages/select/test/select.common.js b/packages/select/test/select.common.js index 56968cd15d..25ef3b0b71 100644 --- a/packages/select/test/select.common.js +++ b/packages/select/test/select.common.js @@ -638,6 +638,35 @@ describe('vaadin-select', () => { expect(changeSpy.callCount).to.equal(1); }); }); + + describe('no-vertical-overlap', () => { + it('should overlap the input by default', async () => { + select.opened = true; + await nextUpdate(select); + const overlayRect = select._overlayElement.getBoundingClientRect(); + const inputRect = select._inputContainer.getBoundingClientRect(); + expect(overlayRect.top).to.be.equal(inputRect.top); + }); + + it('should toggle the `no-vertical-overlap` attribute in the overlay element', async () => { + select.noVerticalOverlap = true; + await nextUpdate(select); + expect(select._overlayElement.hasAttribute('no-vertical-overlap')).to.be.true; + + select.noVerticalOverlap = false; + await nextUpdate(select); + expect(select._overlayElement.hasAttribute('no-vertical-overlap')).to.be.false; + }); + + it('should not overlap the input when overlay is opened', async () => { + select.noVerticalOverlap = true; + select.opened = true; + await nextUpdate(select); + const overlayRect = select._overlayElement.getBoundingClientRect(); + const inputRect = select._inputContainer.getBoundingClientRect(); + expect(overlayRect.top).to.be.equal(inputRect.bottom); + }); + }); }); describe('with value', () => { diff --git a/packages/select/theme/lumo/vaadin-select-styles.js b/packages/select/theme/lumo/vaadin-select-styles.js index 8c7596ff1a..3b039f7191 100644 --- a/packages/select/theme/lumo/vaadin-select-styles.js +++ b/packages/select/theme/lumo/vaadin-select-styles.js @@ -110,6 +110,14 @@ const selectOverlay = css` justify-content: flex-end; } + :host([no-vertical-overlap][top-aligned]) [part='overlay'] { + margin-block-start: var(--lumo-space-xs); + } + + :host([no-vertical-overlap][bottom-aligned]) [part='overlay'] { + margin-block-end: var(--lumo-space-xs); + } + :host([theme~='align-left']) { text-align: left; }