Skip to content

Commit

Permalink
[EuiFlyoutResizable] Add optional onResize callback (#7464)
Browse files Browse the repository at this point in the history
  • Loading branch information
cee-chen authored Jan 23, 2024
1 parent fdf0b7c commit a9d0873
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
1 change: 1 addition & 0 deletions changelogs/upcoming/7464.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Updated `EuiFlyoutResizable` with new optional `onResize` callback
30 changes: 30 additions & 0 deletions src/components/flyout/flyout_resizable.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,36 @@ describe('EuiFlyoutResizable', () => {
cy.get('.euiFlyout').should('have.css', 'inline-size', '400px');
};
});

it('calls the optional onResize callback on mouseup and keyboard events only', () => {
const onResize = cy.stub();
cy.mount(
<EuiFlyoutResizable onClose={onClose} size={800} onResize={onResize} />
);

cy.get('[data-test-subj="euiResizableButton"]')
.trigger('mousedown', { clientX: 400 })
.trigger('mousemove', { clientX: 600 })
.then(() => {
expect(onResize).not.have.been.called;
});
cy.get('[data-test-subj="euiResizableButton"]')
.trigger('mouseup')
.then(() => {
expect(onResize.callCount).to.eql(1);
expect(onResize).to.have.been.calledWith(600);
});

cy.get('[data-test-subj="euiResizableButton"]').focus();
cy.realPress('ArrowRight').then(() => {
expect(onResize.callCount).to.eql(2);
expect(onResize).to.have.been.calledWith(590);
});
cy.realPress('ArrowLeft').then(() => {
expect(onResize.callCount).to.eql(3);
expect(onResize.lastCall.args).to.eql([600]);
});
});
});

describe('push flyouts', () => {
Expand Down
19 changes: 19 additions & 0 deletions src/components/flyout/flyout_resizable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ import { euiFlyoutResizableButtonStyles } from './flyout_resizable.styles';
export type EuiFlyoutResizableProps = Omit<EuiFlyoutProps, 'maxWidth'> & {
maxWidth?: number;
minWidth?: number;
/**
* Optional callback that fires on user resize with the new flyout width
*/
onResize?: (width: number) => void;
};

export const EuiFlyoutResizable = forwardRef(
Expand All @@ -33,6 +37,7 @@ export const EuiFlyoutResizable = forwardRef(
size,
maxWidth,
minWidth = 200,
onResize,
side = 'right',
type = 'overlay',
children,
Expand All @@ -56,11 +61,13 @@ export const EuiFlyoutResizable = forwardRef(
);

const [flyoutWidth, setFlyoutWidth] = useState(0);
const [callOnResize, setCallOnResize] = useState(false);

// Must use state for the flyout ref in order for the useEffect to be correctly called after render
const [flyoutRef, setFlyoutRef] = useState<HTMLElement | null>(null);
const setRefs = useCombinedRefs([setFlyoutRef, ref]);
useEffect(() => {
setCallOnResize(false); // Don't call `onResize` for non-user width changes
setFlyoutWidth(
flyoutRef ? getFlyoutMinMaxWidth(flyoutRef.offsetWidth) : 0
);
Expand Down Expand Up @@ -92,6 +99,7 @@ export const EuiFlyoutResizable = forwardRef(
);

const onMouseUp = useCallback(() => {
setCallOnResize(true);
initialMouseX.current = 0;

window.removeEventListener('mousemove', onMouseMove);
Expand All @@ -102,6 +110,7 @@ export const EuiFlyoutResizable = forwardRef(

const onMouseDown = useCallback(
(e: React.MouseEvent | React.TouchEvent) => {
setCallOnResize(false);
initialMouseX.current = getPosition(e, true);
initialWidth.current = flyoutRef?.offsetWidth ?? 0;

Expand All @@ -117,6 +126,7 @@ export const EuiFlyoutResizable = forwardRef(

const onKeyDown = useCallback(
(e: React.KeyboardEvent) => {
setCallOnResize(true);
const KEYBOARD_OFFSET = 10;

switch (e.key) {
Expand All @@ -136,6 +146,15 @@ export const EuiFlyoutResizable = forwardRef(
[getFlyoutMinMaxWidth, direction]
);

// To reduce unnecessary calls, only fire onResize callback:
// 1. After initial mount / on user width change events only
// 2. If not currently mouse dragging
useEffect(() => {
if (callOnResize) {
onResize?.(flyoutWidth);
}
}, [onResize, callOnResize, flyoutWidth]);

return (
<EuiFlyout
{...rest}
Expand Down

0 comments on commit a9d0873

Please sign in to comment.