From 4aee3be0cc4673864132beccc6bbb210921cd972 Mon Sep 17 00:00:00 2001 From: Anastasiia Mishchenko Date: Tue, 3 Dec 2024 18:19:12 +0000 Subject: [PATCH 01/16] fix: UI, types and functionality of Selected Item Badge --- .../SelectedItemBadge/SelectedItemBadge.scss | 185 +++++++----------- .../SelectedItemBadge/SelectedItemBadge.tsx | 60 ++++-- stories/atoms/Dropdown.stories.tsx | 4 +- .../organisms/SelectedItemBadge.stories.tsx | 20 +- 4 files changed, 132 insertions(+), 137 deletions(-) diff --git a/src/components/SelectedItemBadge/SelectedItemBadge.scss b/src/components/SelectedItemBadge/SelectedItemBadge.scss index fe5598226..41d769eac 100644 --- a/src/components/SelectedItemBadge/SelectedItemBadge.scss +++ b/src/components/SelectedItemBadge/SelectedItemBadge.scss @@ -1,70 +1,3 @@ -@use 'sass:map'; - -@mixin common-button-style( - $hoverColor: var(--color-background-neutral-subtlest-hover), - $activeColor: var(--color-background-neutral-subtlest-pressed) -) { - & { - width: var(--space-400); - height: var(--space-400); - align-items: center; - background-color: var(--transparent); - cursor: pointer; - display: flex; - flex-shrink: 0; - justify-content: center; - } - - &:hover:not([disabled]) { - background-color: $hoverColor; - } - &:active:not([disabled]) { - background-color: $activeColor; - } - - &[disabled] { - cursor: not-allowed; - } -} - -@mixin selected-state( - $selectedColor: var(--color-background-selected-subtlest-default), - $hoverColor: var(--color-background-selected-subtlest-hover), - $activeColor: var(--color-background-selected-subtlest-pressed) -) { - & { - background-color: $selectedColor; - } - &:hover:not([disabled]) { - background-color: $hoverColor; - } - &:active:not([disabled]) { - background-color: $activeColor; - } - &[disabled] { - background-color: $selectedColor; - } -} - -$icon-status-colors: ( - mandatory: ( - normal: var(--color-icon-success-default), - disabled: var(--color-icon-success-disabled), - ), - important: ( - normal: var(--color-icon-cautious-default), - disabled: var(--color-icon-cautious-disabled), - ), - optional: ( - normal: var(--color-icon-subtle), - disabled: var(--color-icon-disabled), - ), - exclude: ( - normal: var(--color-icon-critical-default), - disabled: var(--color-icon-critical-disabled), - ), -); - .SelectedItemBadge { width: 100%; height: var(--space-400); @@ -72,30 +5,6 @@ $icon-status-colors: ( border-radius: var(--space-100); display: flex; align-items: center; - overflow: hidden; - - &__priorityButton { - padding: 0; - border: 0; - border-right: 1px solid var(--color-border-subtle); - - @include common-button-style(); - } - - &__icon { - height: 20px; - width: 20px; - - @each $status, $colors in $icon-status-colors { - &--#{$status} { - fill: map.get($colors, normal); - - &[disabled] { - fill: map.get($colors, disabled); - } - } - } - } &__optionText { max-width: var(--space-600); @@ -109,34 +18,84 @@ $icon-status-colors: ( &__optionButton { width: 100%; + height: 100%; padding: 0 var(--space-100); + border-radius: inherit; + background-color: var(--transparent); border: 0; - flex-grow: 1; + display: flex; + align-items: center; + justify-content: center; gap: var(--space-50); + flex-grow: 1; - &[disabled] { - .SelectedItemBadge__optionText { - color: var(--color-text-info-disabled); - } + cursor: pointer; + + &:focus-visible { + box-shadow: 0 0 0 var(--space-25) var(--color-info-20, #99caff); + outline: none; } - @include common-button-style(); - } + &:hover:not([disabled]) { + background-color: var(--color-background-neutral-subtlest-hover); + } + + &:active:not([disabled]) { + background-color: var(--color-background-neutral-subtlest-pressed); + } + + &[disabled] .SelectedItemBadge__optionText { + color: var(--color-text-info-disabled); + } + + &--hasPriorityList { + border-left: 1px solid var(--color-border-subtlest); + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + + &--onDelete { + border-right: 1px solid var(--color-border-subtlest); + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + + &[data-state='open'] { + pointer-events: auto; + background-color: var(--color-background-selected-subtlest-default); + + &:hover { + background-color: var(--color-background-selected-subtlest-hover); + } + + &:active:not([disabled]) { + background-color: var(--color-background-selected-subtlest-pressed); + } - &__priorityButton--isSelected, - &__optionButton--isSelected { - @include selected-state(); + &[disabled] { + background-color: var(--color-background-selected-subtlest-default); + } + } } &__valueContainer { width: 100%; + height: 100%; padding: 0 var(--space-100); - float: left; display: flex; + align-items: center; justify-content: center; gap: var(--space-50); overflow: auto; cursor: default; + + &--hasPriorityList { + border-left: 1px solid var(--color-border-subtle); + } + + &--onDelete { + border-right: 1px solid var(--color-border-subtle); + } } &__valueText { @@ -159,21 +118,23 @@ $icon-status-colors: ( gap: var(--space-100); } - &__deleteButton { - border: 0; - border-left: 1px solid var(--color-border-subtle); - padding: 0; + .SelectedItemBadge__priorityButton { + padding: var(--space-100); + border-radius: var(--space-100) 0 0 var(--space-100); + flex-shrink: 0; + } + + .SelectedItemBadge__deleteButton { + padding: var(--space-100); + border-radius: 0 var(--space-100) var(--space-100) 0; + flex-shrink: 0; & svg { fill: var(--color-icon-subtle); } - &[disabled] { - & svg { - fill: var(--color-icon-disabled); - } + &[disabled] & svg { + fill: var(--color-icon-disabled); } - - @include common-button-style(); } } diff --git a/src/components/SelectedItemBadge/SelectedItemBadge.tsx b/src/components/SelectedItemBadge/SelectedItemBadge.tsx index 703b10da8..457808163 100644 --- a/src/components/SelectedItemBadge/SelectedItemBadge.tsx +++ b/src/components/SelectedItemBadge/SelectedItemBadge.tsx @@ -6,15 +6,16 @@ import { Text } from '../Text'; import styles from './SelectedItemBadge.scss'; import { DropdownContent, DropdownRoot, DropdownTrigger, SingleSelectItemProps } from '../Dropdown'; import { PrioritySelector, PrioritySelectorProps } from '../PrioritySelector'; +import { IconButton } from '../Buttons'; -export interface Props +export interface Props extends Omit, 'onChange'> { /** Children nodes to be rendered within the Dropdown, * which is triggered by the main button * */ children?: ( - | React.ReactElement> - | React.ReactElement>[] + | React.ReactElement> + | React.ReactElement>[] )[]; /** Label of the currently selected option item from filter */ label: React.ReactNode; @@ -36,8 +37,8 @@ export interface Props const { block, elem } = bem('SelectedItemBadge', styles); -export const SelectedItemBadge = React.forwardRef>( - ( +export const SelectedItemBadge = React.forwardRef( + ( { children, label, @@ -49,9 +50,15 @@ export const SelectedItemBadge = React.forwardRef>( priority, refElement, ...rest - }, - ref + }: Props, + ref: React.Ref ) => { + const [isOpen, setIsOpen] = React.useState(false); + + const handleOpenStateChange = (open: boolean) => { + setIsOpen(open); + }; + const badgeRef = React.useRef(null); const hasPriorityList = priority && priority.list.length > 0; @@ -63,15 +70,26 @@ export const SelectedItemBadge = React.forwardRef>( return (
- {hasPriorityList && } + {hasPriorityList && ( + + )} {children ? ( - - + + + + )}
); } -); +) as ( + p: Props & { ref?: React.Ref } +) => React.ReactElement; diff --git a/stories/atoms/Dropdown.stories.tsx b/stories/atoms/Dropdown.stories.tsx index ee812e434..000f94952 100644 --- a/stories/atoms/Dropdown.stories.tsx +++ b/stories/atoms/Dropdown.stories.tsx @@ -317,11 +317,11 @@ export const _DropdownWithSelectedItemBadge: Story = {
- priority={ priority && { ...priority, + list: priorityList, selectedItem: selectedPriorityItem, onChange: handlePriorityChange, } diff --git a/stories/organisms/SelectedItemBadge.stories.tsx b/stories/organisms/SelectedItemBadge.stories.tsx index 8b7dd88ed..e4aa3571f 100644 --- a/stories/organisms/SelectedItemBadge.stories.tsx +++ b/stories/organisms/SelectedItemBadge.stories.tsx @@ -38,7 +38,11 @@ export const _SelectedItemBadge: Story = { list: priorityList, buttonLabel: 'Priority', onChange: () => {}, - selectedItem: { priority: 'mandatory', label: 'Mandatory', value: 'required' }, + selectedItem: { + priority: 'mandatory', + label: 'Mandatory', + value: 'required', + }, }, buttonLabel: 'Select radius', }, @@ -46,7 +50,7 @@ export const _SelectedItemBadge: Story = { const [selectedPriorityItem, setSelectedPriorityItem] = React.useState< PriorityItemType >( - args.priority?.selectedItem || { + (args.priority?.selectedItem as PriorityItemType) || { priority: 'mandatory', label: 'Mandatory', value: 'required', @@ -80,11 +84,12 @@ export const _SelectedItemBadge: Story = { return (
- {...args} priority={ args.priority && { ...args.priority, + list: priorityList, selectedItem: selectedPriorityItem, onChange: handlePriorityChange, } @@ -124,7 +129,7 @@ export const _SelectedItemBadgeMultiSelect: Story = { const [selectedPriorityItem, setSelectedPriorityItem] = React.useState< PriorityItemType >( - args.priority?.selectedItem || { + (args.priority?.selectedItem as PriorityItemType) || { priority: 'mandatory', label: 'Mandatory', value: 'required', @@ -212,6 +217,7 @@ export const _SelectedItemBadgeMultiSelect: Story = { priority={ args.priority && { ...args.priority, + list: priorityList, selectedItem: selectedPriorityItem, onChange: handlePriorityChange, } @@ -331,7 +337,7 @@ export const SelectedItemBadgeWithoutChildren: Story = { const [selectedPriorityItem, setSelectedPriorityItem] = React.useState< PriorityItemType >( - args.priority?.selectedItem || { + (args.priority?.selectedItem as PriorityItemType) || { priority: 'mandatory', label: 'Mandatory', value: 'required', @@ -363,6 +369,7 @@ export const SelectedItemBadgeWithoutChildren: Story = { priority={ args.priority && { ...args.priority, + list: priorityList, selectedItem: selectedPriorityItem, onChange: handlePriorityChange, } @@ -391,7 +398,7 @@ export const SelectedItemBadgeWithoutCloseButton: Story = { const [selectedPriorityItem, setSelectedPriorityItem] = React.useState< PriorityItemType >( - args.priority?.selectedItem || { + (args.priority?.selectedItem as PriorityItemType) || { priority: 'mandatory', label: 'Mandatory', value: 'required', @@ -424,6 +431,7 @@ export const SelectedItemBadgeWithoutCloseButton: Story = { priority={ args.priority && { ...args.priority, + list: priorityList, selectedItem: selectedPriorityItem, onChange: handlePriorityChange, } From bd6315177b3d92f63eb29c045933c442d7c50a18 Mon Sep 17 00:00:00 2001 From: Anastasiia Mishchenko Date: Wed, 4 Dec 2024 14:02:13 +0000 Subject: [PATCH 02/16] feat: use tooltip for pill content for consistency --- .../Pill/PillButtonEnhanced/PillButtonEnhanced.tsx | 6 +++--- .../__snapshots__/PillButtonEnhanced.spec.tsx.snap | 4 ---- .../Pill/__tests__/__snapshots__/Pill.spec.tsx.snap | 2 -- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/components/Pill/PillButtonEnhanced/PillButtonEnhanced.tsx b/src/components/Pill/PillButtonEnhanced/PillButtonEnhanced.tsx index 0caa9b427..0f95d4e7d 100644 --- a/src/components/Pill/PillButtonEnhanced/PillButtonEnhanced.tsx +++ b/src/components/Pill/PillButtonEnhanced/PillButtonEnhanced.tsx @@ -99,9 +99,9 @@ export const PillButtonEnhanced = React.forwardRef( {!!content && ( <> : - - {content} - + + {content} + )} {additionalContentLabel && ( diff --git a/src/components/Pill/PillButtonEnhanced/__tests__/__snapshots__/PillButtonEnhanced.spec.tsx.snap b/src/components/Pill/PillButtonEnhanced/__tests__/__snapshots__/PillButtonEnhanced.spec.tsx.snap index 3ccfdf924..7d1eeedcf 100644 --- a/src/components/Pill/PillButtonEnhanced/__tests__/__snapshots__/PillButtonEnhanced.spec.tsx.snap +++ b/src/components/Pill/PillButtonEnhanced/__tests__/__snapshots__/PillButtonEnhanced.spec.tsx.snap @@ -29,7 +29,6 @@ exports[` component in active, collapsed state (with content This pill is in use @@ -92,7 +91,6 @@ exports[` component in active, open state (content and isOpe This pill is in use @@ -256,7 +254,6 @@ exports[` component with additional props should render corr This pill is in use @@ -320,7 +317,6 @@ exports[` component with additional props should set style a This pill is in use diff --git a/src/components/Pill/__tests__/__snapshots__/Pill.spec.tsx.snap b/src/components/Pill/__tests__/__snapshots__/Pill.spec.tsx.snap index b396b2c2b..9a4b10850 100644 --- a/src/components/Pill/__tests__/__snapshots__/Pill.spec.tsx.snap +++ b/src/components/Pill/__tests__/__snapshots__/Pill.spec.tsx.snap @@ -179,7 +179,6 @@ exports[` component with enhanced button variant should open dropdown when Pill content @@ -276,7 +275,6 @@ exports[` component with enhanced button variant should render correctly 1 Pill content From ddd0225553941649c056df026979a885e97f63a4 Mon Sep 17 00:00:00 2001 From: Anastasiia Mishchenko Date: Wed, 4 Dec 2024 16:06:13 +0000 Subject: [PATCH 03/16] fix: completelly fix the selectedItembadge --- .../SelectedItemBadge/SelectedItemBadge.scss | 6 ++-- .../SelectedItemBadge/SelectedItemBadge.tsx | 31 ++++++++++++------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/components/SelectedItemBadge/SelectedItemBadge.scss b/src/components/SelectedItemBadge/SelectedItemBadge.scss index 41d769eac..54fa74e3e 100644 --- a/src/components/SelectedItemBadge/SelectedItemBadge.scss +++ b/src/components/SelectedItemBadge/SelectedItemBadge.scss @@ -53,7 +53,6 @@ border-top-left-radius: 0; border-bottom-left-radius: 0; } - &--onDelete { border-right: 1px solid var(--color-border-subtlest); border-top-right-radius: 0; @@ -105,13 +104,14 @@ white-space: nowrap; } - .badgeDropdownList { + &__badgeDropdownList { width: 100%; border-radius: var(--space-100); + z-index: 600; overflow: hidden; } - .badgeListItem { + &__badgeListItem { display: flex; align-items: center; justify-content: flex-start; diff --git a/src/components/SelectedItemBadge/SelectedItemBadge.tsx b/src/components/SelectedItemBadge/SelectedItemBadge.tsx index 457808163..d21bc5a4b 100644 --- a/src/components/SelectedItemBadge/SelectedItemBadge.tsx +++ b/src/components/SelectedItemBadge/SelectedItemBadge.tsx @@ -1,10 +1,15 @@ import * as React from 'react'; import Close from '@material-design-icons/svg/round/close.svg'; - import { bem } from '../../utils'; import { Text } from '../Text'; import styles from './SelectedItemBadge.scss'; -import { DropdownContent, DropdownRoot, DropdownTrigger, SingleSelectItemProps } from '../Dropdown'; +import { + DropdownContent, + DropdownPortal, + DropdownRoot, + DropdownTrigger, + SingleSelectItemProps, +} from '../Dropdown'; import { PrioritySelector, PrioritySelectorProps } from '../PrioritySelector'; import { IconButton } from '../Buttons'; @@ -61,13 +66,14 @@ export const SelectedItemBadge = React.forwardRef( const badgeRef = React.useRef(null); + const triggerRef = React.useRef(null); + const hasPriorityList = priority && priority.list.length > 0; const handleOnDelete = (e: React.KeyboardEvent | React.MouseEvent) => { e.stopPropagation(); onDelete?.(e); }; - return (
{hasPriorityList && ( @@ -82,6 +88,7 @@ export const SelectedItemBadge = React.forwardRef(