From 77abd42d6642bd5c21b6c133ee2012a7ad6ad24e Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Tue, 28 Feb 2023 12:30:05 -0500 Subject: [PATCH] fix popup positioning edge case; closes #1135 --- docs/resources/changelog.md | 2 ++ package-lock.json | 41 ++++++++++++++++++++++------------- package.json | 3 ++- src/components/popup/popup.ts | 23 ++++++++++++++++---- 4 files changed, 49 insertions(+), 20 deletions(-) diff --git a/docs/resources/changelog.md b/docs/resources/changelog.md index f90d92fe..982d5e27 100644 --- a/docs/resources/changelog.md +++ b/docs/resources/changelog.md @@ -19,7 +19,9 @@ New versions of Shoelace are released as-needed and generally occur when a criti - Fixed a bug in `` that caused `--track-color` to be invisible with certain colors - Fixed a bug in `` that caused the focus color to show when selecting menu items with a mouse or touch device - Fixed a bug in `` that caused `sl-change` and `sl-input` to be emitted too early [#1201](https://github.com/shoelace-style/shoelace/issues/1201) +- Fixed a positioning edge case that caused `` to positioned nested popups incorrectly [#1135](https://github.com/shoelace-style/shoelace/issues/1135) - Updated `@shoelace-style/localize` to 3.1.0 +- Updated `@floating-ui/dom` to 1.2.1 When using `` the default value for `autocapitalize`, `autocomplete`, and `autocorrect` may be affected due to the bug fixed in [#1205](https://github.com/shoelace-style/shoelace/issues/1205). For any affected users, setting these attributes to `off` will restore the previous behavior. diff --git a/package-lock.json b/package-lock.json index ea65b4ee..57c3f7f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,10 +10,11 @@ "license": "MIT", "dependencies": { "@ctrl/tinycolor": "^3.5.0", - "@floating-ui/dom": "^1.1.0", + "@floating-ui/dom": "^1.2.1", "@lit-labs/react": "^1.1.1", "@shoelace-style/animations": "^1.1.0", "@shoelace-style/localize": "^3.1.0", + "composed-offset-position": "^0.0.4", "lit": "^2.6.1", "qr-creator": "^1.0.0" }, @@ -1043,16 +1044,16 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.1.0.tgz", - "integrity": "sha512-zbsLwtnHo84w1Kc8rScAo5GMk1GdecSlrflIbfnEBJwvTSj1SL6kkOYV+nHraMCPEy+RNZZUaZyL8JosDGCtGQ==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.1.tgz", + "integrity": "sha512-LSqwPZkK3rYfD7GKoIeExXOyYx6Q1O4iqZWwIehDNuv3Dv425FIAE8PRwtAx1imEolFTHgBEcoFHm9MDnYgPCg==" }, "node_modules/@floating-ui/dom": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.1.0.tgz", - "integrity": "sha512-TSogMPVxbRe77QCj1dt8NmRiJasPvuc+eT5jnJ6YpLqgOD2zXc5UA3S1qwybN+GVCDNdKfpKy1oj8RpzLJvh6A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.1.tgz", + "integrity": "sha512-Rt45SmRiV8eU+xXSB9t0uMYiQ/ZWGE/jumse2o3i5RGlyvcbqOF4q+1qBnzLE2kZ5JGhq0iMkcGXUKbFe7MpTA==", "dependencies": { - "@floating-ui/core": "^1.0.5" + "@floating-ui/core": "^1.2.1" } }, "node_modules/@gar/promisify": { @@ -4523,6 +4524,11 @@ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", "dev": true }, + "node_modules/composed-offset-position": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/composed-offset-position/-/composed-offset-position-0.0.4.tgz", + "integrity": "sha512-vMlvu1RuNegVE0YsCDSV/X4X10j56mq7PCIyOKK74FxkXzGLwhOUmdkJLSdOBOMwWycobGUMgft2lp+YgTe8hw==" + }, "node_modules/compress-brotli": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/compress-brotli/-/compress-brotli-1.3.8.tgz", @@ -16270,16 +16276,16 @@ } }, "@floating-ui/core": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.1.0.tgz", - "integrity": "sha512-zbsLwtnHo84w1Kc8rScAo5GMk1GdecSlrflIbfnEBJwvTSj1SL6kkOYV+nHraMCPEy+RNZZUaZyL8JosDGCtGQ==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.1.tgz", + "integrity": "sha512-LSqwPZkK3rYfD7GKoIeExXOyYx6Q1O4iqZWwIehDNuv3Dv425FIAE8PRwtAx1imEolFTHgBEcoFHm9MDnYgPCg==" }, "@floating-ui/dom": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.1.0.tgz", - "integrity": "sha512-TSogMPVxbRe77QCj1dt8NmRiJasPvuc+eT5jnJ6YpLqgOD2zXc5UA3S1qwybN+GVCDNdKfpKy1oj8RpzLJvh6A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.1.tgz", + "integrity": "sha512-Rt45SmRiV8eU+xXSB9t0uMYiQ/ZWGE/jumse2o3i5RGlyvcbqOF4q+1qBnzLE2kZ5JGhq0iMkcGXUKbFe7MpTA==", "requires": { - "@floating-ui/core": "^1.0.5" + "@floating-ui/core": "^1.2.1" } }, "@gar/promisify": { @@ -18941,6 +18947,11 @@ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", "dev": true }, + "composed-offset-position": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/composed-offset-position/-/composed-offset-position-0.0.4.tgz", + "integrity": "sha512-vMlvu1RuNegVE0YsCDSV/X4X10j56mq7PCIyOKK74FxkXzGLwhOUmdkJLSdOBOMwWycobGUMgft2lp+YgTe8hw==" + }, "compress-brotli": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/compress-brotli/-/compress-brotli-1.3.8.tgz", diff --git a/package.json b/package.json index 1297ee13..0cf9da79 100644 --- a/package.json +++ b/package.json @@ -63,10 +63,11 @@ }, "dependencies": { "@ctrl/tinycolor": "^3.5.0", - "@floating-ui/dom": "^1.1.0", + "@floating-ui/dom": "^1.2.1", "@lit-labs/react": "^1.1.1", "@shoelace-style/animations": "^1.1.0", "@shoelace-style/localize": "^3.1.0", + "composed-offset-position": "^0.0.4", "lit": "^2.6.1", "qr-creator": "^1.0.0" }, diff --git a/src/components/popup/popup.ts b/src/components/popup/popup.ts index c9e7f4f4..1527e7e4 100644 --- a/src/components/popup/popup.ts +++ b/src/components/popup/popup.ts @@ -1,7 +1,8 @@ -import { arrow, autoUpdate, computePosition, flip, offset, shift, size } from '@floating-ui/dom'; +import { arrow, autoUpdate, computePosition, flip, offset, platform, shift, size } from '@floating-ui/dom'; import { classMap } from 'lit/directives/class-map.js'; import { customElement, property, query } from 'lit/decorators.js'; import { html } from 'lit'; +import { offsetParent } from 'composed-offset-position'; import ShoelaceElement from '../../internal/shoelace-element'; import styles from './popup.styles'; import type { CSSResultGroup } from 'lit'; @@ -76,8 +77,8 @@ export default class SlPopup extends ShoelaceElement { | 'left-end' = 'top'; /** - * Determines how the popup is positioned. The `absolute` strategy works well in most cases, but if - * overflow is clipped, using a `fixed` position strategy can often workaround it. + * Determines how the popup is positioned. The `absolute` strategy works well in most cases, but if overflow is + * clipped, using a `fixed` position strategy can often workaround it. */ @property({ reflect: true }) strategy: 'absolute' | 'fixed' = 'absolute'; @@ -365,10 +366,24 @@ export default class SlPopup extends ShoelaceElement { ); } + // + // Use custom positioning logic if the strategy is absolute. Otherwise, fall back to the default logic. + // + // More info: https://github.com/shoelace-style/shoelace/issues/1135 + // + const getOffsetParent = + this.strategy === 'absolute' + ? (element: Element) => platform.getOffsetParent(element, offsetParent) + : platform.getOffsetParent; + computePosition(this.anchorEl, this.popup, { placement: this.placement, middleware, - strategy: this.strategy + strategy: this.strategy, + platform: { + ...platform, + getOffsetParent + } }).then(({ x, y, middlewareData, placement }) => { // // Even though we have our own localization utility, it uses different heuristics to determine RTL. Because of