plugin-ui-for-kzt 0.0.62 → 0.0.64

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.
Files changed (38) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/dist/components/BaseBadge/BaseBadge.vue.d.ts +1 -1
  3. package/dist/components/BaseButton/BaseButton.vue.d.ts +2 -6
  4. package/dist/components/BaseCalendar/BaseCalendar.vue.d.ts +2 -2
  5. package/dist/components/BaseCheckbox/BaseCheckbox.vue.d.ts +2 -6
  6. package/dist/components/BaseDropdown/BaseDropdown.vue.d.ts +2 -6
  7. package/dist/components/BaseField/BaseField.vue.d.ts +3 -3
  8. package/dist/components/BaseInput/BaseInput.vue.d.ts +2 -2
  9. package/dist/components/BaseInputCalendar/BaseInputCalendar.vue.d.ts +2 -2
  10. package/dist/components/BaseInputCurrency/BaseInputCurrency.vue.d.ts +3 -3
  11. package/dist/components/BaseInputEmail/BaseInputEmail.vue.d.ts +2 -2
  12. package/dist/components/BaseInputPhone/BaseInputPhone.vue.d.ts +2 -2
  13. package/dist/components/BaseOpenedListItem/BaseOpenedListItem.vue.d.ts +2 -6
  14. package/dist/components/BasePagination/BasePagination.vue.d.ts +1 -1
  15. package/dist/components/BaseRadio/BaseRadio.vue.d.ts +2 -6
  16. package/dist/components/BaseSegmentedButtons/BaseSegmentedButtons.vue.d.ts +2 -6
  17. package/dist/components/BaseSelect/BaseSelect.vue.d.ts +5 -13
  18. package/dist/components/BaseTextarea/BaseTextarea.vue.d.ts +2 -2
  19. package/dist/components/BaseToggle/BaseToggle.vue.d.ts +2 -6
  20. package/dist/components/BaseTooltip/BaseTooltip.vue.d.ts +1 -1
  21. package/dist/components/BaseUpload/BaseUpload.vue.d.ts +2 -4
  22. package/dist/index.js +1 -1
  23. package/dist/sprite.svg +1 -1
  24. package/dist/store/modal.d.ts +13 -13
  25. package/dist/utils/viewPort.d.ts +5 -0
  26. package/example/App.vue +1 -0
  27. package/package.json +1 -1
  28. package/src/assets/icons/upload-2.svg +7 -0
  29. package/src/assets/icons/upload.svg +3 -3
  30. package/src/components/BaseInputPhone/README.md +78 -0
  31. package/src/components/BaseModal/README.md +88 -0
  32. package/src/components/BaseSiteInput/README.md +76 -0
  33. package/src/components/BaseSwiper/README.md +88 -0
  34. package/src/components/BaseTabs/README.md +110 -0
  35. package/src/components/BaseUpload/BaseUpload.vue +132 -18
  36. package/src/components/BaseUpload/README.md +126 -0
  37. package/src/types/uploadedFile.d.ts +10 -2
  38. package/src/utils/viewPort.ts +50 -0
@@ -0,0 +1,76 @@
1
+ # BaseSiteInput
2
+
3
+ Компонент для ввода URL-адреса сайта. Автоматически добавляет префикс `https://`, убирает его из отображаемого значения и валидирует формат URL в реальном времени.
4
+
5
+ ## Использование
6
+
7
+ ```vue
8
+ <template>
9
+ <BaseSiteInput
10
+ v-model="siteUrl"
11
+ placeholder="example.com"
12
+ size="medium"
13
+ />
14
+ </template>
15
+
16
+ <script setup lang="ts">
17
+ import { ref } from 'vue';
18
+ const siteUrl = ref('');
19
+ </script>
20
+ ```
21
+
22
+ ## Пропсы
23
+
24
+ | Пропс | Тип | По умолчанию | Описание |
25
+ |------------------|-----------|:----------------------:|-------------------------------------------------------|
26
+ | `modelValue` | `string` | `''` | Значение поля (v-model). Хранится с префиксом `https://` |
27
+ | `size` | `string` | `'medium'` | Размер: `'small'`, `'medium'`, `'large'` |
28
+ | `focusable` | `boolean` | `true` | Управляет фокусируемостью поля |
29
+ | `id` | `string` | — | HTML-атрибут `id` для поля |
30
+ | `error` | `boolean` | — | Внешнее состояние ошибки |
31
+ | `validationText` | `string` | `'Некорректный URL'` | Текст ошибки при невалидном URL |
32
+
33
+ ## События
34
+
35
+ | Событие | Payload | Описание |
36
+ |---------------------|----------|-------------------------------------------------|
37
+ | `update:modelValue` | `string` | Всегда эмитирует значение с префиксом `https://` |
38
+
39
+ ## Поведение
40
+
41
+ - Префикс `https://` **всегда хранится** в `modelValue`, но **не отображается** в поле ввода — пользователь видит только домен.
42
+ - При вводе значения `https://` автоматически добавляется, если его нет.
43
+ - Валидация происходит в реальном времени через `watch`. Проверяется формат домена: `example.com`, `sub.example.org/path` и т.д.
44
+ - Если введён некорректный URL, показывается ошибка (из `validationText` или дефолтная).
45
+ - Внешний пропс `error` объединяется с внутренней ошибкой валидации: если хотя бы одно из них — показывается состояние ошибки.
46
+
47
+ ## Примеры
48
+
49
+ ### Получение значения
50
+
51
+ ```vue
52
+ <BaseSiteInput v-model="url" placeholder="example.com" />
53
+ <!-- После ввода "example.com" значение url === 'https://example.com' -->
54
+ ```
55
+
56
+ ### Кастомный текст ошибки
57
+
58
+ ```vue
59
+ <BaseSiteInput
60
+ v-model="url"
61
+ validation-text="Введите корректный адрес сайта"
62
+ placeholder="example.com"
63
+ />
64
+ ```
65
+
66
+ ### Разные размеры
67
+
68
+ ```vue
69
+ <BaseSiteInput v-model="url" size="small" placeholder="example.com" />
70
+ <BaseSiteInput v-model="url" size="medium" placeholder="example.com" />
71
+ <BaseSiteInput v-model="url" size="large" placeholder="example.com" />
72
+ ```
73
+
74
+ ## Зависимости
75
+
76
+ - `BaseInput`
@@ -0,0 +1,88 @@
1
+ # BaseSwiper
2
+
3
+ Компонент карусели изображений с кнопками навигации, пагинацией и поддержкой автопрокрутки.
4
+
5
+ ## Использование
6
+
7
+ ```vue
8
+ <template>
9
+ <BaseSwiper
10
+ :images="images"
11
+ :autoplay="true"
12
+ :autoplay-interval="4000"
13
+ />
14
+ </template>
15
+
16
+ <script setup lang="ts">
17
+ const images = [
18
+ '/img/slide1.jpg',
19
+ '/img/slide2.jpg',
20
+ '/img/slide3.jpg',
21
+ ];
22
+ </script>
23
+ ```
24
+
25
+ ## Пропсы
26
+
27
+ | Пропс | Тип | По умолчанию | Описание |
28
+ |----------------------|-----------------------|:-------------------------------------:|-------------------------------------------------|
29
+ | `images` | `string[]` | `[]` | Массив URL изображений |
30
+ | `currentSlide` | `number` | `0` | Индекс текущего слайда (для внешнего управления)|
31
+ | `autoplay` | `boolean` | `false` | Включить автопрокрутку |
32
+ | `autoplayInterval` | `number` | `3000` | Интервал автопрокрутки в миллисекундах |
33
+ | `buttonSize` | `'medium' \| 'large'` | `'medium'` | Размер кнопок навигации |
34
+ | `paginationSettings` | `PaginationSettings` | `{ type: 'dots', color: 'primary' }` | Настройки пагинации |
35
+
36
+ ### Тип `PaginationSettings`
37
+
38
+ ```ts
39
+ interface PaginationSettings {
40
+ type?: PaginationType; // тип пагинации (например, 'dots')
41
+ color?: PaginationColor; // цвет: 'primary' | 'secondary'
42
+ size?: ICoreSize;
43
+ }
44
+ ```
45
+
46
+ ## События
47
+
48
+ | Событие | Payload | Описание |
49
+ |-----------------------|----------|---------------------------------------------|
50
+ | `update:currentSlide` | `number` | Вызывается при смене слайда, передаёт индекс |
51
+
52
+ ## Поведение
53
+
54
+ - Кнопка «назад» недоступна (`disabled`) на первом слайде, кнопка «вперёд» — на последнем.
55
+ - При автопрокрутке слайды переключаются **циклически** (после последнего возвращается к первому).
56
+ - Автопрокрутка запускается при монтировании (`onMounted`) и останавливается при размонтировании (`onUnmounted`).
57
+ - Пагинация синхронизирована с текущим слайдом через `watch` в обе стороны — можно управлять слайдом как через кнопки, так и через пагинацию.
58
+ - Максимальная ширина контейнера: `640px`.
59
+
60
+ ## Примеры
61
+
62
+ ### С кастомной пагинацией и автопрокруткой
63
+
64
+ ```vue
65
+ <BaseSwiper
66
+ :images="images"
67
+ :autoplay="true"
68
+ :autoplay-interval="5000"
69
+ :pagination-settings="{ type: 'dots', color: 'secondary' }"
70
+ button-size="large"
71
+ @update:current-slide="onSlideChange"
72
+ />
73
+ ```
74
+
75
+ ### Внешнее управление слайдом
76
+
77
+ ```vue
78
+ <BaseSwiper
79
+ :images="images"
80
+ :current-slide="currentSlide"
81
+ @update:current-slide="currentSlide = $event"
82
+ />
83
+ ```
84
+
85
+ ## Зависимости
86
+
87
+ - `BaseIcon` (иконки `arrow-left-circle`, `arrow-right-circle`)
88
+ - `BasePagination`
@@ -0,0 +1,110 @@
1
+ # BaseTabs
2
+
3
+ Компонент вкладок (табов) с поддержкой иконок, состояния `disabled` и нескольких размеров.
4
+
5
+ ## Использование
6
+
7
+ ```vue
8
+ <template>
9
+ <BaseTabs v-model="activeTab" :tabs="tabs">
10
+ <div v-if="activeTab === 0">Контент первой вкладки</div>
11
+ <div v-if="activeTab === 1">Контент второй вкладки</div>
12
+ <div v-if="activeTab === 2">Контент третьей вкладки</div>
13
+ </BaseTabs>
14
+ </template>
15
+
16
+ <script setup lang="ts">
17
+ import { ref } from 'vue';
18
+
19
+ const activeTab = ref(0);
20
+
21
+ const tabs = [
22
+ { id: 0, title: 'Обзор' },
23
+ { id: 1, title: 'Настройки' },
24
+ { id: 2, title: 'История' },
25
+ ];
26
+ </script>
27
+ ```
28
+
29
+ ## Пропсы
30
+
31
+ | Пропс | Тип | По умолчанию | Описание |
32
+ |--------------|----------|:------------:|-------------------------------------------------------------------|
33
+ | `tabs` | `ITab[]` | — | Массив объектов вкладок |
34
+ | `modelValue` | `number` | `0` | ID активной вкладки (v-model) |
35
+ | `size` | `string` | `'medium'` | Размер: `'extra-small'`, `'small'`, `'medium'` |
36
+
37
+ ### Тип `ITab`
38
+
39
+ ```ts
40
+ interface ITab {
41
+ id: number;
42
+ title: string;
43
+ icon?: Component; // Vue-компонент иконки
44
+ disabled?: boolean;
45
+ }
46
+ ```
47
+
48
+ ## События
49
+
50
+ | Событие | Payload | Описание |
51
+ |---------------------|----------|---------------------------------------|
52
+ | `update:modelValue` | `number` | Вызывается при выборе вкладки, передаёт `id` |
53
+
54
+ ## Слоты
55
+
56
+ | Слот | Описание |
57
+ |-----------|--------------------------------------------|
58
+ | `default` | Контент вкладок (управляется снаружи через `v-if`) |
59
+
60
+ ## Размеры
61
+
62
+ | Значение | Высота таба | Шрифт |
63
+ |---------------|-------------|--------------------------------|
64
+ | `extra-small` | 38px | `typography-text-s-medium` |
65
+ | `small` | 48px | `typography-text-m-medium` |
66
+ | `medium` | 56px | `typography-text-l-medium` |
67
+
68
+ ## Поведение
69
+
70
+ - Клик по вкладке с `disabled: true` игнорируется.
71
+ - Активная вкладка выделяется синей нижней границей.
72
+ - Внешнее изменение `modelValue` через `watch` синхронизируется с внутренним состоянием.
73
+ - Горизонтальная линия-разделитель рисуется через псевдоэлемент `::before` на заголовке, активный таб перекрывает её через `z-index`.
74
+
75
+ ## Примеры
76
+
77
+ ### С иконками
78
+
79
+ ```vue
80
+ <script setup lang="ts">
81
+ import IconHome from '@/icons/IconHome.vue';
82
+ import IconSettings from '@/icons/IconSettings.vue';
83
+
84
+ const tabs = [
85
+ { id: 0, title: 'Главная', icon: IconHome },
86
+ { id: 1, title: 'Настройки', icon: IconSettings },
87
+ ];
88
+ </script>
89
+
90
+ <template>
91
+ <BaseTabs v-model="activeTab" :tabs="tabs" size="small">
92
+ <div v-if="activeTab === 0">Главная</div>
93
+ <div v-if="activeTab === 1">Настройки</div>
94
+ </BaseTabs>
95
+ </template>
96
+ ```
97
+
98
+ ### С заблокированной вкладкой
99
+
100
+ ```vue
101
+ const tabs = [
102
+ { id: 0, title: 'Активная' },
103
+ { id: 1, title: 'Заблокированная', disabled: true },
104
+ { id: 2, title: 'Ещё одна' },
105
+ ];
106
+ ```
107
+
108
+ ## Зависимости
109
+
110
+ - `BaseButton`
@@ -9,6 +9,7 @@
9
9
  :accept="acceptedFormats.join(',')"
10
10
  />
11
11
  <div
12
+ v-if="!isMobile || !multiple || uploadedFiles.length === 0"
12
13
  class="base-file-upload__wrapper"
13
14
  :class="{ '--is-drag-over': isDragOver }"
14
15
  @click="triggerFileInput"
@@ -20,16 +21,32 @@
20
21
  class="base-file-upload__block"
21
22
  >
22
23
  <base-icon
24
+ v-if="!isMobile"
23
25
  name="upload"
24
26
  class="base-file-upload__icon-upload"
25
27
  size="large"
26
28
  />
27
- <p class="base-file-upload__title">
28
- <slot name="title">Перетащите или кликните для загрузки</slot>
29
- </p>
30
- <p class="base-file-upload__description">
31
- <slot name="description">Допустимый формат файлов: pdf, docx, jpeg до 25 MB</slot>
32
- </p>
29
+ <base-icon
30
+ v-else
31
+ name="upload-2"
32
+ class="base-file-upload__icon-upload"
33
+ size="medium"
34
+ />
35
+ <div
36
+ class="base-file-upload__content"
37
+ >
38
+ <p class="base-file-upload__title">
39
+ <slot name="title">{{ texts?.instructions }}</slot>
40
+ <base-icon
41
+ v-if="isMobile"
42
+ name="upload"
43
+ size="medium"
44
+ />
45
+ </p>
46
+ <p class="base-file-upload__description">
47
+ <slot name="description">{{ texts?.allowableFormats }}</slot>
48
+ </p>
49
+ </div>
33
50
  </div>
34
51
  <div v-else>
35
52
  <div
@@ -47,7 +64,7 @@
47
64
  class="base-file-upload__file-item-button"
48
65
  size="custom"
49
66
  color="custom"
50
- @click="downloadFile(file, index, false)"
67
+ @click="downloadFile(file)"
51
68
  >
52
69
  <base-icon
53
70
  name="export"
@@ -109,12 +126,13 @@
109
126
  @drop="handleDrop"
110
127
  >
111
128
  <base-icon name="gallery" size="medium" class="base-file-upload__placeholder-icon"/>
112
- <p class="base-file-upload__placeholder-text"><span>Загрузить</span> <br/> фото</p>
129
+ <p class="base-file-upload__placeholder-text"><span>{{ texts?.upload }}</span> <br/> {{ texts?.photo }}</p>
113
130
  </div>
114
131
  </div>
115
132
 
116
133
  <!-- Остальные файлы в колонках -->
117
134
  <div v-if="otherFiles.length > 0 && multiple" class="base-file-upload__file-list">
135
+ <div class="base-file-upload__list-title"> {{ texts?.documents }}</div>
118
136
  <div
119
137
  v-for="(file, index) in otherFiles"
120
138
  :key="index"
@@ -129,7 +147,7 @@
129
147
  class="base-file-upload__file-item-button"
130
148
  size="custom"
131
149
  color="custom"
132
- @click="downloadFile(file, index, false)"
150
+ @click="downloadFile(file)"
133
151
  >
134
152
  <base-icon
135
153
  name="export"
@@ -151,6 +169,16 @@
151
169
  </base-button>
152
170
  </div>
153
171
  </div>
172
+ <div v-if="isMobile && props.multiple"
173
+ class="base-file-upload__more"
174
+ @click="triggerFileInput">
175
+ {{ texts?.loadMore }}
176
+ <base-icon
177
+ name="upload"
178
+ class="base-file-upload__icon-upload"
179
+ size="medium"
180
+ />
181
+ </div>
154
182
  </div>
155
183
  </div>
156
184
 
@@ -166,6 +194,7 @@ import { useModal } from '../../composables/useModal';
166
194
  import type { UploadedFile, IpropsUpload } from '../../types/uploadedFile.d';
167
195
  import ImageModal from './ImageModal.vue';
168
196
  import CropModal from './CropModal.vue';
197
+ import { isMobile } from "../../utils/viewPort";
169
198
 
170
199
  const props = withDefaults( defineProps<IpropsUpload>(), {
171
200
  multiple: true,
@@ -182,7 +211,7 @@ const errorMessage = ref<string | null>( null );
182
211
  const isDragOver = ref( false );
183
212
  const modal = useModal();
184
213
 
185
- const mediaExtensions = ['.jpg', '.jpeg', '.png', '.svg'];
214
+ const mediaExtensions = ['.jpg', '.jpeg', '.png'];
186
215
  const mediaFiles = computed( () =>
187
216
  uploadedFiles.value.filter( ( file ) =>
188
217
  mediaExtensions.includes( `.${file.name.split( '.' ).pop()?.toLowerCase() || ''}` )
@@ -232,18 +261,27 @@ const processFiles = ( files: File[] ) => {
232
261
  uploadedFiles.value = [];
233
262
  }
234
263
 
264
+ const errors: string[] = [];
265
+ const normalizedFormats = props.acceptedFormats.map( ( f: string ) => f.toLowerCase() );
266
+
235
267
  filesToProcess.forEach( ( file ) => {
236
268
  const fileExtension = `.${file.name.split( '.' ).pop()?.toLowerCase() || ''}`;
237
- if ( !props.acceptedFormats.includes( fileExtension ) ) {
238
- errorMessage.value = `Недопустимый формат файла: ${file.name}. Допустимый: ${props.acceptedFormats.join( ', ' )}.`;
269
+
270
+ if ( !normalizedFormats.includes( fileExtension ) ) {
271
+ errors.push( `Недопустимый формат файла: ${file.name}. Допустимый: ${props.acceptedFormats.join( ', ' )}.` );
239
272
  return;
240
273
  }
241
274
 
242
275
  if ( file.size > props.maxFileSize ) {
243
- errorMessage.value = `Файл ${file.name} превышает максимальный размер ${formatFileSize( props.maxFileSize )}.`;
276
+ errors.push( `Файл ${file.name} превышает максимальный размер ${formatFileSize( props.maxFileSize )}.` );
244
277
  return;
245
278
  }
246
279
 
280
+ const isDuplicate = uploadedFiles.value.some(
281
+ ( f: UploadedFile ) => f.name === file.name && f.size === file.size
282
+ );
283
+ if ( isDuplicate ) return;
284
+
247
285
  if ( props.enableCrop && isImageFile( file ) ) {
248
286
  openCropModal( file );
249
287
  } else {
@@ -252,6 +290,10 @@ const processFiles = ( files: File[] ) => {
252
290
  }
253
291
  } );
254
292
 
293
+ if ( errors.length > 0 ) {
294
+ errorMessage.value = errors.join( ' ' );
295
+ }
296
+
255
297
  isUploading.value = false;
256
298
  };
257
299
 
@@ -306,7 +348,7 @@ const removeFile = ( index: number, isMedia: boolean ) => {
306
348
  }
307
349
  };
308
350
 
309
- const downloadFile = ( file: { file: File, name: string }, index: number, isMedia: boolean ) => {
351
+ const downloadFile = ( file: { file: File, name: string } ) => {
310
352
  if ( file?.file?.type ) {
311
353
  const url = URL.createObjectURL( file.file );
312
354
  const link = document.createElement( 'a' );
@@ -387,12 +429,18 @@ watch( () => props.files,
387
429
  color: var(--primary-blue);
388
430
  }
389
431
 
390
- .base-file-upload__icon-upload {
391
- color: var(--primary-blue);
392
- }
432
+ }
433
+
434
+ @media #{$mobile-max-767} {
435
+ padding: 12px;
436
+ align-items: start;
393
437
  }
394
438
  }
395
439
 
440
+ &__icon-upload {
441
+ color: var(--primary-blue);
442
+ }
443
+
396
444
  &__block {
397
445
  margin: 0 auto;
398
446
  text-align: center;
@@ -400,16 +448,45 @@ watch( () => props.files,
400
448
  svg {
401
449
  margin: 0 auto;
402
450
  }
451
+
452
+ @media #{$mobile-max-767} {
453
+ display: flex;
454
+ gap: 12px;
455
+ margin: 0;
456
+ svg {
457
+ margin: 0;
458
+ }
459
+ }
460
+ }
461
+
462
+ &__content {
463
+ @media #{$mobile-max-767} {
464
+ text-align: start;
465
+ }
403
466
  }
404
467
 
405
468
  &__title {
406
- color: var(--primary-text-primary);
469
+ color: var(--primary-blue);
407
470
  font: var(--typography-text-m-medium);
471
+
472
+ @media #{$mobile-max-767} {
473
+ font: var(--typography-text-s-bold);
474
+ display: flex;
475
+ color: var(--primary-blue);
476
+ gap: 2px;
477
+ svg {
478
+ margin: 0;
479
+ color: var(--primary-blue);
480
+ }
481
+ }
408
482
  }
409
483
 
410
484
  &__description {
411
485
  color: var(--primary-text-tertiary);
412
486
  font: var(--typography-text-s-regular);
487
+ @media #{$mobile-max-767} {
488
+ font: var(--typography-text-xs-bold);
489
+ }
413
490
  }
414
491
 
415
492
  &__input {
@@ -466,6 +543,23 @@ watch( () => props.files,
466
543
  flex-direction: column;
467
544
  }
468
545
 
546
+ &__list-title {
547
+ font: var(--typography-text-s-medium);
548
+ margin: 12px 0;
549
+ color: var(--primary-black);
550
+ }
551
+
552
+
553
+ &__more {
554
+ display: flex;
555
+ justify-content: end;
556
+ align-items: center;
557
+ gap: 8px;
558
+ padding: 14px 4px;
559
+ cursor: pointer;
560
+ color: var(--primary-blue);
561
+ }
562
+
469
563
  &__file-item {
470
564
  display: flex;
471
565
  justify-content: space-between;
@@ -473,10 +567,15 @@ watch( () => props.files,
473
567
  padding: 8px 12px;
474
568
  border-bottom: 1px solid var(--primary-black-200);
475
569
 
570
+
476
571
  &:last-child {
477
572
  border-bottom: none;
478
573
  }
479
574
 
575
+ @media #{$mobile-max-767} {
576
+ padding: 8px 0;
577
+ }
578
+
480
579
  @include hover {
481
580
  .base-file-upload__file-item-wrapper {
482
581
  color: var(--primary-blue);
@@ -510,6 +609,12 @@ watch( () => props.files,
510
609
  gap: 8px;
511
610
  color: var(--primary-text-primary);
512
611
  font: var(--typography-text-m-regular);
612
+
613
+ @media #{$mobile-max-767} {
614
+ span {
615
+ font: var(--typography-text-xs-regular);
616
+ }
617
+ }
513
618
  }
514
619
 
515
620
  &__file-item-button {
@@ -568,5 +673,14 @@ watch( () => props.files,
568
673
  color: var(--primary-blue);
569
674
  }
570
675
  }
676
+
677
+ &__files {
678
+ @media #{$mobile-max-767} {
679
+ padding: 0 8px;
680
+ border-radius: var(--corner-radius-m);
681
+ background: var(--bg-light);
682
+ }
683
+ }
684
+
571
685
  }
572
686
  </style>