Skip to content

Commit

Permalink
feat(ld-select): implement scrollable options container
Browse files Browse the repository at this point in the history
  • Loading branch information
borisdiakur committed Jul 1, 2021
1 parent f52f1c1 commit a3b2ab0
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 59 deletions.
6 changes: 0 additions & 6 deletions src/liquid/components/ld-option/ld-option.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,12 @@
-webkit-touch-callout: none;

[data-popper-placement*='bottom'] & {
&:first-of-type {
border-top: solid var(--ld-col-rblck1) 1px;
}
&:last-of-type {
border-bottom-left-radius: var(--ld-br-m);
border-bottom-right-radius: var(--ld-br-m);
}
}
[data-popper-placement*='top'] & {
&:last-of-type {
border-bottom: solid var(--ld-col-rblck1) 1px;
}
&:first-of-type {
border-top-left-radius: var(--ld-br-m);
border-top-right-radius: var(--ld-br-m);
Expand Down
23 changes: 22 additions & 1 deletion src/liquid/components/ld-select/ld-select.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.ld-select {
--ld-select-popper-max-height: 16rem;
display: inline-flex;
}

Expand All @@ -19,11 +20,14 @@
user-select: none;
touch-action: manipulation;
background-color: var(--ld-col-wht);
box-shadow: inset 0 0 0 0.1rem var(--ld-col-rblck1);
line-height: 1;
text-align: left;
-webkit-touch-callout: none;

&:where([aria-expanded='false']) {
box-shadow: inset 0 0 0 0.1rem var(--ld-col-rblck1);
}

&:where(:disabled),
&:where([aria-disabled]) {
opacity: 0.2;
Expand Down Expand Up @@ -89,6 +93,11 @@
position: absolute;
}

.ld-select__scroll-container {
max-height: var(--ld-select-popper-max-height);
overflow-y: auto;
}

.ld-select__popper--expanded {
visibility: inherit;

Expand All @@ -108,10 +117,22 @@
&:after {
bottom: 0;
}

.ld-select__scroll-container {
border-top: solid var(--ld-col-rblck1) 1px;
border-bottom-left-radius: var(--ld-br-m);
border-bottom-right-radius: var(--ld-br-m);
}
}
&[data-popper-placement*='top'] {
&:after {
top: 0;
}

.ld-select__scroll-container {
border-bottom: solid var(--ld-col-rblck1) 1px;
border-top-left-radius: var(--ld-br-m);
border-top-right-radius: var(--ld-br-m);
}
}
}
119 changes: 67 additions & 52 deletions src/liquid/components/ld-select/ld-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export class LdSelect {
private selectRef!: HTMLElement
private triggerRef!: HTMLElement
private popperRef!: HTMLElement
private scrollContainerRef!: HTMLElement
private popper: PopperInstance
private observer: MutationObserver

Expand Down Expand Up @@ -80,6 +81,7 @@ export class LdSelect {
this.popper = createPopper<StrictModifiers>(
this.selectRef,
this.popperRef,
// portal,
{
modifiers: [preventOverflow, flip /*, offset*/],
placement: 'bottom-start',
Expand All @@ -89,7 +91,7 @@ export class LdSelect {
}

private initOptions() {
const children = this.popperRef.children
const children = this.scrollContainerRef.children
if (!children.length) {
throw new TypeError(
`ld-select requires at least one ld-option element as a child, but found none.`
Expand All @@ -114,7 +116,6 @@ export class LdSelect {
}

private togglePopper() {
console.info('toggle popper')
this.expanded = !this.expanded

if (this.expanded) {
Expand Down Expand Up @@ -149,12 +150,59 @@ export class LdSelect {
this.initOptions()
}

private expandAndFocus() {
this.handleTriggerClick()
setTimeout(() => {
// If selected in single select mode, focus selected
let optionToFocus
if (!this.multiple) {
optionToFocus = this.popperRef.querySelector(
'ld-option[aria-selected="true"]'
)
}
if (!optionToFocus) {
optionToFocus = this.triggerRef
}
optionToFocus.focus()
})
}

private handleHome(ev) {
// Move focus to the first option.
if (this.expanded) {
ev.preventDefault()
if (this.popperRef.dataset.popperPlacement.includes('top')) {
this.popperRef.querySelector('ld-option')?.focus()
} else {
this.triggerRef.focus()
}
}
}

private handleEnd(ev) {
// Move focus to the last option.
if (this.expanded) {
ev.preventDefault()
if (this.popperRef.dataset.popperPlacement.includes('top')) {
this.triggerRef.focus()
} else {
const options = this.popperRef.querySelectorAll('ld-option')
options[options.length - 1]?.focus()
}
}
}

private handleKeyDown(ev: KeyboardEvent) {
switch (ev.key) {
case 'ArrowDown': {
// Move focus to the next option.
ev.preventDefault()
if (this.expanded) {
if (ev.metaKey) {
this.handleEnd(ev)
return
}

if (document.activeElement.nextElementSibling) {
;(document.activeElement.nextElementSibling as HTMLElement)?.focus()
} else {
Expand All @@ -165,27 +213,19 @@ export class LdSelect {
}
}
} else {
this.handleTriggerClick()
setTimeout(() => {
// If selected in single select mode, focus selected
let optionToFocus
if (!this.multiple) {
optionToFocus = this.popperRef.querySelector(
'ld-option[aria-selected="true"]'
)
}
if (!optionToFocus) {
optionToFocus = this.triggerRef
}
optionToFocus.focus()
})
this.expandAndFocus()
}
break
}
case 'ArrowUp':
// Move focus to the previous option.
ev.preventDefault()
if (this.expanded) {
if (ev.metaKey) {
this.handleHome(ev)
return
}

if (document.activeElement.previousElementSibling) {
;(document.activeElement
.previousElementSibling as HTMLElement)?.focus()
Expand All @@ -200,44 +240,14 @@ export class LdSelect {
}
}
} else {
this.handleTriggerClick()
setTimeout(() => {
// If selected in single select mode, focus selected
let optionToFocus
if (!this.multiple) {
optionToFocus = this.popperRef.querySelector(
'ld-option[aria-selected="true"]'
)
}
if (!optionToFocus) {
optionToFocus = this.triggerRef
}
optionToFocus.focus()
})
this.expandAndFocus()
}
break
case 'Home':
// Move focus to the first option.
if (this.expanded) {
ev.preventDefault()
if (this.popperRef.dataset.popperPlacement.includes('top')) {
this.popperRef.querySelector('ld-option')?.focus()
} else {
this.triggerRef.focus()
}
}
this.handleHome(ev)
break
case 'End':
// Move focus to the last option.
if (this.expanded) {
ev.preventDefault()
if (this.popperRef.dataset.popperPlacement.includes('top')) {
this.triggerRef.focus()
} else {
const options = this.popperRef.querySelectorAll('ld-option')
options[options.length - 1]?.focus()
}
}
this.handleEnd(ev)
break
case ' ':
// If expanded: Select focused option, close (if single select).
Expand Down Expand Up @@ -356,13 +366,18 @@ export class LdSelect {
this.placeholder}
</button>
</div>
<ul
<div
role="listbox"
class={popperCl}
ref={(el) => (this.popperRef = el as HTMLElement)}
>
<slot></slot>
</ul>
<div
ref={(el) => (this.scrollContainerRef = el as HTMLElement)}
class="ld-select__scroll-container"
>
<slot></slot>
</div>
</div>
</Host>
)
}
Expand Down
19 changes: 19 additions & 0 deletions src/liquid/components/ld-select/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ permalink: components/ld-select/
<ld-option value="banana">Banana</ld-option>
<ld-option value="strawberry">Strawberry</ld-option>
<ld-option value="watermelon" disabled>Watermelon</ld-option>
<ld-option value="honeymelon">Honeymelon</ld-option>
<ld-option value="rasberry">Rasberry</ld-option>
<ld-option value="cherry">Cherry</ld-option>
<ld-option value="blueberry">Blueberry</ld-option>
<ld-option value="peach">Peach</ld-option>
<ld-option value="grape">Grape</ld-option>
<ld-option value="pear">Pear</ld-option>
<ld-option value="pineapple">Pineapple</ld-option>
<ld-option value="plum">Plum</ld-option>
</ld-select>
{% endexample %}

Expand All @@ -31,6 +40,16 @@ permalink: components/ld-select/
<ld-option value="apple">Apple</ld-option>
<ld-option value="banana">Banana</ld-option>
<ld-option value="strawberry">Strawberry</ld-option>
<ld-option value="watermelon" disabled>Watermelon</ld-option>
<ld-option value="honeymelon">Honeymelon</ld-option>
<ld-option value="rasberry">Rasberry</ld-option>
<ld-option value="cherry">Cherry</ld-option>
<ld-option value="blueberry">Blueberry</ld-option>
<ld-option value="peach">Peach</ld-option>
<ld-option value="grape">Grape</ld-option>
<ld-option value="pear">Pear</ld-option>
<ld-option value="pineapple">Pineapple</ld-option>
<ld-option value="plum">Plum</ld-option>
</ld-select>
{% endexample %}

Expand Down

0 comments on commit a3b2ab0

Please sign in to comment.