Unverified Commit b0cd5378 authored by Lyza Gardner's avatar Lyza Gardner Committed by GitHub

Merge pull request #1473 from hypothesis/add-sidebar-panel-callback-support

Help & Tutorial 4/n: Add support for status-change callback to `SidebarPanel`
parents e9def31d 80a7a423
......@@ -17,7 +17,7 @@ const SvgIcon = require('./svg-icon');
* as providing a close button. Only one sidebar panel (as defined by the panel's
* `panelName`) is active at one time.
*/
function SidebarPanel({ children, panelName, title }) {
function SidebarPanel({ children, panelName, title, onActiveChanged }) {
const panelIsActive = useStore(store => store.isSidebarPanelOpen(panelName));
const togglePanelFn = useStore(store => store.toggleSidebarPanel);
......@@ -31,8 +31,11 @@ function SidebarPanel({ children, panelName, title }) {
if (panelIsActive) {
scrollIntoView(panelElement.current);
}
if (typeof onActiveChanged === 'function') {
onActiveChanged(panelIsActive);
}
}
}, [panelIsActive]);
}, [panelIsActive, onActiveChanged]);
const closePanel = () => {
togglePanelFn(panelName, false);
......@@ -75,6 +78,9 @@ SidebarPanel.propTypes = {
/** The panel's title: rendered in its containing visual "frame" */
title: propTypes.string.isRequired,
/** Optional callback to invoke when this panel's active status changes */
onActiveChanged: propTypes.func,
};
module.exports = SidebarPanel;
......@@ -62,27 +62,55 @@ describe('SidebarPanel', () => {
assert.isFalse(wrapper.find('Slider').prop('visible'));
});
it('scrolls panel into view when opened', () => {
fakeStore.isSidebarPanelOpen.returns(false);
// Initial render will establish in state that the panel is not active
const wrapper = createSidebarPanel();
// Now, make it so the panel will have an active state
fakeStore.isSidebarPanelOpen.returns(true);
context('when panel state changes', () => {
// Establish a component with an initial state and then change
// that state
const wrapperWithInitialState = (initialState, props = {}) => {
fakeStore.isSidebarPanelOpen.returns(initialState);
const wrapper = createSidebarPanel(props);
fakeStore.isSidebarPanelOpen.returns(!initialState);
return wrapper;
};
// Trick to make things re-render now with updated state
wrapper.setProps({});
it('scrolls panel into view when opened after being closed', () => {
const wrapper = wrapperWithInitialState(false, {});
// force re-render
wrapper.setProps({});
assert.calledOnce(fakeScrollIntoView);
});
assert.calledOnce(fakeScrollIntoView);
});
it('does not scroll panel if already opened', () => {
fakeStore.isSidebarPanelOpen.returns(true);
// Initial render will establish in state that the panel is already active
const wrapper = createSidebarPanel();
it('fires `onActiveChanged` callback if provided when opened', () => {
const fakeCallback = sinon.stub();
const wrapper = wrapperWithInitialState(false, {
onActiveChanged: fakeCallback,
});
// force re-render
wrapper.setProps({});
assert.calledWith(fakeCallback, true);
});
// Re-rendering should not cause `scrollIntoView` to be invoked
wrapper.setProps({});
it('fires `onActiveChanged` callback if provided when closed', () => {
const fakeCallback = sinon.stub();
const wrapper = wrapperWithInitialState(true, {
onActiveChanged: fakeCallback,
});
// force re-render
wrapper.setProps({});
assert.isFalse(fakeScrollIntoView.called);
assert.calledWith(fakeCallback, false);
});
it('does not scroll panel if already opened', () => {
// First render: panel is active
fakeStore.isSidebarPanelOpen.returns(true);
const wrapper = createSidebarPanel();
// Re-rendering should not cause `scrollIntoView` to be invoked
// As the panel is already open
wrapper.setProps({});
assert.isFalse(fakeScrollIntoView.called);
});
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment