@citizenplane/pimp 9.4.1 → 9.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,13 @@
1
1
  <template>
2
2
  <div class="cpInput" :class="dynamicClasses" :aria-disabled="isDisabled" @click="focusOnInput">
3
- <base-input-label v-if="label" v-bind-once="{ for: inputIdentifier }">
4
- {{ capitalizedLabel }} <span v-if="isRequired" class="u-asterisk">*</span>
5
- <cp-tooltip v-if="tooltip" :content="tooltip">
6
- <button type="button" class="cpInput__tooltip">
7
- <cp-icon class="cpInput__tooltipIcon" type="tooltip" />
8
- </button>
9
- </cp-tooltip>
3
+ <base-input-label
4
+ v-if="label"
5
+ v-bind-once="{ for: inputIdentifier }"
6
+ :is-invalid="isInputInvalid"
7
+ :tooltip="tooltip"
8
+ :required="isRequired"
9
+ >
10
+ {{ capitalizedLabel }}
10
11
  </base-input-label>
11
12
  <div
12
13
  ref="cpInputContainer"
@@ -17,21 +18,13 @@
17
18
  <cp-icon v-if="isSearch" type="search" />
18
19
  <slot v-else name="leading-icon" />
19
20
  </div>
20
- <transition name="fade-in">
21
- <div
22
- v-if="displayInvalidityIcon"
23
- class="cpInput__icon cpInput__icon--isInvalidity"
24
- :class="iconInvalidityClasses"
25
- >
26
- <cp-icon type="alert-circle" />
27
- </div>
28
- </transition>
29
21
  <input
30
22
  v-model="inputModel"
31
23
  v-bind-once="{ id: inputIdentifier }"
32
24
  v-maska
33
25
  :data-maska="mask"
34
26
  v-bind="restAttributes"
27
+ :disabled="isDisabled"
35
28
  :aria-invalid="isInputInvalid"
36
29
  :aria-describedby="inputDescribedByAttribute"
37
30
  class="cpInput__inner"
@@ -61,6 +54,7 @@ import { ref, useAttrs, useSlots, computed, nextTick, onMounted, useId } from 'v
61
54
 
62
55
  import BaseInputLabel from '@/components/BaseInputLabel.vue'
63
56
 
57
+ import { Sizes } from '@/constants'
64
58
  import { randomString, capitalizeFirstLetter } from '@/helpers'
65
59
 
66
60
  interface Emits {
@@ -70,15 +64,14 @@ interface Emits {
70
64
  interface Props {
71
65
  errorMessage?: string
72
66
  help?: string
73
- hideInvalidityIcon?: boolean
74
67
  inputId?: string | null
75
68
  isInvalid?: boolean
76
- isLarge?: boolean
77
69
  isSearch?: boolean
78
70
  label?: string
79
71
  mask?: string | Record<string, unknown> | null
80
72
  modelValue?: string | number | boolean
81
73
  removeBorder?: boolean
74
+ size?: Sizes
82
75
  tooltip?: string
83
76
  }
84
77
 
@@ -90,11 +83,10 @@ const props = withDefaults(defineProps<Props>(), {
90
83
  isInvalid: false,
91
84
  errorMessage: '',
92
85
  mask: null,
93
- hideInvalidityIcon: false,
94
86
  removeBorder: false,
95
- isLarge: false,
96
87
  isSearch: false,
97
88
  help: '',
89
+ size: Sizes.MD,
98
90
  })
99
91
 
100
92
  const emit = defineEmits<Emits>()
@@ -136,18 +128,17 @@ const isRequired = computed(() => checkAttribute('required'))
136
128
  const dynamicClasses = computed(() => {
137
129
  return [
138
130
  attrs.class,
131
+ `cpInput--${props.size}`,
139
132
  {
140
133
  'cpInput--isInvalid': isInputInvalid.value,
141
134
  'cpInput--isDisabled': isDisabled.value,
142
135
  'cpInput--hasNoBorder': props.removeBorder,
143
- 'cpInput--isLarge': props.isLarge,
144
136
  'cpInput--isSearch': props.isSearch,
145
137
  },
146
138
  ]
147
139
  })
148
140
 
149
141
  const isInputInvalid = computed(() => props.isInvalid || !isDOMElementValid.value)
150
- const displayInvalidityIcon = computed(() => !props.hideInvalidityIcon && isInputInvalid.value)
151
142
 
152
143
  const hasBeforeIconSlot = computed(() => !!slots['leading-icon'])
153
144
  const hasBeforeIcon = computed(() => hasBeforeIconSlot.value || props.isSearch)
@@ -155,16 +146,10 @@ const hasBeforeIcon = computed(() => hasBeforeIconSlot.value || props.isSearch)
155
146
  const hasAfterIconSlot = computed(() => !!slots['trailing-icon'])
156
147
  const hasAfterIcon = computed(() => hasAfterIconSlot.value || props.isSearch)
157
148
 
158
- const iconInvalidityClasses = computed(() => {
159
- return {
160
- 'cpInput__icon--hasAfterAndInvalidityIcon': hasAfterIconSlot.value,
161
- }
162
- })
163
-
164
149
  const DOMElement = computed(() => cpInputContainer.value.children.namedItem(inputIdentifier.value))
165
150
 
166
151
  const displayErrorMessage = computed(() => isInputInvalid.value && props.errorMessage.length)
167
- const isClearButtonVisible = computed(() => props.isSearch && inputModel.value.toString().length)
152
+ const isClearButtonVisible = computed(() => props.isSearch && inputModel.value.toString().length && !isDisabled.value)
168
153
 
169
154
  const displayHelp = computed(() => props.help?.length && !displayErrorMessage.value)
170
155
 
@@ -197,11 +182,6 @@ onMounted(async () => {
197
182
  </script>
198
183
 
199
184
  <style lang="scss">
200
- // Mixins
201
- @mixin cp-input-hover-style() {
202
- outline: fn.px-to-rem(1) solid colors.$primary-color;
203
- }
204
-
205
185
  // Main
206
186
  .cpInput {
207
187
  position: relative;
@@ -222,41 +202,21 @@ onMounted(async () => {
222
202
  }
223
203
  }
224
204
 
225
- &__clear {
226
- display: flex;
227
- padding: fn.px-to-em(3);
228
- color: colors.$neutral-light;
229
- border-radius: 50%;
230
- background-color: colors.$neutral-dark-1;
231
-
232
- &:focus-visible {
233
- outline: fn.px-to-em(3) solid color.scale(colors.$primary-color, $lightness: 80%);
234
- }
235
- }
236
-
237
- &__clearIcon {
238
- width: fn.px-to-em(12);
239
- height: fn.px-to-em(12);
240
- pointer-events: none;
241
- }
242
-
243
205
  &__inner {
244
- box-shadow: inset 0 fn.px-to-em(1) fn.px-to-em(2) rgba(0, 0, 0, 0.12);
206
+ box-shadow: 0 0 0 fn.px-to-rem(1) rgba(0, 0, 0, 0.12);
245
207
  appearance: none;
246
- outline: fn.px-to-rem(1) solid colors.$neutral-dark-4;
247
- border-radius: fn.px-to-em(10);
208
+ border-radius: fn.px-to-rem(10);
248
209
  width: 100%;
249
210
  color: inherit;
250
- padding: sp.$space;
211
+ padding: sp.$space sp.$space-lg;
251
212
  line-height: fn.px-to-rem(24);
252
213
  font-size: fn.px-to-em(14);
253
214
 
254
215
  &:hover {
255
- @include cp-input-hover-style;
216
+ box-shadow: 0 0 0 fn.px-to-rem(1) colors.$primary-color;
256
217
  }
257
218
 
258
219
  &:focus {
259
- box-shadow: 0 0 0 fn.px-to-em(2) color.scale(colors.$primary-color, $lightness: 80%);
260
220
  outline: fn.px-to-rem(2) solid colors.$primary-color;
261
221
  background-color: colors.$neutral-light;
262
222
  }
@@ -271,7 +231,7 @@ onMounted(async () => {
271
231
  .cpInput__inner:hover,
272
232
  .cpInput__inner:focus,
273
233
  .cpInput__icon:hover ~ .cpInput__inner {
274
- outline: fn.px-to-rem(1) solid colors.$error-color;
234
+ box-shadow: 0 0 0 fn.px-to-rem(1) colors.$error-color;
275
235
  }
276
236
 
277
237
  .cpInput__inner:focus {
@@ -281,7 +241,7 @@ onMounted(async () => {
281
241
  }
282
242
 
283
243
  &--isDisabled {
284
- color: colors.$neutral-dark-2 !important;
244
+ color: colors.$neutral-dark-2;
285
245
 
286
246
  .cpInput__container * {
287
247
  cursor: not-allowed;
@@ -293,11 +253,11 @@ onMounted(async () => {
293
253
 
294
254
  .cpInput__inner,
295
255
  .cpInput__inner:hover {
296
- outline: fn.px-to-rem(1) solid colors.$neutral-dark-4 !important;
256
+ box-shadow: 0 0 0 fn.px-to-rem(1) colors.$neutral-dark-4;
297
257
  }
298
258
 
299
259
  .cpInput__icon svg {
300
- stroke: colors.$neutral-dark-2 !important;
260
+ stroke: colors.$neutral-dark-2;
301
261
  }
302
262
  }
303
263
 
@@ -309,63 +269,18 @@ onMounted(async () => {
309
269
  box-shadow: none;
310
270
  }
311
271
 
312
- &__tooltip {
313
- display: flex;
314
- padding: sp.$space-sm;
315
- align-items: center;
316
- justify-content: center;
317
- border-radius: 50%;
318
- color: colors.$neutral-dark-3;
319
- outline-offset: fn.px-to-em(-3);
320
-
321
- &:hover,
322
- &:focus {
323
- color: colors.$primary-color;
324
- }
325
-
326
- &:focus-visible {
327
- outline: fn.px-to-em(2) solid colors.$primary-color;
328
- }
329
- }
330
-
331
- &__tooltipIcon {
332
- width: fn.px-to-rem(16);
333
- height: fn.px-to-rem(16);
334
- }
335
-
336
- &__help,
337
- &__error {
338
- font-size: fn.px-to-em(14);
339
- line-height: fn.px-to-rem(24);
340
- }
341
-
342
- &__help {
343
- color: colors.$neutral-dark-1;
344
- }
345
-
346
- &__error {
347
- color: colors.$error-color;
348
- font-weight: 500;
349
-
350
- &::first-letter {
351
- text-transform: capitalize;
352
- }
353
- }
354
-
355
- $cp-input-icon-size: fn.px-to-em(20);
356
-
357
272
  &__icon {
358
- left: fn.px-to-rem(8);
273
+ @include mx.square-sizing(16);
274
+
275
+ left: fn.px-to-rem(14);
359
276
  z-index: 1;
360
277
  position: absolute;
361
278
  top: 50%;
362
279
  transform: translateY(-50%);
363
- width: $cp-input-icon-size;
364
- height: $cp-input-icon-size;
365
280
  overflow: hidden;
366
281
 
367
282
  &:hover ~ .cpInput__inner {
368
- @include cp-input-hover-style;
283
+ box-shadow: 0 0 0 fn.px-to-rem(1) colors.$primary-color;
369
284
  }
370
285
 
371
286
  svg {
@@ -374,102 +289,115 @@ onMounted(async () => {
374
289
  stroke-width: 1.6;
375
290
  }
376
291
 
377
- &--isInvalidity svg {
378
- stroke: colors.$error-color;
379
- }
380
-
381
- &--isAfter,
382
- &--isInvalidity {
292
+ &--isAfter {
383
293
  left: auto;
384
- right: fn.px-to-rem(8);
385
- justify-content: flex-end;
294
+ right: fn.px-to-rem(14);
386
295
  }
387
296
 
388
- &--isAfter {
389
- transition: 50ms right 0.25s cubic-bezier(0.17, 0.84, 0.44, 1);
297
+ &--isBefore ~ input {
298
+ padding-left: calc(#{sp.$space-md} + #{sp.$space-sm} + #{fn.px-to-rem(16) + sp.$space});
390
299
  }
391
300
 
392
301
  &--isAfter ~ input {
393
- padding-right: calc(#{fn.px-to-rem(8)} + #{$cp-input-icon-size} * 2 + #{fn.px-to-em(8)});
302
+ padding-right: calc(#{sp.$space-md} + #{sp.$space-sm} + #{fn.px-to-rem(16) + sp.$space});
394
303
  }
304
+ }
395
305
 
396
- &--isBefore ~ input {
397
- padding-left: calc(#{fn.px-to-rem(8)} + #{$cp-input-icon-size} + #{fn.px-to-em(8)});
306
+ &--sm {
307
+ .cpInput__inner {
308
+ padding: sp.$space-sm sp.$space-md;
309
+ font-size: fn.px-to-rem(14);
398
310
  }
399
311
 
400
- &--isInvalidity ~ input {
401
- padding-right: calc(#{fn.px-to-rem(8)} + #{$cp-input-icon-size} + #{fn.px-to-em(8)});
312
+ .cpInput__icon {
313
+ left: fn.px-to-rem(10);
402
314
  }
403
315
 
404
- &--hasAfterAndInvalidityIcon ~ input {
405
- padding-right: calc(#{fn.px-to-rem(8)} + #{$cp-input-icon-size} * 2 + #{fn.px-to-em(8)} * 2);
316
+ .cpInput__icon--isAfter {
317
+ left: auto;
318
+ right: fn.px-to-rem(10);
406
319
  }
407
320
 
408
- &--isInvalidity {
409
- & ~ .cpInput__icon--isAfter {
410
- right: calc(#{fn.px-to-rem(8)} + #{$cp-input-icon-size} + #{fn.px-to-em(8)});
411
- transition: right 0.25s cubic-bezier(0.17, 0.84, 0.44, 1);
412
- }
321
+ .cpInput__icon--isBefore ~ input {
322
+ padding-left: calc(#{sp.$space-sm * 2} + #{fn.px-to-rem(20) + sp.$space});
413
323
  }
414
- }
415
324
 
416
- &--isLarge {
417
- $cp-input-large-icon-size: fn.px-to-em(24);
418
- $cp-input-large-spacing: fn.px-to-em(12);
419
- $cp-input-large-padding: fn.px-to-em(16);
325
+ .cpInput__icon--isAfter ~ input {
326
+ padding-right: calc(#{sp.$space-sm * 2} + #{fn.px-to-rem(20) + sp.$space});
327
+ }
328
+ }
420
329
 
330
+ &--lg {
421
331
  .cpInput__inner {
422
- height: sizing.$component-size-large;
423
- padding: $cp-input-large-padding;
332
+ padding: sp.$space-md sp.$space-lg;
333
+ font-size: fn.px-to-rem(16);
424
334
  }
425
335
 
426
336
  .cpInput__icon {
427
- left: $cp-input-large-padding;
428
- width: $cp-input-large-icon-size;
429
- height: $cp-input-large-icon-size;
337
+ @include mx.square-sizing(20);
338
+
339
+ left: fn.px-to-rem(12);
430
340
  }
431
341
 
432
- .cpInput__icon--isInvalidity,
433
342
  .cpInput__icon--isAfter {
434
343
  left: auto;
435
- right: $cp-input-large-padding;
344
+ right: fn.px-to-rem(12);
436
345
  }
437
346
 
438
347
  .cpInput__icon--isAfter ~ input {
439
- padding-right: calc(#{$cp-input-large-padding} + #{$cp-input-large-icon-size} * 2 + #{$cp-input-large-spacing});
348
+ padding-right: calc(#{sp.$space-lg} + #{fn.px-to-rem(20)} + #{sp.$space-sm});
440
349
  }
441
350
 
442
351
  .cpInput__icon--isBefore ~ input {
443
- padding-left: calc(#{$cp-input-large-padding} + #{$cp-input-large-icon-size} + #{$cp-input-large-spacing});
352
+ padding-left: calc(#{sp.$space-lg} + #{fn.px-to-rem(20)} + #{sp.$space-sm});
444
353
  }
354
+ }
445
355
 
446
- .cpInput__icon--isInvalidity ~ input {
447
- padding-right: calc(#{$cp-input-large-padding} + #{$cp-input-large-icon-size} + #{$cp-input-large-spacing});
356
+ &--isSearch {
357
+ .cpInput__icon--isAfter {
358
+ width: auto;
359
+ height: auto;
360
+ overflow: visible;
448
361
  }
449
362
 
450
- .cpInput__icon--hasAfterAndInvalidityIcon ~ input {
451
- padding-right: calc(
452
- #{$cp-input-large-padding} + #{$cp-input-large-icon-size} * 2 + #{$cp-input-large-spacing} * 2
453
- );
454
- }
363
+ .cpInput__clear {
364
+ display: flex;
365
+ color: colors.$neutral-light;
366
+ padding: sp.$space-xs;
367
+ border-radius: 50%;
368
+ background-color: colors.$neutral-dark-1;
455
369
 
456
- .cpInput__icon--isInvalidity ~ .cpInput__icon--isAfter {
457
- & ~ .cpInput__icon--isAfter {
458
- right: calc(#{$cp-input-large-padding} + #{$cp-input-large-icon-size} + #{fn.px-to-em(8)});
370
+ &:focus-visible {
371
+ outline: fn.px-to-rem(2) solid color.scale(colors.$primary-color, $lightness: 80%);
459
372
  }
460
373
  }
461
- }
462
374
 
463
- &--isSearch {
464
- .cpInput__icon--isAfter {
465
- display: flex;
466
- align-items: center;
467
- justify-content: center;
468
- overflow: visible;
375
+ .cpInput__clearIcon {
376
+ @include mx.square-sizing(12);
377
+
378
+ pointer-events: none;
469
379
  }
470
380
 
471
- .cpInput__inner {
472
- padding-right: calc(#{$cp-input-icon-size} * 2);
381
+ &.cpInput--lg .cpInput__clearIcon {
382
+ @include mx.square-sizing(16);
383
+ }
384
+ }
385
+
386
+ &__help,
387
+ &__error {
388
+ font-size: fn.px-to-em(14);
389
+ line-height: fn.px-to-rem(24);
390
+ }
391
+
392
+ &__help {
393
+ color: colors.$neutral-dark-1;
394
+ }
395
+
396
+ &__error {
397
+ color: colors.$error-color;
398
+
399
+ &::first-letter {
400
+ text-transform: capitalize;
473
401
  }
474
402
  }
475
403
  }
@@ -1,7 +1,14 @@
1
1
  <template>
2
2
  <div class="cpSelect" :class="dynamicClasses">
3
- <base-input-label v-if="label" :for="selectReferenceId" class="cpSelect__label">
4
- {{ capitalizedLabel }} <span v-if="required" class="u-asterisk">*</span>
3
+ <base-input-label
4
+ v-if="label"
5
+ :for="selectReferenceId"
6
+ :tooltip="tooltip"
7
+ :is-invalid="isInvalid"
8
+ :required="required"
9
+ class="cpSelect__label"
10
+ >
11
+ {{ capitalizedLabel }}
5
12
  </base-input-label>
6
13
  <div class="cpSelect__container">
7
14
  <select
@@ -18,25 +25,24 @@
18
25
  <option v-for="(option, index) in options" :key="index" :value="option.value">{{ option.label }}</option>
19
26
  </select>
20
27
  </div>
21
- <transition-expand>
22
- <base-input-label
23
- v-if="displayErrorMessage"
24
- :is-invalid="isInvalid"
25
- :for="selectReferenceId"
26
- class="cpSelect__label cpSelect__label--isAfter"
27
- >
28
+ <transition-expand mode="out-in">
29
+ <p v-if="displayErrorMessage" :id="errorMessageId" class="cpSelect__error">
28
30
  {{ errorMessage }}
29
- </base-input-label>
31
+ </p>
32
+ <p v-else-if="displayHelp" :id="helpMessageId" class="cpSelect__help">
33
+ {{ help }}
34
+ </p>
30
35
  </transition-expand>
31
36
  </div>
32
37
  </template>
33
38
 
34
39
  <script setup lang="ts">
35
- import { ref, computed, onMounted } from 'vue'
40
+ import { ref, computed, onMounted, useId } from 'vue'
36
41
 
37
42
  import BaseInputLabel from '@/components/BaseInputLabel.vue'
38
43
  import TransitionExpand from '@/components/TransitionExpand.vue'
39
44
 
45
+ import { Sizes } from '@/constants'
40
46
  import { randomString, capitalizeFirstLetter } from '@/helpers'
41
47
 
42
48
  interface Emits {
@@ -53,14 +59,16 @@ interface Props {
53
59
  defaultValue?: string
54
60
  disabled?: boolean
55
61
  errorMessage?: string
62
+ help?: string
56
63
  hideDefaultValue?: boolean
57
64
  isInvalid?: boolean
58
- isLarge?: boolean
59
65
  label?: string
60
66
  modelValue?: string | number
61
67
  name?: string
62
68
  options: SelectOption[]
63
69
  required?: boolean
70
+ size?: Sizes
71
+ tooltip?: string
64
72
  }
65
73
 
66
74
  const props = withDefaults(defineProps<Props>(), {
@@ -74,28 +82,34 @@ const props = withDefaults(defineProps<Props>(), {
74
82
  autocomplete: 'on',
75
83
  isInvalid: false,
76
84
  errorMessage: '',
77
- isLarge: false,
85
+ size: Sizes.MD,
86
+ help: '',
87
+ tooltip: '',
78
88
  })
79
89
 
80
90
  const emit = defineEmits<Emits>()
81
91
 
82
92
  const selectReferenceId = ref('')
83
93
 
94
+ const helpMessageId = useId()
95
+ const errorMessageId = useId()
96
+
84
97
  const capitalizedLabel = computed(() => {
85
98
  return capitalizeFirstLetter(props.label)
86
99
  })
87
100
 
88
101
  const dynamicClasses = computed(() => {
89
- return {
90
- 'cpSelect--isInvalid': props.isInvalid,
91
- 'cpSelect--isDisabled': props.disabled,
92
- 'cpSelect--isLarge': props.isLarge,
93
- }
102
+ return [
103
+ `cpSelect--${props.size}`,
104
+ {
105
+ 'cpSelect--isInvalid': props.isInvalid,
106
+ 'cpSelect--isDisabled': props.disabled,
107
+ },
108
+ ]
94
109
  })
95
110
 
96
- const displayErrorMessage = computed(() => {
97
- return props.isInvalid && props.errorMessage.length
98
- })
111
+ const displayHelp = computed(() => props.help?.length && !displayErrorMessage.value)
112
+ const displayErrorMessage = computed(() => props.isInvalid && props.errorMessage.length)
99
113
 
100
114
  const handleChange = (e: Event): void => {
101
115
  const target = e.target as HTMLSelectElement
@@ -109,19 +123,23 @@ onMounted(() => {
109
123
 
110
124
  <style lang="scss">
111
125
  .cpSelect {
112
- $cp-select-icon-size: fn.px-to-em(16);
126
+ position: relative;
127
+
128
+ &:has(.cpSelect__help, .cpSelect__error) .cpSelect__container {
129
+ margin-bottom: sp.$space;
130
+ }
113
131
 
114
132
  &__container {
115
133
  position: relative;
116
134
 
117
135
  &:after {
136
+ @include mx.square-sizing(16);
137
+
118
138
  content: '';
119
139
  position: absolute;
120
140
  right: fn.px-to-em(12);
121
141
  top: 50%;
122
142
  transform: translateY(-50%);
123
- width: $cp-select-icon-size;
124
- height: $cp-select-icon-size;
125
143
  background-image: url('@/assets/images/icons/chevron-down-icon.svg');
126
144
  background-size: cover;
127
145
  pointer-events: none;
@@ -130,50 +148,50 @@ onMounted(() => {
130
148
 
131
149
  &__inner {
132
150
  @extend %u-text-ellipsis;
133
- box-shadow: inset 0 fn.px-to-em(1) fn.px-to-em(2) rgba(0, 0, 0, 0.12);
151
+
152
+ box-shadow: 0 0 0 fn.px-to-rem(1) rgba(0, 0, 0, 0.12);
134
153
  appearance: none;
135
- -webkit-appearance: none;
136
- -moz-appearance: none;
137
154
  border: none;
138
- outline: fn.px-to-rem(1) solid colors.$neutral-dark-4;
139
- border-radius: fn.px-to-em(10);
155
+ border-radius: fn.px-to-rem(10);
140
156
  background-color: colors.$neutral-light;
141
157
  width: 100%;
142
158
  color: colors.$neutral-dark;
143
159
  cursor: pointer;
144
- padding: fn.px-to-rem(8) calc(#{$cp-select-icon-size} + #{fn.px-to-rem(8)} + #{fn.px-to-rem(8)}) fn.px-to-rem(8)
145
- fn.px-to-rem(8);
160
+ padding: sp.$space calc(#{sp.$space-md} + #{sp.$space-sm} + #{fn.px-to-rem(16) + sp.$space}) sp.$space sp.$space-lg;
146
161
  line-height: fn.px-to-rem(24);
147
- font-size: fn.px-to-em(14);
162
+ font-size: fn.px-to-rem(14);
148
163
 
149
- &:hover,
150
- &:focus {
151
- outline: fn.px-to-rem(1) solid colors.$primary-color;
152
- background-color: colors.$neutral-light;
164
+ &:hover {
165
+ box-shadow: 0 0 0 fn.px-to-rem(1) colors.$primary-color;
153
166
  }
154
167
 
155
168
  &:focus {
156
169
  outline: fn.px-to-rem(2) solid colors.$primary-color;
157
- box-shadow: 0 0 0 fn.px-to-em(2) color.scale(colors.$primary-color, $lightness: 80%);
170
+ background-color: colors.$neutral-light;
158
171
  }
159
172
  }
160
173
 
161
- &__label {
162
- display: block;
174
+ &__help,
175
+ &__error {
176
+ font-size: fn.px-to-em(14);
163
177
  line-height: fn.px-to-rem(24);
178
+ }
164
179
 
165
- &:not(#{&}--isAfter) {
166
- margin-bottom: sp.$space;
167
- }
180
+ &__help {
181
+ color: colors.$neutral-dark-1;
182
+ }
183
+
184
+ &__error {
185
+ color: colors.$error-color;
168
186
 
169
- &--isAfter {
170
- margin-top: fn.px-to-em(6);
187
+ &::first-letter {
188
+ text-transform: capitalize;
171
189
  }
172
190
  }
173
191
 
174
192
  &--isDisabled {
175
193
  .cpSelect__inner {
176
- outline: fn.px-to-rem(1) solid colors.$neutral-dark-4 !important;
194
+ box-shadow: 0 0 0 fn.px-to-rem(1) colors.$neutral-dark-4;
177
195
  background: colors.$neutral-light-1;
178
196
  }
179
197
 
@@ -192,28 +210,28 @@ onMounted(() => {
192
210
  .cpSelect__inner,
193
211
  .cpSelect__inner:hover,
194
212
  .cpSelect__inner:focus {
195
- outline-color: colors.$error-color;
213
+ box-shadow: 0 0 0 fn.px-to-rem(1) colors.$error-color;
196
214
  }
197
215
 
198
216
  .cpSelect__inner:focus {
199
- box-shadow: 0 0 0 fn.px-to-em(2) color.scale(colors.$error-color, $lightness: 60%);
217
+ outline: fn.px-to-rem(2) solid colors.$error-color;
200
218
  }
201
219
  }
202
220
 
203
- &--isLarge {
204
- $cp-select-large-icon-size: fn.px-to-em(24);
205
- $cp-select-large-padding: fn.px-to-em(16);
206
-
207
- .cpSelect__container:after {
208
- right: fn.px-to-em(16);
209
- width: $cp-select-large-icon-size;
210
- height: $cp-select-large-icon-size;
221
+ &--sm {
222
+ .cpSelect__inner {
223
+ padding: sp.$space-sm calc(sp.$space-xl + fn.px-to-rem(12)) sp.$space-sm sp.$space-md;
211
224
  }
225
+ }
212
226
 
227
+ &--lg {
213
228
  .cpSelect__inner {
214
- padding: fn.px-to-em(16) calc(#{$cp-select-large-icon-size} + #{fn.px-to-em(16)} + #{fn.px-to-em(8)})
215
- fn.px-to-em(16) fn.px-to-em(16);
216
- height: sizing.$component-size-large;
229
+ font-size: fn.px-to-rem(16);
230
+ padding: sp.$space-md calc(#{sp.$space-lg} + #{fn.px-to-rem(20)} + #{sp.$space-sm}) sp.$space-md sp.$space-lg;
231
+ }
232
+
233
+ .cpSelect__container:after {
234
+ @include mx.square-sizing(20);
217
235
  }
218
236
  }
219
237
  }