Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement "Toolbar" component (#37) #68

Merged
merged 16 commits into from
Nov 13, 2017
Original file line number Diff line number Diff line change
@@ -1,15 +0,0 @@
.oc-fm--context-menu-item {
padding: 8px 12px;
display: flex;
align-items: center;

&:hover {
cursor: pointer;
background-color: #f5f5f5;
}
}

.oc-fm--context-menu-item__icon {
margin-right: 12px;
fill: #333;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import './ContextMenuItem.less';
import { MenuItem } from "react-contextmenu";
import SVG from '@opuscapita/react-svg/lib/SVG';
import DropdownMenuItem from '../DropdownMenuItem';

const propTypes = {
icon: PropTypes.shape({
Expand All @@ -22,22 +22,13 @@ class ContextMenuItem extends Component {
}

render() {
let { icon, ...restProps } = this.props;

let iconElement = icon ? (
<SVG
className="oc-fm--context-menu-item__icon"
svg={icon.svg}
style={{ fill: icon.fill || '#333' }}
/>
): null;
let { icon, children, ...restProps } = this.props;

return (
<MenuItem {...restProps}>
<div className="oc-fm--context-menu-item">
{iconElement}
{this.props.children}
</div>
<DropdownMenuItem icon={icon} {...restProps}>
{children}
</DropdownMenuItem>
</MenuItem>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
### Synopsis

DropdownMenu is
*Write here a short introduction and/or overview that explains **what** component is.*

### Props Reference

| Name | Type | Description |
| ------------------------------ | :---------------------- | ----------------------------------------------------------- |
| demoProp | string | Write a description of the property |

### Code Example

```
<div style={{ position: 'relative' }}>
<DropdownMenu
show={_scope.state.show}
showToTop={true}
onHide={_scope.toggle}
>

<DropdownMenuItem
icon={{
svg: `<svg viewBox="0 0 120 120" version="1.1">
<circle cx="60" cy="60" r="50"/>
</svg>`,
fill: '#333'
}}
>
<span>Circle</span>
</DropdownMenuItem>

<DropdownMenuItem
icon={{
svg: `<svg viewBox="0 0 120 120" version="1.1">
<circle cx="60" cy="60" r="50"/>
</svg>`,
fill: '#333'
}}
>
<span>Circle</span>
</DropdownMenuItem>

<DropdownMenuItem
icon={{
svg: `<svg viewBox="0 0 120 120" version="1.1">
<circle cx="60" cy="60" r="50"/>
</svg>`,
fill: '#333'
}}
>
<span>Circle</span>
</DropdownMenuItem>

</DropdownMenu>
</div>
```

### Component Name

DropdownMenu

### License

Licensed by © 2017 OpusCapita

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
What is a SCOPE file. See documentation here:
https://github.com/OpusCapita/react-showroom-client/blob/master/docs/scope-component.md
*/

import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { showroomScopeDecorator } from '@opuscapita/react-showroom-client';
import DropdownMenuItem from '../DropdownMenuItem';

window.DropdownMenuItem = DropdownMenuItem;

@showroomScopeDecorator
export default
class DropdownMenuScope extends Component {
constructor(props) {
super(props);
this.state = {
show: false
};
}

toggle = () => {
this.setState({ show: !this.state.show });
}

render() {
return (
<div>
<button onClick={this.toggle}>Toggle context menu</button>
{this._renderChildren()}
</div>
);
}
}

DropdownMenuScope.contextTypes = {
i18n: PropTypes.object
};
DropdownMenuScope.childContextTypes = {
i18n: PropTypes.object
};
32 changes: 32 additions & 0 deletions client-react/src/client/components/DropdownMenu/DropdownMenu.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@keyframes keyframes-oc-fm--dropdown-menu-appearing {
0% { opacity: 0; }
100% { opacity: 1; }
}

@keyframes keyframes-oc-fm--dropdown-menu-appearing--to-top {
0% { opacity: 0; }
100% { opacity: 1; }
}

.oc-fm--dropdown-menu {
background: #fff;
z-index: 999;
box-shadow: 0 2px 16px rgba(0, 0, 0, 0.25), 0px 1px 4px rgba(0, 0, 0, 0.15);
border-radius: 2px;
overflow: hidden;
width: 240px;
position: absolute;
bottom: -4px;
left: 0;
transform: translate(0, 100%);

animation: keyframes-oc-fm--dropdown-menu-appearing 80ms;
animation-timing-function: ease-in-out;
}

.oc-fm--dropdown-menu--to-top {
top: -4px;
bottom: auto;
transform: translate(0, -100%);
animation: keyframes-oc-fm--dropdown-menu-appearing--to-top 80ms;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import PropTypes from 'prop-types';
import React, { Component, Children } from 'react';
import './DropdownMenu.less';
import clickOutside from 'react-click-outside';

const propTypes = {
show: PropTypes.bool,
showToTop: PropTypes.bool,
onHide: PropTypes.func
};
const defaultProps = {
show: false,
showToTop: false,
onHide: () => {}
};

@clickOutside
export default
class DropdownMenu extends Component {
constructor(props) {
super(props);
this.state = { };
this.handleKeyDown = this.handleKeyDown.bind(this);
}

componentDidMount() {
window.addEventListener('keydown', this.handleKeyDown);
}

componentWillUnmount() {
window.removeEventListener('keydown', this.handleKeyDown);
}

handleKeyDown = (e) => {
let shouldHide = (e.which === 27 || e.which === 9); // Hide on "Esc" or "Tab" key
if (this.props.show && shouldHide) {
this.props.onHide();
}
}

handleClickOutside = () => {
if (this.props.show) {
this.props.onHide();
}
}

render() {
let { show, showToTop, onHide, children } = this.props;

if (!show) {
return null;
}

return (
<div className={`oc-fm--dropdown-menu ${showToTop ? 'oc-fm--dropdown-menu--to-top' : ''}`}>
{Children.toArray(children).map(child => {
let childProps = {
...child.props,
onClick: (e) => {
if (child.onClick) {
child.onClick(e);
}
onHide();
}
};

return ({ ...child, props: childProps });
})}
</div>
);
}
}

DropdownMenu.propTypes = propTypes;
DropdownMenu.defaultProps = defaultProps;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import { expect } from 'chai';
import { shallow } from 'enzyme';
import DropdownMenu from '.';

describe('<DropdownMenu />', () => {
/* Recommended test-cases

it('should have default props', () => {
let component = <DropdownMenu />;
expect(component.props.testProp).to.equal('Give me back my label!');
expect(component.props.onClick).to.be.a('function');
});
it('should have the right class name', () => {
let wrapper = shallow(<DropdownMenu className="test-class-name" />);
expect(wrapper).to.have.className('dropdown-menu');
expect(wrapper).to.have.className('test-class-name');
});

*/
});
1 change: 1 addition & 0 deletions client-react/src/client/components/DropdownMenu/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default require('./DropdownMenu.react').default;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
### Synopsis

DropdownMenuItem is
*Write here a short introduction and/or overview that explains **what** component is.*

### Props Reference

| Name | Type | Description |
| ------------------------------ | :---------------------- | ----------------------------------------------------------- |
| demoProp | string | Write a description of the property |

### Code Example

```
<DropdownMenuItem
icon={{
svg: `<svg viewBox="0 0 120 120" version="1.1">
<circle cx="60" cy="60" r="50"/>
</svg>`,
fill: '#333'
}}
>
<span>Circle</span>
</DropdownMenuItem>
```

### Component Name

DropdownMenuItem

### License

Licensed by © 2017 OpusCapita

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
What is a SCOPE file. See documentation here:
https://github.com/OpusCapita/react-showroom-client/blob/master/docs/scope-component.md
*/

import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { showroomScopeDecorator } from '@opuscapita/react-showroom-client';

@showroomScopeDecorator
export default
class DropdownMenuItemScope extends Component {
constructor(props) {
super(props);
this.state = {};
}

render() {
return (
<div>
{this._renderChildren()}
</div>
);
}
}

DropdownMenuItemScope.contextTypes = {
i18n: PropTypes.object
};
DropdownMenuItemScope.childContextTypes = {
i18n: PropTypes.object
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.oc-fm--dropdown-menu-item {
}

.oc-fm--dropdown-menu-item {
padding: 8px 12px;
display: flex;
align-items: center;

&:hover {
cursor: pointer;
background-color: #f5f5f5;
}
}

.oc-fm--dropdown-menu-item__icon {
margin-right: 12px;
fill: #333;
}
Loading