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

fix(Table): added ActionsColumn prop to control close on click #10179

Merged
merged 2 commits into from
Mar 26, 2024
Merged
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
61 changes: 33 additions & 28 deletions packages/react-table/src/components/Table/ActionsColumn.tsx
Original file line number Diff line number Diff line change
@@ -30,6 +30,8 @@ export interface ActionsColumnProps extends Omit<React.HTMLProps<HTMLElement>, '
innerRef?: React.Ref<any>;
/** Ref to forward to the first item in the popup menu */
firstActionItemRef?: React.Ref<HTMLButtonElement>;
/** Flag indicating that the dropdown's onOpenChange callback should not be called. */
isOnOpenChangeDisabled?: boolean;
Comment on lines +33 to +34
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Per above I've added this prop. From what I can tell since ActionsColumn has its own isOpen state, being able to pass a custom onOpenChange callback wouldn't be as easy without introducing other props to customize things, and at that point I'd wonder if it wouldjust make more sense to allow passing a custom Dropdown itself (rather than right now we only really allow a custom actionsToggle)

}

const ActionsColumnBase: React.FunctionComponent<ActionsColumnProps> = ({
@@ -44,6 +46,7 @@ const ActionsColumnBase: React.FunctionComponent<ActionsColumnProps> = ({
},
innerRef,
firstActionItemRef,
isOnOpenChangeDisabled = false,
...props
}: ActionsColumnProps) => {
const [isOpen, setIsOpen] = React.useState(false);
@@ -91,7 +94,7 @@ const ActionsColumnBase: React.FunctionComponent<ActionsColumnProps> = ({

<Dropdown
isOpen={isOpen}
onOpenChange={(isOpen: boolean) => setIsOpen(isOpen)}
onOpenChange={!isOnOpenChangeDisabled ? (isOpen: boolean) => setIsOpen(isOpen) : undefined}
toggle={(toggleRef: any) =>
actionsToggle ? (
actionsToggle({ onToggle, isOpen, isDisabled, toggleRef })
@@ -116,35 +119,37 @@ const ActionsColumnBase: React.FunctionComponent<ActionsColumnProps> = ({
<DropdownList>
{items
.filter((item) => !item.isOutsideDropdown)
.map(({ title, itemKey, onClick, tooltipProps, isSeparator, ...props }, index) => {
if (isSeparator) {
return <Divider key={itemKey || index} data-key={itemKey || index} />;
}
const item = (
<DropdownItem
onClick={(event: any) => {
onActionClick(event, onClick);
onToggle();
}}
{...props}
key={itemKey || index}
data-key={itemKey || index}
ref={index === 0 ? firstActionItemRef : undefined}
>
{title}
</DropdownItem>
);

if (tooltipProps?.content) {
return (
<Tooltip key={itemKey || index} {...tooltipProps}>
{item}
</Tooltip>
.map(
({ title, itemKey, onClick, tooltipProps, isSeparator, shouldCloseOnClick = true, ...props }, index) => {
if (isSeparator) {
return <Divider key={itemKey || index} data-key={itemKey || index} />;
}
const item = (
<DropdownItem
onClick={(event: any) => {
onActionClick(event, onClick);
shouldCloseOnClick && onToggle();
}}
{...props}
key={itemKey || index}
data-key={itemKey || index}
ref={index === 0 ? firstActionItemRef : undefined}
>
{title}
</DropdownItem>
);
} else {
return item;

if (tooltipProps?.content) {
return (
<Tooltip key={itemKey || index} {...tooltipProps}>
{item}
</Tooltip>
);
} else {
return item;
}
}
})}
)}
</DropdownList>
</Dropdown>
</React.Fragment>
2 changes: 2 additions & 0 deletions packages/react-table/src/components/Table/TableTypes.tsx
Original file line number Diff line number Diff line change
@@ -166,6 +166,8 @@ export interface IAction extends Omit<DropdownItemProps, 'title' | 'onClick'>, P
onClick?: (event: React.MouseEvent, rowIndex: number, rowData: IRowData, extraData: IExtraData) => void;
/** Flag indicating this action should be placed outside the actions menu, beside the toggle */
isOutsideDropdown?: boolean;
/** Flag indicating whether the actions dropdown should close after an item is clicked. */
shouldCloseOnClick?: boolean;
}

export interface ISeparator extends IAction {

Unchanged files with check annotations Beta

const [scrollElement, setScrollElement] = React.useState(null);
const toggleVisible = () => {

Check warning on line 36 in packages/react-core/src/components/BackToTop/BackToTop.tsx

GitHub Actions / lint

The 'toggleVisible' function makes the dependencies of useEffect Hook (at line 74) change on every render. Move it inside the useEffect callback. Alternatively, wrap the definition of 'toggleVisible' in its own useCallback() Hook
if (scrollElement) {
const scrolled = scrollElement.scrollY ? scrollElement.scrollY : scrollElement.scrollTop;
if (!isAlwaysVisible) {
} else if (!dateProp) {
setFocusedDate(today);
}
}, [dateProp]);

Check warning on line 184 in packages/react-core/src/components/CalendarMonth/CalendarMonth.tsx

GitHub Actions / lint

React Hook useEffect has a missing dependency: 'focusedDate'. Either include it or remove the dependency array
useEffect(() => {
// Calendar month should not be focused on page load
if ((shouldFocus || isDateFocused) && focusedDateValidated && focusRef.current) {
focusRef.current.focus();
}
}, [focusedDate, isDateFocused, focusedDateValidated, focusRef]);

Check warning on line 191 in packages/react-core/src/components/CalendarMonth/CalendarMonth.tsx

GitHub Actions / lint

React Hook useEffect has a missing dependency: 'shouldFocus'. Either include it or remove the dependency array
const onMonthClick = (ev: React.MouseEvent, newDate: Date) => {
setFocusedDate(newDate);
test('Renders label before checkbox input if isLabelBeforeButton is provided', () => {
render(<Checkbox id="test-id" isLabelBeforeButton label={'test checkbox label'} />);
const wrapper = screen.getByRole('checkbox').parentElement!;

Check warning on line 269 in packages/react-core/src/components/Checkbox/__tests__/Checkbox.test.tsx

GitHub Actions / lint

Forbidden non-null assertion
expect(wrapper.children[0].tagName).toBe('LABEL');
expect(wrapper.children[1].tagName).toBe('INPUT');
const [selectOpen, setSelectOpen] = React.useState(false);
const [pristine, setPristine] = React.useState(true);
const [textInputFocused, setTextInputFocused] = React.useState(false);
const widthChars = React.useMemo(() => Math.max(dateFormat(new Date()).length, placeholder.length), [dateFormat]);

Check warning on line 134 in packages/react-core/src/components/DatePicker/DatePicker.tsx

GitHub Actions / lint

React Hook React.useMemo has a missing dependency: 'placeholder.length'. Either include it or remove the dependency array
const style = { [cssFormControlWidthChars.name]: widthChars, ...styleProps };
const buttonRef = React.useRef<HTMLButtonElement>();
const datePickerWrapperRef = React.useRef<HTMLDivElement>();
React.useEffect(() => {
setValue(valueProp);
setValueDate(dateParse(valueProp));
}, [valueProp]);

Check warning on line 145 in packages/react-core/src/components/DatePicker/DatePicker.tsx

GitHub Actions / lint

React Hook React.useEffect has a missing dependency: 'dateParse'. Either include it or remove the dependency array. If 'dateParse' changes too often, find the parent component that defines it and wrap that definition in useCallback
React.useEffect(() => {
setPristine(!value);
if (value === '' && !pristine && !textInputFocused) {
dateIsRequired ? setErrorText(emptyDateText) : setErrorText('');
}
}, [value]);

Check warning on line 156 in packages/react-core/src/components/DatePicker/DatePicker.tsx

GitHub Actions / lint

React Hook React.useEffect has missing dependencies: 'dateIsRequired', 'dateParse', 'emptyDateText', 'errorText', 'pristine', 'setError', and 'textInputFocused'. Either include them or remove the dependency array. If 'dateParse' changes too often, find the parent component that defines it and wrap that definition in useCallback
const setError = (date: Date) => {
setErrorText(validators.map((validator) => validator(date)).join('\n') || '');
},
isCalendarOpen: popoverOpen
}),
[setPopoverOpen, popoverOpen, selectOpen]

Check warning on line 222 in packages/react-core/src/components/DatePicker/DatePicker.tsx

GitHub Actions / lint

React Hook useImperativeHandle has an unnecessary dependency: 'selectOpen'. Either exclude it or remove the dependency array
);
const createFocusSelectorString = (modifierClass: string) =>
drawerRef.current.classList.remove(css(styles.modifiers.resizing));
isResizing = false;
onResize && onResize(e, currWidth, id);
setInitialVals = true;

Check warning on line 245 in packages/react-core/src/components/Drawer/DrawerPanelContent.tsx

GitHub Actions / lint

Assignments to the 'setInitialVals' variable from inside React Hook React.useCallback will be lost after each render. To preserve the value over time, store it in a useRef Hook and keep the mutable value in the '.current' property. Otherwise, you can move this variable directly inside React.useCallback
document.removeEventListener('mousemove', callbackMouseMove);
document.removeEventListener('mouseup', callbackMouseUp);
};
document.removeEventListener('touchend', callbackTouchEnd);
};
const callbackMouseMove = React.useCallback(handleMouseMove, []);

Check warning on line 261 in packages/react-core/src/components/Drawer/DrawerPanelContent.tsx

GitHub Actions / lint

React Hook React.useCallback has missing dependencies: 'handleControlMove' and 'position'. Either include them or remove the dependency array
const callbackTouchEnd = React.useCallback(handleTouchEnd, []);
const callbackTouchMove = React.useCallback(handleTouchMove, []);
const callbackMouseUp = React.useCallback(handleMouseup, []);