adata-ui 2.1.40 → 2.1.41-beta.1

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 (258) hide show
  1. package/-error.vue +2 -2
  2. package/.playground/app.vue +13 -13
  3. package/.playground/nuxt.config.ts +1 -1
  4. package/CLAUDE.md +63 -0
  5. package/assets/styles/main.css +12 -0
  6. package/assets/styles/theme.css +583 -0
  7. package/assets/styles/ui.css +247 -0
  8. package/components/elements/a-select-row/ASelectRowV2.vue +13 -17
  9. package/components/elements/a-select-row/index.vue +13 -12
  10. package/components/elements/accordion/AAccordion.vue +2 -2
  11. package/components/elements/accordion/AAccordionGroup/AAccordionGroup.vue +1 -1
  12. package/components/elements/accordion/AAccordionGroup/ui.config.ts +4 -4
  13. package/components/elements/accordion/ui.config.ts +4 -4
  14. package/components/elements/alert/AAlert.vue +5 -5
  15. package/components/elements/bg-block/ABgBlock.vue +1 -1
  16. package/components/elements/button/AButton.vue +48 -45
  17. package/components/elements/button/AButtonV2.vue +74 -30
  18. package/components/elements/button-login/index.vue +2 -1
  19. package/components/elements/carousel/config.ui.ts +2 -2
  20. package/components/elements/chip-wrapper/AChipWrapper.vue +4 -3
  21. package/components/elements/chips/AChips.vue +4 -3
  22. package/components/elements/companies/AOurClients.vue +1 -1
  23. package/components/elements/count-up/ACountUp.vue +54 -0
  24. package/components/elements/curve-block/ACurveBlock.vue +15 -48
  25. package/components/elements/curve-block-v2/ACurveBlockV2.vue +60 -25
  26. package/components/elements/digit-badge/ADigitBadge.vue +17 -16
  27. package/components/elements/empty-box/empty-box-V2.vue +92 -0
  28. package/components/elements/error-template/index.vue +99 -31
  29. package/components/elements/feature-description/AFeatureDescription.vue +8 -8
  30. package/components/elements/illustrations/noAccess.vue +1 -1
  31. package/components/elements/infinite-carousel/AInfiniteCarousel.vue +44 -16
  32. package/components/elements/leave-note/ALeaveNote.vue +2 -2
  33. package/components/elements/pagination/APagination.vue +8 -8
  34. package/components/elements/section-heading/ASectionHeading.vue +35 -0
  35. package/components/elements/segmented/ASegmentedV2.vue +24 -21
  36. package/components/elements/select/ASelect.vue +28 -27
  37. package/components/elements/select/ASelectMobile.vue +5 -5
  38. package/components/elements/select/ASelectV2.vue +20 -28
  39. package/components/elements/select/ui/select-button.vue +8 -8
  40. package/components/elements/select/ui/select-list.vue +2 -2
  41. package/components/elements/show-more/AShowMore.vue +2 -2
  42. package/components/elements/show-more/AShowMoreV2.vue +3 -3
  43. package/components/elements/skeleton/ASkeleton.vue +1 -1
  44. package/components/elements/slider/ASlider.vue +3 -2
  45. package/components/elements/slider/ASliderV2.vue +182 -0
  46. package/components/elements/star-rating/AStarRating.vue +2 -2
  47. package/components/elements/status-badge/AStatusBadge.vue +40 -36
  48. package/components/elements/step-slider/AStepSliderColCard.vue +77 -39
  49. package/components/elements/step-slider/AStepSliderColNumber.vue +74 -53
  50. package/components/elements/table/table.config.ts +8 -8
  51. package/components/elements/tree-select/components/ATreeSelectNode.vue +4 -4
  52. package/components/elements/tree-select-mobile/components/ATreeSelectNodesMobile.vue +3 -3
  53. package/components/elements/tree-select-modal/ATreeSelectModal.vue +4 -4
  54. package/components/features/color-mode/AColorMode.client.vue +2 -24
  55. package/components/features/dropdown/ADropdownV2.vue +1 -1
  56. package/components/features/lang-switcher/lang-switcher.vue +6 -6
  57. package/components/features/payment/banner/BasicPlusLimitBanner.vue +3 -23
  58. package/components/features/payment/banner/PaymentBanner.vue +3 -23
  59. package/components/features/payment/banner/UpSellBanner.vue +1 -21
  60. package/components/features/payment/process/PaymentKaspiQrSidePanel.vue +8 -7
  61. package/components/features/payment/process/PaymentKaspiRedirectSidePanel.vue +5 -5
  62. package/components/features/payment/process/PaymentMethodSidePanel.vue +12 -12
  63. package/components/features/payment/process/PaymentTopUpSidePanel.vue +6 -6
  64. package/components/features/pk-mobile-services/APkMobileServices.vue +14 -43
  65. package/components/features//321/201hange-version/AChangeVersion.vue +1 -1
  66. package/components/forms/checkbox/ACheckbox.vue +8 -8
  67. package/components/forms/checkbox/ACheckboxV2.vue +8 -8
  68. package/components/forms/feedback-form/FeedbackForm.vue +8 -8
  69. package/components/forms/feedback-form/FeedbackFormV2.vue +9 -8
  70. package/components/forms/input/AInputV2.vue +39 -25
  71. package/components/forms/input/button/AInputButton.vue +1 -1
  72. package/components/forms/input/date/AInputDate.vue +13 -9
  73. package/components/forms/input/password/AInputPassword.vue +1 -1
  74. package/components/forms/input/standard/AInputStandard.vue +23 -14
  75. package/components/forms/input/textarea/ATextarea.vue +15 -11
  76. package/components/forms/input/textarea/ATextareaV2.vue +18 -13
  77. package/components/forms/radio-button/ARadioButton.vue +4 -4
  78. package/components/forms/request-demo/ARequestDemo.vue +5 -5
  79. package/components/forms/toggle/AToggle.vue +8 -7
  80. package/components/forms/toggle/AToggleV2.vue +7 -6
  81. package/components/modals/AConfirmationEmail.vue +3 -3
  82. package/components/modals/AboutTariffModal.vue +10 -9
  83. package/components/modals/AnotherDeviceModal.vue +11 -10
  84. package/components/modals/ApplicationAcceptedModal.vue +3 -2
  85. package/components/modals/ConnectingTariffModal.vue +1 -1
  86. package/components/modals/ContactsMobileModel.vue +5 -5
  87. package/components/modals/ContentNavigationModal.vue +8 -7
  88. package/components/modals/Insufficient-funds-modal.vue +4 -4
  89. package/components/modals/LimitReachedModal.vue +18 -7
  90. package/components/modals/NoAccessModal.vue +7 -3
  91. package/components/modals/PaymentMethodModal.vue +4 -4
  92. package/components/modals/RedirectsBanksModal.vue +4 -4
  93. package/components/modals/ReplenishModal.vue +2 -2
  94. package/components/modals/ReportBugConfirmModal.vue +2 -2
  95. package/components/modals/ReportBugModal.vue +2 -2
  96. package/components/modals/Resend.vue +4 -4
  97. package/components/modals/SubmitApplicationModal.vue +1 -5
  98. package/components/modals/id/AuthModal.vue +27 -47
  99. package/components/modals/id/IdAutoLogoutModal.vue +23 -24
  100. package/components/modals/id/IdBanner.vue +4 -24
  101. package/components/modals/id/IdConfirmAccountOtpModal.vue +5 -4
  102. package/components/modals/id/IdConfirmSuccessfulModal.vue +3 -3
  103. package/components/modals/id/IdLoginModal.vue +8 -8
  104. package/components/modals/id/IdModals.vue +1 -3
  105. package/components/modals/id/IdNewPasswordModal.vue +3 -3
  106. package/components/modals/id/IdOtpInput.vue +3 -3
  107. package/components/modals/id/IdPasswordSuccessfulModal.vue +3 -3
  108. package/components/modals/id/IdRecoveryModal.vue +3 -3
  109. package/components/modals/id/IdRegistrationModal.vue +4 -4
  110. package/components/modals/id/IdResetPasswordOtpModal.vue +5 -4
  111. package/components/modals/id/IdTwoFactorModal.vue +3 -2
  112. package/components/navigation/bottom-navigation/ABottomNavigation.vue +7 -7
  113. package/components/navigation/breadcrumbs/ABreadcrumbs.vue +4 -4
  114. package/components/navigation/footer/AFooter.vue +2 -2
  115. package/components/navigation/footer/ui/a-footer-accordion.vue +1 -1
  116. package/components/navigation/header/AHeader.vue +11 -11
  117. package/components/navigation/header/AlmatyContacts.vue +7 -7
  118. package/components/navigation/header/AstanaContacts.vue +4 -4
  119. package/components/navigation/header/CardGallery.vue +8 -7
  120. package/components/navigation/header/ContactMenu.vue +1 -1
  121. package/components/navigation/header/HeaderLink.vue +5 -5
  122. package/components/navigation/header/HeaderUsage.vue +14 -14
  123. package/components/navigation/header/ListItem.vue +4 -3
  124. package/components/navigation/header/NavCard.vue +6 -5
  125. package/components/navigation/header/NavList.vue +9 -8
  126. package/components/navigation/header/NotificationsMenu.vue +10 -10
  127. package/components/navigation/header/ProductMenu.vue +10 -9
  128. package/components/navigation/header/ProfileMenu.vue +13 -12
  129. package/components/navigation/header/SystemNotification.vue +4 -4
  130. package/components/navigation/line-tabs/ALineTabs.vue +10 -9
  131. package/components/navigation/pill-tabs/APillTabs.vue +18 -16
  132. package/components/navigation/pill-tabs/APillTabsV2.vue +40 -25
  133. package/components/navigation/side-navigation/ASideNavigation.vue +3 -3
  134. package/components/overlays/drawer/ADrawerV2.vue +12 -11
  135. package/components/overlays/modal/AModal.vue +4 -4
  136. package/components/overlays/modal/AModalV2.vue +17 -13
  137. package/components/overlays/side-panel/ASidePanel.vue +7 -7
  138. package/components/overlays/sideover/ASlideover.vue +4 -4
  139. package/components/overlays/tooltip/ATooltip.vue +3 -2
  140. package/components/overlays/tooltip/ATooltipV2.vue +2 -2
  141. package/composables/highlight.ts +2 -1
  142. package/eslint.config.mjs +14 -1
  143. package/icons/arrow/arrow-left.vue +14 -0
  144. package/icons/arrow-currency-gray.vue +1 -1
  145. package/icons/arrow-currency-green.vue +1 -1
  146. package/icons/arrow-currency-red.vue +1 -1
  147. package/icons/avatar.vue +1 -1
  148. package/icons/bar-chart-3.vue +3 -0
  149. package/icons/book-open.vue +3 -0
  150. package/icons/bookmark/bookmark-filled.vue +1 -0
  151. package/icons/braces.vue +3 -0
  152. package/icons/check/check-outline.vue +3 -0
  153. package/icons/chevron/chevron-down-outline.vue +3 -0
  154. package/icons/clipboard-list.vue +3 -0
  155. package/icons/clock-outline.vue +3 -0
  156. package/icons/company-egov-small.vue +1 -1
  157. package/icons/database.vue +3 -0
  158. package/icons/download-outline.vue +3 -0
  159. package/icons/download.vue +1 -1
  160. package/icons/egov.vue +1 -1
  161. package/icons/elicense.vue +1 -1
  162. package/icons/file-json.vue +3 -0
  163. package/icons/file-search.vue +3 -0
  164. package/icons/file-text.vue +3 -0
  165. package/icons/flask-conical.vue +3 -0
  166. package/icons/folder-open.vue +3 -0
  167. package/icons/gift-outline.vue +3 -0
  168. package/icons/globe-2.vue +3 -0
  169. package/icons/graph-loading.vue +2 -2
  170. package/icons/hand/hand-thumb-up-filled.vue +1 -1
  171. package/icons/home.vue +14 -0
  172. package/icons/invoice.vue +1 -0
  173. package/icons/key-round.vue +3 -0
  174. package/icons/letter/letter-a.vue +4 -2
  175. package/icons/letter/letter-b.vue +2 -2
  176. package/icons/letter/letter-c.vue +2 -2
  177. package/icons/letter/letter-d.vue +2 -2
  178. package/icons/letter/letter-e.vue +2 -2
  179. package/icons/logo.vue +1 -1
  180. package/icons/main-filter.vue +1 -1
  181. package/icons/menu.vue +4 -4
  182. package/icons/message/message.vue +1 -1
  183. package/icons/messages-square.vue +3 -0
  184. package/icons/more.vue +1 -1
  185. package/icons/payment/payment-card.vue +2 -2
  186. package/icons/radio/radio-check.vue +1 -1
  187. package/icons/robot-outline.vue +3 -0
  188. package/icons/scales/scale-outline.vue +3 -0
  189. package/icons/search-outline.vue +3 -0
  190. package/icons/send.vue +3 -0
  191. package/icons/star/star-filled.vue +1 -0
  192. package/icons/star/star-half-filled.vue +1 -0
  193. package/icons/sun.vue +1 -0
  194. package/icons/terminal.vue +3 -0
  195. package/icons/toasts/warning-triangle-toast.vue +1 -0
  196. package/icons/triangle-alert.vue +3 -0
  197. package/icons/users-outline.vue +3 -0
  198. package/icons/webhook.vue +3 -0
  199. package/icons/x-outline.vue +3 -0
  200. package/icons/yandex.vue +2 -1
  201. package/illustrations/address-location.vue +2 -2
  202. package/illustrations/award-badge.vue +105 -0
  203. package/illustrations/ball-with-chain.vue +7 -7
  204. package/illustrations/bill.vue +5 -5
  205. package/illustrations/buildings.vue +4 -4
  206. package/illustrations/calendar.vue +11 -11
  207. package/illustrations/chains.vue +12 -12
  208. package/illustrations/coin-percent.vue +3 -3
  209. package/illustrations/coins-stack.vue +4 -4
  210. package/illustrations/delete-dark.vue +1 -0
  211. package/illustrations/delete.vue +1 -0
  212. package/illustrations/doc-with-stamp.vue +5 -5
  213. package/illustrations/document.vue +3 -3
  214. package/illustrations/door.vue +79 -68
  215. package/illustrations/empty-badge-check.vue +20 -0
  216. package/illustrations/empty-ban.vue +18 -0
  217. package/illustrations/empty-box.vue +5 -5
  218. package/illustrations/empty-filter.vue +20 -0
  219. package/illustrations/empty-inbox.vue +19 -0
  220. package/illustrations/empty-scale.vue +22 -0
  221. package/illustrations/empty-search-x.vue +21 -0
  222. package/illustrations/empty-shopping-cart.vue +21 -0
  223. package/illustrations/empty-users-round.vue +20 -0
  224. package/illustrations/empty-wallet.vue +121 -155
  225. package/illustrations/graph-in-coin.vue +2 -2
  226. package/illustrations/hammer.vue +5 -5
  227. package/illustrations/hand-cash.vue +1 -1
  228. package/illustrations/info.vue +49 -36
  229. package/illustrations/mail-active.vue +86 -0
  230. package/illustrations/mail.vue +4 -4
  231. package/illustrations/no-access.vue +92 -0
  232. package/illustrations/ok.vue +86 -58
  233. package/illustrations/people-group.vue +1 -1
  234. package/illustrations/person-with-phone.vue +5 -5
  235. package/illustrations/person.vue +3 -3
  236. package/illustrations/phone-check.vue +104 -84
  237. package/illustrations/phone-payment-method.vue +1 -1
  238. package/illustrations/shield-user.vue +94 -0
  239. package/illustrations/stop-hand.vue +78 -71
  240. package/illustrations/stop-sign.vue +1 -1
  241. package/illustrations/suit.vue +93 -107
  242. package/illustrations/suitcase.vue +6 -6
  243. package/illustrations/terminal.vue +94 -228
  244. package/illustrations/trash-can.vue +60 -102
  245. package/illustrations/turn-on-tariff.vue +2 -2
  246. package/illustrations/two-persons.vue +2 -2
  247. package/lang/en.ts +25 -29
  248. package/lang/kk.ts +24 -28
  249. package/lang/ru.ts +24 -29
  250. package/nuxt.config.ts +11 -4
  251. package/package.json +7 -12
  252. package/assets/styles/index.scss +0 -166
  253. package/assets/styles/modules/_base.scss +0 -5
  254. package/assets/styles/modules/_typography.scss +0 -152
  255. package/components/elements/error-template/types.ts +0 -23
  256. package/illustrations/terminal-dark.vue +0 -48
  257. package/tailwind.config.ts +0 -194
  258. package/tests/AButton.test.ts +0 -81
@@ -1,33 +1,31 @@
1
1
  <script setup lang="ts">
2
2
  import { NuxtLinkLocale } from '#components'
3
- import { computed } from 'vue'
4
3
 
5
4
  // Same logic/props as ACurveBlock — only the visual design differs.
6
- const props = withDefaults(defineProps<{
5
+ withDefaults(defineProps<{
7
6
  icon: Component
8
7
  title: string
9
8
  description: string
10
9
  to?: string
11
- /** Accent color as a hex code, e.g. "#068dff". */
12
10
  color?: string
11
+ tint?: string
12
+ forceActive?: boolean
13
13
  }>(), {
14
- color: '#068dff',
14
+ color: 'var(--color-icon-brand)',
15
+ tint: undefined,
16
+ forceActive: true,
15
17
  })
16
-
17
- const bg = computed(() => `${props.color}1A`) // ~10% opacity в hex
18
18
  </script>
19
19
 
20
20
  <template>
21
- <component
22
- :is="to ? NuxtLinkLocale : 'button'"
21
+ <nuxt-link-locale
23
22
  :to="to"
24
- :style="{ '--cb-color': color, '--cb-bg': bg }"
25
- class="curve-block-v2 group relative flex w-full cursor-pointer flex-col gap-4 rounded-2xl border border-gray-100 bg-white p-6 text-left transition-all duration-200 hover:-translate-y-1 hover:border-gray-300 hover:shadow-lg dark:border-gray-700 dark:bg-gray-800"
26
- :class="{ 'active-item': !to }"
23
+ :style="{ '--cb-color': color, '--cb-tint': tint }"
24
+ class="curve-block-v2 group relative flex w-full cursor-pointer flex-col gap-4 rounded-2xl border border-default bg-main p-6 text-left"
25
+ :class="{ 'active-item': !to && forceActive }"
27
26
  active-class="active-item"
28
27
  >
29
- <!-- arrow, top-right -->
30
- <div class="arrow-icon absolute right-4 top-4 flex size-7 items-center justify-center rounded-full p-2 bg-[#068dff]/10 text-[#068dff]">
28
+ <div class="arrow-icon absolute top-4 right-4 flex size-8 items-center justify-center rounded-full bg-canvas p-2 text-secondary transition-all duration-200 group-hover:translate-x-0.5 group-hover:-translate-y-0.5">
31
29
  <svg
32
30
  class="size-2"
33
31
  viewBox="16 16 16 16"
@@ -43,7 +41,6 @@ const bg = computed(() => `${props.color}1A`) // ~10% opacity в hex
43
41
  </svg>
44
42
  </div>
45
43
 
46
- <!-- icon -->
47
44
  <div class="icon-item w-fit rounded-xl p-3">
48
45
  <component
49
46
  :is="icon"
@@ -52,34 +49,72 @@ const bg = computed(() => `${props.color}1A`) // ~10% opacity в hex
52
49
  </div>
53
50
 
54
51
  <div class="flex flex-col gap-2 pr-6">
55
- <p class="title text-base font-semibold text-deepblue-900 dark:text-white">
52
+ <p class="title text-h5 text-primary transition-colors duration-200">
56
53
  {{ title }}
57
54
  </p>
58
- <p class="text-sm leading-relaxed text-gray-500 dark:text-gray-300">
55
+ <p class="text-body-md leading-relaxed text-quaternary">
59
56
  {{ description }}
60
57
  </p>
61
58
  </div>
62
- </component>
59
+ </nuxt-link-locale>
63
60
  </template>
64
61
 
65
- <style lang="scss" scoped>
66
- /* icon uses the card's accent color at 10% bg + full-color glyph */
62
+ <style scoped>
63
+ .curve-block-v2 {
64
+ --cb-fill: var(--cb-tint, color-mix(in srgb, var(--cb-color) 10%, transparent));
65
+ transition:
66
+ transform 0.2s ease,
67
+ border-color 0.2s ease,
68
+ box-shadow 0.2s ease;
69
+ }
70
+
67
71
  .icon-item {
68
- background-color: var(--cb-bg);
72
+ background-color: var(--cb-fill);
73
+ color: var(--cb-color);
74
+ }
75
+
76
+ .curve-block-v2:hover {
77
+ transform: translateY(-4px);
78
+ border-color: var(--cb-color);
79
+ box-shadow: 0 0 22px -12px var(--cb-color);
80
+ }
81
+
82
+ .curve-block-v2:hover .title,
83
+ .curve-block-v2:hover .arrow-icon {
69
84
  color: var(--cb-color);
70
85
  }
71
86
 
72
- /* active state (route match, or forced when there is no `to`) */
87
+ .curve-block-v2:hover .arrow-icon {
88
+ background-color: var(--cb-fill);
89
+ }
90
+
73
91
  .active-item {
74
92
  border-color: var(--cb-color);
75
- background-color: var(--cb-bg);
93
+ box-shadow: 0 0 22px -12px var(--cb-color);
94
+ }
95
+
96
+ .active-item:hover {
97
+ transform: none;
76
98
  }
99
+
77
100
  .active-item .title,
78
101
  .active-item .arrow-icon {
79
102
  color: var(--cb-color);
80
103
  }
81
- .active-item .icon-item {
82
- background-color: var(--cb-color);
83
- color: #fff;
104
+
105
+ .active-item .arrow-icon {
106
+ background-color: var(--cb-fill);
107
+ }
108
+
109
+ @media (prefers-reduced-motion: reduce) {
110
+ .curve-block-v2,
111
+ .curve-block-v2 .title,
112
+ .curve-block-v2 .arrow-icon {
113
+ transition: none;
114
+ }
115
+
116
+ .curve-block-v2:hover {
117
+ transform: none;
118
+ }
84
119
  }
85
120
  </style>
@@ -27,8 +27,8 @@ const formattedValue = computed(() => {
27
27
  })
28
28
  const classes = computed(() =>
29
29
  [
30
- props.disabled ? 'text-gray-500 bg-deepblue-900/5' : typeSwitchValues[props.view][props.type],
31
- 'inline-flex items-center justify-center font-medium rounded-full select-none inline-flex outline-none',
30
+ props.disabled ? 'bg-action-disabled text-action-disabled-fg' : typeSwitchValues[props.view][props.type],
31
+ 'inline-flex items-center justify-center font-medium rounded-full select-none inline-flex outline-hidden',
32
32
  sizeSwitchValues[props.size],
33
33
  props.value && props.value.toString().length > 1 ? 'w-auto' : '',
34
34
  ])
@@ -48,24 +48,25 @@ type SizeSwitchValues = {
48
48
 
49
49
  const typeSwitchValues: ViewType = {
50
50
  default: {
51
- primary: 'bg-blue-700 text-white dark:bg-blue-500 dark:text-gray-900',
52
- success: 'bg-green-500 text-white dark:bg-green-400 dark:text-gray-900',
53
- danger: 'bg-red-500 text-white dark:bg-red-400 dark:text-gray-900',
54
- warning: 'bg-yellow-400 text-white dark:text-gray-900',
55
- gray: 'bg-gray-50 text-gray-500 dark:text-gray-900',
56
- orange: 'bg-orange-600 text-white dark:bg-orange-500 dark:text-gray-900',
51
+ primary: 'bg-action-primary text-action-primary-fg',
52
+ /* осознанно константный text-white: белая цифра на цветных solid-фонах в обеих темах */
53
+ success: 'bg-success text-white',
54
+ danger: 'bg-danger text-white',
55
+ warning: 'bg-warning text-white',
56
+ gray: 'bg-muted text-secondary',
57
+ orange: 'bg-warning text-white',
57
58
  },
58
59
  inverted: {
59
- primary: 'bg-white text-blue-700 dark:text-blue-500 dark:bg-gray-900',
60
- success: 'bg-white text-green-500 dark:text-green-400 dark:bg-gray-900',
61
- danger: 'bg-white text-red-500 dark:text-red-400 dark:bg-gray-900',
62
- warning: 'bg-white text-yellow-400 dark:bg-gray-900',
63
- gray: 'bg-white text-gray-500 dark:text-gray-200 dark:bg-gray-200/10',
64
- orange: 'bg-white text-deepblue-900 dark:text-orange-500 dark:bg-gray-900',
60
+ primary: 'bg-main text-brand',
61
+ success: 'bg-main text-success',
62
+ danger: 'bg-main text-danger',
63
+ warning: 'bg-main text-warning',
64
+ gray: 'bg-main text-secondary',
65
+ orange: 'bg-main text-primary',
65
66
  },
66
67
  transparent: {
67
- success: 'bg-green-500/20 text-green-500',
68
- danger: 'bg-red-500/20 text-red-500 dark:text-red-400',
68
+ success: 'bg-success-subtle text-success',
69
+ danger: 'bg-danger-subtle text-danger',
69
70
  },
70
71
  }
71
72
 
@@ -0,0 +1,92 @@
1
+ <script setup lang="ts">
2
+ import type { Component } from 'vue'
3
+ import EmptyBan from '#adata-ui/illustrations/empty-ban.vue'
4
+
5
+ interface Props {
6
+ icon: Component
7
+ title?: string
8
+ subtitle?: string
9
+ }
10
+
11
+ defineProps<Props>()
12
+ </script>
13
+
14
+ <template>
15
+ <div
16
+ class="flex min-h-[220px] flex-col items-center justify-center gap-4 p-6 text-center md:p-10"
17
+ >
18
+ <!-- Ореол -->
19
+ <div class="relative grid place-items-center">
20
+ <!-- свечение -->
21
+ <span
22
+ aria-hidden="true"
23
+ class="pointer-events-none absolute size-[130px] rounded-full bg-[radial-gradient(circle,var(--color-brand-500)/15%,transparent_70%)]"
24
+ />
25
+
26
+ <!-- пульсирующее кольцо -->
27
+ <span
28
+ aria-hidden="true"
29
+ class="halo-ring absolute size-[72px] rounded-full border border-brand-500/20 motion-reduce:animate-none"
30
+ />
31
+
32
+ <!-- иконка -->
33
+ <div
34
+ class="relative grid size-[72px] place-items-center rounded-full border border-brand-500/20 bg-brand-500/5 text-brand-500"
35
+ >
36
+ <component
37
+ :is="icon"
38
+ class="size-[30px]"
39
+ :stroke-width="2"
40
+ aria-hidden="true"
41
+ />
42
+
43
+ <!-- нет данных -->
44
+ <span
45
+ class="absolute -bottom-1.5 -right-1.5 grid size-[26px] place-items-center rounded-full border border-default bg-main text-icon-default shadow-sm"
46
+ >
47
+ <empty-ban class="size-3.5" />
48
+ </span>
49
+ </div>
50
+ </div>
51
+
52
+ <!-- текст -->
53
+ <div class="flex flex-col items-center gap-2">
54
+ <h3 class="font-semibold text-primary">
55
+ {{ title }}
56
+ </h3>
57
+
58
+ <p
59
+ v-if="subtitle"
60
+ class="mt-1 text-secondary"
61
+ >
62
+ {{ subtitle }}
63
+ </p>
64
+ </div>
65
+
66
+ <slot />
67
+ </div>
68
+ </template>
69
+
70
+ <style scoped>
71
+ .halo-ring {
72
+ animation: halo-pulse 3.2s ease-out infinite;
73
+ }
74
+
75
+ @keyframes halo-pulse {
76
+ 0% {
77
+ transform: scale(0.72);
78
+ opacity: 0.85;
79
+ }
80
+
81
+ 100% {
82
+ transform: scale(1.16);
83
+ opacity: 0;
84
+ }
85
+ }
86
+
87
+ @media (prefers-reduced-motion: reduce) {
88
+ .halo-ring {
89
+ animation: none;
90
+ }
91
+ }
92
+ </style>
@@ -1,48 +1,116 @@
1
1
  <script setup lang="ts">
2
- import type { ErrorTemplateData } from './types'
2
+ import { AIconArrowLeft, AIconHome } from '#components'
3
3
 
4
4
  interface Props {
5
- error: ErrorTemplateData
5
+ statusCode: number
6
6
  }
7
+ const props = defineProps<Props>()
7
8
 
8
- defineProps<Props>()
9
+ const { t } = useI18n()
10
+ const localePath = useLocalePath()
11
+ const router = useRouter()
12
+
13
+ const errorTitle = computed(() => t(`errorPage.${props.statusCode}.title`))
14
+ const errorSubTitle = computed(() => t(`errorPage.${props.statusCode}.subTitle`))
15
+
16
+ function goToMainPage() {
17
+ return navigateTo(`${localePath('/')}`, { external: true })
18
+ }
19
+
20
+ function goBack() {
21
+ if (import.meta.client && window.history.length > 1) {
22
+ router.back()
23
+ }
24
+ else {
25
+ return navigateTo(`${localePath('/')}`, { external: true })
26
+ }
27
+ }
9
28
  </script>
10
29
 
11
30
  <template>
12
- <div class="flex items-center justify-center gap-14">
13
- <slot name="icon">
14
- <div class="hidden lg:block max-w-[600px]">
15
- <img
16
- :src="error.icon"
17
- class="hidden lg:block"
18
- alt="error-icon"
31
+ <div class="relative flex min-h-screen flex-col items-center justify-center gap-6 px-4 text-center">
32
+ <div class="pointer-events-none absolute inset-0 -z-10 flex items-center justify-center">
33
+ <div class="error-gradient" />
34
+ </div>
35
+
36
+ <p class="text-overline text-secondary uppercase tracking-widest">
37
+ {{ t('errorPage.error') }} {{ statusCode }}
38
+ </p>
39
+ <p class="bignum text-[90px] leading-none md:text-[210px]">
40
+ {{ statusCode }}
41
+ </p>
42
+ <h1 class="text-h2 md:text-display-lg">
43
+ {{ errorTitle }}
44
+ </h1>
45
+ <h2 class="text-body-md md:text-body-lg text-secondary max-w-[560px]">
46
+ {{ errorSubTitle }}
47
+ </h2>
48
+ <slot name="button">
49
+ <div class="flex w-full flex-col gap-3 md:w-fit md:flex-row md:gap-4">
50
+ <a-button-v2
51
+ :icon="AIconHome"
52
+ size="lg"
53
+ rounded="md"
54
+ block
55
+ @click="goToMainPage"
19
56
  >
57
+ {{ t('actions.goToMainPage') }}
58
+ </a-button-v2>
59
+ <a-button-v2
60
+ :icon="AIconArrowLeft"
61
+ view="outline"
62
+ color="gray"
63
+ size="lg"
64
+ rounded="md"
65
+ block
66
+ @click="goBack"
67
+ >
68
+ {{ t('actions.back') }}
69
+ </a-button-v2>
20
70
  </div>
21
71
  </slot>
22
- <div class="flex min-h-screen flex-col lg:min-h-0">
23
- <div class="flex-1 px-4 py-8 lg:p-0">
24
- <slot name="status">
25
- <p class="mb-6 text-4xl font-bold">
26
- {{ error.statusCode }}
27
- </p>
28
- </slot>
29
- <slot name="title">
30
- <h2 class="lg:heading-03 text-2xl font-bold ">
31
- {{ error.title }}
32
- </h2>
33
- </slot>
34
- <slot
35
- name="content"
36
- :data="error"
37
- />
38
- </div>
39
- <div class="sticky bottom-0 z-[10000] lg:static lg:flex">
40
- <slot name="default" />
41
- </div>
42
- </div>
43
72
  </div>
44
73
  </template>
45
74
 
46
75
  <style scoped>
76
+ .error-gradient {
77
+ width: 760px;
78
+ height: 520px;
79
+ max-width: 90vw;
80
+ background: color-mix(in srgb, var(--color-brand-500) 18%, transparent);
81
+ filter: blur(80px);
82
+ border-radius: 50%;
83
+ }
84
+
85
+ .dark .error-gradient {
86
+ background: color-mix(in srgb, var(--color-brand-500) 14%, transparent);
87
+ filter: blur(130px);
88
+ }
89
+
90
+ .bignum {
91
+ position: relative;
92
+ font-weight: 700;
93
+ letter-spacing: -0.04em;
94
+ background: linear-gradient(
95
+ 180deg,
96
+ color-mix(in srgb, var(--color-brand-500) 50%, transparent) 0%,
97
+ color-mix(in srgb, var(--color-brand-500) 50%, transparent) 50%,
98
+ color-mix(in srgb, var(--color-brand-500) 12%, transparent) 100%
99
+ );
100
+ background-clip: text;
101
+ -webkit-background-clip: text;
102
+ color: transparent;
103
+ -webkit-text-fill-color: transparent;
104
+ }
47
105
 
106
+ .dark .bignum {
107
+ background: linear-gradient(
108
+ 180deg,
109
+ var(--color-brand-400) 0%,
110
+ var(--color-brand-400) 50%,
111
+ color-mix(in srgb, var(--color-brand-400) 28%, transparent) 100%
112
+ );
113
+ background-clip: text;
114
+ -webkit-background-clip: text;
115
+ }
48
116
  </style>
@@ -50,30 +50,30 @@ onUnmounted(() => clearTimer())
50
50
  >
51
51
  <div
52
52
  v-if="selected === idx"
53
- class="absolute left-0 top-0 w-[2px] bg-blue-700 dark:bg-blue-500 z-20 h-full rounded-full"
53
+ class="absolute left-0 top-0 z-20 h-full w-[2px] rounded-full bg-brand"
54
54
  :class="{ 'fill-animation': selected === idx }"
55
55
  />
56
56
 
57
57
  <div
58
- class="absolute left-0 top-0 w-[2px] bg-gray-500/50 z-10 h-full rounded-full"
58
+ class="absolute left-0 top-0 z-10 h-full w-[2px] rounded-full bg-(--border-color-strong)/50"
59
59
  />
60
60
 
61
61
  <div class="flex items-center gap-2 relative z-10">
62
62
  <div
63
63
  :class="[
64
64
  'transition-all duration-300 ease-in-out',
65
- selected === idx ? 'rounded-sm bg-blue-700 dark:bg-blue-500 p-2 icon-bg' : 'size-fit'
65
+ selected === idx ? 'rounded-sm bg-action-primary p-2 icon-bg' : 'size-fit'
66
66
  ]"
67
67
  >
68
68
  <component
69
69
  :is="item.icon"
70
70
  class="shrink-0 size-6 transition-colors duration-300 ease-in-out"
71
- :class="selected === idx ? 'text-white dark:text-gray-900' : 'text-gray-600 dark:text-[#9DA3AC]'"
71
+ :class="selected === idx ? 'text-action-primary-fg' : 'text-quaternary'"
72
72
  />
73
73
  </div>
74
74
  <p
75
- class="font-semibold text-base lg:text-xl transition-colors duration-300 ease-in-out"
76
- :class="selected === idx ? 'dark:text-[#E3E5E8]' : 'text-gray-600 dark:text-[#9DA3AC]'"
75
+ class="text-body-lg-strong lg:text-h3 transition-colors duration-300 ease-in-out"
76
+ :class="selected === idx ? '' : 'text-quaternary'"
77
77
  >
78
78
  {{ item.title }}
79
79
  </p>
@@ -88,7 +88,7 @@ onUnmounted(() => clearTimer())
88
88
  <div
89
89
  v-if="selected === idx"
90
90
  >
91
- <p class="text-xs lg:text-sm pt-3">
91
+ <p class="text-body-sm lg:text-body-md pt-3">
92
92
  {{ item.description }}
93
93
  </p>
94
94
  </div>
@@ -98,7 +98,7 @@ onUnmounted(() => clearTimer())
98
98
 
99
99
  <style lang="scss" scoped>
100
100
  .icon-bg {
101
- box-shadow: -4px 4px 0px 0px #007AFF1A;
101
+ box-shadow: -4px 4px 0 0 color-mix(in srgb, var(--background-color-brand) 10%, transparent);
102
102
  }
103
103
 
104
104
  .fill-animation {
@@ -45,7 +45,7 @@ function goAuth() {
45
45
  </script>
46
46
 
47
47
  <template>
48
- <div class="flex flex-col items-center gap-4 text-center text-sm">
48
+ <div class="flex flex-col items-center gap-4 text-center text-body-md">
49
49
  <div v-if="!noIll">
50
50
  <slot name="illustration">
51
51
  <a-ill-door :class="illClass" />
@@ -1,10 +1,31 @@
1
1
  <script setup lang="ts">
2
-
2
+ /* fade: gradient — краевые градиенты на bg-main (историческое поведение,
3
+ верно только когда карусель лежит на основной поверхности);
4
+ mask — краевая маска, не зависящая от фона под каруселью. */
5
+ withDefaults(defineProps<{
6
+ duration?: number
7
+ pauseOnHover?: boolean
8
+ fade?: 'gradient' | 'mask' | 'none'
9
+ }>(), {
10
+ duration: 25,
11
+ pauseOnHover: false,
12
+ fade: 'gradient',
13
+ })
3
14
  </script>
4
15
 
5
16
  <template>
6
- <div class="carousel overflow-hidden w-full relative">
7
- <div class="flex w-max animate-scroll">
17
+ <div
18
+ class="carousel relative w-full overflow-hidden"
19
+ :class="[
20
+ fade === 'gradient' ? 'carousel--fade-gradient' : '',
21
+ fade === 'mask' ? 'carousel--fade-mask' : '',
22
+ pauseOnHover ? 'carousel--pausable' : '',
23
+ ]"
24
+ >
25
+ <div
26
+ class="animate-scroll flex w-max"
27
+ :style="{ animationDuration: `${duration}s` }"
28
+ >
8
29
  <div
9
30
  v-for="i in 2"
10
31
  :key="i"
@@ -16,17 +37,22 @@
16
37
  </div>
17
38
  </template>
18
39
 
19
- <style lang="scss">
40
+ <style scoped>
20
41
  @keyframes scroll {
21
42
  0% { transform: translateX(0); }
22
43
  100% { transform: translateX(-50%); }
23
44
  }
45
+
24
46
  .animate-scroll {
25
47
  animation: scroll 25s linear infinite;
26
48
  }
27
49
 
28
- .carousel:before,
29
- .carousel:after {
50
+ .carousel--pausable:hover .animate-scroll {
51
+ animation-play-state: paused;
52
+ }
53
+
54
+ .carousel--fade-gradient:before,
55
+ .carousel--fade-gradient:after {
30
56
  position: absolute;
31
57
  top: 0;
32
58
  width: 120px;
@@ -35,23 +61,25 @@
35
61
  z-index: 2;
36
62
  }
37
63
 
38
- .carousel:before {
64
+ .carousel--fade-gradient:before {
39
65
  left: 0;
40
- background: linear-gradient(to left, rgba(255, 255, 255, 0), white);
66
+ background: linear-gradient(to left, transparent, var(--background-color-main));
41
67
  }
42
68
 
43
- .carousel:after {
69
+ .carousel--fade-gradient:after {
44
70
  right: 0;
45
- background: linear-gradient(to right, rgba(255, 255, 255, 0), white);
71
+ background: linear-gradient(to right, transparent, var(--background-color-main));
46
72
  }
47
73
 
48
- .dark {
49
- .carousel:before {
50
- background: linear-gradient(to left, rgba(38, 40, 43, 0), #161617);
51
- }
74
+ /* Маска читает только альфу, поэтому #000 здесь — не цвет (осознанное
75
+ исключение из запрета сырых hex). */
76
+ .carousel--fade-mask {
77
+ mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent);
78
+ }
52
79
 
53
- .carousel:after {
54
- background: linear-gradient(to right, rgba(38, 40, 43, 0), #161617);
80
+ @media (prefers-reduced-motion: reduce) {
81
+ .animate-scroll {
82
+ animation: none;
55
83
  }
56
84
  }
57
85
  </style>
@@ -54,13 +54,13 @@ defineExpose({
54
54
 
55
55
  <template>
56
56
  <div class="flex flex-col items-start rounded-sm">
57
- <p class="text-sm font-semibold mb-4">
57
+ <p class="text-body-md-strong mb-4">
58
58
  {{ t('forms.leaveNote.title') }}
59
59
  </p>
60
60
  <a-textarea
61
61
  v-model="note"
62
62
  class="min-h-[120px]"
63
- color-classes="bg-deepblue-900/5 outline outline-1 outline-gray-200 dark:outline-gray-600 dark:bg-gray-200/5 !rounded-[10px]"
63
+ color-classes="bg-muted outline outline-1 outline-(--border-color-default) !rounded-[10px]"
64
64
  size="sm"
65
65
  resizeable="y"
66
66
  data-test-id="favorites-notes-textarea"
@@ -35,17 +35,17 @@ const showFirstPageIndex = computed(() => modelValue.value > 3)
35
35
  v-if="showFirstPageIndex"
36
36
  :class="[
37
37
  defaultClasses,
38
- { 'bg-blue-700 text-white hover:bg-blue-900': modelValue === 1 },
38
+ { 'bg-action-primary text-action-primary-fg hover:bg-action-primary-hover': modelValue === 1 },
39
39
  !!activeClasses && 1 === modelValue ? activeClasses : ''
40
40
  ]"
41
- class="flex size-[40px] cursor-pointer items-center justify-center rounded-md transition hover:bg-[#2C3E500D] dark:hover:bg-[#E3E5E80D]"
41
+ class="flex size-[40px] cursor-pointer items-center justify-center rounded-md transition hover:bg-action-secondary-hover"
42
42
  @click="modelValue = 1"
43
43
  >
44
44
  <double-chevron-right class="rotate-180 text-base" />
45
45
  </li>
46
46
  <li
47
47
  v-show="prevPage"
48
- class="flex size-[40px] cursor-pointer items-center justify-center rounded-md transition hover:bg-[#2C3E500D] dark:text-white"
48
+ class="flex size-[40px] cursor-pointer items-center justify-center rounded-md transition hover:bg-action-secondary-hover"
49
49
  @click="modelValue -= 1"
50
50
  >
51
51
  <a-icon-chevron-left />
@@ -56,7 +56,7 @@ const showFirstPageIndex = computed(() => modelValue.value > 3)
56
56
  :key="page"
57
57
  :class="[
58
58
  defaultClasses,
59
- 'flex size-[40px] cursor-pointer items-center justify-center rounded-md transition hover:bg-[#2C3E500D] dark:hover:bg-[#E3E5E80D]'
59
+ 'flex size-[40px] cursor-pointer items-center justify-center rounded-md transition hover:bg-action-secondary-hover'
60
60
  ]"
61
61
  @click="modelValue = page"
62
62
  >
@@ -66,7 +66,7 @@ const showFirstPageIndex = computed(() => modelValue.value > 3)
66
66
  <li
67
67
  :class="[
68
68
  defaultClasses,
69
- 'bg-blue-700 text-white hover:bg-blue-900',
69
+ 'bg-action-primary text-action-primary-fg hover:bg-action-primary-hover',
70
70
  'flex size-[40px] cursor-pointer items-center justify-center rounded-md transition'
71
71
  ]"
72
72
  >
@@ -78,7 +78,7 @@ const showFirstPageIndex = computed(() => modelValue.value > 3)
78
78
  :key="idx"
79
79
  :class="[
80
80
  defaultClasses,
81
- 'flex size-[40px] cursor-pointer items-center justify-center rounded-md transition hover:bg-[#2C3E500D] dark:hover:bg-[#E3E5E80D]'
81
+ 'flex size-[40px] cursor-pointer items-center justify-center rounded-md transition hover:bg-action-secondary-hover'
82
82
  ]"
83
83
  @click="modelValue = n"
84
84
  >
@@ -88,7 +88,7 @@ const showFirstPageIndex = computed(() => modelValue.value > 3)
88
88
  <li
89
89
  v-show="nextPage"
90
90
  :class="{ disabled: disabled }"
91
- class="flex size-[40px] cursor-pointer items-center justify-center rounded-md hover:bg-[#2C3E500D] dark:hover:bg-[#E3E5E80D]"
91
+ class="flex size-[40px] cursor-pointer items-center justify-center rounded-md hover:bg-action-secondary-hover"
92
92
  @click="modelValue += 1"
93
93
  >
94
94
  <a-icon-chevron-right />
@@ -100,7 +100,7 @@ const showFirstPageIndex = computed(() => modelValue.value > 3)
100
100
  { disabled: disabled },
101
101
  !!activeClasses && lastPage === modelValue ? activeClasses : ''
102
102
  ]"
103
- class="flex size-[40px] cursor-pointer items-center justify-center rounded-md hover:bg-[#2C3E500D] dark:hover:bg-[#E3E5E80D]"
103
+ class="flex size-[40px] cursor-pointer items-center justify-center rounded-md hover:bg-action-secondary-hover"
104
104
  @click="modelValue = lastPage"
105
105
  >
106
106
  <double-chevron-right class="text-base" />