adding bookmarklet

This commit is contained in:
Benjamin Boudreau
2018-06-03 16:01:32 -04:00
parent 5a2184062e
commit 799221f411
11 changed files with 60 additions and 15 deletions

View File

@@ -0,0 +1,175 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Widget /> open/close 1`] = `
<Widget>
<div
className="docked-widget"
>
<Transition
appear={false}
enter={true}
exit={true}
in={false}
mountOnEnter={false}
onEnter={[Function]}
onEntered={[Function]}
onEntering={[Function]}
onExit={[Function]}
onExited={[Function]}
onExiting={[Function]}
timeout={250}
unmountOnExit={false}
>
<div
className="widget widget-exited"
>
<div
className="widget-header"
>
<div
className="widget-header-title"
>
Header
</div>
<a
className="widget-header-icon"
onClick={[Function]}
>
X
</a>
</div>
<div
className="widget-body"
>
Body
</div>
<div
className="widget-footer"
>
Footer
</div>
</div>
</Transition>
<a
className="dock"
onClick={[Function]}
>
^ OPEN ^
</a>
</div>
</Widget>
`;
exports[`<Widget /> open/close 2`] = `
<Widget>
<div
className="docked-widget"
>
<Transition
appear={false}
enter={true}
exit={true}
in={true}
mountOnEnter={false}
onEnter={[Function]}
onEntered={[Function]}
onEntering={[Function]}
onExit={[Function]}
onExited={[Function]}
onExiting={[Function]}
timeout={250}
unmountOnExit={false}
>
<div
className="widget widget-entering"
>
<div
className="widget-header"
>
<div
className="widget-header-title"
>
Header
</div>
<a
className="widget-header-icon"
onClick={[Function]}
>
X
</a>
</div>
<div
className="widget-body"
>
Body
</div>
<div
className="widget-footer"
>
Footer
</div>
</div>
</Transition>
</div>
</Widget>
`;
exports[`<Widget /> open/close 3`] = `
<Widget>
<div
className="docked-widget"
>
<Transition
appear={false}
enter={true}
exit={true}
in={false}
mountOnEnter={false}
onEnter={[Function]}
onEntered={[Function]}
onEntering={[Function]}
onExit={[Function]}
onExited={[Function]}
onExiting={[Function]}
timeout={250}
unmountOnExit={false}
>
<div
className="widget widget-exited"
>
<div
className="widget-header"
>
<div
className="widget-header-title"
>
Header
</div>
<a
className="widget-header-icon"
onClick={[Function]}
>
X
</a>
</div>
<div
className="widget-body"
>
Body
</div>
<div
className="widget-footer"
>
Footer
</div>
</div>
</Transition>
<a
className="dock"
onClick={[Function]}
>
^ OPEN ^
</a>
</div>
</Widget>
`;

75
src/components/widget.js Normal file
View File

@@ -0,0 +1,75 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Transition } from 'react-transition-group';
import './widget.scss';
class Widget extends Component {
state = {
opened: false,
showDock: true,
}
handleToggleOpen = () => {
this.setState((prev) => {
let { showDock } = prev;
if (!prev.opened) {
showDock = false;
}
return {
showDock,
opened: !prev.opened,
};
});
}
handleWidgetExit = () => {
this.setState({
showDock: true,
});
}
renderBody = () => {
if (this.state.showDock) {
return (
<a className="dock" onClick={this.handleToggleOpen}>
^ OPEN ^
</a>
);
}
return '';
}
render() {
const body = this.renderBody();
return (
<div className="docked-widget">
<Transition in={this.state.opened} timeout={250} onExited={this.handleWidgetExit}>
{status => (
<div className={`widget widget-${status}`}>
<div className="widget-header">
<div className="widget-header-title">
Header
</div>
<a className="widget-header-icon" onClick={this.handleToggleOpen}>
X
</a>
</div>
<div className="widget-body">
Body
</div>
<div className="widget-footer">
Footer
</div>
</div>
)}
</Transition>
{body}
</div>
);
}
}
Widget.propTypes = {};
export default Widget;

View File

@@ -0,0 +1,94 @@
@keyframes slideInUp {
from {
transform: translate3d(0, 100%, 0);
visibility: visible;
}
to {
transform: translate3d(0, 0, 0);
}
}
@keyframes slideOutDown {
from {
transform: translate3d(0, 0, 0);
}
to {
visibility: hidden;
transform: translate3d(0, 100%, 0);
}
}
.docked-widget {
position: fixed;
bottom: 0px;
right: 10px;
width: 200px;
}
.dock {
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
padding: 10px;
width: 180px;
border: 1px solid grey;
}
.widget {
width: 200px;
border: 1px solid grey;
border-bottom: none;
animation-duration: 0.2s;
animation-fill-mode: forwards;
&-entering {
animation-name: slideInUp;
}
&-entered {
visibility: visible;
}
&-exiting {
animation-name: slideOutDown;
}
&-exited {
visibility: hidden;
}
&-header {
height: 30px;
line-height: 30px;
background: lightgrey;
color: grey;
padding-left: 10px;
display: flex;
align-items: stretch;
&-title {
display: flex;
flex-grow: 1;
}
&-icon {
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
padding: .75rem;
}
}
&-body {
background: white;
padding: 10px;
height: 150px;
}
&-footer {
background: green;
line-height: 30px;
padding-left: 10px;
}
}

View File

@@ -0,0 +1,37 @@
import React from 'react';
import { mount } from 'enzyme';
import Widget from './widget';
import { waitForSelection } from '../test-helpers';
describe('<Widget />', () => {
test('open/close', async () => {
const widgetDom = mount(<Widget />);
expect(widgetDom).toMatchSnapshot();
{
const dockAnchorEl = widgetDom.find('a.dock');
expect(dockAnchorEl).toHaveLength(1);
// open widget
dockAnchorEl.simulate('click');
}
expect(widgetDom).toMatchSnapshot();
// dock does not exist anymore
expect(widgetDom.find('a.dock')).toHaveLength(0);
const closeAnchorEl = await waitForSelection(widgetDom, 'a.widget-header-icon');
expect(closeAnchorEl).toHaveLength(1);
// close widget
closeAnchorEl.simulate('click');
{
const dockAnchorEl = await waitForSelection(widgetDom, 'a.dock');
expect(dockAnchorEl).toHaveLength(1);
}
expect(widgetDom).toMatchSnapshot();
});
});