@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,116 @@
1
+ import debounce from 'lodash.debounce';
2
+ import { useEffect, useMemo, useRef, useState } from 'react';
3
+
4
+ import { extractSupportProps, WithLayoutType, WithSupportProps } from '@cloud-ru/uikit-product-utils';
5
+ import { Carousel, CarouselProps } from '@snack-uikit/carousel';
6
+ import { Typography } from '@snack-uikit/typography';
7
+
8
+ import { CardLeading, CardLeadingItem } from '../../helperComponents';
9
+ import { SectionBasic, SectionBasicProps } from '../SectionBasic';
10
+ import styles from './styles.module.scss';
11
+ import { calculateAmountOfItemsPerPage } from './utils';
12
+
13
+ export type SectionLeadingProps = WithSupportProps<
14
+ WithLayoutType<
15
+ Pick<SectionBasicProps, 'title' | 'description' | 'titleSectionSize' | 'titleTag' | 'backgroundColor'> &
16
+ Pick<CarouselProps, 'autoSwipe'> & {
17
+ /** id секции */
18
+ id?: string;
19
+ /** Массив айтемов */
20
+ items: CardLeadingItem[];
21
+ /** Описание секции */
22
+ footerDescription?: string;
23
+ /** CSS - класснейм */
24
+ className?: string;
25
+ }
26
+ >
27
+ >;
28
+
29
+ const MOBILE_LAYOUTS = ['tablet', 'mobile'];
30
+
31
+ export function SectionLeading({
32
+ id,
33
+ title,
34
+ description,
35
+ titleSectionSize = 'm',
36
+ titleTag,
37
+ items,
38
+ footerDescription,
39
+ backgroundColor,
40
+ className,
41
+ layoutType,
42
+ autoSwipe = 9,
43
+ ...rest
44
+ }: SectionLeadingProps) {
45
+ const [currentPage, setCurrentPage] = useState<number>(0);
46
+ const [itemsPerPageAmount, setItemsPerPageAmount] = useState<number>(0);
47
+
48
+ const wrapperRef = useRef<HTMLDivElement>(null);
49
+
50
+ useEffect(() => {
51
+ const node = wrapperRef.current;
52
+ if (!node) {
53
+ return;
54
+ }
55
+
56
+ const calculateAmountOfItems = () => {
57
+ const wrapperWidth = node.offsetWidth;
58
+ if (!wrapperWidth) {
59
+ return;
60
+ }
61
+
62
+ setItemsPerPageAmount(calculateAmountOfItemsPerPage(wrapperWidth));
63
+ };
64
+
65
+ const observer = new ResizeObserver(debounce(calculateAmountOfItems, 100));
66
+ observer.observe(node);
67
+ return () => observer.disconnect();
68
+ }, []);
69
+
70
+ const showArrows = useMemo(() => {
71
+ if (MOBILE_LAYOUTS.includes(layoutType)) {
72
+ return false;
73
+ }
74
+
75
+ return items.length > itemsPerPageAmount;
76
+ }, [items.length, itemsPerPageAmount, layoutType]);
77
+
78
+ return (
79
+ <SectionBasic
80
+ id={id}
81
+ layoutType={layoutType}
82
+ className={className}
83
+ backgroundColor={backgroundColor}
84
+ title={title}
85
+ description={description}
86
+ titleSectionSize={titleSectionSize}
87
+ titleTag={titleTag}
88
+ {...extractSupportProps(rest)}
89
+ >
90
+ <div ref={wrapperRef} className={styles.leadingSection} data-layout-type={layoutType}>
91
+ {itemsPerPageAmount > 0 && (
92
+ <Carousel
93
+ state={{ page: currentPage, onChange: setCurrentPage }}
94
+ arrows={showArrows}
95
+ controlsVisibility='always'
96
+ showItems={itemsPerPageAmount}
97
+ pagination={items.length > itemsPerPageAmount}
98
+ swipe={items.length > itemsPerPageAmount}
99
+ autoSwipe={autoSwipe}
100
+ infiniteScroll
101
+ >
102
+ {items.map(item => (
103
+ <CardLeading key={item.label} {...item} layoutType={layoutType} data-test-id={item['data-test-id']} />
104
+ ))}
105
+ </Carousel>
106
+ )}
107
+
108
+ {footerDescription && (
109
+ <div className={styles.footerDescription} data-layout-type={layoutType}>
110
+ <Typography.SansBodyL className={styles.footerDescriptionText}>{footerDescription}</Typography.SansBodyL>
111
+ </div>
112
+ )}
113
+ </div>
114
+ </SectionBasic>
115
+ );
116
+ }
@@ -0,0 +1 @@
1
+ export * from './SectionLeading';
@@ -0,0 +1,30 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as var;
2
+
3
+ .leadingSection {
4
+ width: 100%;
5
+
6
+ display: flex;
7
+ flex-direction: column;
8
+ gap: var.$dimension-5m 0;
9
+
10
+ &[data-layout-type='tablet'] {
11
+ gap: var.$dimension-4m 0;
12
+ }
13
+
14
+ &[data-layout-type='mobile'] {
15
+ gap: var.$dimension-3m 0;
16
+ }
17
+ }
18
+
19
+ .footerDescription {
20
+ max-width: 704px;
21
+
22
+ &[data-layout-type='tablet'],
23
+ &[data-layout-type='mobile'] {
24
+ max-width: unset;
25
+ }
26
+ }
27
+
28
+ .footerDescriptionText {
29
+ color: var.$sys-neutral-text-support;
30
+ }
@@ -0,0 +1,11 @@
1
+ const CARD_LEADING_MINIMAL_WIDTH = 328;
2
+ const MAX_PER_PAGE = 3;
3
+
4
+ export const calculateAmountOfItemsPerPage = (wrapperWidth: number): number => {
5
+ const amount = Math.floor(wrapperWidth / CARD_LEADING_MINIMAL_WIDTH);
6
+ if (amount < 1) {
7
+ return 1;
8
+ }
9
+
10
+ return amount > MAX_PER_PAGE ? MAX_PER_PAGE : amount;
11
+ };
@@ -0,0 +1,23 @@
1
+ import { useMemo } from 'react';
2
+
3
+ import { CardMarketplace, CardMarketplaceProps } from '@cloud-ru/uikit-product-site-cards';
4
+
5
+ import { LimitedSectionCarouselProps, SectionCarousel } from '../../helperComponents';
6
+ import { getCarouselProps } from './utils';
7
+
8
+ export type SectionMarketplaceCarouselProps = Omit<
9
+ LimitedSectionCarouselProps<CardMarketplaceProps>,
10
+ 'gap' | 'titleLink'
11
+ >;
12
+
13
+ export function SectionMarketplaceCarousel({ items, ...props }: SectionMarketplaceCarouselProps) {
14
+ const carouselProps = useMemo(() => getCarouselProps(props.layoutType), [props]);
15
+
16
+ return (
17
+ <SectionCarousel {...props} {...carouselProps}>
18
+ {items.map(item => (
19
+ <CardMarketplace key={item.title} {...item} />
20
+ ))}
21
+ </SectionCarousel>
22
+ );
23
+ }
@@ -0,0 +1 @@
1
+ export * from './SectionMarketplaceCarousel';
@@ -0,0 +1,33 @@
1
+ import { themeVars } from '@sbercloud/figma-tokens-cloud-platform';
2
+ import { LayoutType } from '@cloud-ru/uikit-product-utils';
3
+
4
+ import { SectionCarouselProps } from '../../helperComponents';
5
+
6
+ export const getCarouselProps = (
7
+ layoutType: LayoutType,
8
+ ): Pick<SectionCarouselProps, 'itemMinWidth' | 'maxItemsPerPage' | 'gap'> => {
9
+ switch (layoutType) {
10
+ case 'mobile':
11
+ return {
12
+ itemMinWidth: 270,
13
+ maxItemsPerPage: 1,
14
+ gap: themeVars.dimension['2m'],
15
+ };
16
+
17
+ case 'tablet':
18
+ return {
19
+ itemMinWidth: 270,
20
+ maxItemsPerPage: 2,
21
+ gap: themeVars.dimension['2m'],
22
+ };
23
+
24
+ case 'desktop':
25
+ case 'desktopSmall':
26
+ default:
27
+ return {
28
+ itemMinWidth: 380,
29
+ maxItemsPerPage: 3,
30
+ gap: themeVars.dimension['3m'],
31
+ };
32
+ }
33
+ };
@@ -0,0 +1,57 @@
1
+ import { SiteVideo } from '@cloud-ru/uikit-product-site-media';
2
+ import { extractSupportProps, WithLayoutType, WithSupportProps } from '@cloud-ru/uikit-product-utils';
3
+
4
+ import { MediaContentProps } from '../../types';
5
+ import { SectionBasic, SectionBasicProps } from '../SectionBasic';
6
+ import styles from './styles.module.scss';
7
+
8
+ export type SectionMediaProps = WithLayoutType<
9
+ WithSupportProps<Pick<SectionBasicProps, 'id' | 'title' | 'titleTag' | 'description'> & MediaContentProps>
10
+ >;
11
+
12
+ export function SectionMedia({
13
+ id,
14
+ title,
15
+ titleTag,
16
+ layoutType,
17
+ description,
18
+ video,
19
+ onPlay,
20
+ onError,
21
+ image,
22
+ 'data-test-id': dataTestId = 'section-media',
23
+ ...rest
24
+ }: SectionMediaProps) {
25
+ return (
26
+ <SectionBasic
27
+ id={id}
28
+ layoutType={layoutType}
29
+ title={title}
30
+ titleTag={titleTag}
31
+ description={description}
32
+ data-test-id={dataTestId}
33
+ {...extractSupportProps(rest)}
34
+ >
35
+ <div className={styles.content}>
36
+ {image && (
37
+ <img
38
+ className={styles.image}
39
+ src={image.src}
40
+ alt={image?.alt || title}
41
+ data-test-id={`${dataTestId}__image`}
42
+ />
43
+ )}
44
+
45
+ {video && (
46
+ <SiteVideo
47
+ video={video}
48
+ onPlay={onPlay}
49
+ onError={onError}
50
+ layoutType={layoutType}
51
+ data-test-id={`${dataTestId}__video`}
52
+ />
53
+ )}
54
+ </div>
55
+ </SectionBasic>
56
+ );
57
+ }
@@ -0,0 +1 @@
1
+ export * from './SectionMedia';
@@ -0,0 +1,9 @@
1
+ .content {
2
+ display: flex;
3
+ }
4
+
5
+ .image {
6
+ width: 100%;
7
+ height: 100%;
8
+ object-fit: contain;
9
+ }
@@ -0,0 +1,135 @@
1
+ import cn from 'classnames';
2
+ import { useMemo } from 'react';
3
+
4
+ import { CloudMoveSVG, HeadphonesSVG, UsersSVG } from '@cloud-ru/uikit-product-icons';
5
+ import { useLocale } from '@cloud-ru/uikit-product-locale';
6
+ import { CardBasic, CardBasicProps } from '@cloud-ru/uikit-product-site-cards';
7
+ import { extractSupportProps, WithLayoutType, WithSupportProps } from '@cloud-ru/uikit-product-utils';
8
+ import { ButtonFilled } from '@snack-uikit/button';
9
+ import { Typography } from '@snack-uikit/typography';
10
+
11
+ import { SectionBasic } from '../SectionBasic';
12
+ import styles from './styles.module.scss';
13
+ import { getCardTitleTypographyProps } from './utils';
14
+
15
+ export type SectionPersonalManagerProps = WithSupportProps<
16
+ WithLayoutType<{
17
+ /** id секции */
18
+ id?: string;
19
+ title?: string;
20
+ description?: string;
21
+ manager: {
22
+ img: string;
23
+ title?: string;
24
+ text?: string;
25
+ };
26
+ card?: {
27
+ title: string;
28
+ text: string;
29
+ };
30
+ benefits?: Pick<CardBasicProps, 'title' | 'icon'>[];
31
+ withoutBenefits?: boolean;
32
+ /** CSS-класс */
33
+ className?: string;
34
+ /** Хэндлер клика по кнопке "Получить консультацию" */
35
+ onGetConsultationClick(): void;
36
+ }>
37
+ >;
38
+
39
+ export function SectionPersonalManager({
40
+ id,
41
+ layoutType,
42
+ title,
43
+ description,
44
+ manager,
45
+ card,
46
+ benefits,
47
+ withoutBenefits,
48
+ className,
49
+ onGetConsultationClick,
50
+ ...rest
51
+ }: SectionPersonalManagerProps) {
52
+ const { t } = useLocale('SiteSection');
53
+
54
+ const benefitsCards = useMemo<SectionPersonalManagerProps['benefits']>(() => {
55
+ if (benefits) {
56
+ return benefits;
57
+ }
58
+
59
+ return [
60
+ {
61
+ title: t('PersonalManager.argumentAmountOfExperts'),
62
+ icon: UsersSVG,
63
+ },
64
+ {
65
+ title: t('PersonalManager.argumentMethodologies'),
66
+ icon: CloudMoveSVG,
67
+ },
68
+ {
69
+ title: t('PersonalManager.argumentPersonalManager'),
70
+ icon: HeadphonesSVG,
71
+ },
72
+ ];
73
+ }, [benefits, t]);
74
+
75
+ return (
76
+ <SectionBasic
77
+ id={id}
78
+ title={title || t('PersonalManager.title')}
79
+ description={description || t('PersonalManager.subtitle')}
80
+ backgroundColor='neutral-background1-level'
81
+ layoutType={layoutType}
82
+ className={cn(className, styles.sectionPersonalManager)}
83
+ {...extractSupportProps(rest)}
84
+ >
85
+ <div className={styles.content} data-layout-type={layoutType}>
86
+ <div className={cn(styles.card, styles.leftSide)} data-layout-type={layoutType}>
87
+ <div className={styles.approachTextWrapper} data-layout-type={layoutType}>
88
+ <div className={styles.cardTextContent}>
89
+ <Typography family='sans' {...getCardTitleTypographyProps(layoutType)}>
90
+ {manager.title || t('PersonalManager.individualApproachTitle')}
91
+ </Typography>
92
+ <Typography family='sans' purpose='body' size='l' className={styles.cardDescription}>
93
+ {manager.text || t('PersonalManager.individualApproachDescription')}
94
+ </Typography>
95
+ </div>
96
+ <ButtonFilled
97
+ className={styles.consultationButton}
98
+ size='l'
99
+ appearance='primary'
100
+ label={t('PersonalManager.consultationButton')}
101
+ onClick={onGetConsultationClick}
102
+ data-layout-type={layoutType}
103
+ data-test-id='personal-manager_get-consultation-button'
104
+ />
105
+ </div>
106
+ <div className={styles.imageWrapper} data-layout-type={layoutType}>
107
+ <div className={styles.imageBackground}></div>
108
+ <img
109
+ src={manager.img}
110
+ alt='personal_manager'
111
+ className={styles.approachManager}
112
+ data-layout-type={layoutType}
113
+ />
114
+ </div>
115
+ </div>
116
+ <div className={cn(styles.card, styles.cardTextContent, styles.rightSide)} data-layout-type={layoutType}>
117
+ <Typography family='sans' {...getCardTitleTypographyProps(layoutType)}>
118
+ {card?.title || t('PersonalManager.allDaySupportTitle')}
119
+ </Typography>
120
+ <Typography family='sans' purpose='body' size='l' className={styles.cardDescription}>
121
+ {card?.text || t('PersonalManager.allDaySupportDescription')}
122
+ </Typography>
123
+ </div>
124
+ </div>
125
+
126
+ {!withoutBenefits && (
127
+ <div className={styles.expertiseCards} data-layout-type={layoutType}>
128
+ {benefitsCards?.map(card => (
129
+ <CardBasic key={card.title} title={card.title} icon={card.icon} layoutType={layoutType} />
130
+ ))}
131
+ </div>
132
+ )}
133
+ </SectionBasic>
134
+ );
135
+ }
@@ -0,0 +1 @@
1
+ export * from './SectionPersonalManager';
@@ -0,0 +1,146 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables' as var;
2
+
3
+ .sectionPersonalManager {
4
+ width: 100%;
5
+ box-sizing: border-box;
6
+ }
7
+
8
+ .content {
9
+ display: flex;
10
+ box-sizing: border-box;
11
+
12
+ flex-direction: row;
13
+ gap: var.$dimension-4m;
14
+
15
+ &[data-layout-type='tablet'] {
16
+ flex-direction: column;
17
+ gap: var.$dimension-2m;
18
+ }
19
+
20
+ &[data-layout-type='mobile'] {
21
+ flex-direction: column;
22
+ gap: var.$dimension-2m;
23
+ }
24
+ }
25
+
26
+ .card {
27
+ box-sizing: border-box;
28
+ background-color: var.$sys-neutral-background;
29
+
30
+ padding: var.$dimension-4m;
31
+
32
+ &[data-layout-type='tablet'],
33
+ &[data-layout-type='mobile'] {
34
+ padding: var.$dimension-3m;
35
+ }
36
+ }
37
+
38
+ .cardDescription {
39
+ color: var.$sys-neutral-text-support;
40
+ }
41
+
42
+ .cardTextContent {
43
+ box-sizing: border-box;
44
+ display: flex;
45
+ flex-direction: column;
46
+ gap: var.$dimension-2m;
47
+ }
48
+
49
+ .leftSide {
50
+ box-sizing: border-box;
51
+ display: flex;
52
+ gap: var.$dimension-3m;
53
+
54
+ align-items: flex-start;
55
+ flex-direction: row;
56
+
57
+ &[data-layout-type='tablet'] {
58
+ justify-content: space-between;
59
+ }
60
+
61
+ &[data-layout-type='mobile'] {
62
+ flex-direction: column-reverse;
63
+ }
64
+ }
65
+
66
+ .rightSide {
67
+ box-sizing: border-box;
68
+
69
+ &[data-layout-type='desktop'],
70
+ &[data-layout-type='desktopSmall'] {
71
+ max-width: 384px;
72
+ flex-shrink: 0;
73
+ }
74
+ }
75
+
76
+ .approachTextWrapper {
77
+ box-sizing: border-box;
78
+ display: flex;
79
+ flex-direction: column;
80
+ justify-content: space-between;
81
+ gap: var.$dimension-3m;
82
+
83
+ &[data-layout-type='desktop'],
84
+ &[data-layout-type='desktopSmall'] {
85
+ max-width: 472px;
86
+ }
87
+ }
88
+
89
+ .consultationButton {
90
+ &[data-layout-type='mobile'] {
91
+ width: 100%;
92
+ }
93
+ }
94
+
95
+ .expertiseCards {
96
+ box-sizing: border-box;
97
+ display: flex;
98
+
99
+ flex-direction: row;
100
+ gap: var.$dimension-4m;
101
+
102
+ &[data-layout-type='tablet'],
103
+ &[data-layout-type='mobile']{
104
+ flex-direction: column;
105
+ gap: var.$dimension-2m;
106
+ }
107
+ }
108
+
109
+ .imageWrapper {
110
+ box-sizing: border-box;
111
+ display: flex;
112
+ justify-content: center;
113
+ position: relative;
114
+ max-width: 288px;
115
+
116
+ &[data-layout-type='desktop'],
117
+ &[data-layout-type='desktopSmall'] {
118
+ min-width: 216px;
119
+ }
120
+
121
+ &[data-layout-type='tablet'] {
122
+ overflow: hidden;
123
+ min-width: 196px;
124
+
125
+ width: 100%;
126
+ }
127
+
128
+ &[data-layout-type='mobile'] {
129
+ overflow: hidden;
130
+ }
131
+ }
132
+
133
+ .imageBackground {
134
+ position: absolute;
135
+ width: 100%;
136
+ height: 100%;
137
+ background-color: var.$sys-neutral-accent-default;
138
+ opacity: 0.08;
139
+ }
140
+
141
+ .approachManager {
142
+ position: relative;
143
+ object-fit: cover;
144
+ pointer-events: none;
145
+ width: 100%;
146
+ }
@@ -0,0 +1,15 @@
1
+ import { LayoutType } from '@cloud-ru/uikit-product-utils';
2
+ import { TypographyProps } from '@snack-uikit/typography';
3
+
4
+ export const getCardTitleTypographyProps = (layoutType: LayoutType): Pick<TypographyProps, 'purpose' | 'size'> => {
5
+ switch (layoutType) {
6
+ case 'mobile':
7
+ case 'tablet':
8
+ return { purpose: 'title', size: 'm' };
9
+
10
+ case 'desktop':
11
+ case 'desktopSmall':
12
+ default:
13
+ return { purpose: 'headline', size: 's' };
14
+ }
15
+ };
@@ -0,0 +1,66 @@
1
+ import cn from 'classnames';
2
+
3
+ import { extractSupportProps, WithLayoutType, WithSupportProps } from '@cloud-ru/uikit-product-utils';
4
+
5
+ import { PromoList, PromoListProps } from '../../helperComponents';
6
+ import { SectionBasic } from '../SectionBasic';
7
+ import styles from './styles.module.scss';
8
+
9
+ export type SectionPromoListProps = WithSupportProps<
10
+ WithLayoutType<{
11
+ /** id секции */
12
+ id?: string;
13
+ /** CSS-класс */
14
+ className?: string;
15
+ /** Заголовок */
16
+ title: string;
17
+ /** Описание */
18
+ description?: string;
19
+ /** Ссылка на изображение */
20
+ image: string;
21
+ /** Элементы левого списка */
22
+ leftList: PromoListProps;
23
+ /** Элементы правого списка */
24
+ rightList: PromoListProps;
25
+ }>
26
+ >;
27
+
28
+ export function SectionPromoList({
29
+ id,
30
+ layoutType,
31
+ className,
32
+ title,
33
+ description,
34
+ image,
35
+ leftList,
36
+ rightList,
37
+ ...rest
38
+ }: SectionPromoListProps) {
39
+ return (
40
+ <SectionBasic
41
+ id={id}
42
+ title={title}
43
+ description={description}
44
+ backgroundColor='neutral-background1-level'
45
+ layoutType={layoutType}
46
+ className={cn(className, styles.sectionPromoList)}
47
+ {...extractSupportProps(rest)}
48
+ >
49
+ <div className={styles.cards} data-layout-type={layoutType}>
50
+ <div className={styles.left} data-test-id='promo-list__card'>
51
+ <PromoList {...leftList} layoutType={layoutType} />
52
+ </div>
53
+ <div
54
+ className={styles.right}
55
+ data-layout-type={layoutType}
56
+ data-test-id='promo-list__card'
57
+ style={{ '--image': `url(${image})` }}
58
+ >
59
+ <div className={styles.rightSectionText} data-layout-type={layoutType}>
60
+ <PromoList {...rightList} layoutType={layoutType} />
61
+ </div>
62
+ </div>
63
+ </div>
64
+ </SectionBasic>
65
+ );
66
+ }
@@ -0,0 +1 @@
1
+ export * from './SectionPromoList';