@cloud-ru/uikit-product-site-section 0.23.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/CHANGELOG.md +1406 -0
  2. package/LICENSE +201 -0
  3. package/README.md +335 -0
  4. package/package.json +70 -0
  5. package/src/components/SectionAccordion/SectionAccordion.tsx +99 -0
  6. package/src/components/SectionAccordion/index.ts +1 -0
  7. package/src/components/SectionAccordion/styles.module.scss +13 -0
  8. package/src/components/SectionAccordion/types.ts +11 -0
  9. package/src/components/SectionAccordion/utils.ts +29 -0
  10. package/src/components/SectionBasic/SectionBasic.tsx +157 -0
  11. package/src/components/SectionBasic/index.ts +1 -0
  12. package/src/components/SectionBasic/styles.module.scss +88 -0
  13. package/src/components/SectionBenefits/SectionBenefits.tsx +163 -0
  14. package/src/components/SectionBenefits/components/CardNumeric/CardNumeric.tsx +17 -0
  15. package/src/components/SectionBenefits/components/CardNumeric/index.ts +1 -0
  16. package/src/components/SectionBenefits/components/CardNumeric/styles.module.scss +6 -0
  17. package/src/components/SectionBenefits/components/index.ts +1 -0
  18. package/src/components/SectionBenefits/index.ts +1 -0
  19. package/src/components/SectionBenefits/styles.module.scss +15 -0
  20. package/src/components/SectionBenefits/types.ts +91 -0
  21. package/src/components/SectionBenefitsBanner/SectionBenefitsBanner.tsx +91 -0
  22. package/src/components/SectionBenefitsBanner/index.ts +1 -0
  23. package/src/components/SectionBenefitsBanner/styles.module.scss +119 -0
  24. package/src/components/SectionBenefitsBanner/types.ts +42 -0
  25. package/src/components/SectionBenefitsBanner/utils.ts +15 -0
  26. package/src/components/SectionBlogCarousel/SectionBlogCarousel.tsx +22 -0
  27. package/src/components/SectionBlogCarousel/index.ts +1 -0
  28. package/src/components/SectionBlogCarousel/utils.ts +29 -0
  29. package/src/components/SectionCaseCarousel/SectionCaseCarousel.tsx +22 -0
  30. package/src/components/SectionCaseCarousel/index.ts +1 -0
  31. package/src/components/SectionCaseCarousel/styles.module.scss +3 -0
  32. package/src/components/SectionCaseCarousel/utils.ts +24 -0
  33. package/src/components/SectionCatalog/SectionCatalog.tsx +105 -0
  34. package/src/components/SectionCatalog/constants.ts +5 -0
  35. package/src/components/SectionCatalog/index.ts +1 -0
  36. package/src/components/SectionCatalog/styles.module.scss +45 -0
  37. package/src/components/SectionClientsCarousel/SectionClientsCarousel.tsx +23 -0
  38. package/src/components/SectionClientsCarousel/index.ts +1 -0
  39. package/src/components/SectionClientsCarousel/utils.ts +29 -0
  40. package/src/components/SectionContent/SectionContent.tsx +98 -0
  41. package/src/components/SectionContent/index.ts +1 -0
  42. package/src/components/SectionContent/styles.module.scss +70 -0
  43. package/src/components/SectionContentList/SectionContentList.tsx +99 -0
  44. package/src/components/SectionContentList/index.ts +1 -0
  45. package/src/components/SectionContentList/styles.module.scss +56 -0
  46. package/src/components/SectionContentTabs/SectionContentTabs.tsx +156 -0
  47. package/src/components/SectionContentTabs/index.ts +1 -0
  48. package/src/components/SectionContentTabs/styles.module.scss +85 -0
  49. package/src/components/SectionExpertsCarousel/SectionExpertsCarousel.tsx +18 -0
  50. package/src/components/SectionExpertsCarousel/constants.ts +2 -0
  51. package/src/components/SectionExpertsCarousel/index.ts +1 -0
  52. package/src/components/SectionExpertsCarousel/types.ts +6 -0
  53. package/src/components/SectionLeading/SectionLeading.tsx +116 -0
  54. package/src/components/SectionLeading/index.ts +1 -0
  55. package/src/components/SectionLeading/styles.module.scss +30 -0
  56. package/src/components/SectionLeading/utils.ts +11 -0
  57. package/src/components/SectionMarketplaceCarousel/SectionMarketplaceCarousel.tsx +23 -0
  58. package/src/components/SectionMarketplaceCarousel/index.ts +1 -0
  59. package/src/components/SectionMarketplaceCarousel/utils.ts +33 -0
  60. package/src/components/SectionMedia/SectionMedia.tsx +57 -0
  61. package/src/components/SectionMedia/index.ts +1 -0
  62. package/src/components/SectionMedia/styles.module.scss +9 -0
  63. package/src/components/SectionPersonalManager/SectionPersonalManager.tsx +135 -0
  64. package/src/components/SectionPersonalManager/index.ts +1 -0
  65. package/src/components/SectionPersonalManager/styles.module.scss +146 -0
  66. package/src/components/SectionPersonalManager/utils.ts +15 -0
  67. package/src/components/SectionPromoList/SectionPromoList.tsx +66 -0
  68. package/src/components/SectionPromoList/index.ts +1 -0
  69. package/src/components/SectionPromoList/styles.module.scss +52 -0
  70. package/src/components/SectionSocial/SectionSocial.tsx +66 -0
  71. package/src/components/SectionSocial/constants.ts +5 -0
  72. package/src/components/SectionSocial/index.ts +1 -0
  73. package/src/components/SectionSocial/styles.module.scss +4 -0
  74. package/src/components/SectionTable/SectionTable.tsx +46 -0
  75. package/src/components/SectionTable/index.ts +1 -0
  76. package/src/components/SectionTable/styles.module.scss +19 -0
  77. package/src/components/index.ts +19 -0
  78. package/src/constants.ts +4 -0
  79. package/src/helperComponents/BenefitItem/BenefitItem.tsx +34 -0
  80. package/src/helperComponents/BenefitItem/index.ts +1 -0
  81. package/src/helperComponents/BenefitItem/styles.module.scss +34 -0
  82. package/src/helperComponents/BenefitItem/utils.ts +28 -0
  83. package/src/helperComponents/CardClient/CardClient.tsx +15 -0
  84. package/src/helperComponents/CardClient/index.ts +1 -0
  85. package/src/helperComponents/CardClient/styles.module.scss +25 -0
  86. package/src/helperComponents/CardLeading/CardLeading.tsx +29 -0
  87. package/src/helperComponents/CardLeading/index.ts +2 -0
  88. package/src/helperComponents/CardLeading/styles.module.scss +43 -0
  89. package/src/helperComponents/CardLeading/types.ts +12 -0
  90. package/src/helperComponents/CardLeading/utils.ts +28 -0
  91. package/src/helperComponents/CardSocial/CardSocial.tsx +105 -0
  92. package/src/helperComponents/CardSocial/index.ts +1 -0
  93. package/src/helperComponents/CardSocial/styles.module.scss +48 -0
  94. package/src/helperComponents/CardSocial/utils.ts +13 -0
  95. package/src/helperComponents/Expert/Expert.tsx +28 -0
  96. package/src/helperComponents/Expert/index.ts +1 -0
  97. package/src/helperComponents/Expert/styles.module.scss +39 -0
  98. package/src/helperComponents/PromoList/PromoList.tsx +26 -0
  99. package/src/helperComponents/PromoList/index.ts +1 -0
  100. package/src/helperComponents/PromoList/styles.module.scss +46 -0
  101. package/src/helperComponents/SectionButton/SectionButton.tsx +19 -0
  102. package/src/helperComponents/SectionButton/index.tsx +1 -0
  103. package/src/helperComponents/SectionButton/types.ts +9 -0
  104. package/src/helperComponents/SectionCarousel/SectionCarousel.tsx +109 -0
  105. package/src/helperComponents/SectionCarousel/index.ts +2 -0
  106. package/src/helperComponents/SectionCarousel/styles.module.scss +8 -0
  107. package/src/helperComponents/SectionCarousel/types.ts +42 -0
  108. package/src/helperComponents/SectionCarousel/utils.ts +10 -0
  109. package/src/helperComponents/SectionCatalogFooter/SectionCatalogFooter.tsx +29 -0
  110. package/src/helperComponents/SectionCatalogFooter/index.ts +1 -0
  111. package/src/helperComponents/SectionCatalogFooter/styles.module.scss +10 -0
  112. package/src/helperComponents/SectionTitle/SectionTitle.tsx +72 -0
  113. package/src/helperComponents/SectionTitle/constants.ts +5 -0
  114. package/src/helperComponents/SectionTitle/index.ts +1 -0
  115. package/src/helperComponents/SectionTitle/styles.module.scss +33 -0
  116. package/src/helperComponents/SectionTitle/types.ts +7 -0
  117. package/src/helperComponents/SectionTitle/utils.ts +83 -0
  118. package/src/helperComponents/index.ts +10 -0
  119. package/src/index.ts +2 -0
  120. package/src/types.ts +23 -0
@@ -0,0 +1,29 @@
1
+ import { LayoutType } from '@cloud-ru/uikit-product-utils';
2
+
3
+ import { SectionCarouselProps } from '../../helperComponents';
4
+
5
+ export const getCarouselProps = (
6
+ layoutType: LayoutType,
7
+ ): Pick<SectionCarouselProps, 'itemMinWidth' | 'maxItemsPerPage'> => {
8
+ switch (layoutType) {
9
+ case 'mobile':
10
+ return {
11
+ itemMinWidth: 270,
12
+ maxItemsPerPage: 1,
13
+ };
14
+
15
+ case 'tablet':
16
+ return {
17
+ itemMinWidth: 270,
18
+ maxItemsPerPage: 2,
19
+ };
20
+
21
+ case 'desktop':
22
+ case 'desktopSmall':
23
+ default:
24
+ return {
25
+ itemMinWidth: 300,
26
+ maxItemsPerPage: 4,
27
+ };
28
+ }
29
+ };
@@ -0,0 +1,98 @@
1
+ import cn from 'classnames';
2
+
3
+ import { Layout } from '@cloud-ru/uikit-product-site-layout';
4
+ import { SiteVideo } from '@cloud-ru/uikit-product-site-media';
5
+ import { extractSupportProps, WithLayoutType, WithSupportProps } from '@cloud-ru/uikit-product-utils';
6
+ import { ButtonFilled, ButtonFilledProps } from '@snack-uikit/button';
7
+
8
+ import { SECTION_COLORS } from '../../constants';
9
+ import { SectionTitle, SectionTitleProps } from '../../helperComponents';
10
+ import { MediaContentProps, SectionColor } from '../../types';
11
+ import styles from './styles.module.scss';
12
+
13
+ export type SectionContentProps = WithSupportProps<
14
+ WithLayoutType<
15
+ {
16
+ /** id секции */
17
+ id?: string;
18
+ /** CSS-класс */
19
+ className?: string;
20
+ /** Заголовок */
21
+ title?: string;
22
+ /** Описание */
23
+ description?: string;
24
+ /** Кнопка действия */
25
+ button?: Omit<ButtonFilledProps, 'fullWidth' | 'size'>;
26
+ /** Цвет фона */
27
+ backgroundColor?: SectionColor;
28
+ /** Местоположение контента в секции */
29
+ contentPosition: 'left' | 'right';
30
+ } & MediaContentProps &
31
+ Pick<SectionTitleProps, 'titleTag'>
32
+ >
33
+ >;
34
+
35
+ export function SectionContent({
36
+ id,
37
+ title,
38
+ description,
39
+ button,
40
+ className,
41
+ layoutType,
42
+ backgroundColor = SECTION_COLORS.NeutralBackground1Level,
43
+ contentPosition = 'left',
44
+ image,
45
+ video,
46
+ onPlay,
47
+ titleTag,
48
+ 'data-test-id': dataTestId = 'section-content',
49
+ ...rest
50
+ }: SectionContentProps) {
51
+ const isDesktop = ['desktop', 'desktopSmall'].includes(layoutType);
52
+
53
+ return (
54
+ <Layout.SectionWrapper
55
+ id={id}
56
+ layoutType={layoutType}
57
+ className={cn(className, styles.wrapper)}
58
+ data-section-background={backgroundColor}
59
+ data-test-id={dataTestId}
60
+ {...extractSupportProps(rest)}
61
+ >
62
+ <div className={styles.sectionContent} data-layout-type={layoutType} data-content-position={contentPosition}>
63
+ {Boolean(title || description || button) && (
64
+ <div className={styles.content}>
65
+ {Boolean(title || description) && (
66
+ <SectionTitle
67
+ layoutType={layoutType}
68
+ title={title}
69
+ description={description}
70
+ titleSectionSize='m'
71
+ titleTag={titleTag}
72
+ />
73
+ )}
74
+
75
+ {Boolean(button) && (
76
+ <ButtonFilled {...button} fullWidth={!isDesktop} size='l' data-test-id={`${dataTestId}__button`} />
77
+ )}
78
+ </div>
79
+ )}
80
+
81
+ <div className={styles.mediaWrapper}>
82
+ {image && (
83
+ <img
84
+ className={styles.image}
85
+ src={image.src}
86
+ alt={image.alt || title || 'section-content-image'}
87
+ data-test-id={`${dataTestId}__image`}
88
+ />
89
+ )}
90
+
91
+ {video && (
92
+ <SiteVideo video={video} onPlay={onPlay} layoutType={layoutType} data-test-id={`${dataTestId}__video`} />
93
+ )}
94
+ </div>
95
+ </div>
96
+ </Layout.SectionWrapper>
97
+ );
98
+ }
@@ -0,0 +1 @@
1
+ export * from './SectionContent';
@@ -0,0 +1,70 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as var;
2
+
3
+ .wrapper {
4
+ &[data-section-background='neutral-background1-level'] {
5
+ background-color: var.$sys-neutral-background1-level;
6
+ }
7
+
8
+ &[data-section-background='neutral-background'] {
9
+ background-color: var.$sys-neutral-background;
10
+ }
11
+ }
12
+
13
+ .sectionContent {
14
+ display: flex;
15
+ flex-direction: row;
16
+ align-items: flex-start;
17
+
18
+ gap: var.$dimension-4m;
19
+ padding: var.$dimension-7m 0;
20
+
21
+ &[data-content-position='right'] {
22
+ flex-direction: row-reverse;
23
+ }
24
+
25
+ &[data-layout-type='tablet'] {
26
+ flex-direction: column;
27
+ padding: var.$dimension-5m 0;
28
+ align-items: center;
29
+ }
30
+
31
+ &[data-layout-type='mobile'] {
32
+ gap: var.$dimension-3m;
33
+ padding: var.$dimension-4m 0;
34
+ flex-direction: column;
35
+ align-items: center;
36
+ }
37
+ }
38
+
39
+ .content {
40
+ display: flex;
41
+ flex-direction: column;
42
+ gap: var.$dimension-4m;
43
+ width: 384px;
44
+ flex-shrink: 0;
45
+
46
+ [data-layout-type='tablet'] &,
47
+ [data-layout-type='mobile'] & {
48
+ width: 100%;
49
+ }
50
+ }
51
+
52
+ .mediaWrapper {
53
+ flex-grow: 1;
54
+
55
+ [data-layout-type='tablet'] & {
56
+ width: 100%;
57
+ max-width: 704px;
58
+ }
59
+
60
+ [data-layout-type='mobile'] & {
61
+ width: 100%;
62
+ }
63
+ }
64
+
65
+ .image {
66
+ width: 100%;
67
+ height: 100%;
68
+ object-fit: contain;
69
+ object-position: top left;
70
+ }
@@ -0,0 +1,99 @@
1
+ import { SiteVideo } from '@cloud-ru/uikit-product-site-media';
2
+ import { extractSupportProps, WithLayoutType, WithSupportProps } from '@cloud-ru/uikit-product-utils';
3
+
4
+ import { SectionTitle, SectionTitleProps } from '../../helperComponents';
5
+ import { MediaContentProps, SectionColor } from '../../types';
6
+ import { SectionBasic, SectionBasicProps } from '../SectionBasic';
7
+ import styles from './styles.module.scss';
8
+
9
+ type Item = {
10
+ title: string;
11
+ description: string;
12
+ } & Pick<SectionTitleProps, 'titleLink'>;
13
+
14
+ export type SectionContentListProps = WithSupportProps<
15
+ WithLayoutType<
16
+ {
17
+ /** id секции */
18
+ id?: string;
19
+ /** CSS-класс */
20
+ className?: string;
21
+ /** Заголовок */
22
+ title?: string;
23
+ /** Описание */
24
+ description?: string;
25
+ /** Список элементов */
26
+ items?: Item[];
27
+ /** Цвет фона */
28
+ backgroundColor?: SectionColor;
29
+ /** Местоположение контента в секции */
30
+ contentPosition: 'left' | 'right';
31
+ } & MediaContentProps &
32
+ Pick<SectionBasicProps, 'titleTag'>
33
+ >
34
+ >;
35
+
36
+ export function SectionContentList({
37
+ id,
38
+ title,
39
+ description,
40
+ items,
41
+ className,
42
+ layoutType,
43
+ backgroundColor,
44
+ contentPosition = 'left',
45
+ image,
46
+ video,
47
+ onPlay,
48
+ titleTag,
49
+ 'data-test-id': dataTestId = 'section-content-list',
50
+ ...rest
51
+ }: SectionContentListProps) {
52
+ return (
53
+ <SectionBasic
54
+ id={id}
55
+ layoutType={layoutType}
56
+ title={title}
57
+ description={description}
58
+ className={className}
59
+ backgroundColor={backgroundColor}
60
+ data-test-id={dataTestId}
61
+ titleTag={titleTag}
62
+ {...extractSupportProps(rest)}
63
+ >
64
+ <div className={styles.sectionContent} data-layout-type={layoutType} data-content-position={contentPosition}>
65
+ <div className={styles.mediaWrapper}>
66
+ {image && (
67
+ <img
68
+ className={styles.image}
69
+ src={image.src}
70
+ alt={image.alt || title || 'section-content-image'}
71
+ data-test-id={`${dataTestId}__image`}
72
+ />
73
+ )}
74
+
75
+ {video && (
76
+ <SiteVideo video={video} onPlay={onPlay} layoutType={layoutType} data-test-id={`${dataTestId}__video`} />
77
+ )}
78
+ </div>
79
+
80
+ {items && items.length > 0 && (
81
+ <ul className={styles.list}>
82
+ {items.map((item, index) => (
83
+ <li key={`${title}__${index}`} className={styles.item}>
84
+ <SectionTitle
85
+ layoutType={layoutType}
86
+ title={item.title}
87
+ titleLink={item.titleLink}
88
+ description={item.description}
89
+ titleSectionSize='s'
90
+ titleTag='h3'
91
+ />
92
+ </li>
93
+ ))}
94
+ </ul>
95
+ )}
96
+ </div>
97
+ </SectionBasic>
98
+ );
99
+ }
@@ -0,0 +1 @@
1
+ export * from './SectionContentList';
@@ -0,0 +1,56 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as var;
2
+
3
+ .sectionContent {
4
+ display: flex;
5
+ flex-direction: row;
6
+ align-items: flex-start;
7
+ gap: var.$dimension-4m;
8
+
9
+ &[data-content-position='left'] {
10
+ flex-direction: row-reverse;
11
+ }
12
+
13
+ &[data-layout-type='tablet'] {
14
+ flex-direction: column;
15
+ }
16
+
17
+ &[data-layout-type='mobile'] {
18
+ flex-direction: column;
19
+ gap: var.$dimension-3m;
20
+ }
21
+ }
22
+
23
+ .mediaWrapper {
24
+ width: 50%;
25
+
26
+ [data-layout-type='tablet'] &,
27
+ [data-layout-type='mobile'] & {
28
+ width: 100%;
29
+ }
30
+ }
31
+
32
+ .image {
33
+ width: 100%;
34
+ height: 100%;
35
+ object-fit: contain;
36
+ object-position: top left;
37
+ }
38
+
39
+ .list {
40
+ display: flex;
41
+ flex-direction: column;
42
+ flex-grow: 1;
43
+ margin: 0;
44
+ padding: 0;
45
+ gap: var.$dimension-3m;
46
+ width: 50%;
47
+
48
+ [data-layout-type='tablet'] &,
49
+ [data-layout-type='mobile'] & {
50
+ width: 100%;
51
+ }
52
+ }
53
+
54
+ .item {
55
+ list-style: none;
56
+ }
@@ -0,0 +1,156 @@
1
+ import cn from 'classnames';
2
+ import { ReactNode } from 'react';
3
+ import { useUncontrolledProp } from 'uncontrollable';
4
+
5
+ import { SiteVideo } from '@cloud-ru/uikit-product-site-media';
6
+ import { RichText } from '@cloud-ru/uikit-product-site-rich-text';
7
+ import { extractSupportProps, WithLayoutType, WithSupportProps } from '@cloud-ru/uikit-product-utils';
8
+ import { ButtonFilled, ButtonFilledProps } from '@snack-uikit/button';
9
+ import { Tabs } from '@snack-uikit/tabs';
10
+
11
+ import { SectionTitle } from '../../helperComponents';
12
+ import { MediaContentProps, SectionColor } from '../../types';
13
+ import { SectionBasic, SectionBasicProps } from '../SectionBasic';
14
+ import styles from './styles.module.scss';
15
+
16
+ type TabItem = {
17
+ id: string;
18
+ title: string;
19
+ mediaTitle?: string;
20
+ mediaSubtitle?: string;
21
+ mediaDescription?: string;
22
+ onClick?: () => void;
23
+ href?: string;
24
+ disabled?: boolean;
25
+ icon?: string | ReactNode;
26
+ } & MediaContentProps;
27
+
28
+ export type SectionContentTabsProps = WithSupportProps<
29
+ WithLayoutType<
30
+ {
31
+ /** id секции */
32
+ id?: string;
33
+ /** CSS-класс */
34
+ className?: string;
35
+ /** Заголовок */
36
+ title?: string;
37
+ /** Список вкладок */
38
+ tabs: TabItem[];
39
+ /** Выбранная вкладок */
40
+ activeTab?: string;
41
+ /** колбэк на смену вкладки */
42
+ onActiveTabChange?: () => void;
43
+ /** Кнопка действия */
44
+ button?: Omit<ButtonFilledProps, 'fullWidth' | 'size'>;
45
+ /** Цвет фона */
46
+ backgroundColor?: SectionColor;
47
+ } & Pick<SectionBasicProps, 'titleTag'>
48
+ >
49
+ >;
50
+
51
+ function TabIcon({ icon }: Pick<TabItem, 'icon'>) {
52
+ if (icon && typeof icon === 'string') {
53
+ return <img src={icon} alt='' className={styles.tabIconImage} />;
54
+ }
55
+
56
+ return icon;
57
+ }
58
+
59
+ export function SectionContentTabs({
60
+ id,
61
+ title,
62
+ tabs,
63
+ activeTab: activeTabProp,
64
+ onActiveTabChange,
65
+ button,
66
+ className,
67
+ layoutType,
68
+ backgroundColor,
69
+ titleTag,
70
+ 'data-test-id': dataTestId = 'section-content-tabs',
71
+ ...rest
72
+ }: SectionContentTabsProps) {
73
+ const [activeTab, setActiveTab] = useUncontrolledProp(activeTabProp, tabs[0].id, onActiveTabChange);
74
+ const isDesktop = ['desktop', 'desktopSmall'].includes(layoutType);
75
+
76
+ return (
77
+ <SectionBasic
78
+ id={id}
79
+ layoutType={layoutType}
80
+ title={title}
81
+ className={className}
82
+ backgroundColor={backgroundColor}
83
+ data-test-id={dataTestId}
84
+ titleTag={titleTag}
85
+ {...extractSupportProps(rest)}
86
+ >
87
+ <Tabs value={activeTab} onChange={setActiveTab}>
88
+ <div className={styles.sectionContent} data-layout-type={layoutType}>
89
+ <div className={cn(styles.tabsWrapper, { [styles.desktopTabsWrapper]: isDesktop })}>
90
+ <Tabs.TabBar
91
+ orientation={isDesktop ? 'vertical' : 'horizontal'}
92
+ markerPosition={isDesktop ? 'before' : 'after'}
93
+ className={cn({ [styles.desktopTabs]: isDesktop })}
94
+ >
95
+ {tabs.map(({ id, title, disabled, icon }) => (
96
+ <Tabs.Tab
97
+ key={id}
98
+ value={id}
99
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
100
+ // @ts-ignore
101
+ label={
102
+ <>
103
+ <RichText richText={title} />
104
+ <TabIcon icon={icon} />
105
+ </>
106
+ }
107
+ disabled={disabled}
108
+ />
109
+ ))}
110
+ </Tabs.TabBar>
111
+
112
+ {Boolean(button) && (
113
+ <ButtonFilled {...button} fullWidth={!isDesktop} size='l' data-test-id={`${dataTestId}__button`} />
114
+ )}
115
+ </div>
116
+
117
+ {tabs.map(({ id, mediaTitle, mediaSubtitle, mediaDescription, image, video, onPlay }) => (
118
+ <Tabs.TabContent key={id} value={id} className={styles.mediaWrapper}>
119
+ {image && (
120
+ <div className={styles.imageWrapper}>
121
+ <img
122
+ className={styles.image}
123
+ src={image.src}
124
+ alt={image.alt || title || 'section-content-image'}
125
+ data-test-id={`${dataTestId}__image`}
126
+ />
127
+ </div>
128
+ )}
129
+
130
+ {video && (
131
+ <SiteVideo
132
+ video={video}
133
+ onPlay={onPlay}
134
+ layoutType={layoutType}
135
+ data-test-id={`${dataTestId}__video`}
136
+ />
137
+ )}
138
+
139
+ {/* TODO: избавиться от title/subtitle после обновления cms-ки */}
140
+ {(mediaTitle || mediaSubtitle) && (
141
+ <SectionTitle
142
+ titleSectionSize='s'
143
+ layoutType={layoutType}
144
+ title={mediaTitle}
145
+ description={mediaSubtitle}
146
+ />
147
+ )}
148
+
149
+ {mediaDescription && <SectionTitle layoutType={layoutType} description={mediaDescription} />}
150
+ </Tabs.TabContent>
151
+ ))}
152
+ </div>
153
+ </Tabs>
154
+ </SectionBasic>
155
+ );
156
+ }
@@ -0,0 +1 @@
1
+ export * from './SectionContentTabs';
@@ -0,0 +1,85 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as var;
2
+
3
+ $tabs-width: 280px;
4
+
5
+ .sectionContent {
6
+ display: flex;
7
+ flex-direction: row;
8
+ align-items: flex-start;
9
+ gap: var.$dimension-4m;
10
+
11
+ &[data-layout-type='tablet'] {
12
+ flex-direction: column;
13
+ }
14
+
15
+ &[data-layout-type='mobile'] {
16
+ flex-direction: column;
17
+ gap: var.$dimension-3m;
18
+ }
19
+ }
20
+
21
+ .tabsWrapper {
22
+ display: flex;
23
+ flex-direction: column;
24
+ gap: var.$dimension-4m;
25
+ width: $tabs-width;
26
+ flex-shrink: 0;
27
+
28
+ [data-layout-type='tablet'] &,
29
+ [data-layout-type='mobile'] & {
30
+ width: 100%;
31
+ }
32
+ }
33
+
34
+ .desktopTabs button {
35
+ text-wrap: auto;
36
+ text-align: left;
37
+ box-sizing: border-box;
38
+ padding-top: 12px;
39
+ padding-bottom: 12px;
40
+ }
41
+
42
+ .desktopTabsWrapper,
43
+ .desktopTabs,
44
+ .desktopTabs button {
45
+ max-width: $tabs-width;
46
+ flex-shrink: 0;
47
+ }
48
+
49
+ .mediaWrapper {
50
+ display: flex;
51
+ flex-direction: column;
52
+ flex-grow: 1;
53
+ gap: var.$dimension-4m;
54
+
55
+ [data-layout-type='tablet'] &,
56
+ [data-layout-type='mobile'] & {
57
+ width: 100%;
58
+ }
59
+ }
60
+
61
+ .imageWrapper {
62
+ box-sizing: border-box;
63
+ position: relative;
64
+ width: 100%;
65
+ height: 100%;
66
+ display: flex;
67
+ padding-bottom: 56.5%;
68
+ border: 0;
69
+ }
70
+
71
+ .image {
72
+ position: absolute;
73
+ top: 0;
74
+ left: 0;
75
+ height: 100%;
76
+ width: 100%;
77
+ border: 0;
78
+ background-color: var.$sys-neutral-background;
79
+ object-fit: contain;
80
+ }
81
+
82
+ .tabIconImage {
83
+ width: 20px;
84
+ height: 20px;
85
+ }
@@ -0,0 +1,18 @@
1
+ import { Expert, LimitedSectionCarouselProps, SectionCarousel } from '../../helperComponents';
2
+ import { EXPERT_MINIMAL_WIDTH, MAX_PER_PAGE } from './constants';
3
+ import { ExpertDetails } from './types';
4
+
5
+ export type SectionExpertsCarouselProps = Omit<
6
+ LimitedSectionCarouselProps<ExpertDetails>,
7
+ 'description' | 'gap' | 'titleLink'
8
+ >;
9
+
10
+ export function SectionExpertsCarousel({ items, ...props }: SectionExpertsCarouselProps) {
11
+ return (
12
+ <SectionCarousel {...props} itemMinWidth={EXPERT_MINIMAL_WIDTH} maxItemsPerPage={MAX_PER_PAGE}>
13
+ {items.map(item => (
14
+ <Expert key={item.name} {...item} />
15
+ ))}
16
+ </SectionCarousel>
17
+ );
18
+ }
@@ -0,0 +1,2 @@
1
+ export const EXPERT_MINIMAL_WIDTH = 240;
2
+ export const MAX_PER_PAGE = 4;
@@ -0,0 +1 @@
1
+ export * from './SectionExpertsCarousel';
@@ -0,0 +1,6 @@
1
+ export type ExpertDetails = {
2
+ image: string;
3
+ name: string;
4
+ surname: string;
5
+ jobTitle: string;
6
+ };