|
1 | 1 | <template> |
2 | 2 | <div |
| 3 | + class="a-select" |
3 | 4 | :class="{ |
4 | | - 'a-select': true, |
5 | | - [`a-select--behavior-${behavior}`]: behavior != 'default', |
6 | 5 | [`a-select--size-${size}`]: size, |
| 6 | + [`a-select--behavior-${behavior}`]: behavior != 'default', |
7 | 7 | }" |
| 8 | + :tabindex="tabindex" |
| 9 | + @blur="open = false" |
8 | 10 | > |
9 | | - <select |
10 | | - :class="{ |
11 | | - 'a-select__field': true, |
12 | | - }" |
13 | | - v-bind="$attrs" |
14 | | - v-on="$listeners" |
| 11 | + <div |
| 12 | + class="a-select__field" |
| 13 | + :class="{ 'a-select__field--open': open }" |
| 14 | + @click="open = !open" |
15 | 15 | > |
16 | | - <option |
17 | | - v-if="placeholder" |
18 | | - :value="placeholder" |
19 | | - disabled |
20 | | - hidden |
21 | | - selected |
22 | | - > |
23 | | - {{ placeholder }} |
24 | | - </option> |
| 16 | + {{ selected }} |
| 17 | + </div> |
25 | 18 |
|
26 | | - <option |
27 | | - v-for="option in options" |
28 | | - :key="option.value" |
29 | | - :value="option.value" |
| 19 | + <AIcon |
| 20 | + v-if="icon" |
| 21 | + :icon="icon" |
| 22 | + :color="iconColor" |
| 23 | + class="a-select__icon" |
| 24 | + @click.native="open = !open" |
| 25 | + /> |
| 26 | + |
| 27 | + <div |
| 28 | + v-if="options && options.length" |
| 29 | + class="a-select__list-items" |
| 30 | + :class="{ 'a-select__list-items--hide': !open }" |
| 31 | + > |
| 32 | + <div |
| 33 | + v-for="(option, index) of options" |
| 34 | + :key="index" |
| 35 | + class="a-select__item" |
| 36 | + @click=" |
| 37 | + selected = option; |
| 38 | + open = false; |
| 39 | + $emit('input', option); |
| 40 | + " |
30 | 41 | > |
31 | | - {{ option.text }} |
32 | | - </option> |
33 | | - </select> |
| 42 | + {{ option }} |
| 43 | + </div> |
| 44 | + </div> |
34 | 45 | </div> |
35 | 46 | </template> |
36 | 47 |
|
37 | 48 | <script> |
| 49 | +import { AIcon } from '@/components/atoms/a-icon'; |
38 | 50 | import { shouldBeOneOf } from 'vue-prop-validation-helper'; |
39 | 51 |
|
40 | 52 | export default { |
| 53 | + components: { |
| 54 | + AIcon, |
| 55 | + }, |
41 | 56 | props: { |
| 57 | + placeholder: { |
| 58 | + type: String, |
| 59 | + default: null, |
| 60 | + }, |
| 61 | + icon: { |
| 62 | + type: String, |
| 63 | + default: 'fas fa-chevron-down', |
| 64 | + }, |
| 65 | + iconColor: { |
| 66 | + type: String, |
| 67 | + default: 'inherit', |
| 68 | + validator: shouldBeOneOf([ |
| 69 | + 'inherit', |
| 70 | + 'primary', |
| 71 | + 'secondary', |
| 72 | + 'tertiary', |
| 73 | + 'interactive', |
| 74 | + 'grey', |
| 75 | + 'success', |
| 76 | + 'danger', |
| 77 | + 'warn', |
| 78 | + 'info', |
| 79 | + 'inverse', |
| 80 | + ]), |
| 81 | + }, |
42 | 82 | behavior: { |
43 | 83 | type: String, |
44 | 84 | default: 'default', |
45 | 85 | validator: shouldBeOneOf(['default', 'block']), |
46 | 86 | }, |
47 | | - size: { |
48 | | - default: 'medium', |
49 | | - type: String, |
50 | | - validator: shouldBeOneOf(['small', 'medium']), |
51 | | - }, |
52 | 87 | options: { |
53 | | - default() { |
54 | | - return []; |
55 | | - }, |
56 | 88 | type: Array, |
| 89 | + default: () => [], |
57 | 90 | }, |
58 | | - placeholder: { |
59 | | - default: '', |
| 91 | + value: { |
60 | 92 | type: String, |
| 93 | + required: false, |
| 94 | + default: null, |
| 95 | + }, |
| 96 | + tabindex: { |
| 97 | + type: Number, |
| 98 | + required: false, |
| 99 | + default: 0, |
| 100 | + }, |
| 101 | + size: { |
| 102 | + type: String, |
| 103 | + default: 'medium', |
61 | 104 | }, |
62 | 105 | }, |
| 106 | + data() { |
| 107 | + return { |
| 108 | + selected: null, |
| 109 | + open: false, |
| 110 | + }; |
| 111 | + }, |
| 112 | + mounted() { |
| 113 | + this.selected = this.value || this.placeholder; |
| 114 | +
|
| 115 | + this.$emit('input', this.selected); |
| 116 | + }, |
63 | 117 | }; |
64 | 118 | </script> |
65 | 119 |
|
66 | | -<style lang="scss"> |
| 120 | +<style scoped lang="scss"> |
67 | 121 | .a-select { |
68 | 122 | border-radius: var(--border-radius-normal); |
69 | 123 | border: var(--size-micro) solid var(--colors-scale-grey-medium); |
@@ -94,26 +148,71 @@ export default { |
94 | 148 | width: 100%; |
95 | 149 | } |
96 | 150 | } |
| 151 | +} |
97 | 152 |
|
98 | | - &__field { |
99 | | - background-color: var(--colors-original-white); |
100 | | - border-radius: var(--border-radius-normal); |
101 | | - border: none; |
102 | | - color: var(--colors-scale-grey-dark); |
103 | | - flex: 1; |
104 | | - font-family: 'Red Hat Text', sans-serif; |
105 | | - font-weight: 500; |
106 | | - height: 100%; |
107 | | - left: 0; |
108 | | - padding-left: var(--size-medium); |
109 | | - padding-right: var(--size-medium); |
110 | | - top: 0; |
111 | | - transition: background-color 250ms, color 250ms; |
112 | | - width: 100%; |
113 | | - &::placeholder { |
114 | | - color: var(--colors-scale-grey-medium); |
115 | | - font-weight: 500; |
116 | | - } |
| 153 | +.a-select__field { |
| 154 | + align-items: center; |
| 155 | + background-color: var(--colors-original-white); |
| 156 | + border-radius: var(--border-radius-normal); |
| 157 | + border: none; |
| 158 | + color: var(--colors-scale-grey-dark); |
| 159 | + cursor: pointer; |
| 160 | + display: flex; |
| 161 | + flex: 1; |
| 162 | + font-family: 'Red Hat Text', sans-serif; |
| 163 | + font-weight: 500; |
| 164 | + height: 100%; |
| 165 | + left: 0; |
| 166 | + padding-left: var(--size-medium); |
| 167 | + padding-right: var(--size-medium); |
| 168 | + position: relative; |
| 169 | + top: 0; |
| 170 | + transition: background-color 250ms, color 250ms; |
| 171 | + user-select: none; |
| 172 | + width: 100%; |
| 173 | +
|
| 174 | + &--open { |
| 175 | + border: var(--size-nano) solid var(--color-theme-secondary); |
| 176 | + } |
| 177 | +} |
| 178 | +
|
| 179 | +.a-select__icon { |
| 180 | + color: var(--colors-scale-grey-dark); |
| 181 | + position: absolute; |
| 182 | + right: var(--size-extra-small); |
| 183 | + display: flex; |
| 184 | + align-items: center; |
| 185 | + height: 100%; |
| 186 | +} |
| 187 | +
|
| 188 | +.a-select__list-items { |
| 189 | + background-color: var(--colors-original-white); |
| 190 | + border-radius: var(--border-radius-normal); |
| 191 | + border: var(--size-micro) solid var(--color-theme-primary); |
| 192 | + color: var(--color-theme-secondary); |
| 193 | + overflow: hidden; |
| 194 | + position: absolute; |
| 195 | + left: 0; |
| 196 | + right: 0; |
| 197 | + top: 120%; |
| 198 | + z-index: 1; |
| 199 | +} |
| 200 | +
|
| 201 | +.a-select__list-items--hide { |
| 202 | + display: none; |
| 203 | +} |
| 204 | +
|
| 205 | +.a-select__item { |
| 206 | + color: var(--color-theme-secondary); |
| 207 | + padding: var(--size-small) var(--size-medium); |
| 208 | + font-family: 'Red Hat Text', sans-serif; |
| 209 | + font-weight: 500; |
| 210 | + cursor: pointer; |
| 211 | + user-select: none; |
| 212 | +
|
| 213 | + &:hover { |
| 214 | + background-color: var(--colors-scale-grey-light); |
117 | 215 | } |
118 | 216 | } |
| 217 | +
|
119 | 218 | </style> |
0 commit comments