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

[EuiFlyoutResizable] Allow consumers to update the size prop #7759

Merged
merged 2 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
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
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);
Copy link
Contributor

Choose a reason for hiding this comment

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

🧠

}, [size, getFlyoutMinMaxWidth]);

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