diff --git a/packages/react-components/src/components/ActionMenu/ActionMenu.module.scss b/packages/react-components/src/components/ActionMenu/ActionMenu.module.scss index 1db6cfd6b..f5cd10319 100644 --- a/packages/react-components/src/components/ActionMenu/ActionMenu.module.scss +++ b/packages/react-components/src/components/ActionMenu/ActionMenu.module.scss @@ -6,15 +6,19 @@ $base-class: 'action-menu'; border-radius: var(--radius-3); background-color: var(--picker-list-background); padding: 0; + padding: var(--spacing-2); overflow: hidden; list-style: none; &__item { display: flex; + position: relative; align-items: center; + margin-bottom: var(--spacing-05); outline: 0; border: 0; border-radius: 0; + border-radius: var(--radius-3); background: none; padding: 7px var(--spacing-3); width: 100%; @@ -27,13 +31,32 @@ $base-class: 'action-menu'; cursor: pointer; } + &:focus, + &:active { + background-color: var(--picker-list-option-background-active); + } + &:focus { outline: 2px solid var(--action-primary-default); outline-offset: -2px; } + > * { + pointer-events: none; + } + &--with-divider { - border-top: 1px solid var(--border-basic-secondary); + margin-top: var(--spacing-2); + + &::before { + position: absolute; + top: -4.5px; + right: -8px; + left: -8px; + background-color: var(--border-basic-secondary); + height: 1px; + content: ''; + } } &--disabled { @@ -44,6 +67,21 @@ $base-class: 'action-menu'; cursor: not-allowed; } } + + &--active { + background-color: var(--picker-list-option-background-active); + + &::after { + position: absolute; + left: -8px; + border-top-right-radius: var(--radius-3); + border-bottom-right-radius: var(--radius-3); + background: var(--action-primary-default); + width: 3px; + height: 36px; + content: ''; + } + } } } } diff --git a/packages/react-components/src/components/ActionMenu/ActionMenu.stories.tsx b/packages/react-components/src/components/ActionMenu/ActionMenu.stories.tsx index 4517e8c1e..56c632bd2 100644 --- a/packages/react-components/src/components/ActionMenu/ActionMenu.stories.tsx +++ b/packages/react-components/src/components/ActionMenu/ActionMenu.stories.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { MoreHoriz } from '@livechat/design-system-icons/react/tabler'; +import { Checkbox } from '../Checkbox'; import { Icon } from '../Icon'; import { RadioButton } from '../RadioButton'; import { Switch } from '../Switch'; @@ -31,35 +32,75 @@ export const Default = (): React.ReactElement => ( ); export const KeepOpenOnItemClick = (): React.ReactElement => { - const [checkboxValue, setCheckboxValue] = React.useState('one'); - const [switchOneValue, setSwitchOneValue] = React.useState(false); + const [radioButtonValue, setRadioButtonValue] = React.useState('one'); + const [switchOneValue, setSwitchOneValue] = React.useState(true); const [switchTwoValue, setSwitchTwoValue] = React.useState(false); + const [checkboxOneValue, setCheckboxOneValue] = React.useState(true); + const [checkboxTwoValue, setCheckboxTwoValue] = React.useState(true); + const [activeOptionsKeys, setActiveOptionsKeys] = React.useState([ + 'one', + 'three', + 'five', + 'six', + ]); + + const handleOptionSelect = ( + key: string, + type: string, + optionHandler: void + ) => { + const newActiveOptions = activeOptionsKeys; + + if (type === 'radio') { + if (!activeOptionsKeys.includes(key)) { + const keyToRemove = key === 'one' ? 'two' : 'one'; + const index = activeOptionsKeys.indexOf(keyToRemove); + newActiveOptions.splice(index, 1); + setActiveOptionsKeys([...newActiveOptions, key]); + } + } + + if (type === 'switch' || type === 'checkbox') { + if (activeOptionsKeys.includes(key)) { + const index = activeOptionsKeys.indexOf(key); + newActiveOptions.splice(index, 1); + setActiveOptionsKeys([...newActiveOptions]); + } else { + activeOptionsKeys.push(key); + } + } + + return optionHandler; + }; return (
- + Radio label one ), - onClick: () => setCheckboxValue('one'), + onClick: () => + handleOptionSelect('one', 'radio', setRadioButtonValue('one')), }, { key: 'two', element: ( - + Radio label two ), - onClick: () => setCheckboxValue('two'), + onClick: () => + handleOptionSelect('two', 'radio', setRadioButtonValue('two')), }, { key: 'three', @@ -73,7 +114,12 @@ export const KeepOpenOnItemClick = (): React.ReactElement => { Toggle label one ), - onClick: () => setSwitchOneValue((s) => !s), + onClick: () => + handleOptionSelect( + 'three', + 'switch', + setSwitchOneValue((s) => !s) + ), }, { key: 'four', @@ -87,7 +133,49 @@ export const KeepOpenOnItemClick = (): React.ReactElement => { Toggle label two ), - onClick: () => setSwitchTwoValue((s) => !s), + onClick: () => + handleOptionSelect( + 'four', + 'switch', + setSwitchTwoValue((s) => !s) + ), + }, + { + key: 'five', + withDivider: true, + element: ( + + Checkbox label one + + } + /> + ), + onClick: () => + handleOptionSelect( + 'five', + 'checkbox', + setCheckboxOneValue((s) => !s) + ), + }, + { + key: 'six', + element: ( + + Checkbox label two + + } + /> + ), + onClick: () => + handleOptionSelect( + 'six', + 'checkbox', + setCheckboxTwoValue((s) => !s) + ), }, ]} triggerRenderer={} diff --git a/packages/react-components/src/components/ActionMenu/ActionMenu.tsx b/packages/react-components/src/components/ActionMenu/ActionMenu.tsx index c8621a9ca..375283503 100644 --- a/packages/react-components/src/components/ActionMenu/ActionMenu.tsx +++ b/packages/react-components/src/components/ActionMenu/ActionMenu.tsx @@ -40,6 +40,10 @@ export interface ActionMenuProps { * Menu will stay open after option click */ keepOpenOnClick?: boolean; + /** + * Set the keys array for active elements + */ + activeOptionKeys?: string[]; } const baseClass = 'action-menu'; @@ -51,6 +55,7 @@ export const ActionMenu: React.FC = ({ placement = 'bottom-end', openedOnInit = false, keepOpenOnClick, + activeOptionKeys, ...props }) => { const [isVisible, setIsVisible] = React.useState(openedOnInit); @@ -137,6 +142,8 @@ export const ActionMenu: React.FC = ({ [styles[`${baseClass}__list__item--disabled`]]: o.disabled, [styles[`${baseClass}__list__item--with-divider`]]: o.withDivider, + [styles[`${baseClass}__list__item--active`]]: + activeOptionKeys?.includes(o.key), })} > {o.element}