@cloud-ru/ds-uikit-product-header 1.3.2 → 1.3.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 (33) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +2 -0
  3. package/dist/cjs/components/MainMenu/helperComponents/Content/Content.js +1 -1
  4. package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.d.ts +3 -1
  5. package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.js +3 -2
  6. package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/styles.module.css +16 -0
  7. package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SortableGroupSkeleton.js +1 -1
  8. package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategory.js +5 -2
  9. package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategoryTitle.js +6 -2
  10. package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/styles.module.css +3 -0
  11. package/dist/cjs/components/MainMenu/types.d.ts +2 -0
  12. package/dist/cjs/style.css +19 -0
  13. package/dist/esm/components/MainMenu/helperComponents/Content/Content.js +1 -1
  14. package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.d.ts +3 -1
  15. package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.js +3 -2
  16. package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/styles.module.css +16 -0
  17. package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SortableGroupSkeleton.js +1 -1
  18. package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategory.js +5 -2
  19. package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategoryTitle.js +6 -2
  20. package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/styles.module.css +3 -0
  21. package/dist/esm/components/MainMenu/types.d.ts +2 -0
  22. package/dist/esm/style.css +19 -0
  23. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  24. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  25. package/package.json +9 -9
  26. package/src/components/MainMenu/helperComponents/Content/Content.tsx +1 -0
  27. package/src/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.tsx +29 -11
  28. package/src/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/styles.module.scss +22 -0
  29. package/src/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SortableGroupSkeleton.tsx +1 -1
  30. package/src/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategory.tsx +6 -2
  31. package/src/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategoryTitle.tsx +10 -2
  32. package/src/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/styles.module.scss +7 -0
  33. package/src/components/MainMenu/types.ts +2 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloud-ru/ds-uikit-product-header",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "Продуктовая шапка консоли — HeaderLayout, MainMenu, UserMenu, Logo, PathBreadcrumbs и PlatformLogo.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -47,29 +47,29 @@
47
47
  "fuse.js": "^7.1.0",
48
48
  "@cloud-ru/ds-accordion": "^1.0.6",
49
49
  "@cloud-ru/ds-adaptive": "^1.0.1",
50
- "@cloud-ru/ds-avatar": "^1.0.3",
51
50
  "@cloud-ru/ds-breadcrumbs": "^1.0.13",
52
- "@cloud-ru/ds-button": "^1.0.2",
53
- "@cloud-ru/ds-divider": "^1.0.1",
54
51
  "@cloud-ru/ds-drag-and-drop": "^1.1.1",
52
+ "@cloud-ru/ds-avatar": "^1.0.3",
55
53
  "@cloud-ru/ds-drawer": "^1.1.1",
56
- "@cloud-ru/ds-icons": "^1.1.0",
54
+ "@cloud-ru/ds-button": "^1.0.2",
55
+ "@cloud-ru/ds-divider": "^1.0.1",
57
56
  "@cloud-ru/ds-info-block": "^1.0.1",
58
- "@cloud-ru/ds-list": "^2.1.2",
59
- "@cloud-ru/ds-locale": "^1.0.0",
60
57
  "@cloud-ru/ds-modal": "^1.1.1",
58
+ "@cloud-ru/ds-list": "^2.1.2",
61
59
  "@cloud-ru/ds-portal-context": "^1.0.1",
60
+ "@cloud-ru/ds-locale": "^1.0.0",
62
61
  "@cloud-ru/ds-promo-tag": "^1.0.1",
63
62
  "@cloud-ru/ds-scroll": "^1.0.2",
63
+ "@cloud-ru/ds-icons": "^1.1.0",
64
64
  "@cloud-ru/ds-search": "^1.0.6",
65
65
  "@cloud-ru/ds-segment-control": "^1.0.5",
66
66
  "@cloud-ru/ds-skeleton": "^1.0.1",
67
67
  "@cloud-ru/ds-tooltip": "^1.0.4",
68
- "@cloud-ru/ds-theme": "^1.1.0",
69
68
  "@cloud-ru/ds-typography": "^1.0.0",
69
+ "@cloud-ru/ds-theme": "^1.1.0",
70
70
  "@cloud-ru/ds-uikit-product-card-predefined": "^3.0.6",
71
- "@cloud-ru/ds-uikit-product-switch-row": "^1.0.5",
72
71
  "@cloud-ru/ds-uikit-product-title-clickable": "^1.0.8",
72
+ "@cloud-ru/ds-uikit-product-switch-row": "^1.0.5",
73
73
  "@cloud-ru/ds-utils": "^1.1.0"
74
74
  },
75
75
  "publishConfig": {
@@ -280,6 +280,7 @@ export function Content({
280
280
  onToggleAllGroupsExpanded={handleToggleAllGroupsExpanded}
281
281
  preferences={preferences}
282
282
  isMobile={isMobile}
283
+ loading={loading}
283
284
  />
284
285
 
285
286
  {!isMobile && rightTop}
@@ -2,6 +2,7 @@ import { Button } from '@cloud-ru/ds-button';
2
2
  import { CollapseVerticalSVG, ExpandVerticalSVG, SettingsSVG } from '@cloud-ru/ds-icons/interface/system';
3
3
  import { Modal } from '@cloud-ru/ds-modal';
4
4
  import { SegmentControl } from '@cloud-ru/ds-segment-control';
5
+ import { Skeleton, WithSkeleton } from '@cloud-ru/ds-skeleton';
5
6
  import { SwitchRow } from '@cloud-ru/ds-uikit-product-switch-row';
6
7
  import { useValueControl } from '@cloud-ru/ds-utils';
7
8
  import { ReactNode, startTransition } from 'react';
@@ -33,6 +34,9 @@ export type ContentToolbarProps = {
33
34
  preferences?: MainMenuPreferencesProps;
34
35
 
35
36
  isMobile?: boolean;
37
+
38
+ /** Флаг загрузки данных — сегменты подгружаются с бэка, поэтому SegmentControl тоже уходит в скелетон. */
39
+ loading?: boolean;
36
40
  };
37
41
 
38
42
  export function ContentToolbar({
@@ -43,6 +47,7 @@ export function ContentToolbar({
43
47
  onToggleAllGroupsExpanded,
44
48
  preferences,
45
49
  isMobile,
50
+ loading,
46
51
  }: ContentToolbarProps) {
47
52
  const { t } = headerLocale.useTranslations();
48
53
  const [open = false, setOpen] = useValueControl<boolean>({
@@ -62,19 +67,32 @@ export function ContentToolbar({
62
67
  return (
63
68
  <div className={styles.root} data-test-id={TEST_IDS.toolbar}>
64
69
  {hasSegmentItems && (
65
- <SegmentControl
66
- size='m'
67
- outline
68
- value={segment}
69
- onChange={onSegmentChange}
70
- className={styles.segmentControl}
71
- data-test-id={TEST_IDS.segmentControl}
72
- items={segmentItems}
73
- width={isMobile ? 'full' : 'auto'}
74
- />
70
+ <WithSkeleton
71
+ loading={loading}
72
+ skeleton={
73
+ <div
74
+ className={styles.segmentControlSkeleton}
75
+ data-test-id={TEST_IDS.segmentControl}
76
+ data-mobile={isMobile || undefined}
77
+ >
78
+ <Skeleton className={styles.segmentControlSkeletonBlock} />
79
+ </div>
80
+ }
81
+ >
82
+ <SegmentControl
83
+ size='m'
84
+ outline
85
+ value={segment}
86
+ onChange={onSegmentChange}
87
+ className={styles.segmentControl}
88
+ data-test-id={TEST_IDS.segmentControl}
89
+ items={segmentItems}
90
+ width={isMobile ? 'full' : 'auto'}
91
+ />
92
+ </WithSkeleton>
75
93
  )}
76
94
 
77
- {(preferences || !isMobile) && (
95
+ {(preferences || !isMobile) && !loading && (
78
96
  <div className={styles.actions}>
79
97
  {preferences && (
80
98
  <>
@@ -1,3 +1,4 @@
1
+ @use '@cloud-ru/ds-figma-variables/build/scss/components/segmentControl.module' as segmentControl;
1
2
  @use '@cloud-ru/ds-figma-variables/build/scss/styles/styles.module' as base;
2
3
 
3
4
  .root {
@@ -15,6 +16,27 @@
15
16
  flex-shrink: 0;
16
17
  }
17
18
 
19
+ .segmentControlSkeleton {
20
+ display: flex;
21
+ flex-shrink: 0;
22
+ // Ширина placeholder'а не выводится из токена: `SegmentControl` шириной `auto` считается по
23
+ // тексту лейблов сегментов, которых на момент загрузки ещё нет — значение приблизительное.
24
+ width: 264px;
25
+
26
+ // Высота — реальный токен анатомии SegmentControl(size='m'), а не подобранное на глаз число.
27
+ height: base.simple-var(segmentControl.$segmentControl, 'anatomy', 'size', 'm', 'segment', 'container', 'height');
28
+
29
+ &[data-mobile] {
30
+ width: 100%;
31
+ }
32
+ }
33
+
34
+ .segmentControlSkeletonBlock {
35
+ width: 100%;
36
+ height: 100%;
37
+ border-radius: base.simple-var(segmentControl.$segmentControl, 'anatomy', 'size', 'm', 'container', 'border-radius');
38
+ }
39
+
18
40
  .actions {
19
41
  display: flex;
20
42
  flex-shrink: 0;
@@ -11,7 +11,7 @@ export function SortableGroupSkeleton({ isMobile }: SortableGroupSkeletonProps)
11
11
  <div className={styles.group}>
12
12
  <SkeletonContext.Provider value={true}>
13
13
  <div className={styles.skeletonTitle}>
14
- <SkeletonText lines={1} width={isMobile ? '50%' : '30%'} />
14
+ <SkeletonText variant='title' size='m' lines={1} width={isMobile ? '50%' : '30%'} />
15
15
  </div>
16
16
  <div className={styles.skeletonBody}>
17
17
  <div className={styles.groupBody} data-mobile={isMobile || undefined}>
@@ -31,12 +31,16 @@ export function SubCategory({
31
31
  const nestedGroupId = getNestedServiceGroupId(groupId, service.id);
32
32
  const nestedItems = useMemo(() => service.items?.filter(item => !item.hidden) ?? [], [service.items]);
33
33
 
34
+ const isExpandableEnabled = service.expandableEnabled ?? false;
35
+
34
36
  // Раскрытие подкатегории — локальное uncontrolled состояние: наружу его пока не выводим.
35
37
  const [isExpanded, setIsExpanded] = useState<string | undefined>(subcategoryId);
36
38
 
37
39
  const handleExpandedChange = useCallback(() => {
38
- setIsExpanded(isExpanded ? undefined : subcategoryId);
39
- }, [isExpanded, subcategoryId]);
40
+ if (isExpandableEnabled) {
41
+ setIsExpanded(isExpanded ? undefined : subcategoryId);
42
+ }
43
+ }, [isExpanded, subcategoryId, isExpandableEnabled]);
40
44
 
41
45
  return (
42
46
  <div className={styles.subcategory} data-test-id={`${TEST_IDS.subcategory}-${service.id}`}>
@@ -56,7 +56,7 @@ export function SubCategoryTitle({
56
56
 
57
57
  if (expandable?.value) {
58
58
  return (
59
- <div className={styles.subcategoryTitle}>
59
+ <div className={styles.subcategoryTitle} data-mobile={isMobile || undefined}>
60
60
  {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
61
61
  <div className={styles.subcategoryTitleRow} onKeyDown={handleKeyDown}>
62
62
  <TitleClickable
@@ -73,6 +73,7 @@ export function SubCategoryTitle({
73
73
  <CardActionsSurface
74
74
  className={styles.subcategoryTitleActions}
75
75
  actionsVisibility='always'
76
+ actionsSize={isMobile ? 's' : 'm'}
76
77
  tooltip={
77
78
  hasTooltip
78
79
  ? {
@@ -115,7 +116,14 @@ export function SubCategoryTitle({
115
116
  }
116
117
 
117
118
  return (
118
- <div className={styles.subcategoryTitleDraggable} onPointerDown={stopEventPropagation}>
119
+ // Карточка — ссылка `<a>`: клик по ней бы долетал до `onClick={toggleOpen}` заголовка
120
+ // родительского CollapseBlockTertiary (см. TODO там) и лишний раз переключал аккордеон.
121
+ // eslint-disable-next-line jsx-a11y/no-static-element-interactions
122
+ <div
123
+ className={styles.subcategoryTitleDraggable}
124
+ onPointerDown={stopEventPropagation}
125
+ onClick={stopEventPropagation}
126
+ >
119
127
  <DraggableServiceCard
120
128
  groupId={groupId}
121
129
  service={service}
@@ -41,6 +41,13 @@
41
41
  visibility: visible;
42
42
  }
43
43
  }
44
+
45
+ // На мобилке ховера не бывает — действия карточки видны всегда (actionsVisibility='always').
46
+ &[data-mobile] {
47
+ .subcategoryTitleActions {
48
+ visibility: visible;
49
+ }
50
+ }
44
51
  }
45
52
 
46
53
  .subcategoryTitleRow {
@@ -38,6 +38,8 @@ export type InnerLink = {
38
38
  badge?: CardServiceLightProps['promoTag'];
39
39
  /** Разрешено ли добавление карточки в избранное. default=true - разрешено */
40
40
  favoritesEnabled?: boolean;
41
+ /** Разрешено ли раскрытие карточки. default=false - Запрещено */
42
+ expandableEnabled?: boolean;
41
43
  /**
42
44
  * Вложенные сервисы подкатегории.
43
45
  *