itube-specs 0.0.904 → 0.0.911

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 (40) hide show
  1. package/assets/icons/common/playlist.svg +1 -1
  2. package/assets/scss/themes/dark/_theme.scss +44 -19
  3. package/assets/scss/themes/light/_theme.scss +41 -16
  4. package/assets/scss/vars/_palette.scss +5 -0
  5. package/assets/scss/vars/_vars.scss +1 -0
  6. package/components/auth/login.vue +2 -2
  7. package/components/auth/recovery.vue +2 -2
  8. package/components/auth/register.vue +2 -2
  9. package/components/card/collections-more.vue +133 -0
  10. package/components/card/playlist.vue +6 -1
  11. package/components/grid/playlists.vue +3 -0
  12. package/components/info/main.vue +18 -14
  13. package/components/library/feed.vue +59 -35
  14. package/components/library/follows.vue +19 -4
  15. package/components/library/item.vue +112 -60
  16. package/components/playlist/add.vue +2 -2
  17. package/components/playlist/delete-video.vue +2 -2
  18. package/components/playlist/edit.vue +3 -3
  19. package/components/profile/delete.vue +2 -2
  20. package/components/profile/setup.vue +2 -2
  21. package/components/report/main.vue +9 -4
  22. package/components/search/input.vue +9 -9
  23. package/components/section/collections.vue +110 -0
  24. package/components/ui/follow-btn.vue +162 -0
  25. package/components/ui/section-title.vue +2 -0
  26. package/components/ui/snackbar.vue +93 -44
  27. package/composables/__tests__/use-snackbar.test.ts +126 -20
  28. package/composables/use-snackbar.ts +75 -20
  29. package/composables/use-user.ts +4 -4
  30. package/package.json +1 -1
  31. package/pages/contacts.vue +2 -2
  32. package/pages/library/categories.vue +1 -0
  33. package/pages/library/channels.vue +2 -0
  34. package/pages/library/index.vue +23 -14
  35. package/pages/library/models.vue +2 -0
  36. package/pages/playlists/index.vue +55 -4
  37. package/stubs/library.ts +0 -1
  38. package/types/index.d.ts +1 -0
  39. package/types/library-feed.d.ts +2 -0
  40. package/types/library-item.d.ts +6 -0
@@ -1 +1 @@
1
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 5H3"></path><path d="M10 12H3"></path><path d="M10 19H3"></path><path d="M15 12.003a1 1 0 0 1 1.517-.859l4.997 2.997a1 1 0 0 1 0 1.718l-4.997 2.997a1 1 0 0 1-1.517-.86z"></path></svg>
1
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 12H3"></path><path d="M16 6H3"></path><path d="M12 18H3"></path><path d="m16 12 5 3-5 3v-6Z"></path></svg>
@@ -43,7 +43,7 @@ $nav-border--hover: transparent;
43
43
  $nav-border: $color-zinc-700-50;
44
44
  $nav-icon: $color-zinc-400;
45
45
  $nav-icon-accent: $color-red-400;
46
- $nav-icon--active: $nav-text--active;
46
+ $nav-icon--active: $color-zinc-400;
47
47
  $nav-container-bg: $color-black;
48
48
  $nav-down-icon: $color-zinc-500;
49
49
  $nav-menu-bg: $color-zinc-900;
@@ -105,7 +105,7 @@ $count-bg: $color-zinc-800;
105
105
  $count-text: $color-zinc-400;
106
106
 
107
107
  // ─── Search ───
108
- $search-bg: $color-zinc-800;
108
+ $search-bg: $color-zinc-800-50;
109
109
  $search-text: $color-white;
110
110
  $search-bg--mobile: $color-zinc-800;
111
111
  $search-border--active--mobile: $color-indigo-500;
@@ -119,7 +119,7 @@ $search-button-bg: $color-indigo-600;
119
119
  $search-button-bg--hover: $color-indigo-500;
120
120
  $search-max-width: 500px;
121
121
  $search-max-width-md: 672px;
122
- $search-mobile-bg: $mono-black-95;
122
+ $search-mobile-bg: $color-neutral-940-95;
123
123
  $search-mobile-border: $color-zinc-800;
124
124
  $search-mobile-decorate: $mono-black-50;
125
125
  $search-mobile-button: $color-zinc-200;
@@ -468,18 +468,29 @@ $dropdown-crest: $color-zinc-500;
468
468
  $dropdown-separator: $color-zinc-800-60;
469
469
 
470
470
  // ─── Snackbar ───
471
+ $snackbar-bg: $color-zinc-800;
472
+ $snackbar-border: $color-zinc-700;
471
473
  $snackbar-text: $color-zinc-200;
472
- $snackbar-close: $color-zinc-500;
473
- $snackbar-close--hover: $color-zinc-300;
474
- $snackbar-close-bg--hover: $color-zinc-700;
475
- $snackbar-success: $color-green-200;
476
- $snackbar-success-bg: $color-green-925;
477
- $snackbar-success-icon: $color-green-300;
478
- $snackbar-success-icon-bg: $color-green-800;
479
- $snackbar-error: $color-red-200;
480
- $snackbar-error-bg: $color-red-925;
481
- $snackbar-error-icon: $color-red-300;
482
- $snackbar-error-icon-bg: $color-red-800;
474
+ $snackbar-highlight: $color-white;
475
+ $snackbar-icon: $color-zinc-300;
476
+ $snackbar-icon-bg: $color-zinc-700-60;
477
+ $snackbar-shadow: 0 10px 15px -3px #{$mono-black-25}, 0 4px 6px -4px #{$mono-black-25};
478
+ $snackbar-action-bg: $color-indigo-600;
479
+ $snackbar-action-bg--hover: $color-indigo-500;
480
+ $snackbar-action-text: $color-white;
481
+
482
+ // ─── Follow button ───
483
+ $follow-btn-bg: $color-indigo-600;
484
+ $follow-btn-bg--hover: $color-indigo-500;
485
+ $follow-btn-border: $color-indigo-500;
486
+ $follow-btn-border--hover: $color-indigo-500;
487
+ $follow-btn-text: $color-white;
488
+ $follow-btn-following-bg: $color-zinc-800;
489
+ $follow-btn-following-bg--hover: $color-red-600;
490
+ $follow-btn-following-border: $color-zinc-800;
491
+ $follow-btn-following-border--hover: $color-red-500;
492
+ $follow-btn-following-text: $color-white;
493
+ $follow-btn-following-text--hover: $color-white;
483
494
 
484
495
  // ─── Button ───
485
496
  $button-primary-bg: $color-indigo-600;
@@ -854,6 +865,18 @@ $playlist-card-placeholder-bg: $color-zinc-700;
854
865
  $playlist-card-dropdown-icon: $color-zinc-500;
855
866
  $playlist-card-dropdown-icon--hover: $color-white;
856
867
 
868
+ // ─── Collections section ───
869
+ $collections-badge-text: $color-indigo-300;
870
+ $collections-badge-bg: $color-indigo-500-20;
871
+ $collections-badge-border: $color-indigo-500-40;
872
+ $collections-more-bg: $color-zinc-800;
873
+ $collections-more-border: $color-zinc-800-50;
874
+ $collections-more-border--hover: $color-zinc-700;
875
+ $collections-more-scrim: $color-black-50;
876
+ $collections-more-scrim--hover: $color-black-42;
877
+ $collections-more-count: $color-white;
878
+ $collections-more-text: $color-zinc-200;
879
+
857
880
  // ─── Channel card ───
858
881
  $channel-card-border: $color-zinc-800-50;
859
882
  $channel-card-bg: $color-zinc-800-50;
@@ -978,15 +1001,15 @@ $library-item-icon-border--hover: $color-indigo-500-40;
978
1001
  $library-item-title: $color-white;
979
1002
  $library-item-title--hover: $color-indigo-400;
980
1003
  $library-item-subtitle: $color-zinc-500;
981
- $library-item-badge-bg: $color-indigo-600-90;
982
- $library-item-badge-text: $color-white;
983
- $library-item-badge-bordered-border: $color-zinc-600;
984
- $library-item-badge-bordered-text: $color-zinc-400;
1004
+ $library-item-avatar-bg: $color-zinc-700;
1005
+ $library-item-avatar-text: $color-zinc-200;
1006
+ $library-item-avatar-border: $color-zinc-900;
1007
+ $library-item-rest-bg: $color-zinc-800;
1008
+ $library-item-rest-text: $color-zinc-400;
985
1009
 
986
1010
  // ─── Library feed (блок подписки: модель / канал / категория) ───
987
1011
  $library-feed-bg: $color-zinc-900-40;
988
1012
  $library-feed-border: $color-zinc-800;
989
- $library-feed-fade: $color-zinc-950;
990
1013
  $library-feed-avatar-border: $color-zinc-700;
991
1014
  $library-feed-avatar-border--hover: $color-zinc-500;
992
1015
  $library-feed-initials: $color-zinc-400;
@@ -1001,6 +1024,8 @@ $library-feed-age: $color-zinc-500;
1001
1024
  $library-feed-meta: $color-zinc-500;
1002
1025
  $library-feed-meta-dot: $color-zinc-600;
1003
1026
  $library-feed-title: $color-zinc-500;
1027
+ $library-feed-open: $color-zinc-400;
1028
+ $library-feed-open--hover: $color-white;
1004
1029
 
1005
1030
  // ─── Page: library ───
1006
1031
  $page-library-toggle-text: $color-zinc-300;
@@ -523,18 +523,29 @@ $dropdown-crest: $color-gray-400;
523
523
  $dropdown-separator: $color-slate-750;
524
524
 
525
525
  // ─── Snackbar ───
526
+ $snackbar-bg: $color-slate-800;
527
+ $snackbar-border: $color-slate-750;
526
528
  $snackbar-text: $color-gray-200;
527
- $snackbar-close: $color-gray-500;
528
- $snackbar-close--hover: $color-gray-300;
529
- $snackbar-close-bg--hover: $color-slate-700;
530
- $snackbar-success: $color-green-200;
531
- $snackbar-success-bg: $color-green-925;
532
- $snackbar-success-icon: $color-green-300;
533
- $snackbar-success-icon-bg: $color-green-800;
534
- $snackbar-error: $color-red-200;
535
- $snackbar-error-bg: $color-red-925;
536
- $snackbar-error-icon: $color-red-300;
537
- $snackbar-error-icon-bg: $color-red-800;
529
+ $snackbar-highlight: $color-white;
530
+ $snackbar-icon: $color-gray-300;
531
+ $snackbar-icon-bg: $color-slate-700;
532
+ $snackbar-shadow: 0 10px 15px -3px #{$mono-black-25}, 0 4px 6px -4px #{$mono-black-25};
533
+ $snackbar-action-bg: $color-indigo-600;
534
+ $snackbar-action-bg--hover: $color-indigo-500;
535
+ $snackbar-action-text: $color-white;
536
+
537
+ // ─── Follow button ───
538
+ $follow-btn-bg: $color-indigo-600;
539
+ $follow-btn-bg--hover: $color-indigo-500;
540
+ $follow-btn-border: $color-indigo-500;
541
+ $follow-btn-border--hover: $color-indigo-500;
542
+ $follow-btn-text: $color-white;
543
+ $follow-btn-following-bg: $color-gray-300;
544
+ $follow-btn-following-bg--hover: $color-red-500;
545
+ $follow-btn-following-border: $color-gray-300;
546
+ $follow-btn-following-border--hover: $color-red-500;
547
+ $follow-btn-following-text: $color-gray-700;
548
+ $follow-btn-following-text--hover: $color-white;
538
549
 
539
550
  // ─── Button ───
540
551
  $button-primary-bg: $color-indigo-600;
@@ -882,6 +893,18 @@ $playlist-card-placeholder-bg: $color-gray-300;
882
893
  $playlist-card-dropdown-icon: $color-gray-600;
883
894
  $playlist-card-dropdown-icon--hover: $color-gray-900;
884
895
 
896
+ // ─── Collections section ───
897
+ $collections-badge-text: $color-indigo-600;
898
+ $collections-badge-bg: $color-indigo-500-10;
899
+ $collections-badge-border: $color-indigo-500-20;
900
+ $collections-more-bg: $color-gray-300;
901
+ $collections-more-border: $color-gray-300;
902
+ $collections-more-border--hover: $color-gray-400;
903
+ $collections-more-scrim: $color-black-45;
904
+ $collections-more-scrim--hover: $color-black-32;
905
+ $collections-more-count: $color-white;
906
+ $collections-more-text: $color-white;
907
+
885
908
  // ─── Channel card ───
886
909
  $channel-card-border: transparent;
887
910
  $channel-card-bg: $color-gray-100;
@@ -1006,15 +1029,15 @@ $library-item-icon-border--hover: transparent;
1006
1029
  $library-item-title: $color-gray-900;
1007
1030
  $library-item-title--hover: $color-indigo-600;
1008
1031
  $library-item-subtitle: $color-gray-500;
1009
- $library-item-badge-bg: $color-indigo-600;
1010
- $library-item-badge-text: $color-white;
1011
- $library-item-badge-bordered-border: $color-gray-300;
1012
- $library-item-badge-bordered-text: $color-gray-600;
1032
+ $library-item-avatar-bg: $color-gray-300;
1033
+ $library-item-avatar-text: $color-gray-700;
1034
+ $library-item-avatar-border: $color-gray-100;
1035
+ $library-item-rest-bg: $color-gray-200;
1036
+ $library-item-rest-text: $color-gray-600;
1013
1037
 
1014
1038
  // ─── Library feed (блок подписки: модель / канал / категория) ───
1015
1039
  $library-feed-bg: $color-gray-100;
1016
1040
  $library-feed-border: transparent;
1017
- $library-feed-fade: $color-gray-100;
1018
1041
  $library-feed-avatar-border: $color-gray-300;
1019
1042
  $library-feed-avatar-border--hover: $color-indigo-500-50;
1020
1043
  $library-feed-initials: $color-gray-600;
@@ -1029,6 +1052,8 @@ $library-feed-age: $color-gray-500;
1029
1052
  $library-feed-meta: $color-gray-500;
1030
1053
  $library-feed-meta-dot: $color-gray-400;
1031
1054
  $library-feed-title: $color-gray-500;
1055
+ $library-feed-open: $color-gray-600;
1056
+ $library-feed-open--hover: $color-gray-900;
1032
1057
 
1033
1058
  // ─── Page: library ───
1034
1059
  $page-library-toggle-text: $color-gray-700;
@@ -22,6 +22,7 @@ $color-zinc-750: lab(21.3843% .9572 -2.5207); // #333337
22
22
  $color-zinc-700: lab(26.8019% 1.35387 -4.68303); // #3f3f46
23
23
  $color-zinc-700-80: lab(26.8019% 1.35387 -4.68303 / 80%); // zinc-700 / 70%
24
24
  $color-zinc-700-70: lab(26.8019% 1.35387 -4.68303 / 70%); // zinc-700 / 70%
25
+ $color-zinc-700-60: lab(26.8019% 1.35387 -4.68303 / 60%); // zinc-700 / 60%
25
26
  $color-zinc-700-50: lab(26.8019% 1.35387 -4.68303 / 50%); // zinc-700 / 50%
26
27
  $color-zinc-700-30: lab(26.8019% 1.35387 -4.68303 / 30%); // zinc-700 / 50%
27
28
  $color-zinc-650: lab(31.3256% 2.0703 -5.3354); // #494952
@@ -65,6 +66,10 @@ $color-indigo-800: lab(26.6645% 37.9804 -68.6402); // #372aac
65
66
  $color-indigo-900: lab(23.3911% 24.6978 -50.4718); // #312c85
66
67
  $color-indigo-950: lab(12.9255% 18.7583 -31.0075); // #1e1a4d
67
68
 
69
+ // Neutral gray (untinted — no zinc blue tint)
70
+ $color-neutral-940: lab(3.6355% 0 0); // #0d0d0d
71
+ $color-neutral-940-95: lab(3.6355% 0 0 / 95%); // #0d0d0d / 95%
72
+
68
73
  // Monochrome black (opacity variants)
69
74
  $mono-black-100: lab(0% 0 0);
70
75
  $mono-black-95: lab(0% 0 0 / 95%);
@@ -5,6 +5,7 @@ $radius: 10px;
5
5
  $radius-small: 4px;
6
6
  $radius-md: 8px;
7
7
  $radius-lg: 10px;
8
+ $radius-12: 12px;
8
9
  $radius-xl: 14px;
9
10
  $radius-2xl: 16px;
10
11
  $radius-full: 9999px;
@@ -94,7 +94,7 @@ function onCreateClick() {
94
94
 
95
95
  const loading = ref(false);
96
96
 
97
- const { setErrorState, showError, showSuccess, resetSnackbar } = useSnackbar();
97
+ const { setErrorState, showError, show, resetSnackbar } = useSnackbar();
98
98
 
99
99
  async function login() {
100
100
  resetSnackbar();
@@ -115,7 +115,7 @@ async function login() {
115
115
  loading.value = true;
116
116
  await useUser(AuthorizationApiService).login(form.value);
117
117
  useAuthPopup().closeAuthPopup();
118
- showSuccess('Welcome back!');
118
+ show('Welcome back!');
119
119
  } catch (error) {
120
120
  setErrorState(error);
121
121
  } finally {
@@ -70,7 +70,7 @@ function onLoginClick() {
70
70
 
71
71
  const loading = ref(false);
72
72
 
73
- const { setErrorState, showError, showSuccess, resetSnackbar } = useSnackbar();
73
+ const { setErrorState, showError, show, resetSnackbar } = useSnackbar();
74
74
 
75
75
  // Загружаем reCAPTCHA при открытии формы (onMounted) — даёт Google время собрать данные о поведении
76
76
  onMounted(async () => {
@@ -97,7 +97,7 @@ async function submit() {
97
97
  form.value.token = await getRecaptchaToken('password_reset');
98
98
  await useUser(AuthorizationApiService).password(form.value);
99
99
  useAuthPopup().closeAuthPopup();
100
- showSuccess('Check your email');
100
+ show('Check your email');
101
101
  } catch (error) {
102
102
  setErrorState(error);
103
103
  } finally {
@@ -129,7 +129,7 @@ function onLoginClick() {
129
129
 
130
130
  const loading = ref(false);
131
131
 
132
- const { setErrorState, showError, showSuccess, resetSnackbar } = useSnackbar();
132
+ const { setErrorState, showError, show, resetSnackbar } = useSnackbar();
133
133
  // Загружаем reCAPTCHA при открытии формы (onMounted) — даёт Google время собрать данные о поведении
134
134
  onMounted(async () => {
135
135
  try {
@@ -176,7 +176,7 @@ async function submit() {
176
176
  // await PlaylistsApiService.postPlaylist(FAVORITES_KEY, PlaylistType.Private);
177
177
 
178
178
  useAuthPopup().closeAuthPopup();
179
- showSuccess('Registration success');
179
+ show('Registration success');
180
180
  } catch (err) {
181
181
  setErrorState(err);
182
182
  console.error('Ошибка reCAPTCHA или регистрации:', err);
@@ -0,0 +1,133 @@
1
+ <!-- Плитка «показать ещё» в сетке коллекций: 16 размытых обложек сеткой 4×4, поверх счётчик и подпись -->
2
+ <template>
3
+ <NuxtLink
4
+ :to="generateLink(to)"
5
+ class="card-collections-more"
6
+ >
7
+ <span
8
+ v-if="images.length > 0"
9
+ class="card-collections-more__thumbs"
10
+ aria-hidden="true"
11
+ >
12
+ <UiImg
13
+ v-for="(src, index) in images"
14
+ :key="`collections-more-thumb-${index}`"
15
+ :src="src"
16
+ :width="ThumbSize.Small.split('x')[0]"
17
+ :height="ThumbSize.Small.split('x')[1]"
18
+ alt=""
19
+ class="card-collections-more__thumb"
20
+ />
21
+ </span>
22
+
23
+ <span class="card-collections-more__content">
24
+ <span
25
+ v-if="count"
26
+ class="card-collections-more__count"
27
+ >+{{ count }}</span>
28
+ <span class="card-collections-more__text">{{ text }}</span>
29
+ </span>
30
+ </NuxtLink>
31
+ </template>
32
+
33
+ <script setup lang="ts">
34
+ import { ThumbSize } from '../../runtime';
35
+ import type { IThumbUrls } from '../../types';
36
+
37
+ const props = defineProps<{
38
+ to: string
39
+ text: string
40
+ /** Обложки для мозаики: лишние отбрасываем, если меньше 16 — повторяем по кругу */
41
+ thumbs?: IThumbUrls[]
42
+ /** Сколько коллекций осталось за кадром — «+18» */
43
+ count?: number
44
+ }>();
45
+
46
+ const { generateLink } = useGenerateLink();
47
+
48
+ /** Ячеек в мозаике — сетка 4×4 */
49
+ const CELLS = 16;
50
+
51
+ const images = computed(() => {
52
+ const sources = (props.thumbs || [])
53
+ .map(thumb => thumb?.webp?.[ThumbSize.Small])
54
+ .filter((src): src is string => Boolean(src));
55
+
56
+ if (sources.length === 0) return [];
57
+
58
+ /* добиваем по кругу, чтобы мозаика всегда была полной, а не с дырами */
59
+ return Array.from({ length: CELLS }, (_, index) => sources[index % sources.length]);
60
+ });
61
+ </script>
62
+
63
+ <style lang="scss">
64
+ .card-collections-more {
65
+ position: relative;
66
+ display: grid;
67
+ place-content: center;
68
+ min-height: 240px;
69
+ padding: 12px;
70
+ overflow: hidden;
71
+ text-align: center;
72
+ border-radius: $radius-xl;
73
+ border: 1px solid $collections-more-border;
74
+ background-color: $collections-more-bg;
75
+
76
+ @include hover(border-color) {
77
+ border-color: $collections-more-border--hover;
78
+
79
+ &::after {
80
+ background-color: $collections-more-scrim--hover;
81
+ }
82
+ }
83
+
84
+ /* затемнение поверх обложек — псевдоэлементом, без отдельной ноды-оверлея */
85
+ &::after {
86
+ content: '';
87
+ position: absolute;
88
+ inset: 0;
89
+ background-color: $collections-more-scrim;
90
+ transition: var(--transition) background-color;
91
+ }
92
+ }
93
+
94
+ .card-collections-more__thumbs {
95
+ position: absolute;
96
+ inset: 0;
97
+ display: grid;
98
+
99
+ /* minmax(0, 1fr), иначе auto-минимум трека = min-content картинки и сетка распирает блок */
100
+ grid-template-columns: repeat(4, minmax(0, 1fr));
101
+ grid-template-rows: repeat(4, minmax(0, 1fr));
102
+ gap: 2px;
103
+ filter: blur(12px);
104
+ transform: scale(1.1);
105
+ }
106
+
107
+ .card-collections-more__thumb {
108
+ width: 100%;
109
+ height: 100%;
110
+ object-fit: cover;
111
+ }
112
+
113
+ .card-collections-more__content {
114
+ position: relative;
115
+ z-index: $z-index-plus;
116
+ display: grid;
117
+ row-gap: 2px;
118
+ }
119
+
120
+ .card-collections-more__count {
121
+ @include font-2xl;
122
+
123
+ font-weight: 700;
124
+ color: $collections-more-count;
125
+ }
126
+
127
+ .card-collections-more__text {
128
+ @include font-sm;
129
+
130
+ font-weight: 500;
131
+ color: $collections-more-text;
132
+ }
133
+ </style>
@@ -107,7 +107,10 @@
107
107
  <p class="card-playlist__user">
108
108
  {{ card.username }}
109
109
  </p>
110
- <div class="card-playlist__content-wrapper">
110
+ <div
111
+ v-if="!noActions"
112
+ class="card-playlist__content-wrapper"
113
+ >
111
114
  <UiDropdown
112
115
  ref="dropdownRef"
113
116
  right
@@ -177,6 +180,8 @@ import { CSS_BREAKPOINTS } from '../../config/css-breakpoints';
177
180
  const props = defineProps<{
178
181
  card: IPlaylistCard
179
182
  topPlaylists?: boolean
183
+ /** Без меню «три точки» — вместе с ним уходят share и report */
184
+ noActions?: boolean
180
185
  priority?: boolean
181
186
  }>();
182
187
 
@@ -6,6 +6,7 @@
6
6
  :key="`user-playlist-${index}`"
7
7
  :card="item"
8
8
  :top-playlists="topPlaylists"
9
+ :no-actions="noActions"
9
10
  :priority="priority && index === 0"
10
11
  @share="onShare"
11
12
  />
@@ -32,6 +33,8 @@ import type { IPlaylistCard } from '../../types';
32
33
  defineProps<{
33
34
  items: IPlaylistCard[]
34
35
  topPlaylists?: boolean
36
+ /** Скрыть меню карточки (три точки: share/report) — например у редакционных подборок */
37
+ noActions?: boolean
35
38
  priority?: boolean
36
39
  }>();
37
40
 
@@ -30,19 +30,6 @@
30
30
  class="info-main__count"
31
31
  icon="video-camera"
32
32
  >{{ videosCount || card.videosCount }}</UiCount>
33
- <UiBtn
34
- v-if="featureFlags.FeatureFollowEnabled"
35
- theme="muted"
36
- class="info-main__header-button"
37
- size="s"
38
- @click="onFollowClick"
39
- >
40
- <UiIcon
41
- name="plus"
42
- size="16"
43
- />
44
- {{ t('follow') }}
45
- </UiBtn>
46
33
  <UiBtn
47
34
  theme="muted"
48
35
  size="s"
@@ -55,6 +42,14 @@
55
42
  />
56
43
  {{ t('share') }}
57
44
  </UiBtn>
45
+ <UiFollowBtn
46
+ v-if="featureFlags.FeatureFollowEnabled"
47
+ :following="isFollowing"
48
+ :name="title"
49
+ class="info-main__header-follow"
50
+ size="s"
51
+ @toggle="onFollowClick"
52
+ />
58
53
  </div>
59
54
  </div>
60
55
 
@@ -190,9 +185,12 @@ function showParameters() {
190
185
 
191
186
  const authPopupText = 'register_first';
192
187
 
188
+ /** Заглушка вместо ручки подписки: состояние живёт только в компоненте, на бэк ничего не уходит */
189
+ const isFollowing = ref(false);
190
+
193
191
  function onFollowClick() {
194
192
  if (isAuthorized.value) {
195
- console.log('чото делать');
193
+ isFollowing.value = !isFollowing.value;
196
194
  } else {
197
195
  openAuthPopup(AuthSteps.Login, authPopupText);
198
196
  }
@@ -464,4 +462,10 @@ const socialItems = computed<ILinkItem[]>(() => {
464
462
  .info-main__header-button {
465
463
  @include button-variant(info-button);
466
464
  }
465
+
466
+ .info-main__header-follow {
467
+ @include to-br(sm) {
468
+ margin-inline-start: auto;
469
+ }
470
+ }
467
471
  </style>