Skip to content

Commit

Permalink
fix(ld-select): use tether in place of popper
Browse files Browse the repository at this point in the history
  • Loading branch information
borisdiakur committed Jul 1, 2021
1 parent a3b2ab0 commit b09e0d2
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 43 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@
"watch:stencil": "stencil build --docs --watch --dev --no-open --config=stencil.config.docs.ts"
},
"dependencies": {
"@popperjs/core": "^2.9.2",
"@stencil/core": "^2.5.1"
"@stencil/core": "^2.5.1",
"tether": "^2.0.0"
},
"license": "SEE LICENSE IN LICENSE.md",
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions src/liquid/components/ld-option/ld-option.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.ld-option {
display: flex;
position: relative;
color: var(--ld-col-rblck-default);
background-color: var(--ld-col-wht);
padding: var(--ld-sp-8) var(--ld-sp-12);
font: var(--ld-typo-label-m);
Expand Down
32 changes: 21 additions & 11 deletions src/liquid/components/ld-select/ld-select.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
.ld-select {
:root {
--ld-select-popper-max-height: 16rem;
}

.ld-select {
display: inline-flex;
}

Expand Down Expand Up @@ -28,6 +31,14 @@
box-shadow: inset 0 0 0 0.1rem var(--ld-col-rblck1);
}

&:where([aria-expanded='true']) {
z-index: 2;

&:not(:focus:focus-visible) {
box-shadow: none;
}
}

&:where(:disabled),
&:where([aria-disabled]) {
opacity: 0.2;
Expand Down Expand Up @@ -76,19 +87,13 @@
}

.ld-select--expanded {
z-index: 2147483647;

.ld-select__btn-trigger {
z-index: 2;

&:not(:focus:focus-visible) {
box-shadow: none;
}
}
z-index: 2147483647; /* Highest possible z-index */
}
.ld-select__popper--expanded {
z-index: 2147483646; /* Highest possible z-index - 1 */
}

.ld-select__popper {
z-index: 1;
visibility: hidden;
position: absolute;
}
Expand All @@ -113,6 +118,8 @@
z-index: -1;
}

&.tether-target-attached-bottom,
&.tether-pinned-top,
&[data-popper-placement*='bottom'] {
&:after {
bottom: 0;
Expand All @@ -124,6 +131,9 @@
border-bottom-right-radius: var(--ld-br-m);
}
}

&.tether-target-attached-top,
&.tether-pinned-bottom,
&[data-popper-placement*='top'] {
&:after {
top: 0;
Expand Down
97 changes: 67 additions & 30 deletions src/liquid/components/ld-select/ld-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,7 @@ import {
State,
Watch,
} from '@stencil/core'
import type {
Instance as PopperInstance,
StrictModifiers,
} from '@popperjs/core'
import { createPopper } from '@popperjs/core/lib/popper-lite.js'
import preventOverflow from '@popperjs/core/lib/modifiers/preventOverflow.js'
import flip from '@popperjs/core/lib/modifiers/flip.js'
// import offset from '@popperjs/core/lib/modifiers/offset.js'
import Tether from 'tether'
import { makeInert, unmakeInert } from '../../utils/makeInert'
import { LdOption } from '../ld-option/ld-option'

Expand All @@ -36,7 +29,7 @@ export class LdSelect {
private triggerRef!: HTMLElement
private popperRef!: HTMLElement
private scrollContainerRef!: HTMLElement
private popper: PopperInstance
private popper: Tether
private observer: MutationObserver

/** Multiselect mode. */
Expand Down Expand Up @@ -72,21 +65,25 @@ export class LdSelect {
}

private updatePopper() {
// offset.options = { offset: [0, -21] }
this.popper.update()
this.popper.position()
this.updatePopperWidth()
}

private initPopper() {
this.popper = createPopper<StrictModifiers>(
this.selectRef,
this.popperRef,
// portal,
{
modifiers: [preventOverflow, flip /*, offset*/],
placement: 'bottom-start',
}
)
this.popper = new Tether({
element: this.popperRef,
target: this.selectRef,
attachment: 'top left',
targetAttachment: 'bottom left',
constraints: [
{
to: 'window',
attachment: 'together none',
pin: true,
},
],
})

this.popperRef.classList.add('ld-select__popper--initialized')
}

Expand Down Expand Up @@ -135,9 +132,16 @@ export class LdSelect {
this.updatePopperWidth()
}

@Listen('ldOptionSelect', { passive: true })
@Listen('ldOptionSelect', { target: 'window', passive: true })
handleSelect(ev: CustomEvent<boolean>) {
if (
(ev.target as HTMLElement).closest('[role="listbox"]') !== this.popperRef
) {
return
}

if (!this.multiple) {
// Deselect currently selected option, if it's not the target option.
Array.from(this.popperRef.querySelectorAll('ld-option')).forEach(
(option) => {
if (option !== (ev.target as HTMLElement).closest('ld-option')) {
Expand Down Expand Up @@ -171,7 +175,10 @@ export class LdSelect {
// Move focus to the first option.
if (this.expanded) {
ev.preventDefault()
if (this.popperRef.dataset.popperPlacement.includes('top')) {
if (
this.popperRef.classList.contains('tether-target-attached-top') ||
this.popperRef.classList.contains('tether-pinned-bottom')
) {
this.popperRef.querySelector('ld-option')?.focus()
} else {
this.triggerRef.focus()
Expand All @@ -183,7 +190,10 @@ export class LdSelect {
// Move focus to the last option.
if (this.expanded) {
ev.preventDefault()
if (this.popperRef.dataset.popperPlacement.includes('top')) {
if (
this.popperRef.classList.contains('tether-target-attached-top') ||
this.popperRef.classList.contains('tether-pinned-bottom')
) {
this.triggerRef.focus()
} else {
const options = this.popperRef.querySelectorAll('ld-option')
Expand All @@ -192,7 +202,15 @@ export class LdSelect {
}
}

private handleKeyDown(ev: KeyboardEvent) {
@Listen('keydown', { passive: false, target: 'window' })
handleKeyDown(ev: KeyboardEvent) {
if (
document.activeElement.closest('[role="listbox"]') !== this.popperRef &&
document.activeElement.closest('ld-select') !== this.el
) {
return
}

switch (ev.key) {
case 'ArrowDown': {
// Move focus to the next option.
Expand All @@ -203,10 +221,18 @@ export class LdSelect {
return
}

if (document.activeElement.nextElementSibling) {
if (
document.activeElement.nextElementSibling &&
document.activeElement.nextElementSibling.classList.contains(
'ld-option'
)
) {
;(document.activeElement.nextElementSibling as HTMLElement)?.focus()
} else {
if (this.popperRef.dataset.popperPlacement.includes('top')) {
if (
this.popperRef.classList.contains('tether-target-attached-top') ||
this.popperRef.classList.contains('tether-pinned-bottom')
) {
this.triggerRef.focus()
} else if (document.activeElement === this.triggerRef) {
this.popperRef.querySelector('ld-option')?.focus()
Expand All @@ -226,11 +252,19 @@ export class LdSelect {
return
}

if (document.activeElement.previousElementSibling) {
if (
document.activeElement.previousElementSibling &&
document.activeElement.previousElementSibling.classList.contains(
'ld-option'
)
) {
;(document.activeElement
.previousElementSibling as HTMLElement)?.focus()
} else {
if (this.popperRef.dataset.popperPlacement.includes('top')) {
if (
this.popperRef.classList.contains('tether-target-attached-top') ||
this.popperRef.classList.contains('tether-pinned-bottom')
) {
if (document.activeElement === this.triggerRef) {
const options = this.popperRef.querySelectorAll('ld-option')
options[options.length - 1]?.focus()
Expand Down Expand Up @@ -312,7 +346,10 @@ export class LdSelect {
passive: true,
})
handleClickOutside(ev) {
if (ev.target.closest('ld-select') !== this.el) {
if (
ev.target.closest('ld-select') !== this.el &&
ev.target.closest('[role="listbox"]') !== this.popperRef
) {
this.expanded = false
}
}
Expand Down Expand Up @@ -348,7 +385,7 @@ export class LdSelect {
if (this.expanded) popperCl += ' ld-select__popper--expanded'

return (
<Host class={cl} onKeyDown={this.handleKeyDown.bind(this)}>
<Host class={cl}>
<div
class="ld-select__select"
ref={(el) => (this.selectRef = el as HTMLElement)}
Expand Down

0 comments on commit b09e0d2

Please sign in to comment.