From 55885d0d7956a93eb33ffade8be535fa7f2b7f6e Mon Sep 17 00:00:00 2001 From: Alexey Date: Thu, 2 Nov 2023 19:27:50 +0300 Subject: [PATCH] feat(Menu): add support for item icon on the end of the item (#965) --- src/components/DropdownMenu/DropdownMenu.scss | 12 ++---- .../DropdownMenu/DropdownMenuItem.tsx | 14 ++++--- src/components/DropdownMenu/README.md | 17 +++++---- src/components/Menu/Menu.scss | 21 +++++++++++ src/components/Menu/MenuItem.tsx | 16 ++++++-- src/components/Menu/README.md | 37 +++++++++++++++++-- .../Menu/__stories__/Menu.stories.tsx | 17 +++++++-- .../hoc/withTableActions/withTableActions.tsx | 4 +- 8 files changed, 103 insertions(+), 35 deletions(-) diff --git a/src/components/DropdownMenu/DropdownMenu.scss b/src/components/DropdownMenu/DropdownMenu.scss index f532a8db23..b7ea74aa12 100644 --- a/src/components/DropdownMenu/DropdownMenu.scss +++ b/src/components/DropdownMenu/DropdownMenu.scss @@ -17,15 +17,9 @@ $block: '.#{variables.$ns}dropdown-menu'; pointer-events: none; } - &__menu-item-content { - display: flex; - justify-content: space-between; - align-items: center; - gap: 16px; - } - - &__menu-item-content-children { - flex: auto; + &__sub-menu-arrow { + right: -4px; + position: relative; } &__sub-menu { diff --git a/src/components/DropdownMenu/DropdownMenuItem.tsx b/src/components/DropdownMenu/DropdownMenuItem.tsx index f5ac0f0799..41f84eb79e 100644 --- a/src/components/DropdownMenu/DropdownMenuItem.tsx +++ b/src/components/DropdownMenu/DropdownMenuItem.tsx @@ -92,6 +92,12 @@ export const DropdownMenuItem = ({ }; }, [props.extraProps, closeSubmenu, hasSubmenu, openSubmenu]); + const iconEnd = hasSubmenu ? ( + + ) : ( + props.iconEnd + ); + return ( ({ {...props} extraProps={extraProps} onClick={handleMenuItemClick} + iconEnd={iconEnd} > -
-
- {text || children} -
- {hasSubmenu && } -
+ {text || children}
{hasSubmenu && subMenuItems && ( , + iconStart: , action: () => console.log('Rename'), text: 'Rename', }, { - icon: , + iconStart: , action: () => console.log('Delete'), text: 'Delete', theme: 'danger', @@ -442,7 +442,7 @@ The menu toggle icon can be changed with the `DropdownMenu`'s `switcher` prop. B } items={[ { - icon: ( + iconStart: ( ( @@ -454,7 +454,7 @@ The menu toggle icon can be changed with the `DropdownMenu`'s `switcher` prop. B text: 'Rename', }, { - icon: ( + iconStart: ( ( @@ -483,12 +483,12 @@ LANDING_BLOCK--> } items={[ { - icon: , + iconStart: , action: () => console.log('Rename'), text: 'Rename', }, { - icon: , + iconStart: , action: () => console.log('Delete'), text: 'Delete', theme: 'danger', @@ -528,7 +528,8 @@ This type describes individual dropdown menu items. | :----------- | :------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------: | :-----: | | `text` | Menu item content. | `React.ReactNode` | | | `action` | Menu item click handler. Recieves the parameters from the parent dropdown menu component (both `event` and `data`). | `(event: React.MouseEvent, data: any) => void` | | -| `icon` | Menu item icon. | `React.ReactNode` | | +| `iconStart` | Menu item icon before the item content. | `React.ReactNode` | | +| `iconEnd` | Menu item icon after the item content. Ignored if the item has a submenu. | `React.ReactNode` | | | `hidden` | Determines whether the item is hidden. | `boolean` | | | `disabled` | Determines whether the item is disabled. | `boolean` | | | `href` | Menu item with this prop becomes a link to the specified location. | `string` | | diff --git a/src/components/Menu/Menu.scss b/src/components/Menu/Menu.scss index 5b14126ff7..ccab5a0a71 100644 --- a/src/components/Menu/Menu.scss +++ b/src/components/Menu/Menu.scss @@ -37,6 +37,11 @@ $block: '.#{variables.$ns}menu'; display: flex; } + &-icon-end { + display: flex; + margin-right: 0; + } + &-content { flex-grow: 1; min-width: 0; @@ -104,6 +109,10 @@ $block: '.#{variables.$ns}menu'; margin-right: 3px; } + #{$block}__item-icon-end { + margin-left: 3px; + } + #{$block}__list-group-item + #{$block}__list-group-item, #{$block}__list-item + #{$block}__list-group-item, #{$block}__list-group-item + #{$block}__list-item { @@ -125,6 +134,10 @@ $block: '.#{variables.$ns}menu'; margin-right: 4px; } + #{$block}__item-icon-end { + margin-left: 4px; + } + #{$block}__list-group-item + #{$block}__list-group-item, #{$block}__list-item + #{$block}__list-group-item, #{$block}__list-group-item + #{$block}__list-item { @@ -146,6 +159,10 @@ $block: '.#{variables.$ns}menu'; margin-right: 5px; } + #{$block}__item-icon-end { + margin-left: 5px; + } + #{$block}__list-group-item + #{$block}__list-group-item, #{$block}__list-item + #{$block}__list-group-item, #{$block}__list-group-item + #{$block}__list-item { @@ -168,6 +185,10 @@ $block: '.#{variables.$ns}menu'; margin-right: 6px; } + #{$block}__item-icon-end { + margin-left: 6px; + } + #{$block}__list-group-item:not(:first-child) { margin-top: 6px; padding-top: 6px; diff --git a/src/components/Menu/MenuItem.tsx b/src/components/Menu/MenuItem.tsx index 5daa17e27c..0e1a10a494 100644 --- a/src/components/Menu/MenuItem.tsx +++ b/src/components/Menu/MenuItem.tsx @@ -8,7 +8,10 @@ import {eventBroker} from '../utils/event-broker'; const b = block('menu'); export interface MenuItemProps extends DOMProps, QAProps { + /** @deprecated use `iconStart` instead */ icon?: React.ReactNode; + iconStart?: React.ReactNode; + iconEnd?: React.ReactNode; title?: string; disabled?: boolean; active?: boolean; @@ -27,6 +30,8 @@ export interface MenuItemProps extends DOMProps, QAProps { export const MenuItem = React.forwardRef(function MenuItem( { icon, + iconStart = icon, + iconEnd, title, disabled, active, @@ -69,14 +74,19 @@ export const MenuItem = React.forwardRef(function Me 'data-qa': qa, }; const content = [ - icon && ( -
- {icon} + iconStart && ( +
+ {iconStart}
),
{children}
, + iconEnd && ( +
+ {iconEnd} +
+ ), ]; let item; diff --git a/src/components/Menu/README.md b/src/components/Menu/README.md index b7714ff70c..0e3efe503e 100644 --- a/src/components/Menu/README.md +++ b/src/components/Menu/README.md @@ -133,19 +133,19 @@ This property is used to render menu items. ### Icon -The `Icon` property is used to display an icon for a menu item: +The `iconStart` or `iconEnd` properties is used to display an icon at the start or end of a menu item: ```tsx - }>Item with icon + }>Item with icon + Item without icon + +``` + +```tsx + + }>Item with icon Item without icon ``` @@ -240,6 +267,8 @@ LANDING_BLOCK--> | Name | Description | Type | Default | | :--------- | :----------------------------------------- | :-----------------------: | :--------: | +| iconStart | Menu icon before item text | `ReactNode` | | +| iconEnd | Menu icon after item text | `ReactNode` | | | selected | Menu item selected flag | `boolean` | `false` | | disabled | Menu item disabled flag | `boolean` | `false` | | active | Menu item active flag | `boolean` | `false` | diff --git a/src/components/Menu/__stories__/Menu.stories.tsx b/src/components/Menu/__stories__/Menu.stories.tsx index 23a8cac51c..8fea81f3df 100644 --- a/src/components/Menu/__stories__/Menu.stories.tsx +++ b/src/components/Menu/__stories__/Menu.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import {Gear} from '@gravity-ui/icons'; +import {CircleExclamationFill, Gear} from '@gravity-ui/icons'; import type {Meta, StoryFn} from '@storybook/react'; import {Icon} from '../../Icon'; @@ -10,7 +10,7 @@ import type {MenuProps} from '../Menu'; export default { title: 'Components/Navigation/Menu', component: Menu, -} as Meta; +} as Meta; export const Default: StoryFn = (args) => ( @@ -29,7 +29,18 @@ export const ItemActive: StoryFn = (args) => ( export const ItemIcon: StoryFn = (args) => ( - }>Settings + }>Settings + +); + +export const ItemBothIcons: StoryFn = (args) => ( + + } + iconEnd={} + > + Settings + ); diff --git a/src/components/Table/hoc/withTableActions/withTableActions.tsx b/src/components/Table/hoc/withTableActions/withTableActions.tsx index 8643915a2d..7e1f390594 100644 --- a/src/components/Table/hoc/withTableActions/withTableActions.tsx +++ b/src/components/Table/hoc/withTableActions/withTableActions.tsx @@ -46,7 +46,7 @@ export interface TableAction { ) => void; disabled?: boolean; theme?: MenuItemProps['theme']; - icon?: MenuItemProps['icon']; + icon?: MenuItemProps['iconStart']; } export interface TableActionGroup { @@ -179,7 +179,7 @@ export function withTableActions( disabled={action.disabled} onClick={this.handleActionClick.bind(this, action, popupData!)} theme={action.theme} - icon={action.icon} + iconStart={action.icon} className={bPopup('menu-item')} > {action.text}