@cloud-ru/ds-uikit-product-header 1.5.1 → 1.5.2-preview-0406cbd2.0

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 (95) hide show
  1. package/README.md +0 -1
  2. package/dist/cjs/components/HeaderButton/HeaderButton.js +1 -3
  3. package/dist/cjs/components/HeaderLayout/HeaderLayout.js +1 -12
  4. package/dist/cjs/components/HeaderLayout/styles.module.css +8 -1
  5. package/dist/cjs/components/Logo/styles.module.css +1 -0
  6. package/dist/cjs/components/MainMenu/helperComponents/Banners/MenuBanner.js +1 -3
  7. package/dist/cjs/components/MainMenu/helperComponents/Banners/styles.module.css +1 -0
  8. package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.js +1 -1
  9. package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/styles.module.css +1 -0
  10. package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SortableGroupCards.js +1 -1
  11. package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategory.js +2 -2
  12. package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/styles.module.css +9 -2
  13. package/dist/cjs/components/MainMenu/helperComponents/Favorites/Favorites.js +3 -1
  14. package/dist/cjs/components/MainMenu/helperComponents/Favorites/styles.module.css +5 -2
  15. package/dist/cjs/components/MainMenu/helperComponents/MenuDesktop/styles.module.css +2 -1
  16. package/dist/cjs/components/MainMenu/helperComponents/MenuHeaderBrand/MenuHeaderBrand.d.ts +2 -1
  17. package/dist/cjs/components/MainMenu/helperComponents/MenuHeaderBrand/MenuHeaderBrand.js +2 -2
  18. package/dist/cjs/components/MainMenu/helperComponents/MenuHeaderBrand/styles.module.css +3 -0
  19. package/dist/cjs/components/MainMenu/helperComponents/MenuMobile/MenuMobile.js +1 -6
  20. package/dist/cjs/components/MainMenu/helperComponents/MenuMobile/styles.module.css +1 -5
  21. package/dist/cjs/components/MainMenu/helperComponents/MountAnimation/styles.module.css +6 -6
  22. package/dist/cjs/components/MainMenu/helperComponents/Search/styles.module.css +3 -1
  23. package/dist/cjs/components/PathBreadcrumbs/PathBreadcrumbs.d.ts +1 -2
  24. package/dist/cjs/components/PathBreadcrumbs/PathBreadcrumbs.js +2 -2
  25. package/dist/cjs/components/PlatformLogo/styles.module.css +3 -1
  26. package/dist/cjs/components/UserMenu/UserMenu.js +5 -1
  27. package/dist/cjs/components/UserMenu/styles.module.css +1 -1
  28. package/dist/cjs/hooks/useDesktopComfortClassName.d.ts +2 -0
  29. package/dist/cjs/hooks/useDesktopComfortClassName.js +11 -0
  30. package/dist/cjs/hooks/useMobileLayout.js +1 -0
  31. package/dist/cjs/locale/index.d.ts +8 -8
  32. package/dist/cjs/locale/index.js +4 -4
  33. package/dist/cjs/style.css +44 -20
  34. package/dist/esm/components/HeaderButton/HeaderButton.js +1 -3
  35. package/dist/esm/components/HeaderLayout/HeaderLayout.js +1 -12
  36. package/dist/esm/components/HeaderLayout/styles.module.css +8 -1
  37. package/dist/esm/components/Logo/styles.module.css +1 -0
  38. package/dist/esm/components/MainMenu/helperComponents/Banners/MenuBanner.js +1 -3
  39. package/dist/esm/components/MainMenu/helperComponents/Banners/styles.module.css +1 -0
  40. package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.js +1 -1
  41. package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/styles.module.css +1 -0
  42. package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SortableGroupCards.js +1 -1
  43. package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategory.js +2 -2
  44. package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/styles.module.css +9 -2
  45. package/dist/esm/components/MainMenu/helperComponents/Favorites/Favorites.js +3 -1
  46. package/dist/esm/components/MainMenu/helperComponents/Favorites/styles.module.css +5 -2
  47. package/dist/esm/components/MainMenu/helperComponents/MenuDesktop/styles.module.css +2 -1
  48. package/dist/esm/components/MainMenu/helperComponents/MenuHeaderBrand/MenuHeaderBrand.d.ts +2 -1
  49. package/dist/esm/components/MainMenu/helperComponents/MenuHeaderBrand/MenuHeaderBrand.js +2 -2
  50. package/dist/esm/components/MainMenu/helperComponents/MenuHeaderBrand/styles.module.css +3 -0
  51. package/dist/esm/components/MainMenu/helperComponents/MenuMobile/MenuMobile.js +1 -6
  52. package/dist/esm/components/MainMenu/helperComponents/MenuMobile/styles.module.css +1 -5
  53. package/dist/esm/components/MainMenu/helperComponents/MountAnimation/styles.module.css +6 -6
  54. package/dist/esm/components/MainMenu/helperComponents/Search/styles.module.css +3 -1
  55. package/dist/esm/components/PathBreadcrumbs/PathBreadcrumbs.d.ts +1 -2
  56. package/dist/esm/components/PathBreadcrumbs/PathBreadcrumbs.js +2 -2
  57. package/dist/esm/components/PlatformLogo/styles.module.css +3 -1
  58. package/dist/esm/components/UserMenu/UserMenu.js +5 -1
  59. package/dist/esm/components/UserMenu/styles.module.css +1 -1
  60. package/dist/esm/hooks/useDesktopComfortClassName.d.ts +2 -0
  61. package/dist/esm/hooks/useDesktopComfortClassName.js +8 -0
  62. package/dist/esm/hooks/useMobileLayout.js +1 -0
  63. package/dist/esm/locale/index.d.ts +8 -8
  64. package/dist/esm/locale/index.js +4 -4
  65. package/dist/esm/style.css +44 -20
  66. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  67. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  68. package/package.json +28 -28
  69. package/src/components/HeaderButton/HeaderButton.tsx +1 -4
  70. package/src/components/HeaderLayout/HeaderLayout.tsx +10 -21
  71. package/src/components/HeaderLayout/styles.module.scss +11 -1
  72. package/src/components/Logo/styles.module.scss +1 -0
  73. package/src/components/MainMenu/helperComponents/Banners/MenuBanner.tsx +1 -3
  74. package/src/components/MainMenu/helperComponents/Banners/styles.module.scss +1 -0
  75. package/src/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.tsx +1 -1
  76. package/src/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/styles.module.scss +2 -0
  77. package/src/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SortableGroupCards.tsx +5 -1
  78. package/src/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategory.tsx +12 -2
  79. package/src/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/styles.module.scss +13 -2
  80. package/src/components/MainMenu/helperComponents/Favorites/Favorites.tsx +3 -1
  81. package/src/components/MainMenu/helperComponents/Favorites/styles.module.scss +12 -7
  82. package/src/components/MainMenu/helperComponents/MenuDesktop/styles.module.scss +4 -2
  83. package/src/components/MainMenu/helperComponents/MenuHeaderBrand/MenuHeaderBrand.tsx +3 -2
  84. package/src/components/MainMenu/helperComponents/MenuHeaderBrand/styles.module.scss +4 -0
  85. package/src/components/MainMenu/helperComponents/MenuMobile/MenuMobile.tsx +46 -52
  86. package/src/components/MainMenu/helperComponents/MenuMobile/styles.module.scss +1 -7
  87. package/src/components/MainMenu/helperComponents/MountAnimation/styles.module.scss +4 -2
  88. package/src/components/MainMenu/helperComponents/Search/styles.module.scss +3 -3
  89. package/src/components/PathBreadcrumbs/PathBreadcrumbs.tsx +2 -3
  90. package/src/components/PlatformLogo/styles.module.scss +4 -1
  91. package/src/components/UserMenu/UserMenu.tsx +5 -1
  92. package/src/components/UserMenu/styles.module.scss +1 -1
  93. package/src/hooks/useDesktopComfortClassName.ts +11 -0
  94. package/src/hooks/useMobileLayout.ts +1 -0
  95. package/src/locale/index.ts +4 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloud-ru/ds-uikit-product-header",
3
- "version": "1.5.1",
3
+ "version": "1.5.2-preview-0406cbd2.0",
4
4
  "description": "Продуктовая шапка консоли — HeaderLayout, MainMenu, UserMenu, Logo, PathBreadcrumbs и PlatformLogo.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -45,33 +45,33 @@
45
45
  "@dnd-kit/utilities": "^3.2.2",
46
46
  "classnames": "^2.5.1",
47
47
  "fuse.js": "^7.1.0",
48
- "@cloud-ru/ds-accordion": "^1.1.0",
49
- "@cloud-ru/ds-adaptive": "^1.0.1",
50
- "@cloud-ru/ds-breadcrumbs": "^1.0.18",
51
- "@cloud-ru/ds-avatar": "^1.0.5",
52
- "@cloud-ru/ds-button": "^1.0.3",
53
- "@cloud-ru/ds-card": "^1.0.14",
54
- "@cloud-ru/ds-drawer": "^1.2.2",
55
- "@cloud-ru/ds-divider": "^1.0.1",
56
- "@cloud-ru/ds-drag-and-drop": "^1.1.2",
57
- "@cloud-ru/ds-icons": "^1.2.1",
58
- "@cloud-ru/ds-info-block": "^1.0.2",
59
- "@cloud-ru/ds-list": "^2.2.1",
60
- "@cloud-ru/ds-locale": "^1.0.0",
61
- "@cloud-ru/ds-modal": "^1.1.3",
62
- "@cloud-ru/ds-portal-context": "^1.0.1",
63
- "@cloud-ru/ds-promo-tag": "^1.0.2",
64
- "@cloud-ru/ds-scroll": "^1.0.3",
65
- "@cloud-ru/ds-segment-control": "^1.0.7",
66
- "@cloud-ru/ds-skeleton": "^1.0.1",
67
- "@cloud-ru/ds-search": "^1.0.9",
68
- "@cloud-ru/ds-theme": "^2.0.0",
69
- "@cloud-ru/ds-tooltip": "^1.0.6",
70
- "@cloud-ru/ds-typography": "^1.0.0",
71
- "@cloud-ru/ds-uikit-product-card-predefined": "^3.1.4",
72
- "@cloud-ru/ds-uikit-product-switch-row": "^1.0.8",
73
- "@cloud-ru/ds-uikit-product-title-clickable": "^1.0.10",
74
- "@cloud-ru/ds-utils": "^1.1.0"
48
+ "@cloud-ru/ds-accordion": "1.1.0",
49
+ "@cloud-ru/ds-adaptive": "1.0.1",
50
+ "@cloud-ru/ds-button": "1.0.3",
51
+ "@cloud-ru/ds-divider": "1.0.1",
52
+ "@cloud-ru/ds-drag-and-drop": "1.1.2",
53
+ "@cloud-ru/ds-drawer": "1.2.2",
54
+ "@cloud-ru/ds-icons": "1.2.1",
55
+ "@cloud-ru/ds-info-block": "1.0.2",
56
+ "@cloud-ru/ds-card": "1.0.14",
57
+ "@cloud-ru/ds-list": "2.2.2-preview-0406cbd2.0",
58
+ "@cloud-ru/ds-locale": "1.0.0",
59
+ "@cloud-ru/ds-portal-context": "1.0.1",
60
+ "@cloud-ru/ds-modal": "1.1.3",
61
+ "@cloud-ru/ds-promo-tag": "1.0.2",
62
+ "@cloud-ru/ds-scroll": "1.0.3",
63
+ "@cloud-ru/ds-search": "1.0.9",
64
+ "@cloud-ru/ds-segment-control": "1.0.7",
65
+ "@cloud-ru/ds-skeleton": "1.0.1",
66
+ "@cloud-ru/ds-theme": "2.0.0",
67
+ "@cloud-ru/ds-tooltip": "1.0.6",
68
+ "@cloud-ru/ds-typography": "1.0.0",
69
+ "@cloud-ru/ds-uikit-product-switch-row": "1.0.8",
70
+ "@cloud-ru/ds-uikit-product-card-predefined": "3.1.5-preview-0406cbd2.0",
71
+ "@cloud-ru/ds-uikit-product-title-clickable": "1.0.10",
72
+ "@cloud-ru/ds-utils": "1.1.0",
73
+ "@cloud-ru/ds-avatar": "1.0.5",
74
+ "@cloud-ru/ds-breadcrumbs": "1.0.19-preview-0406cbd2.0"
75
75
  },
76
76
  "publishConfig": {
77
77
  "access": "public"
@@ -1,5 +1,4 @@
1
1
  import { Button, ButtonProps } from '@cloud-ru/ds-button';
2
- import { useThemeClassnames } from '@cloud-ru/ds-theme';
3
2
  import { TooltipProps, WithTooltip } from '@cloud-ru/ds-tooltip';
4
3
  import cn from 'classnames';
5
4
  import { ElementType } from 'react';
@@ -26,8 +25,6 @@ export function HeaderButton<T extends ElementType = 'button'>({
26
25
  className,
27
26
  ...rest
28
27
  }: HeaderButtonProps<T>) {
29
- const compactThemeClassName = useThemeClassnames({ density: 'compact' });
30
-
31
28
  return (
32
29
  // FIXME: typescript ломается, если не указать tip явно
33
30
  // пока не разбирался почему так
@@ -50,7 +47,7 @@ export function HeaderButton<T extends ElementType = 'button'>({
50
47
  size='m'
51
48
  appearance='neutral'
52
49
  view='simple'
53
- className={cn(styles.headerButton, compactThemeClassName, className)}
50
+ className={cn(styles.headerButton, className)}
54
51
  />
55
52
  </WithTooltip>
56
53
  );
@@ -1,8 +1,7 @@
1
1
  import { Divider } from '@cloud-ru/ds-divider';
2
- import { ChildThemeProvider, DENSITY } from '@cloud-ru/ds-theme';
3
2
  import { extractSupportProps, WithSupportProps } from '@cloud-ru/ds-utils';
4
3
  import cn from 'classnames';
5
- import { ReactNode, useRef } from 'react';
4
+ import { ReactNode } from 'react';
6
5
 
7
6
  import { TEST_IDS } from '../../constants';
8
7
  import { useMobileLayout } from '../../hooks/useMobileLayout';
@@ -19,12 +18,10 @@ export type HeaderLayoutProps = WithSupportProps<{
19
18
 
20
19
  export function HeaderLayout({ menu, logo, select, breadcrumbs, toolbar, className, ...rest }: HeaderLayoutProps) {
21
20
  const isMobile = useMobileLayout();
22
- const headerRef = useRef<HTMLElement>(null);
23
-
24
- const header = (
21
+ return (
25
22
  <header
26
- ref={headerRef}
27
23
  className={cn(styles.header, className)}
24
+ data-mobile={isMobile || undefined}
28
25
  {...extractSupportProps({ 'data-test-id': TEST_IDS.headerLayout.root, ...rest })}
29
26
  >
30
27
  <div className={styles.top}>
@@ -35,6 +32,7 @@ export function HeaderLayout({ menu, logo, select, breadcrumbs, toolbar, classNa
35
32
  <>
36
33
  <Divider orientation='vertical' />
37
34
  {menu}
35
+ {isMobile && <Divider orientation='vertical' />}
38
36
  </>
39
37
  )}
40
38
 
@@ -57,21 +55,12 @@ export function HeaderLayout({ menu, logo, select, breadcrumbs, toolbar, classNa
57
55
  </div>
58
56
  <Divider orientation='horizontal' />
59
57
 
60
- {isMobile && Boolean(breadcrumbs) && <div className={styles.bottom}>{breadcrumbs}</div>}
58
+ {isMobile && Boolean(breadcrumbs) && (
59
+ <>
60
+ <div className={styles.bottom}>{breadcrumbs}</div>
61
+ <Divider orientation='horizontal' />
62
+ </>
63
+ )}
61
64
  </header>
62
65
  );
63
-
64
- // Временная фиксация: на mobile прикладная тема переключилась на compact, а шапка сверстана
65
- // под comfort и на compact ещё не переехала. Провайдер (а не класс на `<header>`) нужен потому,
66
- // что поверхности шапки — порталы: они переэмитят набор `sn-*` из контекста на своём корне,
67
- // и класс, поставленный поверх, проиграл бы их собственному.
68
- if (isMobile) {
69
- return (
70
- <ChildThemeProvider value={{ density: DENSITY.Comfort }} rootRef={headerRef}>
71
- {header}
72
- </ChildThemeProvider>
73
- );
74
- }
75
-
76
- return header;
77
66
  }
@@ -22,7 +22,6 @@
22
22
 
23
23
  box-sizing: border-box;
24
24
  height: base.$sn-primitive-dimension-24;
25
- border-bottom: base.$sn-primitive-strokeWeight-strokeRegular solid base.$sn-theme-color-available-borderColor;
26
25
  }
27
26
 
28
27
  .left {
@@ -40,3 +39,14 @@
40
39
  align-items: center;
41
40
  height: 100%;
42
41
  }
42
+
43
+ .header[data-mobile] {
44
+ .top {
45
+ padding: base.$sn-primitive-dimension-0;
46
+ }
47
+
48
+ .left,
49
+ .right {
50
+ gap: base.$sn-primitive-dimension-0;
51
+ }
52
+ }
@@ -39,6 +39,7 @@
39
39
  .logo {
40
40
  position: relative;
41
41
  flex-shrink: 0;
42
+ box-sizing: border-box;
42
43
 
43
44
  &:active:not([data-disabled]) {
44
45
  .iconDefault {
@@ -2,7 +2,6 @@ import { Button } from '@cloud-ru/ds-button';
2
2
  import { Card } from '@cloud-ru/ds-card';
3
3
  import { CrossSVG } from '@cloud-ru/ds-icons/interface/system';
4
4
  import { PromoTag, PromoTagProps, ROLE_APPEARANCE, SIZE } from '@cloud-ru/ds-promo-tag';
5
- import { useThemeClassnames } from '@cloud-ru/ds-theme';
6
5
  import { Typography } from '@cloud-ru/ds-typography';
7
6
  import { WithSupportProps } from '@cloud-ru/ds-utils';
8
7
  import cn from 'classnames';
@@ -38,7 +37,6 @@ export function MenuBanner({
38
37
  ...rest
39
38
  }: MenuBannerProps): ReactElement {
40
39
  const { t } = headerLocale.useTranslations();
41
- const compactThemeClassname = useThemeClassnames({ density: 'compact' });
42
40
 
43
41
  const handleClose: MouseEventHandler<HTMLButtonElement> = useCallback(
44
42
  e => {
@@ -90,7 +88,7 @@ export function MenuBanner({
90
88
 
91
89
  {onClose && (
92
90
  <Button
93
- className={cn(styles.closeButton, compactThemeClassname)}
91
+ className={styles.closeButton}
94
92
  view='elevated'
95
93
  appearance='neutral'
96
94
  size='s'
@@ -13,6 +13,7 @@
13
13
  }
14
14
 
15
15
  .root {
16
+ box-sizing: border-box;
16
17
  width: 100%;
17
18
  min-width: 0;
18
19
 
@@ -64,7 +64,7 @@ export function ContentToolbar({
64
64
  const hasSegmentItems = segmentItems && segmentItems?.length > 0;
65
65
 
66
66
  return (
67
- <div className={styles.root} data-test-id={TEST_IDS.toolbar}>
67
+ <div className={styles.root} data-mobile={isMobile || undefined} data-test-id={TEST_IDS.toolbar}>
68
68
  {hasSegmentItems && (
69
69
  <WithSkeleton
70
70
  loading={loading}
@@ -7,9 +7,11 @@
7
7
  align-items: center;
8
8
  justify-content: space-between;
9
9
 
10
+ box-sizing: border-box;
10
11
  width: 100%;
11
12
  min-width: 0;
12
13
  min-height: base.$sn-primitive-dimension-32;
14
+
13
15
  }
14
16
 
15
17
  .segmentControl {
@@ -25,7 +25,11 @@ export function SortableGroupCards({
25
25
  onServiceClick,
26
26
  }: SortableGroupCardsProps) {
27
27
  return (
28
- <div className={styles.groupBody} data-mobile={isMobile || undefined}>
28
+ <div
29
+ className={styles.groupBody}
30
+ data-mobile={isMobile || undefined}
31
+ data-show-description={showDescription || undefined}
32
+ >
29
33
  {items.map(service => {
30
34
  if (service.hidden) {
31
35
  return null;
@@ -83,7 +83,12 @@ export function SubCategory({
83
83
  onServiceClick={onServiceClick}
84
84
  />
85
85
 
86
- <div className={baseGroupStyles.groupBody} data-subcategory-body='expanded' data-mobile={isMobile || undefined}>
86
+ <div
87
+ className={baseGroupStyles.groupBody}
88
+ data-subcategory-body='expanded'
89
+ data-mobile={isMobile || undefined}
90
+ data-show-description={showDescription || undefined}
91
+ >
87
92
  {nestedItems.map(nestedService => (
88
93
  <DraggableServiceCard
89
94
  key={nestedGroupId + nestedService.id}
@@ -124,7 +129,12 @@ export function SubCategory({
124
129
  />
125
130
  }
126
131
  >
127
- <div className={baseGroupStyles.groupBody} data-subcategory-body data-mobile={isMobile || undefined}>
132
+ <div
133
+ className={baseGroupStyles.groupBody}
134
+ data-subcategory-body
135
+ data-mobile={isMobile || undefined}
136
+ data-show-description={showDescription || undefined}
137
+ >
128
138
  {nestedItems.map(nestedService => (
129
139
  <DraggableServiceCard
130
140
  key={nestedGroupId + nestedService.id}
@@ -54,7 +54,7 @@ $map-block-color-decor: (
54
54
 
55
55
  @media (hover: hover) {
56
56
  &:hover {
57
- background-color: base.$sn-theme-color-material-stateLayer-neutral-onBackground-hovered-filled;
57
+ background-color: base.$sn-theme-color-neutral-decorTransparent;
58
58
 
59
59
  .headerActions {
60
60
  pointer-events: auto;
@@ -86,6 +86,7 @@ $map-block-color-decor: (
86
86
  display: flex;
87
87
  flex-direction: column;
88
88
 
89
+ box-sizing: border-box;
89
90
  width: 100%;
90
91
  min-width: 0;
91
92
  padding: base.$sn-primitive-dimension-4 base.$sn-primitive-dimension-8 base.$sn-primitive-dimension-8
@@ -158,6 +159,15 @@ $map-block-color-decor: (
158
159
  gap: base.$sn-primitive-dimension-4;
159
160
 
160
161
  &:not([data-mobile]) {
162
+ &:not([data-subcategory-body]) {
163
+ padding: base.$sn-primitive-dimension-4;
164
+ }
165
+
166
+ // Карточки без описания в десктопном мастере стоят впритык.
167
+ &:not([data-show-description]) {
168
+ gap: base.$sn-primitive-dimension-0;
169
+ }
170
+
161
171
  // Drawer десктопного меню ресайзится пользователем (см. MenuDesktop.resizable),
162
172
  // поэтому колонки реагируют на реальную ширину контейнера (container query
163
173
  // от `.rightContent`), а не на ширину viewport.
@@ -168,6 +178,7 @@ $map-block-color-decor: (
168
178
  }
169
179
 
170
180
  &[data-mobile] {
181
+ // Нет токена минимальной ширины карточки.
171
182
  grid-template-columns: repeat(1, minmax(200px, 1fr));
172
183
  }
173
184
 
@@ -181,7 +192,7 @@ $map-block-color-decor: (
181
192
  }
182
193
 
183
194
  .decoration {
184
- --highlight-border-width: 1px;
195
+ --highlight-border-width: #{base.$sn-primitive-strokeWeight-strokeRegular};
185
196
 
186
197
  position: absolute;
187
198
  top: 0;
@@ -8,6 +8,7 @@ import { useValueControl } from '@cloud-ru/ds-utils';
8
8
  import cn from 'classnames';
9
9
  import { MouseEvent, useMemo } from 'react';
10
10
 
11
+ import { useDesktopComfortClassName } from '../../../../hooks/useDesktopComfortClassName';
11
12
  import { headerLocale } from '../../../../locale';
12
13
  import { FavoriteProps, InnerLink, LinksGroup } from '../../types';
13
14
  import { resolveInnerLinksByIds } from '../../utils';
@@ -30,6 +31,7 @@ export type FavoritesProps = {
30
31
  export function Favorites({ favorite, allServiceGroups, headerClassName, isMobile }: FavoritesProps) {
31
32
  const { t } = headerLocale.useTranslations();
32
33
  const loading = favorite.loading;
34
+ const comfortClassName = useDesktopComfortClassName();
33
35
 
34
36
  const [segment, setSegment] = useValueControl<FavoritesSegment>({
35
37
  value: favorite.segment,
@@ -146,7 +148,7 @@ export function Favorites({ favorite, allServiceGroups, headerClassName, isMobil
146
148
  />
147
149
 
148
150
  {favorite.actions && (
149
- <Droplist size='m' {...favorite.actions} closeDroplistOnItemClick>
151
+ <Droplist size='m' {...favorite.actions} className={comfortClassName} closeDroplistOnItemClick>
150
152
  <Button
151
153
  view='function'
152
154
  size='m'
@@ -1,5 +1,10 @@
1
1
  @use '@cloud-ru/ds-figma-variables/build/scss/styles/styles.module' as base;
2
2
 
3
+ $card-gap: base.$sn-primitive-dimension-4;
4
+ $card-height: base.$sn-primitive-dimension-32;
5
+ $card-height-mobile: base.$sn-primitive-dimension-40;
6
+ $list-padding-bottom: base.$sn-primitive-dimension-8;
7
+
3
8
  .root {
4
9
  display: flex;
5
10
  flex-direction: column;
@@ -59,23 +64,22 @@
59
64
 
60
65
  .listScrollInner {
61
66
  height: 100%;
62
- // 12 карточек + gap + padding-top + padding-bottom от .list
63
- max-height: calc(
64
- (#{base.$sn-primitive-dimension-32} * 12) + #{base.$sn-primitive-dimension-4} + #{base.$sn-primitive-dimension-8}
65
- );
67
+ // Шаг карточки (высота + зазор) × 12 видимых + нижний паддинг `.list`.
68
+ max-height: calc((#{$card-height} + #{$card-gap}) * 12 + #{$list-padding-bottom});
66
69
 
67
70
  &[data-mobile] {
68
- max-height: calc(
69
- (#{base.$sn-primitive-dimension-40} * 6) + #{base.$sn-primitive-dimension-4} + #{base.$sn-primitive-dimension-8}
70
- );
71
+ max-height: calc((#{$card-height-mobile} + #{$card-gap}) * 6 + #{$list-padding-bottom});
71
72
  }
72
73
  }
73
74
 
74
75
  .list {
75
76
  display: flex;
76
77
  flex-direction: column;
78
+ // Зазор между карточками избранного — из мастера (`+ slotFavourites`, FF-9057).
79
+ gap: $card-gap;
77
80
  align-items: stretch;
78
81
 
82
+ box-sizing: border-box;
79
83
  width: 100%;
80
84
  padding: base.$sn-primitive-dimension-4 base.$sn-primitive-dimension-8 base.$sn-primitive-dimension-8;
81
85
  }
@@ -102,6 +106,7 @@
102
106
  gap: base.$sn-primitive-dimension-4;
103
107
  align-items: stretch;
104
108
 
109
+ box-sizing: border-box;
105
110
  width: 100%;
106
111
  padding: base.$sn-primitive-dimension-8;
107
112
  }
@@ -36,7 +36,7 @@
36
36
 
37
37
  // NOTE: cелектор такой потому, что не получается достучаться до нужной дивки и переопределить стили без !important
38
38
  [data-test-id='header__drawer-menu'][data-small][data-position][data-width] {
39
- // NOTE: ширина по макету 263px, но у дровера еще зашит паддинг. Не стал его обнулять
39
+ // NOTE: ширина по макету 263px (нет токена), но у дровера еще зашит паддинг. Не стал его обнулять
40
40
  // по умолчанию box-sizing: content-box; и из-за этого max-width определяется некорректно
41
41
  box-sizing: border-box;
42
42
  width: 100%;
@@ -74,13 +74,15 @@
74
74
  flex-direction: column;
75
75
  gap: base.$sn-primitive-dimension-4;
76
76
 
77
+ box-sizing: border-box;
77
78
  width: 100%;
78
79
  min-width: 0;
79
80
  padding: base.$sn-primitive-dimension-16;
80
81
  }
81
82
 
82
83
  .menu {
83
- --snack-menu-header-height: 40px;
84
+ --snack-menu-header-height: #{base.$sn-primitive-dimension-40};
85
+ // Нет токена ширины левой колонки меню.
84
86
  --snack-menu-left-width: 263px;
85
87
 
86
88
  position: relative;
@@ -11,13 +11,14 @@ export type MenuHeaderBrandProps = {
11
11
  logo?: ReactNode;
12
12
  onClose(): void;
13
13
  className?: string;
14
+ isMobile?: boolean;
14
15
  };
15
16
 
16
- export function MenuHeaderBrand({ logo, onClose, className }: MenuHeaderBrandProps) {
17
+ export function MenuHeaderBrand({ logo, onClose, className, isMobile }: MenuHeaderBrandProps) {
17
18
  const { t } = headerLocale.useTranslations();
18
19
 
19
20
  return (
20
- <div className={cn(styles.container, className)}>
21
+ <div className={cn(styles.container, className)} data-mobile={isMobile || undefined}>
21
22
  {logo}
22
23
  <Divider orientation='vertical' />
23
24
 
@@ -8,6 +8,10 @@
8
8
  box-sizing: border-box;
9
9
 
10
10
  background-color: base.$sn-theme-color-neutral-background;
11
+
12
+ &[data-mobile] {
13
+ gap: base.$sn-primitive-dimension-0;
14
+ }
11
15
  }
12
16
 
13
17
  .closeButton {
@@ -1,5 +1,4 @@
1
1
  import { Divider } from '@cloud-ru/ds-divider';
2
- import { ChildThemeProvider, DENSITY } from '@cloud-ru/ds-theme';
3
2
  import { useValueControl } from '@cloud-ru/ds-utils';
4
3
  import { useCallback, useMemo } from 'react';
5
4
 
@@ -62,59 +61,54 @@ export function MenuMobile({
62
61
  }, [setOpen]);
63
62
 
64
63
  return (
65
- // Временная фиксация comfort (см. `HeaderLayout`): `MainMenu` используется и отдельно от
66
- // `HeaderLayout`, поэтому объявляем плотность здесь же. Обёртка провайдера layout-прозрачная
67
- // (`display: contents`) — меню рендерится порталом, лишний бокс в строке шапки не нужен.
68
- <ChildThemeProvider value={{ density: DENSITY.Comfort }} className={styles.densityScope}>
69
- <MobileDrawerCustom
70
- open={open}
71
- onClose={handleClose}
72
- position='bottom'
73
- className={styles.drawerMobile}
74
- swipeEnabled={false}
75
- data-test-id={TEST_IDS.mainMenu.drawerMobile}
76
- closeOnPopstate
77
- snapPoints={BOTTOM_SHEET_FULLSCREEN_SNAP_POINTS}
78
- disableMotions={true}
64
+ <MobileDrawerCustom
65
+ open={open}
66
+ onClose={handleClose}
67
+ position='bottom'
68
+ className={styles.drawerMobile}
69
+ swipeEnabled={false}
70
+ data-test-id={TEST_IDS.mainMenu.drawerMobile}
71
+ closeOnPopstate
72
+ snapPoints={BOTTOM_SHEET_FULLSCREEN_SNAP_POINTS}
73
+ disableMotions={true}
74
+ >
75
+ <ScrollWithAnimatedStickyPanel
76
+ panel={
77
+ <>
78
+ <MenuHeaderBrand logo={logo} onClose={handleClose} className={styles.menuHeader} isMobile />
79
+ <Divider orientation='horizontal' />
80
+ </>
81
+ }
79
82
  >
80
- <ScrollWithAnimatedStickyPanel
81
- panel={
82
- <>
83
- <MenuHeaderBrand logo={logo} onClose={handleClose} className={styles.menuHeader} />
84
- <Divider orientation='horizontal' />
85
- </>
86
- }
87
- >
88
- <MountAnimation className={styles.scrollMobile} type='fade-slide-up'>
89
- {leftTop && <div className={styles.rightContent}>{leftTop}</div>}
90
- {search && <Search {...search} ref={searchRef} isMobile />}
91
- {!isSearching && favorite && <Favorites favorite={favorite} allServiceGroups={allServiceGroups} isMobile />}
83
+ <MountAnimation className={styles.scrollMobile} type='fade-slide-up'>
84
+ {leftTop && <div className={styles.rightContent}>{leftTop}</div>}
85
+ {search && <Search {...search} ref={searchRef} isMobile />}
86
+ {!isSearching && favorite && <Favorites favorite={favorite} allServiceGroups={allServiceGroups} isMobile />}
92
87
 
93
- {hasSegments && (
94
- <MainMenuDndContext>
95
- <Content
96
- isMobile
97
- className={styles.rightContent}
98
- searchValue={search && search.value}
99
- rightTop={rightTop}
100
- favorite={favorite}
101
- segments={segments}
102
- searchGroups={resultItems}
103
- segmentPrefs={segmentPrefs}
104
- activeSegmentId={activeSegmentId}
105
- onActiveSegmentChange={onActiveSegmentChange}
106
- onSegmentOrderChange={onSegmentOrderChange}
107
- onSegmentExpandedChange={onSegmentExpandedChange}
108
- onSegmentServiceClick={onSegmentServiceClick}
109
- loading={loading}
110
- />
111
- </MainMenuDndContext>
112
- )}
88
+ {hasSegments && (
89
+ <MainMenuDndContext>
90
+ <Content
91
+ isMobile
92
+ className={styles.rightContent}
93
+ searchValue={search && search.value}
94
+ rightTop={rightTop}
95
+ favorite={favorite}
96
+ segments={segments}
97
+ searchGroups={resultItems}
98
+ segmentPrefs={segmentPrefs}
99
+ activeSegmentId={activeSegmentId}
100
+ onActiveSegmentChange={onActiveSegmentChange}
101
+ onSegmentOrderChange={onSegmentOrderChange}
102
+ onSegmentExpandedChange={onSegmentExpandedChange}
103
+ onSegmentServiceClick={onSegmentServiceClick}
104
+ loading={loading}
105
+ />
106
+ </MainMenuDndContext>
107
+ )}
113
108
 
114
- {!isSearching && hasBottomItems && <MenuBottom settingItems={settingItems} leftBottom={leftBottom} />}
115
- </MountAnimation>
116
- </ScrollWithAnimatedStickyPanel>
117
- </MobileDrawerCustom>
118
- </ChildThemeProvider>
109
+ {!isSearching && hasBottomItems && <MenuBottom settingItems={settingItems} leftBottom={leftBottom} />}
110
+ </MountAnimation>
111
+ </ScrollWithAnimatedStickyPanel>
112
+ </MobileDrawerCustom>
119
113
  );
120
114
  }
@@ -4,15 +4,8 @@
4
4
  $menuHeaderHeight: base.$sn-primitive-dimension-40;
5
5
  $menuHeaderHeightWithDivider: calc(#{$menuHeaderHeight} + #{divider.$sn-divider-anatomy-container-height});
6
6
 
7
- // Обёртка провайдера плотности вокруг портала меню: собственного бокса у неё быть не должно,
8
- // иначе в строке шапки появляется лишний flex-элемент и лишний gap.
9
- .densityScope {
10
- display: contents;
11
- }
12
-
13
7
  .menuHeader {
14
8
  height: $menuHeaderHeight;
15
- padding: 0 base.$sn-primitive-dimension-4;
16
9
  }
17
10
 
18
11
  .rightContent {
@@ -33,6 +26,7 @@ $menuHeaderHeightWithDivider: calc(#{$menuHeaderHeight} + #{divider.$sn-divider-
33
26
  flex-direction: column;
34
27
  gap: base.$sn-primitive-dimension-8;
35
28
 
29
+ box-sizing: border-box;
36
30
  min-height: 100%;
37
31
  margin-top: $menuHeaderHeightWithDivider;
38
32
  padding: base.$sn-primitive-dimension-16;
@@ -1,5 +1,7 @@
1
- $slide-x: -12px;
2
- $slide-y: 4px;
1
+ @use '@cloud-ru/ds-figma-variables/build/scss/styles/styles.module' as base;
2
+
3
+ $slide-x: calc(-1 * #{base.$sn-primitive-dimension-12});
4
+ $slide-y: base.$sn-primitive-dimension-4;
3
5
 
4
6
  .wrapper {
5
7
  will-change: transform, opacity;
@@ -3,9 +3,9 @@
3
3
  .searchWrap {
4
4
  &:not([data-mobile]) {
5
5
  flex: 1 1 auto;
6
-
7
- // NOTE: у Search уже есть свои паддинги внутри компонента, поэтому здесь паддинги на 2px меньше
8
- padding: base.$sn-primitive-dimension-2 base.$sn-primitive-dimension-10;
6
+ box-sizing: border-box;
7
+ margin: 0 base.$sn-primitive-dimension-4;
8
+ padding: base.$sn-primitive-dimension-4 base.$sn-primitive-dimension-12;
9
9
  }
10
10
  }
11
11
 
@@ -5,17 +5,16 @@ import styles from './styles.module.scss';
5
5
 
6
6
  type PathBreadcrumbsProps = {
7
7
  items: BreadcrumbsProps['items'];
8
- isMobile?: boolean;
9
8
  };
10
9
 
11
- export function PathBreadcrumbs({ isMobile, items }: PathBreadcrumbsProps) {
10
+ export function PathBreadcrumbs({ items }: PathBreadcrumbsProps) {
12
11
  return (
13
12
  <Breadcrumbs
14
13
  items={items}
15
14
  className={styles.breadcrumbs}
16
15
  inactiveLastItem={items.length > 1}
17
16
  separator='/'
18
- size={isMobile ? 'xs' : 's'}
17
+ size='xs'
19
18
  data-test-id={TEST_IDS.breadcrumbs.root}
20
19
  />
21
20
  );