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'); ...@@ -17,7 +17,7 @@ const SvgIcon = require('./svg-icon');
* as providing a close button. Only one sidebar panel (as defined by the panel's * as providing a close button. Only one sidebar panel (as defined by the panel's
* `panelName`) is active at one time. * `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 panelIsActive = useStore(store => store.isSidebarPanelOpen(panelName));
const togglePanelFn = useStore(store => store.toggleSidebarPanel); const togglePanelFn = useStore(store => store.toggleSidebarPanel);
...@@ -31,8 +31,11 @@ function SidebarPanel({ children, panelName, title }) { ...@@ -31,8 +31,11 @@ function SidebarPanel({ children, panelName, title }) {
if (panelIsActive) { if (panelIsActive) {
scrollIntoView(panelElement.current); scrollIntoView(panelElement.current);
} }
if (typeof onActiveChanged === 'function') {
onActiveChanged(panelIsActive);
}
} }
}, [panelIsActive]); }, [panelIsActive, onActiveChanged]);
const closePanel = () => { const closePanel = () => {
togglePanelFn(panelName, false); togglePanelFn(panelName, false);
...@@ -75,6 +78,9 @@ SidebarPanel.propTypes = { ...@@ -75,6 +78,9 @@ SidebarPanel.propTypes = {
/** The panel's title: rendered in its containing visual "frame" */ /** The panel's title: rendered in its containing visual "frame" */
title: propTypes.string.isRequired, title: propTypes.string.isRequired,
/** Optional callback to invoke when this panel's active status changes */
onActiveChanged: propTypes.func,
}; };
module.exports = SidebarPanel; module.exports = SidebarPanel;
...@@ -62,27 +62,55 @@ describe('SidebarPanel', () => { ...@@ -62,27 +62,55 @@ describe('SidebarPanel', () => {
assert.isFalse(wrapper.find('Slider').prop('visible')); assert.isFalse(wrapper.find('Slider').prop('visible'));
}); });
it('scrolls panel into view when opened', () => { context('when panel state changes', () => {
fakeStore.isSidebarPanelOpen.returns(false); // Establish a component with an initial state and then change
// Initial render will establish in state that the panel is not active // that state
const wrapper = createSidebarPanel(); const wrapperWithInitialState = (initialState, props = {}) => {
// Now, make it so the panel will have an active state fakeStore.isSidebarPanelOpen.returns(initialState);
fakeStore.isSidebarPanelOpen.returns(true); const wrapper = createSidebarPanel(props);
fakeStore.isSidebarPanelOpen.returns(!initialState);
return wrapper;
};
// Trick to make things re-render now with updated state it('scrolls panel into view when opened after being closed', () => {
wrapper.setProps({}); const wrapper = wrapperWithInitialState(false, {});
// force re-render
wrapper.setProps({});
assert.calledOnce(fakeScrollIntoView); assert.calledOnce(fakeScrollIntoView);
}); });
it('does not scroll panel if already opened', () => { it('fires `onActiveChanged` callback if provided when opened', () => {
fakeStore.isSidebarPanelOpen.returns(true); const fakeCallback = sinon.stub();
// Initial render will establish in state that the panel is already active const wrapper = wrapperWithInitialState(false, {
const wrapper = createSidebarPanel(); onActiveChanged: fakeCallback,
});
// force re-render
wrapper.setProps({});
assert.calledWith(fakeCallback, true);
});
// Re-rendering should not cause `scrollIntoView` to be invoked it('fires `onActiveChanged` callback if provided when closed', () => {
wrapper.setProps({}); 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