diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 31a7ddfb270d..c21cbad18eaf 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -13,7 +13,7 @@ 'npm:unpublishSafe', // https://docs.renovatebot.com/presets-schedule/#scheduledaily - 'schedule:weekday', + 'schedule:every weekday', ], vulnerabilityAlerts: { enabled: true, diff --git a/packages/react/src/components/ComboBox/ComboBox.tsx b/packages/react/src/components/ComboBox/ComboBox.tsx index 3fa05acf5ae3..9fdf344dd3e5 100644 --- a/packages/react/src/components/ComboBox/ComboBox.tsx +++ b/packages/react/src/components/ComboBox/ComboBox.tsx @@ -13,6 +13,7 @@ import React, { useEffect, useState, useRef, + useMemo, forwardRef, type ReactNode, type ComponentType, @@ -655,6 +656,15 @@ const ComboBox = forwardRef( (helperText && !isFluid && helperTextId) || undefined; + const menuProps = useMemo( + () => + getMenuProps({ + 'aria-label': deprecatedAriaLabel || ariaLabel, + ref: autoAlign ? refs.setFloating : null, + }), + [autoAlign, deprecatedAriaLabel, ariaLabel] + ); + return (
{titleText && ( @@ -674,7 +684,7 @@ const ComboBox = forwardRef( light={light} size={size} warn={warn} - ref={refs.setReference} + ref={autoAlign ? refs.setReference : null} warnText={warnText} warnTextId={warnTextId}>
@@ -686,7 +696,7 @@ const ComboBox = forwardRef( aria-haspopup="listbox" title={textInput?.current?.value} {...getInputProps({ - 'aria-controls': isOpen ? undefined : getMenuProps().id, + 'aria-controls': isOpen ? undefined : menuProps.id, placeholder, ref: { ...mergeRefs(textInput, ref) }, onKeyDown: ( @@ -785,11 +795,7 @@ const ComboBox = forwardRef( />
{normalizedSlug} - + {isOpen ? filterItems(items, itemToString, inputValue).map( (item, index) => { diff --git a/packages/react/src/components/Modal/Modal.stories.js b/packages/react/src/components/Modal/Modal.stories.js index fb60764d3560..1dcf41f52be8 100644 --- a/packages/react/src/components/Modal/Modal.stories.js +++ b/packages/react/src/components/Modal/Modal.stories.js @@ -322,6 +322,61 @@ export const Playground = ({ numberOfButtons, ...args }) => { + + (item ? item.text : '')} + direction="top" + /> + +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean id + accumsan augue. Phasellus consequat augue vitae tellus tincidunt + posuere. Curabitur justo urna, consectetur vel elit iaculis, ultrices + condimentum risus. Nulla facilisi. Etiam venenatis molestie tellus. + Quisque consectetur non risus eu rutrum.{' '} +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean id + accumsan augue. Phasellus consequat augue vitae tellus tincidunt + posuere. Curabitur justo urna, consectetur vel elit iaculis, ultrices + condimentum risus. Nulla facilisi. Etiam venenatis molestie tellus. + Quisque consectetur non risus eu rutrum.{' '} +

+ {args.hasScrollingContent && ( <>

diff --git a/packages/react/src/components/MultiSelect/FilterableMultiSelect.tsx b/packages/react/src/components/MultiSelect/FilterableMultiSelect.tsx index 66d2ebebeafe..6b6bd8f25038 100644 --- a/packages/react/src/components/MultiSelect/FilterableMultiSelect.tsx +++ b/packages/react/src/components/MultiSelect/FilterableMultiSelect.tsx @@ -518,8 +518,6 @@ const FilterableMultiSelect = React.forwardRef(function FilterableMultiSelect< return changes; case InputBlur: case InputKeyDownEscape: - setInputFocused(false); - setInputValue(''); setIsOpen(false); return changes; case FunctionToggleMenu: @@ -714,6 +712,10 @@ const FilterableMultiSelect = React.forwardRef(function FilterableMultiSelect< } }, onFocus: () => setInputFocused(true), + onBlur: () => { + !isOpen && setInputFocused(false); + setInputValue(''); + }, }) ); const menuProps = getMenuProps({}, { suppressRefError: true }); diff --git a/packages/react/src/components/MultiSelect/__tests__/FilterableMultiSelect-test.js b/packages/react/src/components/MultiSelect/__tests__/FilterableMultiSelect-test.js index 433debc08b1d..a9f02f2329a0 100644 --- a/packages/react/src/components/MultiSelect/__tests__/FilterableMultiSelect-test.js +++ b/packages/react/src/components/MultiSelect/__tests__/FilterableMultiSelect-test.js @@ -170,6 +170,20 @@ describe('FilterableMultiSelect', () => { expect(screen.getByPlaceholderText('test')).toHaveDisplayValue(3); }); + it('should clear input value when clicking on cross button', async () => { + render(); + await openMenu(); + + await userEvent.type(screen.getByPlaceholderText('test'), '3'); + + const clearButton = screen.getByRole('button', { + name: 'Clear selected item', + }); + await userEvent.click(clearButton); + + expect(screen.getByPlaceholderText('test')).toHaveDisplayValue(''); + }); + it('should respect slug prop', async () => { const { container } = render( } /> diff --git a/packages/react/src/components/OverflowMenu/OverflowMenu-test.js b/packages/react/src/components/OverflowMenu/OverflowMenu-test.js index 46eec3e5834d..daa44bb499d1 100644 --- a/packages/react/src/components/OverflowMenu/OverflowMenu-test.js +++ b/packages/react/src/components/OverflowMenu/OverflowMenu-test.js @@ -10,7 +10,7 @@ import OverflowMenu from './OverflowMenu'; import OverflowMenuItem from '../OverflowMenuItem'; import { Filter } from '@carbon/icons-react'; import userEvent from '@testing-library/user-event'; -import { render, screen } from '@testing-library/react'; +import { render, screen, fireEvent } from '@testing-library/react'; describe('OverflowMenu', () => { describe('Renders as expected', () => { @@ -171,5 +171,29 @@ describe('OverflowMenu', () => { 'true' ); }); + + it('should call onClick handler only once per click', async () => { + const handleClick = jest.fn(); + + render( + + + + + ); + + // Find the OverflowMenu button + const button = screen.getByRole('button'); + + // Click the OverflowMenu button + await userEvent.click(button); + + // Check that the click handler was called only once + expect(handleClick).toHaveBeenCalledTimes(1); + }); }); }); diff --git a/packages/react/src/components/OverflowMenu/OverflowMenu.tsx b/packages/react/src/components/OverflowMenu/OverflowMenu.tsx index 157a976655de..b6ee30ccddb3 100644 --- a/packages/react/src/components/OverflowMenu/OverflowMenu.tsx +++ b/packages/react/src/components/OverflowMenu/OverflowMenu.tsx @@ -439,7 +439,6 @@ class OverflowMenu extends React.Component< handleClick = (evt) => { const { onClick = noopFn } = this.props; this.setState({ click: true }); - evt.stopPropagation(); if (!this._menuBody || !this._menuBody.contains(evt.target)) { this.setState({ open: !this.state.open }); onClick(evt); diff --git a/packages/react/src/components/Popover/Popover.stories.js b/packages/react/src/components/Popover/Popover.stories.js index 1285cf930f7a..f32b32e60068 100644 --- a/packages/react/src/components/Popover/Popover.stories.js +++ b/packages/react/src/components/Popover/Popover.stories.js @@ -15,6 +15,8 @@ import { default as Checkbox } from '../Checkbox'; import mdx from './Popover.mdx'; import { Settings } from '@carbon/icons-react'; import { keys, match } from '../../internal/keyboard'; +import OverflowMenu from '../OverflowMenu/OverflowMenu'; +import OverflowMenuItem from '../OverflowMenuItem'; const prefix = 'cds'; @@ -267,6 +269,67 @@ export const ExperimentalAutoAlign = () => {

); }; +export const Test = () => { + const [open, setOpen] = useState(); + const align = document?.dir === 'rtl' ? 'bottom-right' : 'bottom-left'; + const alignTwo = document?.dir === 'rtl' ? 'bottom-left' : 'bottom-right'; + return ( +
+ + + + + + + + + + { + if (match(evt, keys.Escape)) { + setOpen(false); + } + }} + isTabTip + onRequestClose={() => setOpen(false)}> + + + + + + +
+
+ Edit columns + + + +
+
+
+
+ ); +}; export const TabTipExperimentalAutoAlign = () => { const [open, setOpen] = useState(true); diff --git a/packages/styles/scss/components/modal/_modal.scss b/packages/styles/scss/components/modal/_modal.scss index 65bb53799dfd..bd79cccfd024 100644 --- a/packages/styles/scss/components/modal/_modal.scss +++ b/packages/styles/scss/components/modal/_modal.scss @@ -320,6 +320,11 @@ linear-gradient(to top, $layer 0, 2px, transparent 2px); } + //removing mask image in case we have dropdown in modal + .#{$prefix}--modal-scroll-content:has(.#{$prefix}--dropdown--autoalign) { + mask-image: none; + } + // Required so overflow-indicator disappears at end of content .#{$prefix}--modal-scroll-content > *:last-child { margin-block-end: $spacing-06;