adata-ui 2.1.38 → 2.1.40-beta

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 (41) hide show
  1. package/.nuxtrc +1 -1
  2. package/.playground/app.config.ts +5 -5
  3. package/.playground/app.vue +102 -0
  4. package/README.md +75 -75
  5. package/components/elements/README.md +1 -1
  6. package/components/elements/button-login/index.vue +6 -10
  7. package/components/elements/tree-select/ATreeSelect.vue +5 -1
  8. package/components/elements/tree-select/components/tree-select-nodes.vue +4 -3
  9. package/components/features/color-mode/AColorMode.client.vue +74 -32
  10. package/components/features/dropdown/ADropdownV2.vue +141 -0
  11. package/components/features/lang-switcher/lang-switcher.vue +120 -40
  12. package/components/features//321/201hange-version/AChangeVersion.vue +1 -1
  13. package/components/forms/README.md +1 -1
  14. package/components/navigation/README.md +1 -1
  15. package/components/navigation/footer/AFooter.vue +1 -1
  16. package/components/navigation/header/AHeader.vue +56 -33
  17. package/components/navigation/header/AlmatyContacts.vue +1 -1
  18. package/components/navigation/header/CardGallery.vue +5 -3
  19. package/components/navigation/header/ContactMenu.vue +26 -92
  20. package/components/navigation/header/HeaderLink.vue +189 -215
  21. package/components/navigation/header/HeaderUsage.vue +125 -0
  22. package/components/navigation/header/NavList.vue +35 -50
  23. package/components/navigation/header/ProductMenu.vue +72 -126
  24. package/components/navigation/header/ProfileMenu.vue +131 -150
  25. package/components/navigation/header/SystemNotification.vue +110 -0
  26. package/components/navigation/mobile-navigation/AMobileNavigation.vue +23 -15
  27. package/components/navigation/pill-tabs/APillTabs.vue +7 -2
  28. package/components/overlays/README.md +1 -1
  29. package/components/overlays/tooltip/ATooltipV2.vue +233 -0
  30. package/components/overlays/tooltip/types.ts +26 -0
  31. package/components/overlays/tooltip/useTooltipTrigger.ts +101 -0
  32. package/composables/useHeaderNavigationLinks.ts +15 -8
  33. package/composables/useUrls.ts +1 -1
  34. package/icons/gauge.vue +17 -0
  35. package/icons/sun.vue +13 -3
  36. package/lang/en.ts +6 -0
  37. package/lang/kk.ts +6 -0
  38. package/lang/ru.ts +6 -0
  39. package/package.json +1 -1
  40. package/shared/constans/pages.ts +1 -1
  41. package/components/navigation/header/TopHeader.vue +0 -196
@@ -1,73 +1,153 @@
1
1
  <script setup lang="ts">
2
- import { onClickOutside } from "@vueuse/core";
2
+ import Check from '#adata-ui/icons/check/check.vue'
3
+ import { autoUpdate, flip, offset, shift, useFloating } from '@floating-ui/vue'
4
+ import { onClickOutside } from '@vueuse/core'
5
+
6
+ type LocaleItem = string | { code: string }
3
7
 
4
8
  const props = withDefaults(defineProps<{
5
9
  isMobile?: boolean
6
10
  }>(), {
7
- isMobile: false
11
+ isMobile: false,
8
12
  })
9
13
 
10
- const langSwitcher = ref<HTMLDivElement | null>(null)
11
-
12
14
  const switchLocalePath = useSwitchLocalePath()
13
- const { locale, locales } = useI18n()
14
- const availableLocales = computed(() => {
15
- return (locales.value).filter(i => i.code !== locale.value)
16
- })
15
+ const { t, locale, locales } = useI18n()
16
+
17
+ const testIdSuffix = computed(() => props.isMobile ? '-mobile' : '')
17
18
 
19
+ const wrapper = ref<HTMLDivElement | null>(null)
20
+ const reference = ref<HTMLButtonElement | null>(null)
21
+ const floating = ref<HTMLDivElement | null>(null)
18
22
  const isOpen = ref(false)
19
23
 
20
- onClickOutside(langSwitcher,() => {
21
- isOpen.value = false
24
+ const placement = computed(() => props.isMobile ? 'bottom-end' as const : 'bottom-start' as const)
25
+
26
+ const { x, y, strategy, update } = useFloating(reference, floating, {
27
+ placement,
28
+ strategy: 'absolute',
29
+ middleware: computed(() => [
30
+ offset(6),
31
+ flip({ fallbackPlacements: props.isMobile ? ['top-end'] : ['top-start'] }),
32
+ shift({ padding: 8 }),
33
+ ]),
22
34
  })
23
35
 
24
- const { t } = useI18n()
36
+ let cleanup: (() => void) | null = null
37
+ watch(isOpen, (open) => {
38
+ if (open && reference.value && floating.value) {
39
+ cleanup = autoUpdate(reference.value, floating.value, update)
40
+ }
41
+ else {
42
+ cleanup?.()
43
+ cleanup = null
44
+ }
45
+ })
46
+ onUnmounted(() => cleanup?.())
25
47
 
26
- const testIdSuffix = computed(() => props.isMobile ? '-mobile' : '')
48
+ onClickOutside(wrapper, () => {
49
+ if (isOpen.value) isOpen.value = false
50
+ })
27
51
 
28
- function onClick(loc: any) {
29
- if ((loc?.code || loc) === locale.value) return
52
+ function localeCode(loc: LocaleItem): string {
53
+ return typeof loc === 'string' ? loc : loc.code
54
+ }
30
55
 
56
+ function onSelect(loc: LocaleItem) {
31
57
  isOpen.value = false
32
- window.location.assign(switchLocalePath(loc?.code || loc))
58
+ const code = localeCode(loc)
59
+ if (code === locale.value) return
60
+ window.location.assign(switchLocalePath(code))
33
61
  }
34
62
  </script>
35
63
 
36
64
  <template>
37
- <div
38
- ref="langSwitcher"
39
- class="relative"
40
- >
65
+ <div ref="wrapper" class="relative">
41
66
  <button
42
- class="text-xs font-semibold py-1 px-2 bg-gray-100 dark:bg-gray-200/5 rounded"
43
- @click="isOpen = true"
44
- aria-hidden="true"
67
+ ref="reference"
68
+ type="button"
69
+ class="inline-flex size-8 items-center justify-center rounded-xl text-xs font-semibold text-gray-900 transition-colors duration-150 hover:bg-deepblue-900/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/50 focus-visible:ring-offset-1 dark:text-gray-100 dark:hover:bg-white/10 dark:focus-visible:ring-offset-gray-900"
70
+ :class="[
71
+ isOpen
72
+ ? 'bg-blue-50 text-blue-700 ring-2 ring-blue-500/20 dark:bg-blue-900/40 dark:text-blue-300'
73
+ : '',
74
+ ]"
45
75
  :data-test-id="`header-switch-language-button${testIdSuffix}`"
76
+ :aria-expanded="isOpen"
77
+ aria-haspopup="listbox"
78
+ @click="isOpen = !isOpen"
46
79
  >
47
80
  {{ t(`lang.${locale}.short`) }}
48
81
  </button>
49
- <div
50
- v-show="isOpen"
51
- :class="['absolute z-20 bg-white shadow rounded-md p-2 right-0 lg:right-auto lg:left-0 left-auto flex flex-col dark:bg-gray-900']"
82
+
83
+ <transition
84
+ enter-active-class="lang-switcher__dropdown-enter-active"
85
+ enter-from-class="lang-switcher__dropdown-enter-from"
86
+ enter-to-class="lang-switcher__dropdown-enter-to"
87
+ leave-active-class="lang-switcher__dropdown-leave-active"
88
+ leave-from-class="lang-switcher__dropdown-leave-from"
89
+ leave-to-class="lang-switcher__dropdown-leave-to"
52
90
  >
53
- <nuxt-link
54
- v-for="loc in locales"
55
- :data-test-id="`header-switch-${loc?.code}-language-button${testIdSuffix}`"
56
- :class="[
57
- 'text-sm cursor-pointer px-4 py-2.5 flex justify-between',
58
- {'text-primary bg-deepblue-500/5': locale === loc.code}
59
- ]"
60
- :to="switchLocalePath(loc?.code || loc)"
61
- @click.prevent="onClick(loc)"
91
+ <div
92
+ v-if="isOpen"
93
+ ref="floating"
94
+ class="z-[10000] w-fit rounded-xl border border-gray-200 bg-white shadow-lg shadow-gray-900/10 dark:border-gray-700 dark:bg-gray-900 dark:shadow-black/30"
95
+ :style="{
96
+ position: strategy,
97
+ left: x != null ? `${x}px` : '',
98
+ top: y != null ? `${y}px` : '',
99
+ }"
62
100
  >
63
- {{ t(`lang.${loc?.code || loc}.long`) }}
64
- </nuxt-link>
65
- </div>
101
+ <ul class="flex flex-col gap-1 p-1.5" role="listbox">
102
+ <li v-for="loc in locales" :key="localeCode(loc)" role="option" :aria-selected="localeCode(loc) === locale">
103
+ <nuxt-link
104
+ :data-test-id="`header-switch-${localeCode(loc)}-language-button${testIdSuffix}`"
105
+ :to="switchLocalePath(localeCode(loc))"
106
+ class="flex w-full items-center justify-between gap-3 rounded-lg px-3 py-2 text-sm transition-colors duration-100"
107
+ :class="[
108
+ localeCode(loc) === locale
109
+ ? 'bg-blue-50 font-medium text-blue-700 dark:bg-blue-900/30 dark:text-blue-400'
110
+ : 'text-gray-700 hover:bg-gray-50 dark:text-gray-200 dark:hover:bg-gray-800/60',
111
+ ]"
112
+ @click.prevent="onSelect(loc)"
113
+ >
114
+ <span>{{ t(`lang.${localeCode(loc)}.long`) }}</span>
115
+ <check
116
+ v-if="localeCode(loc) === locale"
117
+ class="size-4 shrink-0 text-blue-600 dark:text-blue-400"
118
+ />
119
+ </nuxt-link>
120
+ </li>
121
+ </ul>
122
+ </div>
123
+ </transition>
66
124
  </div>
67
125
  </template>
68
126
 
69
- <style lang="scss" scoped>
70
- .shadow {
71
- box-shadow: 0 1px 8px 0 #8B929C4D;
127
+ <style scoped>
128
+ .lang-switcher__dropdown-enter-active,
129
+ .lang-switcher__dropdown-leave-active {
130
+ transition:
131
+ opacity 180ms cubic-bezier(0.22, 1, 0.36, 1),
132
+ transform 180ms cubic-bezier(0.22, 1, 0.36, 1);
133
+ }
134
+
135
+ .lang-switcher__dropdown-enter-from,
136
+ .lang-switcher__dropdown-leave-to {
137
+ opacity: 0;
138
+ transform: translateY(-4px);
139
+ }
140
+
141
+ .lang-switcher__dropdown-enter-to,
142
+ .lang-switcher__dropdown-leave-from {
143
+ opacity: 1;
144
+ transform: translateY(0);
145
+ }
146
+
147
+ @media (prefers-reduced-motion: reduce) {
148
+ .lang-switcher__dropdown-enter-active,
149
+ .lang-switcher__dropdown-leave-active {
150
+ transition: none;
151
+ }
72
152
  }
73
153
  </style>
@@ -10,7 +10,7 @@ const { t } = useI18n()
10
10
  <nuxt-link
11
11
  :to="url"
12
12
  target="_blank"
13
- class="flex cursor-pointer items-center justify-center gap-1 rounded-md bg-blue-700/10 px-3 py-2 text-blue-700"
13
+ class="flex cursor-pointer items-center justify-center gap-1 rounded-md bg-blue-700/10 px-3 py-2 text-blue-700 transition-colors duration-150 hover:bg-blue-700/15 dark:bg-blue-400/10 dark:text-blue-300 dark:hover:bg-blue-400/20"
14
14
  >
15
15
  <span class="body-400">{{ t('header.oldVersion') }}</span>
16
16
  <a-icon-arrow-bottom-left-on-square class="rotate-180" />
@@ -1 +1 @@
1
- # inputs
1
+ # inputs
@@ -1 +1 @@
1
- # breadcrumb, tabs
1
+ # breadcrumb, tabs
@@ -80,7 +80,7 @@ const mainLinks = computed(() => ({
80
80
  [
81
81
  {
82
82
  title: t('footer.compliance.title'),
83
- link: urls.compliance + PAGES.compliance.l,
83
+ link: buildLocalizedUrl(locale.value, urls.compliance, PAGES.compliance.l),
84
84
  isNew: true
85
85
  },
86
86
  {
@@ -1,23 +1,26 @@
1
1
  <script lang="ts" setup>
2
2
  import type { ProjectKeys } from '#adata-ui/components/navigation/header/types'
3
3
  import AColorMode from '#adata-ui/components/features/color-mode/AColorMode.client.vue'
4
+ import ADropdownV2 from '#adata-ui/components/features/dropdown/ADropdownV2.vue'
4
5
  import LangSwitcher from '#adata-ui/components/features/lang-switcher/lang-switcher.vue'
5
6
  import AChangeVersion from '#adata-ui/components/features/сhange-version/AChangeVersion.vue'
7
+ import HeaderUsage from '#adata-ui/components/navigation/header/HeaderUsage.vue'
6
8
  import ProfileMenu from '#adata-ui/components/navigation/header/ProfileMenu.vue'
7
- import TopHeader from '#adata-ui/components/navigation/header/TopHeader.vue'
9
+ import SystemNotification from '#adata-ui/components/navigation/header/SystemNotification.vue'
8
10
  import { useContacts, useCurrentModule } from '#adata-ui/composables/projectState'
11
+ import { useUrls } from '#adata-ui/composables/useUrls'
9
12
  import AdataLogo from '#adata-ui/icons/adata-logo.vue'
10
- import Arrow from '#adata-ui/icons/chevron/chevron-down.vue'
11
13
  import Logo from '#adata-ui/icons/logo.vue'
12
14
  import { buildLocalizedUrl, navigateToLocalizedPage } from '#adata-ui/utils/localizedNavigation'
15
+ import { useElementBounding } from '@vueuse/core'
13
16
  import HeaderLink from './HeaderLink.vue'
14
- import { useUrls } from '#adata-ui/composables/useUrls'
15
17
 
16
18
  defineOptions({ name: 'AHeader' })
17
19
 
18
20
  const props = withDefaults(defineProps<Props>(), {
19
21
  limitRemaining: 0,
20
22
  daysRemaining: 0,
23
+ maxLimit: 0,
21
24
  balance: 0,
22
25
  rate: 'Базовый',
23
26
  showLogIn: true,
@@ -31,10 +34,11 @@ interface Props {
31
34
  replenish?: string
32
35
  hasNotification?: boolean
33
36
  email: string | undefined
34
- rate: string
35
- daysRemaining: number
36
- limitRemaining: number
37
- balance: number
37
+ rate?: string
38
+ daysRemaining?: number
39
+ limitRemaining?: number
40
+ maxLimit?: number
41
+ balance?: number
38
42
  isAuthenticated: boolean
39
43
  showLogIn?: boolean
40
44
  mobileHeaderType?: 'search' | 'default'
@@ -42,18 +46,21 @@ interface Props {
42
46
  oldVersion?: string
43
47
  }
44
48
 
45
- const { t } = useI18n()
46
49
  const { locale } = useI18n()
47
50
 
48
51
  useCurrentModule().value = props.module
49
- const appConfig = useAppConfig()
50
52
  const { myLayer }: any = useAppConfig()
51
53
  const urls = useUrls()
52
54
 
53
- const langIsOn = appConfig.myLayer.langIsOn
54
- const contacts = ref(useContacts())
55
+ const langIsOn = myLayer.langIsOn
56
+ const contacts = useContacts()
55
57
  const { loginModal } = useIdModals()
56
58
 
59
+ // Anchor the navigation mega-menu to the actual bottom of the header bar so it
60
+ // stays aligned even when the system-notification banner is shown above it.
61
+ const headerRef = ref<HTMLElement | null>(null)
62
+ const { bottom: headerBottom } = useElementBounding(headerRef)
63
+
57
64
  function goAuth() {
58
65
  if (myLayer.authMode !== 'local') {
59
66
  if (window) {
@@ -82,14 +89,13 @@ function goToAnotherModule() {
82
89
 
83
90
  async function fetchContacts() {
84
91
  try {
85
- const response = await fetch(
92
+ const { data } = await $fetch<{ data: unknown }>(
86
93
  'https://pk-api.adata.kz/api/v1/data/counterparty/contacts/sales-department',
87
94
  )
88
- const { data } = await response.json()
89
95
  contacts.value = data
90
96
  }
91
97
  catch (e) {
92
- console.error(e.message)
98
+ console.error(e instanceof Error ? e.message : e)
93
99
  }
94
100
  }
95
101
 
@@ -100,14 +106,10 @@ onMounted(() => {
100
106
 
101
107
  <template>
102
108
  <div>
103
- <top-header
104
- :days-remaining="daysRemaining"
105
- :is-authenticated="isAuthenticated"
106
- :module-name="module"
107
- :limit-remaining="limitRemaining"
108
- />
109
+ <system-notification />
109
110
  <header
110
- class="relative h-16 border-b border-deepblue-900/10 bg-white dark:border-gray-200/10 dark:bg-gray-900"
111
+ ref="headerRef"
112
+ class="relative h-16 border-b border-deepblue-900/10 bg-gray-50/30 backdrop-blur-lg dark:border-gray-200/10 dark:bg-gray-900/30"
111
113
  >
112
114
  <div class="a-container mobile-padding flex h-full items-center justify-between gap-2">
113
115
  <!-- Desktop hidden -->
@@ -156,7 +158,12 @@ onMounted(() => {
156
158
  />
157
159
  </div>
158
160
  <!-- Mobile hidden -->
159
- <nav class="hidden items-center gap-4 lg:flex" itemscope itemtype="https://schema.org/SiteNavigationElement" role="list">
161
+ <nav
162
+ class="hidden items-center gap-4 lg:flex"
163
+ itemscope
164
+ itemtype="https://schema.org/SiteNavigationElement"
165
+ role="list"
166
+ >
160
167
  <nuxt-link-locale
161
168
  aria-label="Adata-logo"
162
169
  :to="buildLocalizedUrl(locale, urls.landing)"
@@ -169,11 +176,18 @@ onMounted(() => {
169
176
  filled
170
177
  />
171
178
  </nuxt-link-locale>
172
- <header-link />
179
+ <header-link :menu-top="headerBottom || 64" />
173
180
  </nav>
174
181
  <div class="text-deepblue hidden items-center gap-4 dark:text-[#E3E5E8] lg:flex">
182
+ <header-usage
183
+ v-if="isAuthenticated"
184
+ :limit-remaining="limitRemaining"
185
+ :max-limit="maxLimit"
186
+ :days-remaining="daysRemaining"
187
+ />
188
+
175
189
  <!-- Mobile hidden -->
176
- <div class="hidden items-center gap-4 lg:flex">
190
+ <div class="hidden items-center gap-2 lg:flex">
177
191
  <a-change-version
178
192
  v-if="oldVersion"
179
193
  :url="oldVersion"
@@ -182,22 +196,31 @@ onMounted(() => {
182
196
  <lang-switcher v-if="langIsOn || module === 'fea'" />
183
197
  </div>
184
198
 
185
- <a-dropdown
199
+ <a-dropdown-v2
186
200
  v-show="isAuthenticated"
187
- placement="right"
201
+ placement="bottom-end"
188
202
  >
189
- <template #default="{ onExpand, expanded }">
190
- <div
191
- class="hidden cursor-pointer items-center gap-2 text-sm font-semibold lg:flex"
203
+ <template #default="{ toggle, isOpen }">
204
+ <button
205
+ type="button"
206
+ class="hidden h-8 cursor-pointer items-center gap-1.5 rounded-full px-3 text-sm font-medium transition-colors duration-150 hover:bg-deepblue-900/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/50 focus-visible:ring-offset-1 dark:hover:bg-white/10 dark:focus-visible:ring-offset-gray-900 lg:inline-flex"
207
+ :class="isOpen
208
+ ? 'bg-deepblue-900/10 text-deepblue-900 dark:bg-white/15 dark:text-white'
209
+ : 'text-gray-900 dark:text-gray-100'"
192
210
  data-test-id="header-email-text"
193
- @click.stop="onExpand"
211
+ :aria-label="email"
212
+ @click.stop="toggle"
194
213
  >
195
214
  <span>{{ email }}</span>
196
- <arrow :class="{ 'rotate-180': expanded }" />
197
- </div>
215
+ <a-icon-chevron-down
216
+ class="shrink-0 transition-transform duration-200"
217
+ :class="{ 'rotate-180': isOpen }"
218
+ />
219
+ </button>
198
220
  </template>
199
221
  <template #content>
200
222
  <profile-menu
223
+ :email="email"
201
224
  :balance="balance"
202
225
  :days-remaining="daysRemaining"
203
226
  :limit-remaining="limitRemaining"
@@ -206,7 +229,7 @@ onMounted(() => {
206
229
  @logout="$emit('logout')"
207
230
  />
208
231
  </template>
209
- </a-dropdown>
232
+ </a-dropdown-v2>
210
233
  <a-button-login
211
234
  v-show="!isAuthenticated && showLogIn"
212
235
  @click="goAuth"
@@ -104,7 +104,7 @@ import ExpandWindow from "#adata-ui/icons/expand-window.vue";
104
104
  import {useContacts} from "#adata-ui/composables/projectState";
105
105
 
106
106
  const {t} = useI18n()
107
- const contacts = ref(useContacts())
107
+ const contacts = useContacts()
108
108
  const AlmatyItems = computed(() => ([
109
109
  {
110
110
  title: t('header.contacts.almaty.adress.title'),
@@ -150,12 +150,12 @@ onUnmounted(() => clearTimer())
150
150
  </nuxt-link-locale>
151
151
  </div>
152
152
  </transition>
153
- <div class="absolute xl:bottom-4 w-full">
153
+ <div class="absolute bottom-4 w-full">
154
154
  <div class="flex justify-center items-center gap-6">
155
155
  <div
156
156
  v-for="(item, index) in items"
157
157
  :key="index"
158
- class="relative bg-white/50 dark:bg-gray-900/50 rounded-full overflow-hidden cursor-pointer h-2 w-2"
158
+ class="relative bg-white/50 dark:bg-gray-900/50 rounded-full overflow-hidden cursor-pointer h-2 w-2 transition-[width] duration-500 ease-[cubic-bezier(0.22,1,0.36,1)]"
159
159
  :class="{ 'w-[52px]': currentIndex === index }"
160
160
  @click="setCurrentIndex(index)"
161
161
  >
@@ -188,7 +188,9 @@ onUnmounted(() => clearTimer())
188
188
  top: 0;
189
189
  left: 0;
190
190
  width: 100%;
191
- transition: transform 0.3s ease, opacity 0.3s ease;
191
+ transition:
192
+ transform 0.5s cubic-bezier(0.22, 1, 0.36, 1),
193
+ opacity 0.5s cubic-bezier(0.22, 1, 0.36, 1);
192
194
  }
193
195
 
194
196
  .slide-left-enter-from {
@@ -1,19 +1,8 @@
1
1
  <script setup lang="ts">
2
- import AlmatyContacts from "#adata-ui/components/navigation/header/AlmatyContacts.vue";
3
- import AstanaContacts from "#adata-ui/components/navigation/header/AstanaContacts.vue";
2
+ import AlmatyContacts from '#adata-ui/components/navigation/header/AlmatyContacts.vue'
3
+ import AstanaContacts from '#adata-ui/components/navigation/header/AstanaContacts.vue'
4
4
 
5
- const props = withDefaults(
6
- defineProps<{
7
- animation?: string
8
- index?: number
9
- url?: string
10
- }>(),
11
- {
12
- animation: 'previous',
13
- index: 2,
14
- url:''
15
- }
16
- )
5
+ defineProps<{ url?: string }>()
17
6
  defineEmits(['outerClick', 'mouseOver'])
18
7
 
19
8
  const { t } = useI18n()
@@ -21,94 +10,39 @@ const activeTab = ref(0)
21
10
  const options = [
22
11
  {
23
12
  key: 0,
24
- name: 'ТОО "Alldata"'
13
+ name: 'ТОО "Alldata"',
25
14
  },
26
15
  {
27
16
  key: 1,
28
- name: ' ТОО «ADATA Consulting»'
17
+ name: ' ТОО «ADATA Consulting»',
29
18
  },
30
19
  ]
31
-
32
20
  </script>
33
21
 
34
22
  <template>
35
- <div class=" normal-case ">
23
+ <div class="normal-case">
36
24
  <div class="bg-white dark:bg-gray-950">
37
- <transition :name="animation">
38
- <div
39
- :key="index"
40
- class="a-container"
41
- >
42
- <div class="pt-2 mb-8 flex justify-between">
43
- <a-pill-tabs
44
- v-model="activeTab"
45
- class="gap-2"
46
- view="mobile"
47
- :options="options"
48
- size="lg"
49
- />
50
- <nuxt-link :to="url">
51
- <a-button variant="gray">
52
- {{ t('header.contacts.toContacts') }}
53
- <a-icon-arrow-top-right-on-square />
54
- </a-button>
55
- </nuxt-link>
56
- </div>
57
- <div>
58
- <almaty-contacts v-show="activeTab===0" />
59
- <astana-contacts v-show="activeTab===1" />
60
- </div>
25
+ <div class="a-container">
26
+ <div class="mb-8 flex justify-between pt-2">
27
+ <a-pill-tabs
28
+ v-model="activeTab"
29
+ class="gap-2"
30
+ view="mobile"
31
+ :options="options"
32
+ size="lg"
33
+ />
34
+ <nuxt-link :to="url">
35
+ <a-button variant="gray">
36
+ {{ t('header.contacts.toContacts') }}
37
+ <a-icon-arrow-top-right-on-square />
38
+ </a-button>
39
+ </nuxt-link>
40
+ </div>
41
+ <div>
42
+ <almaty-contacts v-show="activeTab === 0" />
43
+ <astana-contacts v-show="activeTab === 1" />
61
44
  </div>
62
- </transition>
63
- <button
64
- class="absolute right-8 top-4"
65
- @click="$emit('outerClick')"
66
- >
67
- <a-icon-x-mark
68
- width="32"
69
- height="32"
70
- />
71
- </button>
45
+ </div>
72
46
  </div>
73
47
  </div>
74
48
  </template>
75
-
76
- <style scoped lang="scss">
77
- $percent: 30%;
78
- .next-enter-from,
79
- .next-leave-to {
80
- opacity: 0;
81
- transform: translateX($percent);
82
- position: absolute;
83
- }
84
-
85
- .next-enter-active {
86
- transition: all 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
87
- }
88
-
89
- .next-leave-active {
90
- transition: all 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
91
- opacity: 0;
92
- transform: translateX(-$percent);
93
- }
94
-
95
- // Backwards transition
96
-
97
- .prev-enter-from,
98
- .prev-leave-to {
99
- position: absolute;
100
-
101
- opacity: 0;
102
- transform: translateX(-$percent);
103
- }
104
-
105
- .prev-enter-active {
106
- transition: all 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
107
- }
108
-
109
- .prev-leave-active {
110
- transition: all 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
111
- opacity: 0;
112
- transform: translateX($percent);
113
- }
114
- </style>