From bcf8aa086b524974cbfa1ad50de1e89390332311 Mon Sep 17 00:00:00 2001 From: Taya Leutina Date: Wed, 23 Jul 2025 12:33:07 +0300 Subject: [PATCH] feat(AsideHeader): add collapseButtonWrapper prop --- src/components/AsideHeader/README-ru.md | 55 +++++++++--------- src/components/AsideHeader/README.md | 55 +++++++++--------- .../__stories__/AsideHeader.stories.tsx | 56 ++++++++++++++++--- .../AsideHeader/__stories__/moc.tsx | 10 ++++ .../CollapseButton/CollapseButton.tsx | 12 +++- src/components/AsideHeader/types.tsx | 7 +++ 6 files changed, 130 insertions(+), 65 deletions(-) diff --git a/src/components/AsideHeader/README-ru.md b/src/components/AsideHeader/README-ru.md index b13ebe1b..1d3c3a0d 100644 --- a/src/components/AsideHeader/README-ru.md +++ b/src/components/AsideHeader/README-ru.md @@ -118,33 +118,34 @@ export const Aside: FC = () => { ## Свойства -| Имя | Описание | Тип | Значение по умолчанию | -| :------------------------ | :--------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------: | :-----------------------: | -| className | HTML-атрибут `class` для логотипа. | `string` | | -| collapseTitle | Заголовок `CollapseButton` для сворачивания элемента навигации. | `string` | `"Свернуть"` `"Collapse"` | -| compact | Визуальное состояние элемента навигации. | `boolean` | `false` | -| customBackground | Фон `AsideHeader`. | `React.ReactNode` | | -| customBackgroundClassName | Переопределяет стили контейнера фона по умолчанию. | `string` | | -| expandTitle | Заголовок `CollapseButton` для разворачивания элемента навигации. | `string` | `"Развернуть"` `"Expand"` | -| headerDecoration | Цвет фона верхнего блока с элементами логотипа и подзаголовка. | `boolean` | `false` | -| hideCollapseButton | Скрывает `CollapseButton`. Для установки дефолтного состояния элемента навигации используйте свойство `compact`. | `boolean` | `false` | -| logo | Контейнер логотипа, включающий иконку с заголовком и обрабатывающий клики. | [`Logo`](./../Logo/Readme.md#logo) | | -| menuItems | Элементы в среднем блоке навигации. | `Array` | `[]` | -| menuMoreTitle | Дополнительный заголовок для `menuItems`, если элементы не помещаются. | `string` | `"Ещё"` `"More"` | -| multipleTooltip | Отображает несколько тултипов при наведении на элементы меню (`menuItems`) в свернутом состоянии. | `boolean` | `false` | -| onChangeCompact | Обратный вызов, срабатывающий при изменении визуального состояния элемента навигации. | `(compact: boolean) => void;` | | -| onClosePanel | Обратный вызов, срабатывающий при закрытии панели. Панели можно добавлять через свойство `PanelItems`. | `() => void;` | | -| onMenuItemsChanged | Обратный вызов, срабатывающий при изменении списка `menuItems` в `AllPagesPanel`. | `(items: Array) => void` | | -| onMenuMoreClick | Обратный вызов, срабатывающий при нажатии кнопки **More** («Еще»), если часть элементов скрыта. | `() => void;` | | -| onAllPagesClick | Обратный вызов, срабатывающий при нажатии кнопки **All pages** («Все станицы»). | `() => void;` | | -| openModalSubscriber | Функция для уведомления `AsideHeader` об изменении состояния видимости модальных окон. | `( (open: boolean) => void) => void` | | -| panelItems | Элементы компонента `Drawer`. Используется для отображения дополнительной информации поверх основного контента. | [`Array`](./../Drawer/README.md#draweritem-props) | `[]` | -| renderContent | Функция рендеринга основного контента справа от `AsideHeader`. | `(data: {size: number}) => React.ReactNode` | | -| renderFooter | Функция рендеринга нижнего блока навигации. | `(data: {size: number}) => React.ReactNode` | | -| ref | Ссылка на якорь целевого всплывающего окна. | `React.ForwardedRef` | | -| subheaderItems | Элементы, расположенные под логотипом в верхнем блоке навигации. | ` Array<{item: MenuItem; enableTooltip?: boolean; bringForward?: boolean}>` | `[]` | -| topAlert | Контейнер над элементом навигации на основе компонента `Alert` из фреймворка UIKit. | `TopAlert` | | -| qa | Значение, которое будет передано в атрибут `data-qa` контейнера `AsideHeader`. | `string` | | +| Имя | Описание | Тип | Значение по умолчанию | +| :------------------------ | :--------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------: | :-----------------------: | +| className | HTML-атрибут `class` для логотипа. | `string` | | +| collapseButtonWrapper | Обертка для `CollapseButton`, позволяющая кастомизировать вид дефолтной кнопки. | `(defaultButton: React.ReactNode, data: {compact: boolean; onChangeCompact?: (compact: boolean) => void}) => React.ReactNode` | | +| collapseTitle | Заголовок `CollapseButton` для сворачивания элемента навигации. | `string` | `"Свернуть"` `"Collapse"` | +| compact | Визуальное состояние элемента навигации. | `boolean` | `false` | +| customBackground | Фон `AsideHeader`. | `React.ReactNode` | | +| customBackgroundClassName | Переопределяет стили контейнера фона по умолчанию. | `string` | | +| expandTitle | Заголовок `CollapseButton` для разворачивания элемента навигации. | `string` | `"Развернуть"` `"Expand"` | +| headerDecoration | Цвет фона верхнего блока с элементами логотипа и подзаголовка. | `boolean` | `false` | +| hideCollapseButton | Скрывает `CollapseButton`. Для установки дефолтного состояния элемента навигации используйте свойство `compact`. | `boolean` | `false` | +| logo | Контейнер логотипа, включающий иконку с заголовком и обрабатывающий клики. | [`Logo`](./../Logo/Readme.md#logo) | | +| menuItems | Элементы в среднем блоке навигации. | `Array` | `[]` | +| menuMoreTitle | Дополнительный заголовок для `menuItems`, если элементы не помещаются. | `string` | `"Ещё"` `"More"` | +| multipleTooltip | Отображает несколько тултипов при наведении на элементы меню (`menuItems`) в свернутом состоянии. | `boolean` | `false` | +| onChangeCompact | Обратный вызов, срабатывающий при изменении визуального состояния элемента навигации. | `(compact: boolean) => void;` | | +| onClosePanel | Обратный вызов, срабатывающий при закрытии панели. Панели можно добавлять через свойство `PanelItems`. | `() => void;` | | +| onMenuItemsChanged | Обратный вызов, срабатывающий при изменении списка `menuItems` в `AllPagesPanel`. | `(items: Array) => void` | | +| onMenuMoreClick | Обратный вызов, срабатывающий при нажатии кнопки **More** («Еще»), если часть элементов скрыта. | `() => void;` | | +| onAllPagesClick | Обратный вызов, срабатывающий при нажатии кнопки **All pages** («Все станицы»). | `() => void;` | | +| openModalSubscriber | Функция для уведомления `AsideHeader` об изменении состояния видимости модальных окон. | `( (open: boolean) => void) => void` | | +| panelItems | Элементы компонента `Drawer`. Используется для отображения дополнительной информации поверх основного контента. | [`Array`](./../Drawer/README.md#draweritem-props) | `[]` | +| renderContent | Функция рендеринга основного контента справа от `AsideHeader`. | `(data: {size: number}) => React.ReactNode` | | +| renderFooter | Функция рендеринга нижнего блока навигации. | `(data: {size: number}) => React.ReactNode` | | +| ref | Ссылка на якорь целевого всплывающего окна. | `React.ForwardedRef` | | +| subheaderItems | Элементы, расположенные под логотипом в верхнем блоке навигации. | ` Array<{item: MenuItem; enableTooltip?: boolean; bringForward?: boolean}>` | `[]` | +| topAlert | Контейнер над элементом навигации на основе компонента `Alert` из фреймворка UIKit. | `TopAlert` | | +| qa | Значение, которое будет передано в атрибут `data-qa` контейнера `AsideHeader`. | `string` | | ### `MenuItem` diff --git a/src/components/AsideHeader/README.md b/src/components/AsideHeader/README.md index fbd1368d..21de1727 100644 --- a/src/components/AsideHeader/README.md +++ b/src/components/AsideHeader/README.md @@ -119,33 +119,34 @@ export const Aside: FC = () => { ## Properties -| Name | Description | Type | Default | -| :------------------------ | :----------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------: | :-----------------------: | -| className | HTML `class` attribute of the Logo | `string` | | -| collapseTitle | `CollapseButton` title for collapsing navigation | `string` | `"Свернуть"` `"Collapse"` | -| compact | Navigation visual state | `boolean` | `false` | -| customBackground | `AsideHeader` background | `React.ReactNode` | | -| customBackgroundClassName | Override default background container's styles | `string` | | -| expandTitle | `CollapseButton` title for expanding navigation | `string` | `"Развернуть"` `"Expand"` | -| headerDecoration | Color background of the top section with logo and subheader items | `boolean` | `false` | -| hideCollapseButton | Hiding `CollapseButton`. Use `compact` prop for setting default navigation state | `boolean` | `false` | -| logo | Logo container includes icon, title, handling clicks | [`Logo`](https://github.com/gravity-ui/navigation/blob/main/src/components/Logo/Readme.md#logo) | | -| menuItems | Items in the navigation middle section | `Array` | `[]` | -| menuMoreTitle | Additional element title of menuItems if elements don't fit | `string` | `"Ещё"` `"More"` | -| multipleTooltip | Show the multiple tooltip by hovering elements of menuItems in collapsed state | `boolean` | `false` | -| onChangeCompact | Callback will be called when changing navigation visual state | `(compact: boolean) => void;` | | -| onClosePanel | Callback will be called when closing panel. You can add panels via `PanelItems` prop | `() => void;` | | -| onMenuItemsChanged | Callback will be called when updating list of the menuItems in `AllPagesPanel` | `(items: Array) => void` | | -| onMenuMoreClick | Callback will be called when some items don't fit and "more" button is clicked | `() => void;` | | -| onAllPagesClick | Callback will be called when "All pages" button is clicked | `() => void;` | | -| openModalSubscriber | Function notifies `AsideHeader` about Modals visibility changes | `( (open: boolean) => void) => void` | | -| panelItems | Items for `Drawer` component. Used for show additional information over main content | [`Array`](https://github.com/gravity-ui/navigation/tree/main/src/components/Drawer#draweritem-props) | `[]` | -| renderContent | Function rendering the main content at the right of the `AsideHeader` | `(data: {size: number}) => React.ReactNode` | | -| renderFooter | Function rendering the navigation bottom section | `(data: {size: number}) => React.ReactNode` | | -| ref | `ref` to target popup anchor | `React.ForwardedRef` | | -| subheaderItems | Items in the navigation top section under Logo | `Array<{item: MenuItem; enableTooltip?: boolean; bringForward?: boolean}>` | `[]` | -| topAlert | The container above the navigation based on the uikit `Alert` component | `TopAlert` | | -| qa | The value to be passed to `data-qa` attribute of the `AsideHeader` container | `string` | | +| Name | Description | Type | Default | +| :------------------------ | :----------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------: | :-----------------------: | +| className | HTML `class` attribute of the Logo | `string` | | +| collapseButtonWrapper | Wrapper for `CollapseButton` allowing customization of the default button appearance | `(defaultButton: React.ReactNode, data: {compact: boolean; onChangeCompact?: (compact: boolean) => void}) => React.ReactNode` | | +| collapseTitle | `CollapseButton` title for collapsing navigation | `string` | `"Свернуть"` `"Collapse"` | +| compact | Navigation visual state | `boolean` | `false` | +| customBackground | `AsideHeader` background | `React.ReactNode` | | +| customBackgroundClassName | Override default background container's styles | `string` | | +| expandTitle | `CollapseButton` title for expanding navigation | `string` | `"Развернуть"` `"Expand"` | +| headerDecoration | Color background of the top section with logo and subheader items | `boolean` | `false` | +| hideCollapseButton | Hiding `CollapseButton`. Use `compact` prop for setting default navigation state | `boolean` | `false` | +| logo | Logo container includes icon, title, handling clicks | [`Logo`](https://github.com/gravity-ui/navigation/blob/main/src/components/Logo/Readme.md#logo) | | +| menuItems | Items in the navigation middle section | `Array` | `[]` | +| menuMoreTitle | Additional element title of menuItems if elements don't fit | `string` | `"Ещё"` `"More"` | +| multipleTooltip | Show the multiple tooltip by hovering elements of menuItems in collapsed state | `boolean` | `false` | +| onChangeCompact | Callback will be called when changing navigation visual state | `(compact: boolean) => void;` | | +| onClosePanel | Callback will be called when closing panel. You can add panels via `PanelItems` prop | `() => void;` | | +| onMenuItemsChanged | Callback will be called when updating list of the menuItems in `AllPagesPanel` | `(items: Array) => void` | | +| onMenuMoreClick | Callback will be called when some items don't fit and "more" button is clicked | `() => void;` | | +| onAllPagesClick | Callback will be called when "All pages" button is clicked | `() => void;` | | +| openModalSubscriber | Function notifies `AsideHeader` about Modals visibility changes | `( (open: boolean) => void) => void` | | +| panelItems | Items for `Drawer` component. Used for show additional information over main content | [`Array`](https://github.com/gravity-ui/navigation/tree/main/src/components/Drawer#draweritem-props) | `[]` | +| renderContent | Function rendering the main content at the right of the `AsideHeader` | `(data: {size: number}) => React.ReactNode` | | +| renderFooter | Function rendering the navigation bottom section | `(data: {size: number}) => React.ReactNode` | | +| ref | `ref` to target popup anchor | `React.ForwardedRef` | | +| subheaderItems | Items in the navigation top section under Logo | `Array<{item: MenuItem; enableTooltip?: boolean; bringForward?: boolean}>` | `[]` | +| topAlert | The container above the navigation based on the uikit `Alert` component | `TopAlert` | | +| qa | The value to be passed to `data-qa` attribute of the `AsideHeader` container | `string` | | ### `MenuItem` diff --git a/src/components/AsideHeader/__stories__/AsideHeader.stories.tsx b/src/components/AsideHeader/__stories__/AsideHeader.stories.tsx index dc2d5a85..b3c43a4d 100644 --- a/src/components/AsideHeader/__stories__/AsideHeader.stories.tsx +++ b/src/components/AsideHeader/__stories__/AsideHeader.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import {Button} from '@gravity-ui/uikit'; +import {Button, Flex, Icon, Text, spacing} from '@gravity-ui/uikit'; import type {Meta, StoryFn} from '@storybook/react'; import {AsideHeader} from '../AsideHeader'; @@ -9,7 +9,7 @@ import {PageLayout} from '../components/PageLayout/PageLayout'; import {PageLayoutAside} from '../components/PageLayout/PageLayoutAside'; import {AsideHeaderShowcase} from './AsideHeaderShowcase'; -import {menuItemsClamped, menuItemsShowcase} from './moc'; +import {DEFAULT_LOGO, menuItemsClamped, menuItemsShowcase} from './moc'; import logoIcon from '../../../../.storybook/assets/logo.svg'; @@ -108,13 +108,7 @@ const AdvancedUsageTemplate: StoryFn = (args) => { alert('click on logo'), - 'aria-label': 'Service', - }} + logo={DEFAULT_LOGO} onChangeCompact={setCompact} qa={'pl-aside'} {...args} @@ -199,3 +193,47 @@ export function LineClamp() { ); } + +const CollapseButtonWrapperTemplate: StoryFn = (args) => { + const [compact, setCompact] = React.useState(args.initialCompact); + + return ( + + ( + + {defaultButton} +
+ + { + + } + {compact ? null : {'Gravity UI'}} + +
+
+ )} + qa={'pl-aside-collapse-wrapper'} + {...args} + /> +
+ ); +}; + +export const CollapseButtonWrapper = CollapseButtonWrapperTemplate.bind({}); +CollapseButtonWrapper.args = { + initialCompact: false, +}; diff --git a/src/components/AsideHeader/__stories__/moc.tsx b/src/components/AsideHeader/__stories__/moc.tsx index df7c4b4c..6f7a02bf 100644 --- a/src/components/AsideHeader/__stories__/moc.tsx +++ b/src/components/AsideHeader/__stories__/moc.tsx @@ -6,6 +6,8 @@ import {ASIDE_HEADER_EXPANDED_WIDTH} from '../../constants'; import {AsideHeaderContextType} from '../AsideHeaderContext'; import {AsideHeaderProps} from '../types'; +import logoIcon from '../../../../.storybook/assets/logo.svg'; + function renderTag(tag: string) { return
{tag.toUpperCase()}
; } @@ -142,6 +144,14 @@ const MENU_ITEMS_CLAMPED: AsideHeaderProps['menuItems'] = [ }, ]; +export const DEFAULT_LOGO = { + text: 'Service', + icon: logoIcon, + href: '#', + onClick: () => alert('click on logo'), + 'aria-label': 'Service', +}; + export const menuItemsClamped = MENU_ITEMS_CLAMPED.concat({ id: 'divider', title: undefined, diff --git a/src/components/AsideHeader/components/CollapseButton/CollapseButton.tsx b/src/components/AsideHeader/components/CollapseButton/CollapseButton.tsx index ceb7db11..0dc6b717 100644 --- a/src/components/AsideHeader/components/CollapseButton/CollapseButton.tsx +++ b/src/components/AsideHeader/components/CollapseButton/CollapseButton.tsx @@ -17,7 +17,8 @@ export interface CollapseButtonProps { } export const CollapseButton = ({className}: CollapseButtonProps) => { - const {onChangeCompact, compact, expandTitle, collapseTitle} = useAsideHeaderInnerContext(); + const {onChangeCompact, compact, expandTitle, collapseTitle, collapseButtonWrapper} = + useAsideHeaderInnerContext(); const onCollapseButtonClick = useCallback(() => { onChangeCompact?.(!compact); @@ -26,7 +27,8 @@ export const CollapseButton = ({className}: CollapseButtonProps) => { const buttonTitle = compact ? expandTitle || i18n('button_expand') : collapseTitle || i18n('button_collapse'); - return ( + + const defaultButton = ( ); + + if (collapseButtonWrapper) { + return collapseButtonWrapper(defaultButton, {compact, onChangeCompact}); + } + + return defaultButton; }; diff --git a/src/components/AsideHeader/types.tsx b/src/components/AsideHeader/types.tsx index f8d7552b..a7f1b050 100644 --- a/src/components/AsideHeader/types.tsx +++ b/src/components/AsideHeader/types.tsx @@ -37,6 +37,13 @@ export interface AsideHeaderGeneralProps extends QAProps { compact: boolean; asideRef: React.RefObject; }) => React.ReactNode; + collapseButtonWrapper?: ( + defaultButton: React.ReactNode, + data: { + compact: boolean; + onChangeCompact?: (compact: boolean) => void; + }, + ) => React.ReactNode; editMenuProps?: EditMenuProps; onClosePanel?: () => void; onChangeCompact?: (compact: boolean) => void;