1<template> 2 <div class="search-global"> 3 <b-form-group 4 :label="$t('global.form.search')" 5 :label-for="`searchInput-${uid}`" 6 label-class="invisible" 7 class="mb-2" 8 > 9 <b-input-group size="md" class="align-items-center"> 10 <template #prepend> 11 <b-input-group-text> 12 <icon-search class="search-icon" /> 13 </b-input-group-text> 14 </template> 15 <b-form-input 16 :id="`searchInput-${uid}`" 17 ref="searchInput" 18 v-model="filter" 19 class="search-input" 20 type="text" 21 :aria-label="$t('global.form.search')" 22 :placeholder="placeholder" 23 @input="onChangeInput" 24 > 25 </b-form-input> 26 <b-button 27 v-if="filter" 28 variant="link" 29 class="btn-icon-only input-action-btn" 30 :title="$t('global.ariaLabel.clearSearch')" 31 @click="onClearSearch" 32 > 33 <icon-close /> 34 <span class="visually-hidden"> 35 {{ $t('global.ariaLabel.clearSearch') }} 36 </span> 37 </b-button> 38 </b-input-group> 39 </b-form-group> 40 </div> 41</template> 42 43<script> 44import IconSearch from '@carbon/icons-vue/es/search/16'; 45import IconClose from '@carbon/icons-vue/es/close/20'; 46import { useI18n } from 'vue-i18n'; 47import i18n from '@/i18n'; 48 49export default { 50 name: 'Search', 51 components: { IconSearch, IconClose }, 52 props: { 53 placeholder: { 54 type: String, 55 default: function () { 56 return i18n.global.t('global.form.search'); 57 }, 58 }, 59 }, 60 emits: ['change-search', 'clear-search'], 61 data() { 62 return { 63 $t: useI18n().t, 64 filter: null, 65 uid: Math.random().toString(36).slice(2), 66 }; 67 }, 68 methods: { 69 onChangeInput() { 70 this.$emit('change-search', this.filter); 71 }, 72 onClearSearch() { 73 this.filter = ''; 74 this.$emit('clear-search'); 75 const input = this.$refs.searchInput; 76 if (input && typeof input.focus === 'function') input.focus(); 77 }, 78 }, 79}; 80</script> 81 82<style lang="scss" scoped> 83.search-icon { 84 stroke: $gray-400; 85} 86</style> 87