Skip to content

Commit

Permalink
feat: move action panel to adslot-ui and rewrite to use it as a modal
Browse files Browse the repository at this point in the history
  • Loading branch information
pphminions committed Jun 20, 2019
1 parent df6714f commit b6fa880
Show file tree
Hide file tree
Showing 8 changed files with 360 additions and 0 deletions.
5 changes: 5 additions & 0 deletions docs/components/Layout/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import HoverDropdownMenuExample from '../../examples/HoverDropdownMenuExample';
import NavigationExample from '../../examples/NavigationExample';
import OverlayLoaderExample from '../../examples/OverlayLoaderExample';
import SearchExample from '../../examples/SearchExample';
import ActionPanelExample from '../../examples/ActionPanelExample';

import './styles.scss';
import '../../examples/styles.scss';
Expand Down Expand Up @@ -97,6 +98,7 @@ const componentsBySection = {
dialogue: ['popover', 'help-icon-popover', 'avatar'],
modals: ['confirm-modal'],
search: ['search', 'tag'],
panels: ['action-panel'],
grouping: [
'page-title',
'card',
Expand Down Expand Up @@ -225,6 +227,9 @@ class PageLayout extends React.Component {
<PageTitle title="Modals" />
<ConfirmModalExample />

<PageTitle title="Panels" />
<ActionPanelExample />

<PageTitle title="Search" />
<SearchExample />
<TagExample />
Expand Down
125 changes: 125 additions & 0 deletions docs/examples/ActionPanelExample.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import React from 'react';
import Example from '../components/Example';
import { Button, ActionPanel } from '../../src';
import SvgSymbol from 'alexandria/SvgSymbol';

class ActionPanelExample extends React.PureComponent {
constructor() {
super();
this.state = {
showActionPanel: false,
};
this.toggleActionPanel = this.toggleActionPanel.bind(this);
}

toggleActionPanel() {
this.setState({ showActionPanel: !this.state.showActionPanel });
}

render() {
return (
<React.Fragment>
<h4>Static markup</h4>
<div>
<ActionPanel
title="Action panel"
size="small"
onClose={this.toggleActionPanel}
children={
<span>
Australia hosts a rich biodiversity. Compared to other regions of the world, it has a unique wildlife.
Endemic animals roam freely in the wild. Some of them are Australia's cultural icons such as the
kangaroos, koalas, and emus.
</span>
}
/>
</div>
<div className="live-demo">
<h4>Demo</h4>
<Button onClick={this.toggleActionPanel}>Action Panel as a modal</Button>
{this.state.showActionPanel && (
<ActionPanel
title="Action Panel"
size="large"
onClose={this.toggleActionPanel}
actionButton={<Button>Action</Button>}
isModal
children={
<span>
Native mammals include the dingoes or wild dogs, numbats, quolls, and Tasmanian devils. Dingoes are
the largest carnivorous mammals that populate the wilds of mainland Australia. But the smaller numbats
and Tasmanian devils, which are house cat-like size can be seen only in wildlife parks. You can also
spot them in the wilds of Tasmania.
</span>
}
/>
)}
</div>
</React.Fragment>
);
}
}

const exampleProps = {
componentName: 'Action Panel',
designNotes: <p>Action panel can be used as a modal or a information display panel.</p>,
exampleCodeSnippet: `
<ActionPanel
title="This is an action panel"
size="small"
onClose={this.toggleActionPanel}
/>`,
propTypeSectionArray: [
{
propTypes: [
{
propType: 'title',
type: 'string',
},
{
propType: 'className',
type: 'string',
},
{
propType: 'size',
type: "oneOf: 'small', 'medium', 'large'",
defaultValue: 'large',
note: 'small - 500px, medium - 700px, large- 1000px',
},
{
propType: 'onClose',
type: 'func',
},
{
propType: 'children',
type: 'node',
},
{
propType: 'actionButton',
type: 'node',
defaultValue: 'null',
},
{
propType: 'isModal',
type: 'bool',
defaultValue: 'false',
},
{
propType: 'closeIcon',
type: 'node',
defaultValue: (
<pre>
<div className="close-icon" />
</pre>
),
},
],
},
],
};

export default () => (
<Example {...exampleProps}>
<ActionPanelExample />
</Example>
);
47 changes: 47 additions & 0 deletions src/components/adslot-ui/ActionPanel/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import Button from 'react-bootstrap/lib/Button';
import './styles.scss';

const ActionPanel = ({ title, className, size, onClose, children, actionButton, isModal, closeIcon }) => (
<div className={classNames('aui--action-panel-wrapper', { 'aui--action-panel-wrapper-backdrop': isModal })}>
<div className={classNames('aui--action-panel', className, `is-${size}`, { 'action-modal': isModal })}>
<div className={classNames('aui--action-panel-header', { 'has-actions': actionButton })}>
<span className="title">{title}</span>
<span className="actions">
<Button
onClick={onClose}
className={classNames('close-button', { 'close-svg-icon': !actionButton })}
dts="header-close-button"
>
{actionButton ? 'Cancel' : closeIcon}
</Button>
{actionButton}
</span>
</div>
<div className="aui--action-panel-body">{children}</div>
</div>
</div>
);

ActionPanel.propTypes = {
title: PropTypes.string.isRequired,
className: PropTypes.string,
// large is intended to be used in a modal
size: PropTypes.oneOf(['small', 'medium', 'large']),
onClose: PropTypes.func.isRequired,
children: PropTypes.node.isRequired,
actionButton: PropTypes.node,
closeIcon: PropTypes.node,
isModal: PropTypes.bool,
};

ActionPanel.defaultProps = {
size: 'large',
actionButton: null,
isModal: false,
closeIcon: <div className="close-icon" />,
};

export default ActionPanel;
38 changes: 38 additions & 0 deletions src/components/adslot-ui/ActionPanel/index.spec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import _ from 'lodash';
import React from 'react';
import { shallow } from 'enzyme';
import { ActionPanel } from 'adslot-ui';
import Button from 'react-bootstrap/lib/Button';

describe('ActionPanelComponent', () => {
const makeProps = override =>
_.merge(
{
title: 'Action Panel',
size: 'small',
onClose: _.noop,
children: <div>content</div>,
},
override
);

it('should render with defaults', () => {
const wrapper = shallow(<ActionPanel {...makeProps()} />);
const headerElement = wrapper.find('.aui--action-panel-header');
expect(headerElement).to.have.length(1);
expect(headerElement.find('.title').text()).to.equal('Action Panel');

const bodyElement = wrapper.find('.aui--action-panel-body');
expect(bodyElement).to.have.length(1);
});

it('should render as a modal', () => {
const wrapper = shallow(
<ActionPanel {...makeProps({ isModal: true, size: 'large', actionButton: <Button>Action</Button> })} />
);
expect(wrapper.prop('className')).to.equal('aui--action-panel-wrapper aui--action-panel-wrapper-backdrop');

const actionPanelElement = wrapper.find('.aui--action-panel');
expect(actionPanelElement.prop('className')).to.equal('aui--action-panel is-large action-modal');
});
});
140 changes: 140 additions & 0 deletions src/components/adslot-ui/ActionPanel/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
@import '~styles/border';
@import '~styles/color';
@import '~styles/font-size';
@import '~styles/variable';
@import '~styles/font-weight';
@import '~styles/icon';

.aui--action-panel {
min-width: 300px;
max-width: 900px;
min-height: 100px;
z-index: $zindex-popover;
border: $border-lighter;
border-radius: 2px;

&.action-modal {
position: fixed;
top: 30px;
background-color: $color-white ;
margin: 30px auto;
border: 0;
}

&.is-small {
width: 500px;
}

&.is-medium {
width: 700px;
}

&.is-large {
width: 1000px;
}

&-header {
height: 48px;
color: $color-gray-darkest;
padding: 12px;
border-bottom: $border-lighter;
display: flex;
justify-content: space-between;
align-items: center;

.title {
font-size: $font-size-header;
font-weight: $font-weight-bold;
}

svg {
fill: $color-gray-darker;
}

.close-svg-icon {
padding: 0;
width: 26px;
height: 26px;
}

.close-button.btn {
background-color: transparent;
color: $color-inverse;

> div {
display: inline-flex;
}
}

.close-icon {
width: 16px;
height: 16px;
background-repeat: no-repeat;
background-size: contain;
background-image: url('~styles/icons/close.svg');
}

.btn {
border: 0;
outline: 0;
margin: 0 0 0 6px;
box-shadow: none;
border-radius: 2px;
background-color: $color-white;
color: $color-blue;
display: inline-flex;
align-items: center;
justify-content: center;

&:focus:active,
&:hover:active {
background-color: transparent;
}
}

&.has-actions {
background-color: $color-blue;
color: $color-inverse;

.actions {
.btn {
&:hover {
color: $color-blue;
}

svg {
fill: $color-inverse;
}
}

.btn:hover {
background-color: $color-inverse;

svg {
fill: $color-blue;
}
}
}
}
}

&-body {
padding: 30px;
}

&-wrapper-backdrop {
position: fixed;
top: 0;
bottom: 0;
left: 0;
background-color: $color-gray-dark;
width: 100%;
z-index: 1040;
display: flex;
justify-content: center;
opacity: .9;
}
}



2 changes: 2 additions & 0 deletions src/components/adslot-ui/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import fastStatelessWrapper from 'adslot-ui/fastStatelessWrapper';
import InformationBox from 'adslot-ui/InformationBox';
import Nav from 'adslot-ui/Navigation';
import OverlayLoader from 'adslot-ui/OverlayLoader';
import ActionPanel from 'adslot-ui/ActionPanel';

export {
Accordion,
Expand Down Expand Up @@ -68,4 +69,5 @@ export {
InformationBox,
HoverDropdownMenu,
OverlayLoader,
ActionPanel,
};
Loading

0 comments on commit b6fa880

Please sign in to comment.