Write steps, start implemenation of search input component

This commit is contained in:
Matt Rider 2019-02-02 17:22:40 -02:00
parent 049fa2893b
commit f09d3ed685
4 changed files with 204 additions and 3 deletions

179
components/SearchInput.vue Normal file
View File

@ -0,0 +1,179 @@
<template>
<div
class="search"
aria-label="search"
role="search"
:class="{ 'is-active': isActive }"
>
<div class="field">
<div class="control has-icons-left has-icons-right">
<input
:id="id"
ref="input"
v-model="searchValue"
v-focus="focus"
class="input"
name="search"
type="text"
placeholder="Search..."
@keyup.exact="onInput"
@keyup.enter="onEnter"
>
</div>
</div>
</div>
</template>
<script>
import { isEmpty } from 'lodash'
export default {
name: 'HcSearchInput',
props: {
id: {
type: String,
default: 'nav-search'
},
value: {
type: String,
default: ''
},
delay: {
type: Number,
default: 700
},
focus: {
type: Boolean,
default: false
}
},
data() {
return {
searchValue: '',
searchProcess: null,
searching: false
}
},
computed: {
isActive() {
return !isEmpty(this.searchValue)
}
},
watch: {
value(value) {
this.$nextTick(() => {
this.updateValue()
})
}
},
mounted() {
this.updateValue()
},
methods: {
updateValue() {
if (!this.value) {
this.searchValue = ''
} else if (this.value.toString() !== this.searchValue.toString()) {
this.searchValue = this.value.toString()
}
},
onInput() {
clearTimeout(this.searchProcess)
this.searching = true
// skip on less then three letters
if (this.searchValue && this.searchValue.toString().length < 3) {
return
}
// skip if nothing changed
if (this.searchValue === this.value) {
return
}
this.searchProcess = setTimeout(() => {
this.searching = false
this.$emit('search', this.searchValue.toString())
}, this.delay)
},
onEnter() {
clearTimeout(this.searchProcess)
this.$nextTick(() => {
clearTimeout(this.searchProcess)
})
this.searching = false
this.$emit('search', this.searchValue.toString())
},
clear() {
clearTimeout(this.searchProcess)
this.searching = false
this.searchValue = ''
if (this.value !== this.searchValue) {
this.$emit('search', '')
}
}
}
}
</script>
<style lang="scss" scoped>
.search {
display: flex;
width: 100%;
position: relative;
.field {
width: 100%;
display: flex;
align-items: center;
}
.control {
width: 100%;
input {
width: 100%;
border-radius: 2px;
height: 2.5em;
padding-left: 2em;
padding-right: 1em;
font-size: 1em;
transition-duration: 0.15s;
transition-timing-function: ease-out;
transition-property: border, background-color;
& {
border-color: hsl(0, 0%, 96%);
}
}
}
input {
padding-right: 2em !important;
background-color: hsl(0, 0%, 96%);
}
input:hover {
background-color: hsl(0, 0%, 98%);
}
input:focus,
&.is-active input.input {
background-color: hsl(0, 0%, 98%);
}
.icon {
height: 2.5em;
font-size: 1em;
&.btn-clear {
position: absolute;
right: 0.25rem;
cursor: pointer !important;
z-index: 10;
padding-left: 1em;
padding-right: 1em;
}
}
&.is-active .icon {
color: hsl(0, 0%, 71%);
}
}
</style>

View File

@ -10,5 +10,5 @@ Feature: Search
Scenario: Search for specific words Scenario: Search for specific words
Given I am logged in as "user" Given I am logged in as "user"
And I search for a specific word When I search for a specific word
Then I should posts with that word included Then I should see posts with that word included

View File

@ -0,0 +1,11 @@
import { When, Then } from 'cypress-cucumber-preprocessor/steps'
When('I search for a specific word', () => {
cy.get('#nav-search').type('Essays')
})
Then('I should see posts with that word included', () => {
cy.get('.ds-card-header:first').then(() => {
cy.title().should('include', 'Essays')
})
})

View File

@ -10,6 +10,9 @@
<ds-logo /> <ds-logo />
</a> </a>
</div> </div>
<div class="main-navigation-center hc-navbar-search">
<search-input />
</div>
<div class="main-navigation-right"> <div class="main-navigation-right">
<no-ssr> <no-ssr>
<locale-switch <locale-switch
@ -105,6 +108,7 @@
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import LocaleSwitch from '~/components/LocaleSwitch' import LocaleSwitch from '~/components/LocaleSwitch'
import Dropdown from '~/components/Dropdown' import Dropdown from '~/components/Dropdown'
import SearchInput from '~/components/SearchInput.vue'
import ReportModal from '~/components/ReportModal' import ReportModal from '~/components/ReportModal'
import seo from '~/components/mixins/seo' import seo from '~/components/mixins/seo'
@ -112,7 +116,8 @@ export default {
components: { components: {
Dropdown, Dropdown,
ReportModal, ReportModal,
LocaleSwitch LocaleSwitch,
SearchInput
}, },
mixins: [seo], mixins: [seo],
computed: { computed: {
@ -183,6 +188,12 @@ export default {
display: flex; display: flex;
margin-right: auto; margin-right: auto;
} }
.main-navigation-center {
display: flex;
margin-right: auto;
}
.main-navigation-right { .main-navigation-right {
display: flex; display: flex;
margin-left: auto; margin-left: auto;