@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.
- package/CHANGELOG.md +7 -0
- package/README.md +2 -0
- package/dist/cjs/components/MainMenu/helperComponents/Content/Content.js +1 -1
- package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.d.ts +3 -1
- package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.js +3 -2
- package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/styles.module.css +16 -0
- package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SortableGroupSkeleton.js +1 -1
- package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategory.js +5 -2
- package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategoryTitle.js +6 -2
- package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/styles.module.css +3 -0
- package/dist/cjs/components/MainMenu/types.d.ts +2 -0
- package/dist/cjs/style.css +19 -0
- package/dist/esm/components/MainMenu/helperComponents/Content/Content.js +1 -1
- package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.d.ts +3 -1
- package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.js +3 -2
- package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/styles.module.css +16 -0
- package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SortableGroupSkeleton.js +1 -1
- package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategory.js +5 -2
- package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategoryTitle.js +6 -2
- package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/styles.module.css +3 -0
- package/dist/esm/components/MainMenu/types.d.ts +2 -0
- package/dist/esm/style.css +19 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +9 -9
- package/src/components/MainMenu/helperComponents/Content/Content.tsx +1 -0
- package/src/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.tsx +29 -11
- package/src/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/styles.module.scss +22 -0
- package/src/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SortableGroupSkeleton.tsx +1 -1
- package/src/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategory.tsx +6 -2
- package/src/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategoryTitle.tsx +10 -2
- package/src/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/styles.module.scss +7 -0
- package/src/components/MainMenu/types.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## 1.3.3 (2026-09-05)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **FF-8974:** cards group title skeleton size ([135daa5](https://github.com/cloud-ru-tech/snack-v2/commit/135daa5eac721af7cda5f79578507d27bc76e65d))
|
|
11
|
+
- **FF-8974:** skeleton for segment, visible subCategory actions on mobile and proper size, disable subCategory expand when clicked on title ([60e0b1a](https://github.com/cloud-ru-tech/snack-v2/commit/60e0b1a3dd9569b206fc5aca781d0a75f2b2ef52))
|
|
12
|
+
|
|
6
13
|
## 1.3.2 (2026-09-03)
|
|
7
14
|
|
|
8
15
|
**Note:** Version bump only for package @ds/uikit-product-header
|
package/README.md
CHANGED
|
@@ -342,6 +342,7 @@ function LocalMainMenu() {
|
|
|
342
342
|
| `badge` | `CardServiceLightProps` \| `PromoTagPredefinedBaseProps` | — | |
|
|
343
343
|
| `description` | `string \| undefined` | — | Краткое описание сервиса — отображается при включённом переключателе «Описание». |
|
|
344
344
|
| `disabled` | `boolean \| undefined` | — | |
|
|
345
|
+
| `expandableEnabled` | `boolean \| undefined` | — | Разрешено ли раскрытие карточки. default=false - Запрещено |
|
|
345
346
|
| `favoritesEnabled` | `boolean \| undefined` | — | Разрешено ли добавление карточки в избранное. default=true - разрешено |
|
|
346
347
|
| `hidden` | `boolean \| undefined` | — | |
|
|
347
348
|
| `href` | `string \| undefined` | — | |
|
|
@@ -513,6 +514,7 @@ import { MainMenu, MenuMobile } from '@cloud-ru/ds-uikit-product-header';
|
|
|
513
514
|
| `badge` | `CardServiceLightProps` \| `PromoTagPredefinedBaseProps` | — | |
|
|
514
515
|
| `description` | `string \| undefined` | — | Краткое описание сервиса — отображается при включённом переключателе «Описание». |
|
|
515
516
|
| `disabled` | `boolean \| undefined` | — | |
|
|
517
|
+
| `expandableEnabled` | `boolean \| undefined` | — | Разрешено ли раскрытие карточки. default=false - Запрещено |
|
|
516
518
|
| `favoritesEnabled` | `boolean \| undefined` | — | Разрешено ли добавление карточки в избранное. default=true - разрешено |
|
|
517
519
|
| `hidden` | `boolean \| undefined` | — | |
|
|
518
520
|
| `href` | `string \| undefined` | — | |
|
|
@@ -97,5 +97,5 @@ function Content({ searchValue, search, rightTop, segments, searchGroups = [], s
|
|
|
97
97
|
appearance: 'neutral',
|
|
98
98
|
}, content: isSearching ? t('noDataFound') : t('noData'), "data-test-id": isSearching ? constants_1.TEST_IDS.noDataFound : constants_1.TEST_IDS.noData, "data-mobile": isMobile || undefined, className: styles_module_scss_1.default.noData }));
|
|
99
99
|
})();
|
|
100
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [search, (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.content, className), "data-empty": (!loading && !hasCards) || undefined, children: [!isSearching && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [isMobile && rightTop, (0, jsx_runtime_1.jsx)(ContentToolbar_1.ContentToolbar, { segment: segmentId, onSegmentChange: setSegmentId, segmentItems: segmentItems, allGroupsExpanded: allGroupsExpanded, onToggleAllGroupsExpanded: handleToggleAllGroupsExpanded, preferences: preferences, isMobile: isMobile }), !isMobile && rightTop] })), cards, footer] })] }));
|
|
100
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [search, (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.content, className), "data-empty": (!loading && !hasCards) || undefined, children: [!isSearching && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [isMobile && rightTop, (0, jsx_runtime_1.jsx)(ContentToolbar_1.ContentToolbar, { segment: segmentId, onSegmentChange: setSegmentId, segmentItems: segmentItems, allGroupsExpanded: allGroupsExpanded, onToggleAllGroupsExpanded: handleToggleAllGroupsExpanded, preferences: preferences, isMobile: isMobile, loading: loading }), !isMobile && rightTop] })), cards, footer] })] }));
|
|
101
101
|
}
|
|
@@ -14,5 +14,7 @@ export type ContentToolbarProps = {
|
|
|
14
14
|
/** Настройки меню (модалка по кнопке). Не передано — кнопка настроек не отображается. */
|
|
15
15
|
preferences?: MainMenuPreferencesProps;
|
|
16
16
|
isMobile?: boolean;
|
|
17
|
+
/** Флаг загрузки данных — сегменты подгружаются с бэка, поэтому SegmentControl тоже уходит в скелетон. */
|
|
18
|
+
loading?: boolean;
|
|
17
19
|
};
|
|
18
|
-
export declare function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, }: ContentToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export declare function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, loading, }: ContentToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -9,6 +9,7 @@ const button_1 = require("@cloud-ru/ds-button");
|
|
|
9
9
|
const system_1 = require("@cloud-ru/ds-icons/interface/system");
|
|
10
10
|
const modal_1 = require("@cloud-ru/ds-modal");
|
|
11
11
|
const segment_control_1 = require("@cloud-ru/ds-segment-control");
|
|
12
|
+
const skeleton_1 = require("@cloud-ru/ds-skeleton");
|
|
12
13
|
const uikit_product_switch_row_1 = require("@cloud-ru/ds-uikit-product-switch-row");
|
|
13
14
|
const utils_1 = require("@cloud-ru/ds-utils");
|
|
14
15
|
const react_1 = require("react");
|
|
@@ -16,7 +17,7 @@ const locale_1 = require("../../../../../../locale");
|
|
|
16
17
|
const HeaderButton_1 = require("../../../../../HeaderButton");
|
|
17
18
|
const constants_1 = require("../../constants");
|
|
18
19
|
const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
|
|
19
|
-
function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, }) {
|
|
20
|
+
function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, loading, }) {
|
|
20
21
|
const { t } = locale_1.headerLocale.useTranslations();
|
|
21
22
|
const [open = false, setOpen] = (0, utils_1.useValueControl)({
|
|
22
23
|
value: preferences?.open,
|
|
@@ -28,7 +29,7 @@ function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpan
|
|
|
28
29
|
(0, react_1.startTransition)(() => preferences?.showDescription?.onChange(value));
|
|
29
30
|
};
|
|
30
31
|
const hasSegmentItems = segmentItems && segmentItems?.length > 0;
|
|
31
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.root, "data-test-id": constants_1.TEST_IDS.toolbar, children: [hasSegmentItems && ((0, jsx_runtime_1.jsx)(segment_control_1.SegmentControl, { size: 'm', outline: true, value: segment, onChange: onSegmentChange, className: styles_module_scss_1.default.segmentControl, "data-test-id": constants_1.TEST_IDS.segmentControl, items: segmentItems, width: isMobile ? 'full' : 'auto' })), (preferences || !isMobile) && ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.actions, children: [preferences && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(button_1.Button, { view: 'simple', size: 'm', appearance: 'neutral', icon: (0, jsx_runtime_1.jsx)(system_1.SettingsSVG, {}), "aria-label": t('menuSettingsTitle'), "data-test-id": constants_1.TEST_IDS.settingsButton, onClick: openModal }), (0, jsx_runtime_1.jsx)(modal_1.Modal, { open: open, onClose: closeModal, title: t('menuSettingsTitle'), "data-test-id": constants_1.TEST_IDS.settingsModal, cancelButton: {
|
|
32
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.root, "data-test-id": constants_1.TEST_IDS.toolbar, children: [hasSegmentItems && ((0, jsx_runtime_1.jsx)(skeleton_1.WithSkeleton, { loading: loading, skeleton: (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.segmentControlSkeleton, "data-test-id": constants_1.TEST_IDS.segmentControl, "data-mobile": isMobile || undefined, children: (0, jsx_runtime_1.jsx)(skeleton_1.Skeleton, { className: styles_module_scss_1.default.segmentControlSkeletonBlock }) }), children: (0, jsx_runtime_1.jsx)(segment_control_1.SegmentControl, { size: 'm', outline: true, value: segment, onChange: onSegmentChange, className: styles_module_scss_1.default.segmentControl, "data-test-id": constants_1.TEST_IDS.segmentControl, items: segmentItems, width: isMobile ? 'full' : 'auto' }) })), (preferences || !isMobile) && !loading && ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.actions, children: [preferences && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(button_1.Button, { view: 'simple', size: 'm', appearance: 'neutral', icon: (0, jsx_runtime_1.jsx)(system_1.SettingsSVG, {}), "aria-label": t('menuSettingsTitle'), "data-test-id": constants_1.TEST_IDS.settingsButton, onClick: openModal }), (0, jsx_runtime_1.jsx)(modal_1.Modal, { open: open, onClose: closeModal, title: t('menuSettingsTitle'), "data-test-id": constants_1.TEST_IDS.settingsModal, cancelButton: {
|
|
32
33
|
label: t('close'),
|
|
33
34
|
onClick: closeModal,
|
|
34
35
|
}, content: (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.settingsContent, children: [preferences.showGroupsColors && ((0, jsx_runtime_1.jsx)(uikit_product_switch_row_1.SwitchRow, { title: t('menuSettingsShowGroupsColors'), checked: preferences.showGroupsColors.value, onChange: preferences.showGroupsColors.onChange, "data-test-id": constants_1.TEST_IDS.settingsShowGroupsColorsSwitch })), (0, jsx_runtime_1.jsx)(uikit_product_switch_row_1.SwitchRow, { title: t('menuSettingsShowDescription'), checked: preferences.showDescription.value, onChange: handleShowDescriptionChange, "data-test-id": constants_1.TEST_IDS.settingsShowDescriptionSwitch })] }) })] })), !isMobile && ((0, jsx_runtime_1.jsx)(HeaderButton_1.HeaderButton, { icon: allGroupsExpanded ? (0, jsx_runtime_1.jsx)(system_1.CollapseVerticalSVG, {}) : (0, jsx_runtime_1.jsx)(system_1.ExpandVerticalSVG, {}), "aria-label": allGroupsExpanded ? t('contentCollapseAllGroups') : t('contentExpandAllGroups'), "data-test-id": constants_1.TEST_IDS.toggleAllGroups, onClick: onToggleAllGroupsExpanded, tooltip: { tip: allGroupsExpanded ? t('contentCollapseAllGroups') : t('contentExpandAllGroups') } }))] }))] }));
|
|
@@ -12,6 +12,22 @@
|
|
|
12
12
|
flex-shrink:0;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
.segmentControlSkeleton{
|
|
16
|
+
display:flex;
|
|
17
|
+
flex-shrink:0;
|
|
18
|
+
width:264px;
|
|
19
|
+
height:var(--sn-segmentControl-anatomy-size-m-segment-container-height, var(--sn-density-size-m, var(--sn-primitive-dimension-56, 56px)));
|
|
20
|
+
}
|
|
21
|
+
.segmentControlSkeleton[data-mobile]{
|
|
22
|
+
width:100%;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.segmentControlSkeletonBlock{
|
|
26
|
+
width:100%;
|
|
27
|
+
height:100%;
|
|
28
|
+
border-radius:var(--sn-segmentControl-anatomy-size-m-container-borderRadius, var(--sn-brand-anatomy-radius-button-m, var(--sn-primitive-dimension-2, 2px)));
|
|
29
|
+
}
|
|
30
|
+
|
|
15
31
|
.actions{
|
|
16
32
|
display:flex;
|
|
17
33
|
flex-shrink:0;
|
|
@@ -8,5 +8,5 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
8
8
|
const skeleton_1 = require("@cloud-ru/ds-skeleton");
|
|
9
9
|
const styles_module_scss_1 = __importDefault(require('../styles.module.css'));
|
|
10
10
|
function SortableGroupSkeleton({ isMobile }) {
|
|
11
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.group, children: (0, jsx_runtime_1.jsxs)(skeleton_1.SkeletonContext.Provider, { value: true, children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.skeletonTitle, children: (0, jsx_runtime_1.jsx)(skeleton_1.SkeletonText, { lines: 1, width: isMobile ? '50%' : '30%' }) }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.skeletonBody, children: (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.groupBody, "data-mobile": isMobile || undefined, children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.skeletonService, children: (0, jsx_runtime_1.jsx)(skeleton_1.Skeleton, { height: 24, borderRadius: 2 }) }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.skeletonService, children: (0, jsx_runtime_1.jsx)(skeleton_1.Skeleton, { height: 24, borderRadius: 2 }) }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.skeletonService, children: (0, jsx_runtime_1.jsx)(skeleton_1.Skeleton, { height: 24, borderRadius: 2 }) }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.skeletonService, children: (0, jsx_runtime_1.jsx)(skeleton_1.Skeleton, { height: 24, borderRadius: 2 }) })] }) })] }) }));
|
|
11
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.group, children: (0, jsx_runtime_1.jsxs)(skeleton_1.SkeletonContext.Provider, { value: true, children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.skeletonTitle, children: (0, jsx_runtime_1.jsx)(skeleton_1.SkeletonText, { variant: 'title', size: 'm', lines: 1, width: isMobile ? '50%' : '30%' }) }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.skeletonBody, children: (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.groupBody, "data-mobile": isMobile || undefined, children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.skeletonService, children: (0, jsx_runtime_1.jsx)(skeleton_1.Skeleton, { height: 24, borderRadius: 2 }) }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.skeletonService, children: (0, jsx_runtime_1.jsx)(skeleton_1.Skeleton, { height: 24, borderRadius: 2 }) }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.skeletonService, children: (0, jsx_runtime_1.jsx)(skeleton_1.Skeleton, { height: 24, borderRadius: 2 }) }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.skeletonService, children: (0, jsx_runtime_1.jsx)(skeleton_1.Skeleton, { height: 24, borderRadius: 2 }) })] }) })] }) }));
|
|
12
12
|
}
|
|
@@ -17,11 +17,14 @@ function SubCategory({ groupId, service, showDescription, isMobile, dragDisabled
|
|
|
17
17
|
const subcategoryId = (0, innerLink_1.getSubCategoryId)(groupId, service.id);
|
|
18
18
|
const nestedGroupId = (0, innerLink_1.getNestedServiceGroupId)(groupId, service.id);
|
|
19
19
|
const nestedItems = (0, react_1.useMemo)(() => service.items?.filter(item => !item.hidden) ?? [], [service.items]);
|
|
20
|
+
const isExpandableEnabled = service.expandableEnabled ?? false;
|
|
20
21
|
// Раскрытие подкатегории — локальное uncontrolled состояние: наружу его пока не выводим.
|
|
21
22
|
const [isExpanded, setIsExpanded] = (0, react_1.useState)(subcategoryId);
|
|
22
23
|
const handleExpandedChange = (0, react_1.useCallback)(() => {
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
if (isExpandableEnabled) {
|
|
25
|
+
setIsExpanded(isExpanded ? undefined : subcategoryId);
|
|
26
|
+
}
|
|
27
|
+
}, [isExpanded, subcategoryId, isExpandableEnabled]);
|
|
25
28
|
return ((0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_2.default.subcategory, "data-test-id": `${constants_1.TEST_IDS.subcategory}-${service.id}`, children: (0, jsx_runtime_1.jsx)(accordion_1.Accordion, { selectionMode: 'single', expanded: isExpanded, onExpandedChange: handleExpandedChange, children: (0, jsx_runtime_1.jsx)(accordion_1.Accordion.CollapseBlockTertiary, { id: subcategoryId, showChevron: false, className: styles_module_scss_2.default.subcategoryAccordion, afterTitle: (0, jsx_runtime_1.jsx)(SubCategoryTitle_1.SubCategoryTitle, { groupId: groupId, service: service, expandable: {
|
|
26
29
|
value: Boolean(isExpanded),
|
|
27
30
|
onClick: handleExpandedChange,
|
|
@@ -39,7 +39,7 @@ function SubCategoryTitle({ groupId, service, showDescription: showDescriptionPr
|
|
|
39
39
|
],
|
|
40
40
|
});
|
|
41
41
|
if (expandable?.value) {
|
|
42
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.subcategoryTitle, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.subcategoryTitleRow, onKeyDown: handleKeyDown, children: [(0, jsx_runtime_1.jsx)(uikit_product_title_clickable_1.TitleClickable, { as: 'a', href: service.href, onClick: handleServiceClick, innerRef: titleRef, title: service.label, icon: (0, utils_2.getLinkEmblem)(service), className: styles_module_scss_1.default.subcategoryTitleClickable, "data-test-id": titleTestId }), (0, jsx_runtime_1.jsx)(uikit_product_card_predefined_1.CardActionsSurface, { className: styles_module_scss_1.default.subcategoryTitleActions, actionsVisibility: 'always', tooltip: hasTooltip
|
|
42
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.subcategoryTitle, "data-mobile": isMobile || undefined, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.subcategoryTitleRow, onKeyDown: handleKeyDown, children: [(0, jsx_runtime_1.jsx)(uikit_product_title_clickable_1.TitleClickable, { as: 'a', href: service.href, onClick: handleServiceClick, innerRef: titleRef, title: service.label, icon: (0, utils_2.getLinkEmblem)(service), className: styles_module_scss_1.default.subcategoryTitleClickable, "data-test-id": titleTestId }), (0, jsx_runtime_1.jsx)(uikit_product_card_predefined_1.CardActionsSurface, { className: styles_module_scss_1.default.subcategoryTitleActions, actionsVisibility: 'always', actionsSize: isMobile ? 's' : 'm', tooltip: hasTooltip
|
|
43
43
|
? {
|
|
44
44
|
tip: service.description,
|
|
45
45
|
buttonRef: tooltipTriggerRef,
|
|
@@ -56,5 +56,9 @@ function SubCategoryTitle({ groupId, service, showDescription: showDescriptionPr
|
|
|
56
56
|
}
|
|
57
57
|
: undefined })] }), showDescription && ((0, jsx_runtime_1.jsx)(typography_1.Typography, { as: 'p', variant: 'body', size: 's', className: styles_module_scss_1.default.subcategoryDescription, "data-test-id": `${titleTestId}-description`, children: service.description }))] }));
|
|
58
58
|
}
|
|
59
|
-
return (
|
|
59
|
+
return (
|
|
60
|
+
// Карточка — ссылка `<a>`: клик по ней бы долетал до `onClick={toggleOpen}` заголовка
|
|
61
|
+
// родительского CollapseBlockTertiary (см. TODO там) и лишний раз переключал аккордеон.
|
|
62
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
63
|
+
(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.subcategoryTitleDraggable, onPointerDown: utils_1.stopEventPropagation, onClick: utils_1.stopEventPropagation, children: (0, jsx_runtime_1.jsx)(ServiceCard_1.DraggableServiceCard, { groupId: groupId, service: service, favorite: favorite, isMobile: isMobile, onServiceClick: onServiceClick, showDescription: showDescriptionProp, dragDisabled: dragDisabled, expandable: expandable }) }));
|
|
60
64
|
}
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
.subcategoryTitle:hover .subcategoryTitleActions, .subcategoryTitle:focus-within .subcategoryTitleActions{
|
|
33
33
|
visibility:visible;
|
|
34
34
|
}
|
|
35
|
+
.subcategoryTitle[data-mobile] .subcategoryTitleActions{
|
|
36
|
+
visibility:visible;
|
|
37
|
+
}
|
|
35
38
|
|
|
36
39
|
.subcategoryTitleRow{
|
|
37
40
|
display:flex;
|
|
@@ -36,6 +36,8 @@ export type InnerLink = {
|
|
|
36
36
|
badge?: CardServiceLightProps['promoTag'];
|
|
37
37
|
/** Разрешено ли добавление карточки в избранное. default=true - разрешено */
|
|
38
38
|
favoritesEnabled?: boolean;
|
|
39
|
+
/** Разрешено ли раскрытие карточки. default=false - Запрещено */
|
|
40
|
+
expandableEnabled?: boolean;
|
|
39
41
|
/**
|
|
40
42
|
* Вложенные сервисы подкатегории.
|
|
41
43
|
*
|
package/dist/cjs/style.css
CHANGED
|
@@ -166,6 +166,22 @@
|
|
|
166
166
|
flex-shrink:0;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
.segmentControlSkeleton{
|
|
170
|
+
display:flex;
|
|
171
|
+
flex-shrink:0;
|
|
172
|
+
width:264px;
|
|
173
|
+
height:var(--sn-segmentControl-anatomy-size-m-segment-container-height, var(--sn-density-size-m, var(--sn-primitive-dimension-56, 56px)));
|
|
174
|
+
}
|
|
175
|
+
.segmentControlSkeleton[data-mobile]{
|
|
176
|
+
width:100%;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.segmentControlSkeletonBlock{
|
|
180
|
+
width:100%;
|
|
181
|
+
height:100%;
|
|
182
|
+
border-radius:var(--sn-segmentControl-anatomy-size-m-container-borderRadius, var(--sn-brand-anatomy-radius-button-m, var(--sn-primitive-dimension-2, 2px)));
|
|
183
|
+
}
|
|
184
|
+
|
|
169
185
|
.actions{
|
|
170
186
|
display:flex;
|
|
171
187
|
flex-shrink:0;
|
|
@@ -214,6 +230,9 @@
|
|
|
214
230
|
.subcategoryTitle:hover .subcategoryTitleActions, .subcategoryTitle:focus-within .subcategoryTitleActions{
|
|
215
231
|
visibility:visible;
|
|
216
232
|
}
|
|
233
|
+
.subcategoryTitle[data-mobile] .subcategoryTitleActions{
|
|
234
|
+
visibility:visible;
|
|
235
|
+
}
|
|
217
236
|
|
|
218
237
|
.subcategoryTitleRow{
|
|
219
238
|
display:flex;
|
|
@@ -91,5 +91,5 @@ export function Content({ searchValue, search, rightTop, segments, searchGroups
|
|
|
91
91
|
appearance: 'neutral',
|
|
92
92
|
}, content: isSearching ? t('noDataFound') : t('noData'), "data-test-id": isSearching ? TEST_IDS.noDataFound : TEST_IDS.noData, "data-mobile": isMobile || undefined, className: styles.noData }));
|
|
93
93
|
})();
|
|
94
|
-
return (_jsxs(_Fragment, { children: [search, _jsxs("div", { className: cn(styles.content, className), "data-empty": (!loading && !hasCards) || undefined, children: [!isSearching && (_jsxs(_Fragment, { children: [isMobile && rightTop, _jsx(ContentToolbar, { segment: segmentId, onSegmentChange: setSegmentId, segmentItems: segmentItems, allGroupsExpanded: allGroupsExpanded, onToggleAllGroupsExpanded: handleToggleAllGroupsExpanded, preferences: preferences, isMobile: isMobile }), !isMobile && rightTop] })), cards, footer] })] }));
|
|
94
|
+
return (_jsxs(_Fragment, { children: [search, _jsxs("div", { className: cn(styles.content, className), "data-empty": (!loading && !hasCards) || undefined, children: [!isSearching && (_jsxs(_Fragment, { children: [isMobile && rightTop, _jsx(ContentToolbar, { segment: segmentId, onSegmentChange: setSegmentId, segmentItems: segmentItems, allGroupsExpanded: allGroupsExpanded, onToggleAllGroupsExpanded: handleToggleAllGroupsExpanded, preferences: preferences, isMobile: isMobile, loading: loading }), !isMobile && rightTop] })), cards, footer] })] }));
|
|
95
95
|
}
|
|
@@ -14,5 +14,7 @@ export type ContentToolbarProps = {
|
|
|
14
14
|
/** Настройки меню (модалка по кнопке). Не передано — кнопка настроек не отображается. */
|
|
15
15
|
preferences?: MainMenuPreferencesProps;
|
|
16
16
|
isMobile?: boolean;
|
|
17
|
+
/** Флаг загрузки данных — сегменты подгружаются с бэка, поэтому SegmentControl тоже уходит в скелетон. */
|
|
18
|
+
loading?: boolean;
|
|
17
19
|
};
|
|
18
|
-
export declare function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, }: ContentToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export declare function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, loading, }: ContentToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -3,6 +3,7 @@ import { Button } from '@cloud-ru/ds-button';
|
|
|
3
3
|
import { CollapseVerticalSVG, ExpandVerticalSVG, SettingsSVG } from '@cloud-ru/ds-icons/interface/system';
|
|
4
4
|
import { Modal } from '@cloud-ru/ds-modal';
|
|
5
5
|
import { SegmentControl } from '@cloud-ru/ds-segment-control';
|
|
6
|
+
import { Skeleton, WithSkeleton } from '@cloud-ru/ds-skeleton';
|
|
6
7
|
import { SwitchRow } from '@cloud-ru/ds-uikit-product-switch-row';
|
|
7
8
|
import { useValueControl } from '@cloud-ru/ds-utils';
|
|
8
9
|
import { startTransition } from 'react';
|
|
@@ -10,7 +11,7 @@ import { headerLocale } from '../../../../../../locale/index.js';
|
|
|
10
11
|
import { HeaderButton } from '../../../../../HeaderButton/index.js';
|
|
11
12
|
import { TEST_IDS } from '../../constants.js';
|
|
12
13
|
import styles from './styles.module.css';
|
|
13
|
-
export function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, }) {
|
|
14
|
+
export function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, loading, }) {
|
|
14
15
|
const { t } = headerLocale.useTranslations();
|
|
15
16
|
const [open = false, setOpen] = useValueControl({
|
|
16
17
|
value: preferences?.open,
|
|
@@ -22,7 +23,7 @@ export function ContentToolbar({ segment, onSegmentChange, segmentItems, allGrou
|
|
|
22
23
|
startTransition(() => preferences?.showDescription?.onChange(value));
|
|
23
24
|
};
|
|
24
25
|
const hasSegmentItems = segmentItems && segmentItems?.length > 0;
|
|
25
|
-
return (_jsxs("div", { className: styles.root, "data-test-id": TEST_IDS.toolbar, children: [hasSegmentItems && (_jsx(SegmentControl, { size: 'm', outline: true, value: segment, onChange: onSegmentChange, className: styles.segmentControl, "data-test-id": TEST_IDS.segmentControl, items: segmentItems, width: isMobile ? 'full' : 'auto' })), (preferences || !isMobile) && (_jsxs("div", { className: styles.actions, children: [preferences && (_jsxs(_Fragment, { children: [_jsx(Button, { view: 'simple', size: 'm', appearance: 'neutral', icon: _jsx(SettingsSVG, {}), "aria-label": t('menuSettingsTitle'), "data-test-id": TEST_IDS.settingsButton, onClick: openModal }), _jsx(Modal, { open: open, onClose: closeModal, title: t('menuSettingsTitle'), "data-test-id": TEST_IDS.settingsModal, cancelButton: {
|
|
26
|
+
return (_jsxs("div", { className: styles.root, "data-test-id": TEST_IDS.toolbar, children: [hasSegmentItems && (_jsx(WithSkeleton, { loading: loading, skeleton: _jsx("div", { className: styles.segmentControlSkeleton, "data-test-id": TEST_IDS.segmentControl, "data-mobile": isMobile || undefined, children: _jsx(Skeleton, { className: styles.segmentControlSkeletonBlock }) }), children: _jsx(SegmentControl, { size: 'm', outline: true, value: segment, onChange: onSegmentChange, className: styles.segmentControl, "data-test-id": TEST_IDS.segmentControl, items: segmentItems, width: isMobile ? 'full' : 'auto' }) })), (preferences || !isMobile) && !loading && (_jsxs("div", { className: styles.actions, children: [preferences && (_jsxs(_Fragment, { children: [_jsx(Button, { view: 'simple', size: 'm', appearance: 'neutral', icon: _jsx(SettingsSVG, {}), "aria-label": t('menuSettingsTitle'), "data-test-id": TEST_IDS.settingsButton, onClick: openModal }), _jsx(Modal, { open: open, onClose: closeModal, title: t('menuSettingsTitle'), "data-test-id": TEST_IDS.settingsModal, cancelButton: {
|
|
26
27
|
label: t('close'),
|
|
27
28
|
onClick: closeModal,
|
|
28
29
|
}, content: _jsxs("div", { className: styles.settingsContent, children: [preferences.showGroupsColors && (_jsx(SwitchRow, { title: t('menuSettingsShowGroupsColors'), checked: preferences.showGroupsColors.value, onChange: preferences.showGroupsColors.onChange, "data-test-id": TEST_IDS.settingsShowGroupsColorsSwitch })), _jsx(SwitchRow, { title: t('menuSettingsShowDescription'), checked: preferences.showDescription.value, onChange: handleShowDescriptionChange, "data-test-id": TEST_IDS.settingsShowDescriptionSwitch })] }) })] })), !isMobile && (_jsx(HeaderButton, { icon: allGroupsExpanded ? _jsx(CollapseVerticalSVG, {}) : _jsx(ExpandVerticalSVG, {}), "aria-label": allGroupsExpanded ? t('contentCollapseAllGroups') : t('contentExpandAllGroups'), "data-test-id": TEST_IDS.toggleAllGroups, onClick: onToggleAllGroupsExpanded, tooltip: { tip: allGroupsExpanded ? t('contentCollapseAllGroups') : t('contentExpandAllGroups') } }))] }))] }));
|
|
@@ -12,6 +12,22 @@
|
|
|
12
12
|
flex-shrink:0;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
.segmentControlSkeleton{
|
|
16
|
+
display:flex;
|
|
17
|
+
flex-shrink:0;
|
|
18
|
+
width:264px;
|
|
19
|
+
height:var(--sn-segmentControl-anatomy-size-m-segment-container-height, var(--sn-density-size-m, var(--sn-primitive-dimension-56, 56px)));
|
|
20
|
+
}
|
|
21
|
+
.segmentControlSkeleton[data-mobile]{
|
|
22
|
+
width:100%;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.segmentControlSkeletonBlock{
|
|
26
|
+
width:100%;
|
|
27
|
+
height:100%;
|
|
28
|
+
border-radius:var(--sn-segmentControl-anatomy-size-m-container-borderRadius, var(--sn-brand-anatomy-radius-button-m, var(--sn-primitive-dimension-2, 2px)));
|
|
29
|
+
}
|
|
30
|
+
|
|
15
31
|
.actions{
|
|
16
32
|
display:flex;
|
|
17
33
|
flex-shrink:0;
|
|
@@ -2,5 +2,5 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Skeleton, SkeletonContext, SkeletonText } from '@cloud-ru/ds-skeleton';
|
|
3
3
|
import styles from '../styles.module.css';
|
|
4
4
|
export function SortableGroupSkeleton({ isMobile }) {
|
|
5
|
-
return (_jsx("div", { className: styles.group, children: _jsxs(SkeletonContext.Provider, { value: true, children: [_jsx("div", { className: styles.skeletonTitle, children: _jsx(SkeletonText, { lines: 1, width: isMobile ? '50%' : '30%' }) }), _jsx("div", { className: styles.skeletonBody, children: _jsxs("div", { className: styles.groupBody, "data-mobile": isMobile || undefined, children: [_jsx("div", { className: styles.skeletonService, children: _jsx(Skeleton, { height: 24, borderRadius: 2 }) }), _jsx("div", { className: styles.skeletonService, children: _jsx(Skeleton, { height: 24, borderRadius: 2 }) }), _jsx("div", { className: styles.skeletonService, children: _jsx(Skeleton, { height: 24, borderRadius: 2 }) }), _jsx("div", { className: styles.skeletonService, children: _jsx(Skeleton, { height: 24, borderRadius: 2 }) })] }) })] }) }));
|
|
5
|
+
return (_jsx("div", { className: styles.group, children: _jsxs(SkeletonContext.Provider, { value: true, children: [_jsx("div", { className: styles.skeletonTitle, children: _jsx(SkeletonText, { variant: 'title', size: 'm', lines: 1, width: isMobile ? '50%' : '30%' }) }), _jsx("div", { className: styles.skeletonBody, children: _jsxs("div", { className: styles.groupBody, "data-mobile": isMobile || undefined, children: [_jsx("div", { className: styles.skeletonService, children: _jsx(Skeleton, { height: 24, borderRadius: 2 }) }), _jsx("div", { className: styles.skeletonService, children: _jsx(Skeleton, { height: 24, borderRadius: 2 }) }), _jsx("div", { className: styles.skeletonService, children: _jsx(Skeleton, { height: 24, borderRadius: 2 }) }), _jsx("div", { className: styles.skeletonService, children: _jsx(Skeleton, { height: 24, borderRadius: 2 }) })] }) })] }) }));
|
|
6
6
|
}
|
|
@@ -11,11 +11,14 @@ export function SubCategory({ groupId, service, showDescription, isMobile, dragD
|
|
|
11
11
|
const subcategoryId = getSubCategoryId(groupId, service.id);
|
|
12
12
|
const nestedGroupId = getNestedServiceGroupId(groupId, service.id);
|
|
13
13
|
const nestedItems = useMemo(() => service.items?.filter(item => !item.hidden) ?? [], [service.items]);
|
|
14
|
+
const isExpandableEnabled = service.expandableEnabled ?? false;
|
|
14
15
|
// Раскрытие подкатегории — локальное uncontrolled состояние: наружу его пока не выводим.
|
|
15
16
|
const [isExpanded, setIsExpanded] = useState(subcategoryId);
|
|
16
17
|
const handleExpandedChange = useCallback(() => {
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
if (isExpandableEnabled) {
|
|
19
|
+
setIsExpanded(isExpanded ? undefined : subcategoryId);
|
|
20
|
+
}
|
|
21
|
+
}, [isExpanded, subcategoryId, isExpandableEnabled]);
|
|
19
22
|
return (_jsx("div", { className: styles.subcategory, "data-test-id": `${TEST_IDS.subcategory}-${service.id}`, children: _jsx(Accordion, { selectionMode: 'single', expanded: isExpanded, onExpandedChange: handleExpandedChange, children: _jsx(Accordion.CollapseBlockTertiary, { id: subcategoryId, showChevron: false, className: styles.subcategoryAccordion, afterTitle: _jsx(SubCategoryTitle, { groupId: groupId, service: service, expandable: {
|
|
20
23
|
value: Boolean(isExpanded),
|
|
21
24
|
onClick: handleExpandedChange,
|
|
@@ -33,7 +33,7 @@ export function SubCategoryTitle({ groupId, service, showDescription: showDescri
|
|
|
33
33
|
],
|
|
34
34
|
});
|
|
35
35
|
if (expandable?.value) {
|
|
36
|
-
return (_jsxs("div", { className: styles.subcategoryTitle, children: [_jsxs("div", { className: styles.subcategoryTitleRow, onKeyDown: handleKeyDown, children: [_jsx(TitleClickable, { as: 'a', href: service.href, onClick: handleServiceClick, innerRef: titleRef, title: service.label, icon: getLinkEmblem(service), className: styles.subcategoryTitleClickable, "data-test-id": titleTestId }), _jsx(CardActionsSurface, { className: styles.subcategoryTitleActions, actionsVisibility: 'always', tooltip: hasTooltip
|
|
36
|
+
return (_jsxs("div", { className: styles.subcategoryTitle, "data-mobile": isMobile || undefined, children: [_jsxs("div", { className: styles.subcategoryTitleRow, onKeyDown: handleKeyDown, children: [_jsx(TitleClickable, { as: 'a', href: service.href, onClick: handleServiceClick, innerRef: titleRef, title: service.label, icon: getLinkEmblem(service), className: styles.subcategoryTitleClickable, "data-test-id": titleTestId }), _jsx(CardActionsSurface, { className: styles.subcategoryTitleActions, actionsVisibility: 'always', actionsSize: isMobile ? 's' : 'm', tooltip: hasTooltip
|
|
37
37
|
? {
|
|
38
38
|
tip: service.description,
|
|
39
39
|
buttonRef: tooltipTriggerRef,
|
|
@@ -50,5 +50,9 @@ export function SubCategoryTitle({ groupId, service, showDescription: showDescri
|
|
|
50
50
|
}
|
|
51
51
|
: undefined })] }), showDescription && (_jsx(Typography, { as: 'p', variant: 'body', size: 's', className: styles.subcategoryDescription, "data-test-id": `${titleTestId}-description`, children: service.description }))] }));
|
|
52
52
|
}
|
|
53
|
-
return (
|
|
53
|
+
return (
|
|
54
|
+
// Карточка — ссылка `<a>`: клик по ней бы долетал до `onClick={toggleOpen}` заголовка
|
|
55
|
+
// родительского CollapseBlockTertiary (см. TODO там) и лишний раз переключал аккордеон.
|
|
56
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
57
|
+
_jsx("div", { className: styles.subcategoryTitleDraggable, onPointerDown: stopEventPropagation, onClick: stopEventPropagation, children: _jsx(DraggableServiceCard, { groupId: groupId, service: service, favorite: favorite, isMobile: isMobile, onServiceClick: onServiceClick, showDescription: showDescriptionProp, dragDisabled: dragDisabled, expandable: expandable }) }));
|
|
54
58
|
}
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
.subcategoryTitle:hover .subcategoryTitleActions, .subcategoryTitle:focus-within .subcategoryTitleActions{
|
|
33
33
|
visibility:visible;
|
|
34
34
|
}
|
|
35
|
+
.subcategoryTitle[data-mobile] .subcategoryTitleActions{
|
|
36
|
+
visibility:visible;
|
|
37
|
+
}
|
|
35
38
|
|
|
36
39
|
.subcategoryTitleRow{
|
|
37
40
|
display:flex;
|
|
@@ -36,6 +36,8 @@ export type InnerLink = {
|
|
|
36
36
|
badge?: CardServiceLightProps['promoTag'];
|
|
37
37
|
/** Разрешено ли добавление карточки в избранное. default=true - разрешено */
|
|
38
38
|
favoritesEnabled?: boolean;
|
|
39
|
+
/** Разрешено ли раскрытие карточки. default=false - Запрещено */
|
|
40
|
+
expandableEnabled?: boolean;
|
|
39
41
|
/**
|
|
40
42
|
* Вложенные сервисы подкатегории.
|
|
41
43
|
*
|
package/dist/esm/style.css
CHANGED
|
@@ -166,6 +166,22 @@
|
|
|
166
166
|
flex-shrink:0;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
.segmentControlSkeleton{
|
|
170
|
+
display:flex;
|
|
171
|
+
flex-shrink:0;
|
|
172
|
+
width:264px;
|
|
173
|
+
height:var(--sn-segmentControl-anatomy-size-m-segment-container-height, var(--sn-density-size-m, var(--sn-primitive-dimension-56, 56px)));
|
|
174
|
+
}
|
|
175
|
+
.segmentControlSkeleton[data-mobile]{
|
|
176
|
+
width:100%;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.segmentControlSkeletonBlock{
|
|
180
|
+
width:100%;
|
|
181
|
+
height:100%;
|
|
182
|
+
border-radius:var(--sn-segmentControl-anatomy-size-m-container-borderRadius, var(--sn-brand-anatomy-radius-button-m, var(--sn-primitive-dimension-2, 2px)));
|
|
183
|
+
}
|
|
184
|
+
|
|
169
185
|
.actions{
|
|
170
186
|
display:flex;
|
|
171
187
|
flex-shrink:0;
|
|
@@ -214,6 +230,9 @@
|
|
|
214
230
|
.subcategoryTitle:hover .subcategoryTitleActions, .subcategoryTitle:focus-within .subcategoryTitleActions{
|
|
215
231
|
visibility:visible;
|
|
216
232
|
}
|
|
233
|
+
.subcategoryTitle[data-mobile] .subcategoryTitleActions{
|
|
234
|
+
visibility:visible;
|
|
235
|
+
}
|
|
217
236
|
|
|
218
237
|
.subcategoryTitleRow{
|
|
219
238
|
display:flex;
|