Skip to content

Commit a6e73df

Browse files
committed
feat(Add Application Launcher Component):
fix #184
1 parent 4a69ebd commit a6e73df

15 files changed

+737
-0
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import classNames from 'classnames';
4+
import ApplicationLauncherToggle from './ApplicationLauncherToggle';
5+
import { Dropdown } from '../Dropdown';
6+
7+
class ApplicationLauncher extends React.Component {
8+
constructor(props) {
9+
super(props);
10+
11+
this.state = {
12+
showLauncher: false,
13+
type: props.type
14+
};
15+
}
16+
17+
componentWillReceiveProps = nextProps => {
18+
this.setState({ type: nextProps.type });
19+
};
20+
21+
toggleLauncher = () => {
22+
this.setState({ showLauncher: !this.state.showLauncher });
23+
};
24+
25+
render() {
26+
const classes = classNames(
27+
{
28+
'applauncher-pf applauncher-pf-block-list dropdown dropdown-kebab-pf':
29+
this.state.type === 'grid'
30+
},
31+
{
32+
'applauncher-pf dropdown dropdown-kebab-pf': this.state.type === 'list'
33+
},
34+
{ open: this.state.showLauncher }
35+
);
36+
return (
37+
<li className={classes}>
38+
<ApplicationLauncherToggle
39+
tooltipPlacement={this.props.tooltipPlacement}
40+
onClick={this.toggleLauncher}
41+
/>
42+
<Dropdown.Menu className="dropdown-menu-right">
43+
{this.props.children}
44+
</Dropdown.Menu>
45+
</li>
46+
);
47+
}
48+
}
49+
ApplicationLauncher.propTypes = {
50+
/** Children Node */
51+
children: PropTypes.node.isRequired,
52+
/** tooltipPlacement */
53+
tooltipPlacement: PropTypes.string,
54+
/** Application Launcher Type */
55+
type: PropTypes.string.isRequired
56+
};
57+
ApplicationLauncher.defaultProps = {
58+
tooltipPlacement: 'left'
59+
};
60+
61+
export default ApplicationLauncher;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { storiesOf } from '@storybook/react';
2+
import { withKnobs } from '@storybook/addon-knobs';
3+
import {
4+
NavApplicationLauncherStory,
5+
WrapperNavApplicationLauncherStory
6+
} from './Stories/index';
7+
8+
const stories = storiesOf('ApplicationLauncher', module);
9+
stories.addDecorator(withKnobs);
10+
11+
NavApplicationLauncherStory(stories);
12+
WrapperNavApplicationLauncherStory(stories);
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import React from 'react';
2+
import { mount } from 'enzyme';
3+
import {
4+
ApplicationLauncher,
5+
ApplicationLauncherItem,
6+
ApplicationLauncherToggle
7+
} from './index';
8+
9+
const handleClick = e => {
10+
e.preventDefault();
11+
};
12+
13+
test('ApplicationLauncher is working properly', () => {
14+
const component = mount(
15+
<ApplicationLauncher type="grid" tooltipPlacement="left">
16+
<ApplicationLauncherItem
17+
icon="pficon pficon-storage-domain"
18+
title="Recteque"
19+
tooltip="Tooltip!"
20+
onClick={handleClick}
21+
/>
22+
</ApplicationLauncher>
23+
);
24+
25+
expect(component.render()).toMatchSnapshot();
26+
});
27+
28+
test('ApplicationLauncherItem is working properly', () => {
29+
const component = mount(
30+
<ApplicationLauncherItem
31+
icon="pficon pficon-storage-domain"
32+
title="Recteque"
33+
tooltip="Tooltip!"
34+
onClick={handleClick}
35+
/>
36+
);
37+
38+
expect(component.render()).toMatchSnapshot();
39+
});
40+
41+
test('ApplicationLauncherToggle is working properly', () => {
42+
const component = mount(
43+
<ApplicationLauncherToggle tooltipPlacement="left" onClick={handleClick} />
44+
);
45+
46+
expect(component.render()).toMatchSnapshot();
47+
});
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import classNames from 'classnames';
2+
import React from 'react';
3+
import PropTypes from 'prop-types';
4+
import { Tooltip } from '../Tooltip';
5+
import { OverlayTrigger } from '../OverlayTrigger';
6+
import { Icon } from '../Icon';
7+
8+
const ApplicationLauncherItem = ({
9+
onClick,
10+
tooltip,
11+
title,
12+
icon,
13+
noIcons,
14+
className,
15+
...props
16+
}) => {
17+
const classes = classNames('applauncher-pf-item', className);
18+
19+
return (
20+
<OverlayTrigger
21+
overlay={<Tooltip id="tooltip">{tooltip}</Tooltip>}
22+
placement="left"
23+
trigger={['hover', 'focus']}
24+
rootClose={false}
25+
>
26+
<li className={classes} role="menuitem">
27+
<a className="applauncher-pf-link" href="#" onClick={e => onClick(e)}>
28+
{!noIcons && (
29+
<Icon name={icon} className="applauncher-pf-link-icon" />
30+
)}
31+
<span className="applauncher-pf-link-title">{title}</span>
32+
</a>
33+
</li>
34+
</OverlayTrigger>
35+
);
36+
};
37+
ApplicationLauncherItem.propTypes = {
38+
/** Additional element css classes */
39+
className: PropTypes.string,
40+
/** onClick func */
41+
onClick: PropTypes.func,
42+
/** Title String */
43+
title: PropTypes.string.isRequired,
44+
/** Icon Type */
45+
icon: PropTypes.string.isRequired,
46+
/** App Tooltip */
47+
tooltip: PropTypes.string.isRequired,
48+
/** No Icons Bool */
49+
noIcons: PropTypes.bool
50+
};
51+
ApplicationLauncherItem.defaultProps = {
52+
className: '',
53+
onClick: null,
54+
noIcons: false
55+
};
56+
export default ApplicationLauncherItem;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import { OverlayTrigger } from '../OverlayTrigger';
4+
import { Tooltip } from '../Tooltip';
5+
import { Icon } from '../Icon';
6+
import { Button } from '../Button';
7+
8+
const ApplicationLauncherToggle = ({ onClick, tooltipPlacement }) => {
9+
const tooltip = <Tooltip id="tooltip">Application Launcher</Tooltip>;
10+
11+
return (
12+
<OverlayTrigger
13+
placement={tooltipPlacement}
14+
id="applauncher-pf-block-list"
15+
overlay={tooltip}
16+
>
17+
<Button onClick={onClick} bsStyle="link" className="nav-item-iconic">
18+
<Icon
19+
className="fa fa-th applauncher-pf-icon"
20+
aria-describedby="tooltip"
21+
name=""
22+
/>
23+
</Button>
24+
</OverlayTrigger>
25+
);
26+
};
27+
ApplicationLauncherToggle.propTypes = {
28+
/** onClick func */
29+
onClick: PropTypes.func,
30+
/** tooltipPlacement */
31+
tooltipPlacement: PropTypes.string
32+
};
33+
ApplicationLauncherToggle.defaultProps = {
34+
onClick: null,
35+
tooltipPlacement: 'bottom'
36+
};
37+
38+
export default ApplicationLauncherToggle;
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import React from 'react';
2+
import { action } from '@storybook/addon-actions';
3+
import { boolean, select } from '@storybook/addon-knobs';
4+
import { inlineTemplate } from '../../../../storybook/decorators/storyTemplates';
5+
import { DOCUMENTATION_URL } from '../../../../storybook/constants';
6+
import ApplicationLauncher from '../ApplicationLauncher';
7+
import ApplicationLauncherItem from '../ApplicationLauncherItem';
8+
9+
const handleClick = e => {
10+
e.preventDefault();
11+
action('app clicked!')();
12+
};
13+
14+
const NavApplicationLauncherStory = stories => {
15+
stories.addWithInfo('Application Launcher', '', () => {
16+
const type = select(
17+
'Launcher Type',
18+
{ grid: 'Grid', list: 'List' },
19+
'grid'
20+
);
21+
22+
const iconBool = boolean('Icons', true);
23+
24+
const story = (
25+
<nav className="navbar navbar-pf-vertical">
26+
<nav className="collapse navbar-collapse">
27+
<ul className="nav navbar-nav navbar-right navbar-iconic">
28+
<ApplicationLauncher type={type} tooltipPlacement="left">
29+
<ApplicationLauncherItem
30+
icon="pficon pficon-storage-domain"
31+
title="Recteque"
32+
tooltip="Tooltip!"
33+
onClick={handleClick}
34+
noIcons={!iconBool}
35+
/>
36+
<ApplicationLauncherItem
37+
icon="pficon pficon-virtual-machine"
38+
title="Ipsum"
39+
tooltip="Tooltip!"
40+
onClick={handleClick}
41+
noIcons={!iconBool}
42+
/>
43+
<ApplicationLauncherItem
44+
icon="pficon pficon-domain"
45+
title="Lorem"
46+
tooltip="Tooltip!"
47+
onClick={handleClick}
48+
noIcons={!iconBool}
49+
/>
50+
<ApplicationLauncherItem
51+
icon="pficon pficon-home"
52+
title="Home"
53+
tooltip="Tooltip!"
54+
onClick={handleClick}
55+
noIcons={!iconBool}
56+
/>
57+
</ApplicationLauncher>
58+
</ul>
59+
</nav>
60+
</nav>
61+
);
62+
return inlineTemplate({
63+
title: 'ApplicationLauncher',
64+
documentationLink: `${
65+
DOCUMENTATION_URL.PATTERNFLY_ORG_APPLICATION_FRAMEWORK
66+
}launcher/`,
67+
story
68+
});
69+
});
70+
};
71+
72+
export default NavApplicationLauncherStory;
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import React from 'react';
2+
import { action } from '@storybook/addon-actions';
3+
import { boolean, select } from '@storybook/addon-knobs';
4+
import { inlineTemplate } from '../../../../storybook/decorators/storyTemplates';
5+
import { DOCUMENTATION_URL } from '../../../../storybook/constants';
6+
import ApplicationLauncherWrapper from '../Wrappers/ApplicationLauncherWrapper';
7+
8+
const handleClick = e => {
9+
e.preventDefault();
10+
action('app clicked!')();
11+
};
12+
13+
const Apps = [
14+
{
15+
title: 'Ipsum',
16+
icon: 'pficon pficon-home',
17+
tooltip: 'Tooltip!',
18+
onClick: e => {
19+
handleClick(e);
20+
}
21+
},
22+
{
23+
title: 'Royal',
24+
icon: 'pficon pficon-virtual-machine',
25+
tooltip: 'Tooltip!',
26+
onClick: e => {
27+
handleClick(e);
28+
}
29+
},
30+
{
31+
title: 'Lemon',
32+
icon: 'pficon pficon-storage-domain',
33+
tooltip: 'Tooltip!',
34+
onClick: e => {
35+
handleClick(e);
36+
}
37+
},
38+
{
39+
title: 'Domain',
40+
icon: 'pficon pficon-domain',
41+
tooltip: 'Tooltip!',
42+
onClick: e => {
43+
handleClick(e);
44+
}
45+
}
46+
];
47+
48+
const WrapperNavApplicationLauncherStory = stories => {
49+
stories.addWithInfo('Wrapper Application Launcher', '', () => {
50+
const type = select(
51+
'Launcher Type',
52+
{ grid: 'Grid', list: 'List' },
53+
'grid'
54+
);
55+
56+
const iconBool = boolean('Icons', true);
57+
58+
const story = (
59+
<nav className="navbar navbar-pf-vertical">
60+
<nav className="collapse navbar-collapse">
61+
<ul className="nav navbar-nav navbar-right navbar-iconic">
62+
<ApplicationLauncherWrapper
63+
apps={Apps}
64+
noIcons={!iconBool}
65+
type={type}
66+
/>
67+
</ul>
68+
</nav>
69+
</nav>
70+
);
71+
return inlineTemplate({
72+
title: 'WrapperApplicationLauncher',
73+
documentationLink: `${
74+
DOCUMENTATION_URL.PATTERNFLY_ORG_APPLICATION_FRAMEWORK
75+
}launcher/`,
76+
story
77+
});
78+
});
79+
};
80+
81+
export default WrapperNavApplicationLauncherStory;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export {
2+
default as NavApplicationLauncherStory
3+
} from './NavApplicationLauncherStory';
4+
export {
5+
default as WrapperNavApplicationLauncherStory
6+
} from './WrapperNavApplicationLauncherStory';

0 commit comments

Comments
 (0)