Skip to content

Instantly share code, notes, and snippets.

@benhenryhunter
Created August 20, 2020 21:17
Show Gist options
  • Save benhenryhunter/0b50b0a35d43f8fed826ef206d57b6e5 to your computer and use it in GitHub Desktop.
Save benhenryhunter/0b50b0a35d43f8fed826ef206d57b6e5 to your computer and use it in GitHub Desktop.
<template>
<div
class="custom-select"
:tabindex="tabindex"
@blur="open = false"
>
<label class="label" :class="{error}">
{{ label }}
</label>
<a
v-if="open || selected"
class="close-select"
:class="{withLabel: !!label}"
@click="filter = ''; open = true; $emit('clear')"
>
x
</a>
<input
v-model="filter"
type="text"
class="selected"
:class="{open: open, error}"
:placeholder="placeholder"
@click="open = !open"
@keypress="checkEnter; $emit('keypress', filter)"
@blur="close"
>
</input>
<div
class="items"
:class="{selectHide: !open, withLabel: !!label}"
>
<div
v-for="(option, i) of filteredOptions"
:key="i"
class="item"
:value="option.value"
@click="select(option)"
@mouseover="hover = true"
@mouseleave="hover = false"
>
<p>{{ option.text }}</p>
<span>{{ option.subtext }}</span>
</div>
</div>
</div>
</template>
<script>
import score from 'string-score'
export default {
props: {
options: {
type: Array,
required: true
},
tabindex: {
type: Number,
required: false,
default: 0
},
placeholder: {
type: String,
required: false,
default: ''
},
label: {
type: String,
required: false,
default: ''
},
error: {
type: Boolean,
required: false,
default: false
}
},
data () {
return {
selected: null,
open: false,
filter: '',
filteredOptions: [],
hover: false
}
},
watch: {
filter () {
if (this.filter === '') {
this.filteredOptions = this.options
return
}
this.filteredOptions = this.options.filter(option =>
score(option.text, this.filter) > 0.3)
},
options () {
if (this.filter === '') {
this.filteredOptions = this.options
return
}
this.filteredOptions = this.options.filter(option =>
score(option.text, this.filter) > 0.7)
}
},
mounted () {
this.filteredOptions = this.options
this.$emit('input', this.selected)
},
methods: {
filterResults () {
this.options = this.options.filter(option =>
score(option.text, this.filter) > 0.7
)
},
checkEnter (e) {
if (e.keyCode === 13) {
this.select(this.filteredOptions[0])
}
},
select (option) {
this.filter = option.text
this.selected = option
this.open = false
this.$emit('input', option)
},
close () {
if (!this.hover) {
this.open = false
}
}
}
}
</script>
<style scoped>
.label {
font-size: 16px;
font-weight: 600;
}
a.withLabel {
bottom: 15px;
}
input {
margin: 5px 0px
}
.custom-select {
display: flex;
flex-direction: column;
position: relative;
width: 100%;
text-align: left;
outline: none;
min-height: 47px;
margin: 10px 0px;
}
.selected {
cursor: pointer;
user-select: none;
/* border-radius: 4px; */
}
.selected:after {
position: absolute;
content: "";
top: 22px;
right: 10px;
width: 0;
height: 0;
border: 4px solid transparent;
border-color: #fff transparent transparent transparent;
}
.items {
color: black;
border-radius: 0px 0px 6px 6px;
overflow: hidden;
/* border-right: solid 1px #e7e9eb; */
/* border-left: solid 1px #e7e9eb; */
/* border-bottom: solid 1px #e7e9eb; */
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
position: absolute;
background-color: white;
left: 0;
right: 0;
top:39px;
z-index: 10;
max-height: 250px;
overflow: scroll;
}
.items.withLabel {
top: 58px;
}
.item{
color: black;
padding-left: 8px;
cursor: pointer;
user-select: none;
display: flex;
font-size: 22px;
line-height: 47px;
}
.item p {
font-weight: 500;
}
.item span {
margin-left: auto;
margin-right: 10px;
color: white;;
font-size: 12px;
}
.item:hover{
background-color: #FDD033;
color:black
}
.selectHide {
display: none;
}
.close-select {
position: absolute;
padding: 0px 10px;
right: 5px;
cursor: pointer;
}
input {
border-left: none;
border-right: none;
border-top: none;
height: 35px;
font-size: 18px;
}
input:focus {
outline: none;
}
input.error {
border-bottom: solid 1px red;
}
label.error {
color: red
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment