Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(ActionMenuItem): expose ActionMenuItem as a standalone component #1457

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import cx from 'clsx';

import { IActionMenuOption } from 'components/ActionMenu/types';

import { ActionMenu, ActionMenuItem } from '../ActionMenu';
import { ActionMenu } from '../ActionMenu';
import { ActionMenuItem } from '../ActionMenuItem';
import { Button } from '../Button';
import { Icon } from '../Icon';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,21 @@ import * as React from 'react';
import { MoreHoriz, Add, Settings } from '@livechat/design-system-icons';

import { customHeightForChromatic } from '../../utils/chromatic-story-helpers';
import { ActionMenuItem } from '../ActionMenuItem';
import { Button } from '../Button';
import { Checkbox } from '../Checkbox';
import { Icon } from '../Icon';
import { RadioButton } from '../RadioButton';
import { Switch } from '../Switch';

import { ActionMenu } from './ActionMenu';
import { ActionMenuItem } from './ActionMenuItem';
import { exampleOptions } from './stories-constants';

import './ActionMenu.stories.css';

export default {
title: 'Components/ActionMenu',
component: ActionMenu,
subcomponents: {
ActionMenuItem,
},
parameters: {
chromatic: { delay: 300 },
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export { ActionMenu } from './ActionMenu';
export { ActionMenuItem } from './ActionMenuItem';
export type { IActionMenuOption } from './types';
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ import {
} from '@livechat/design-system-icons';

import noop from '../../utils/noop';
import { ActionMenuItem } from '../ActionMenuItem';
import { Icon } from '../Icon';

import { ActionMenuItem } from './ActionMenuItem';

export const exampleOptions = [
{
key: 'one',
Expand Down
15 changes: 0 additions & 15 deletions packages/react-components/src/components/ActionMenu/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,3 @@ export interface IActionMenuProps extends ComponentCoreProps {
*/
footer?: React.ReactNode;
}

export interface ActionMenuItemProps {
/**
* Renders given element on the left of element
*/
leftNode?: React.ReactNode;
/**
* Renders given element on the right of element
*/
rightNode?: React.ReactNode;
/**
* Specify the kind of menu item
*/
kind?: 'warning' | undefined;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Canvas, ArgTypes, Meta, Title } from '@storybook/blocks';

import * as ActionMenuItemStories from './ActionMenuItem.stories';

<Meta of={ActionMenuItemStories} />

<Title>ActionMenuItem</Title>

[Intro](#Intro) | [Component API](#ComponentAPI) | [Content Spec](#ContentSpec)

## Intro <a id="Intro" />

The Action Menu Item component is designed to be used within menus, such as the ActionMenu or other custom menus.
It represents a single menu option, allowing users to interact with or select actions.
This component typically displays a label and optionally supports additional elements icons or additional context, which can be positioned on either the left or right side of the item.
This makes it a flexible building block for creating intuitive menus.

<Canvas of={ActionMenuItemStories.Default} sourceState="none" />

#### Example implementation

```jsx
<ActionMenuItem>Simple Option 1</ActionMenuItem>
// OR
<ActionMenuItem leftNode={<Icon icon="chat" />} rightNode={<Icon icon="chevron-down" />}>Complex option 2</ActionMenuItem>
```

## Component API <a id="ComponentAPI" />

<ArgTypes of={ActionMenuItemStories.Default} sort="requiredFirst" />
Comment on lines +28 to +30
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add accessibility documentation

Include a section about ARIA attributes, keyboard navigation, and screen reader considerations.


## Content Spec <a id="ContentSpec" />

<a
className="sb-unstyled"
href="https://www.figma.com/file/9FDwjR8lYvincseDkKypC4/Component-Documentations?type=design&node-id=97-20299&mode=design&t=yMPgy8XRD1OTobuX-4"
target="_blank"
>
Go to Figma documentation
</a>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.action-menu-item-preview {
display: flex;
justify-content: center;
margin-bottom: 200px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { ReactElement } from 'react';

import {
CloseCircle,
ContentCopy,
MoreHoriz,
} from '@livechat/design-system-icons';

import { customHeightForChromatic } from '../../utils/chromatic-story-helpers';
import noop from '../../utils/noop';
import { ActionMenu } from '../ActionMenu';
import { Button } from '../Button';
import { Icon } from '../Icon';

import { ActionMenuItem } from './ActionMenuItem';

import './ActionMenuItem.stories.css';

export default {
title: 'Components/ActionMenuItem',
component: ActionMenuItem,
parameters: {
chromatic: { delay: 300 },
},
};

const defaultOptions = [
{
key: 'one',
element: <ActionMenuItem>Simple Item 1</ActionMenuItem>,
onClick: noop,
},
{
key: 'two',
element: (
<ActionMenuItem
leftNode={<Icon source={ContentCopy} />}
rightNode={<Icon source={CloseCircle} />}
>
Complex Item 2
</ActionMenuItem>
),
onClick: noop,
},
];

const warningOptions = [
{
key: 'one',
element: <ActionMenuItem kind="warning">Simple Item 1</ActionMenuItem>,
onClick: noop,
},
{
key: 'two',
element: (
<ActionMenuItem
kind="warning"
leftNode={<Icon source={ContentCopy} />}
rightNode={<Icon source={CloseCircle} />}
>
Complex Item 2
</ActionMenuItem>
),
onClick: noop,
},
];
export const Default = (): ReactElement => {
return (
<div style={{ height: customHeightForChromatic('1000px') }}>
<div className="action-menu-preview">
<ActionMenu
options={defaultOptions}
triggerRenderer={
<Button icon={<Icon source={MoreHoriz} kind="primary" />} />
}
openedOnInit
/>
</div>
</div>
);
};

export const WarningKind = (): ReactElement => {
return (
<div style={{ height: customHeightForChromatic('1000px') }}>
<div className="action-menu-item-preview">
<ActionMenu
options={warningOptions}
triggerRenderer={
<Button icon={<Icon source={MoreHoriz} kind="primary" />} />
}
openedOnInit
/>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import { FC, PropsWithChildren } from 'react';

import cx from 'clsx';

Expand All @@ -10,9 +10,12 @@ import styles from './ActionMenuItem.module.scss';

const baseClass = 'action-menu-item';

export const ActionMenuItem: React.FC<
React.PropsWithChildren<ActionMenuItemProps>
> = ({ leftNode, rightNode, children, kind }) => {
export const ActionMenuItem: FC<PropsWithChildren<ActionMenuItemProps>> = ({
leftNode,
rightNode,
children,
kind,
}) => {
return (
<div
className={cx(styles[baseClass], {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ActionMenuItem } from './ActionMenuItem';
16 changes: 16 additions & 0 deletions packages/react-components/src/components/ActionMenuItem/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ReactNode } from 'react';

export interface ActionMenuItemProps {
/**
* Renders given element on the left of element
*/
leftNode?: ReactNode;
/**
* Renders given element on the right of element
*/
rightNode?: ReactNode;
/**
* Specify the kind of menu item
*/
kind?: 'warning' | undefined;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import cx from 'clsx';

import { ThemeClassName } from '../../providers';
import { plural } from '../../utils/plural';
import { ActionMenu, ActionMenuItem } from '../ActionMenu';
import { ActionMenu } from '../ActionMenu';
import { ActionMenuItem } from '../ActionMenuItem';
import { Avatar } from '../Avatar';
import { Icon } from '../Icon';
import { Interactive, Tooltip } from '../Tooltip';
Expand Down
2 changes: 1 addition & 1 deletion packages/react-components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export * from './components/Accordion';
export * from './components/ActionBar';
export * from './components/ActionCard';
export * from './components/ActionMenu';
export * from './components/Alert';
export * from './components/ActionMenuItem';
export * from './components/AppFrame';
export * from './components/AutoComplete';
export * from './components/Avatar';
Expand Down
Loading