Skip to content

Commit

Permalink
[EuiFlyoutResizable] Allow consumers to update the size prop (#7759)
Browse files Browse the repository at this point in the history
  • Loading branch information
cee-chen authored May 15, 2024
1 parent f31b897 commit 159fd9c
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 6 deletions.
1 change: 1 addition & 0 deletions packages/eui/changelogs/upcoming/7759.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- `EuiFlyoutResizable` now respects `size` prop updates, allowing for controlled `size` usage
61 changes: 60 additions & 1 deletion packages/eui/src/components/flyout/flyout_resizable.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
/// <reference types="cypress-real-events" />
/// <reference types="../../../cypress/support" />

import React from 'react';
import React, { useState, useCallback } from 'react';

import { EuiFlyoutResizable } from './flyout_resizable';

Expand Down Expand Up @@ -196,6 +196,65 @@ describe('EuiFlyoutResizable', () => {
expect(onResize.lastCall.args).to.eql([600]);
});
});

it('responds to `size` prop updates after user resize', () => {
let onResizeCalls = 0;
const TestComponent = () => {
const [size, setSize] = useState<string | number>(400);
const onResize = useCallback((width: number) => {
setSize(width);
onResizeCalls++;
}, []);

return (
<EuiFlyoutResizable onClose={onClose} size={size} onResize={onResize}>
<button data-test-subj="resetSize" onClick={() => setSize(400)}>
Reset flyout size
</button>
<button data-test-subj="setSize" onClick={() => setSize('200px')}>
Change flyout size
</button>
<button data-test-subj="setSizeKey" onClick={() => setSize('s')}>
Change flyout size to a size key
</button>
</EuiFlyoutResizable>
);
};
cy.mount(<TestComponent />);
cy.get('.euiFlyout').should('have.css', 'inline-size', '400px');

// User resizing
cy.get('[data-test-subj="euiResizableButton"]').focus();
cy.realPress('ArrowLeft').then(() => {
onResizeCalls = 0; // Reset resize calls. Cypress is flaky here so we shouldn't directly assert on the number of calls
});
cy.get('.euiFlyout').should('have.css', 'inline-size', '410px');

// Consumer resizing
cy.wait(100); // Wait a tick for flyout to finish rerendering
cy.get('[data-test-subj="resetSize"]').realClick();
cy.get('.euiFlyout')
.should('have.css', 'inline-size', '400px')
.then(() => {
expect(onResizeCalls).to.eql(0);
});

cy.wait(100); // Wait a tick for flyout to finish rerendering
cy.get('[data-test-subj="setSize"]').realClick();
cy.get('.euiFlyout')
.should('have.css', 'inline-size', '200px')
.then(() => {
expect(onResizeCalls).to.eql(0);
});

cy.wait(100); // Wait a tick for flyout to finish rerendering
cy.get('[data-test-subj="setSizeKey"]').realClick();
cy.get('.euiFlyout')
.should('have.css', 'inline-size', '384px')
.then(() => {
expect(onResizeCalls).to.eql(0);
});
});
});

describe('push flyouts', () => {
Expand Down
18 changes: 13 additions & 5 deletions packages/eui/src/components/flyout/flyout_resizable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,20 @@ export const EuiFlyoutResizable = forwardRef(
// 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(() => {
if (!flyoutWidth && flyoutRef) {
setCallOnResize(false); // Don't call `onResize` for non-user width changes
setFlyoutWidth(getFlyoutMinMaxWidth(flyoutRef.offsetWidth));
}
}, [flyoutWidth, flyoutRef, getFlyoutMinMaxWidth]);

// Update flyout width when consumers pass in a new `size`
useEffect(() => {
setCallOnResize(false); // Don't call `onResize` for non-user width changes
setFlyoutWidth(
flyoutRef ? getFlyoutMinMaxWidth(flyoutRef.offsetWidth) : 0
);
}, [flyoutRef, getFlyoutMinMaxWidth, size]);
setCallOnResize(false);
// For string `size`s, resetting flyoutWidth to 0 will trigger the above useEffect's recalculation
setFlyoutWidth(typeof size === 'number' ? getFlyoutMinMaxWidth(size) : 0);
}, [size, getFlyoutMinMaxWidth]);

// Initial numbers to calculate from, on resize drag start
const initialWidth = useRef(0);
Expand Down

0 comments on commit 159fd9c

Please sign in to comment.