Commit 96425a93 authored by Lyza Danger Gardner's avatar Lyza Danger Gardner Committed by Lyza Gardner

Update `SidebarPanel` to use `Panel` component

parent 93234f34
import { SvgIcon } from '@hypothesis/frontend-shared'; import { useCallback, useEffect, useRef } from 'preact/hooks';
import { useEffect, useRef } from 'preact/hooks';
import scrollIntoView from 'scroll-into-view'; import scrollIntoView from 'scroll-into-view';
import { useStoreProxy } from '../store/use-store'; import { useStoreProxy } from '../store/use-store';
import Button from './Button'; import Panel from './Panel';
import Slider from './Slider'; import Slider from './Slider';
/** /**
...@@ -13,22 +12,19 @@ import Slider from './Slider'; ...@@ -13,22 +12,19 @@ import Slider from './Slider';
/** /**
* @typedef SidebarPanelProps * @typedef SidebarPanelProps
* @prop {Object} [children] * @prop {import("preact").ComponentChildren} children
* @prop {string} [icon] - An optional icon name for display next to the panel's title * @prop {string} [icon] - An optional icon name for display next to the panel's title
* @prop {PanelName} panelName - * @prop {PanelName} panelName -
* A string identifying this panel. Only one `panelName` may be active at any time. * A string identifying this panel. Only one `panelName` may be active at any time.
* Multiple panels with the same `panelName` would be "in sync", opening and closing together. * Multiple panels with the same `panelName` would be "in sync", opening and closing together.
* @prop {string} title - The panel's title: rendered in its containing visual "frame" * @prop {string} title - The panel's title
* @prop {(active: boolean) => any} [onActiveChanged] - * @prop {(active: boolean) => any} [onActiveChanged] -
* Optional callback to invoke when this panel's active status changes * Optional callback to invoke when this panel's active status changes
*/ */
/** /**
* Base component for a sidebar panel. * Base component for a sidebar panel. Only one sidebar panel
* * (as defined by the panel's `panelName`) is active (visible) at one time.
* This component provides a basic visual container for sidebar panels, as well
* as providing a close button. Only one sidebar panel (as defined by the panel's
* `panelName`) is active at one time.
* *
* @param {SidebarPanelProps} props * @param {SidebarPanelProps} props
*/ */
...@@ -58,25 +54,16 @@ export default function SidebarPanel({ ...@@ -58,25 +54,16 @@ export default function SidebarPanel({
} }
}, [panelIsActive, onActiveChanged]); }, [panelIsActive, onActiveChanged]);
const closePanel = () => { const closePanel = useCallback(() => {
store.toggleSidebarPanel(panelName, false); store.toggleSidebarPanel(panelName, false);
}; }, [store, panelName]);
return ( return (
<Slider visible={panelIsActive}> <Slider visible={panelIsActive}>
<div className="SidebarPanel" ref={panelElement}> <div ref={panelElement}>
<div className="SidebarPanel__header"> <Panel title={title} icon={icon} onClose={closePanel}>
{icon && ( {children}
<div className="SidebarPanel__header-icon"> </Panel>
<SvgIcon name={icon} title={title} />
</div>
)}
<h2 className="SidebarPanel__title u-stretch">{title}</h2>
<div>
<Button icon="cancel" buttonText="Close" onClick={closePanel} />
</div>
</div>
<div className="SidebarPanel__content">{children}</div>
</div> </div>
</Slider> </Slider>
); );
......
...@@ -37,24 +37,22 @@ describe('SidebarPanel', () => { ...@@ -37,24 +37,22 @@ describe('SidebarPanel', () => {
$imports.$restore(); $imports.$restore();
}); });
it('renders the provided title', () => { it('renders a panel with provided title and icon', () => {
const wrapper = createSidebarPanel({ title: 'My Panel' }); const wrapper = createSidebarPanel({
const titleEl = wrapper.find('.SidebarPanel__title'); title: 'My Panel',
assert.equal(titleEl.text(), 'My Panel'); icon: 'restricted',
}); });
it('renders an icon if provided', () => { const panel = wrapper.find('Panel');
const wrapper = createSidebarPanel({ icon: 'restricted' });
const icon = wrapper.find('SvgIcon').filter({ name: 'restricted' }); assert.equal(panel.props().icon, 'restricted');
assert.equal(panel.props().title, 'My Panel');
assert.isTrue(icon.exists());
}); });
it('closes the panel when close button is clicked', () => { it('provides an `onClose` handler that closes the panel', () => {
const wrapper = createSidebarPanel({ panelName: 'flibberty' }); const wrapper = createSidebarPanel({ panelName: 'flibberty' });
wrapper.find('Button').props().onClick(); wrapper.find('Panel').props().onClose();
assert.calledWith(fakeStore.toggleSidebarPanel, 'flibberty', false); assert.calledWith(fakeStore.toggleSidebarPanel, 'flibberty', false);
}); });
......
@use "../../mixins/molecules";
.SidebarPanel {
@include molecules.panel;
position: relative;
margin-bottom: 0.75em;
}
...@@ -48,7 +48,6 @@ ...@@ -48,7 +48,6 @@
@use './components/SearchInput'; @use './components/SearchInput';
@use './components/ShareLinks'; @use './components/ShareLinks';
@use './components/SidebarContentError'; @use './components/SidebarContentError';
@use './components/SidebarPanel';
@use './components/Spinner'; @use './components/Spinner';
@use './components/TagEditor'; @use './components/TagEditor';
@use './components/TagList'; @use './components/TagList';
......
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