Skip to content

Commit 0c2a6a7

Browse files
Gilad Leknerglekner
Gilad Lekner
authored andcommitted
feat(ApplicationLauncher): application Launcher Component
affects: patternfly-react fix #184 ISSUES CLOSED: #184
1 parent d51c760 commit 0c2a6a7

16 files changed

+1003
-1
lines changed

packages/core/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"react-bootstrap": "^0.32.1",
3333
"react-bootstrap-switch": "^15.5.3",
3434
"react-c3js": "^0.1.20",
35+
"react-click-outside": "^3.0.1",
3536
"react-fontawesome": "^1.6.1",
3637
"reactabular-table": "^8.12.1",
3738
"recompose": "^0.26.0"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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+
import { noop } from '../../common/helpers';
7+
8+
const ApplicationLauncher = ({
9+
open,
10+
grid,
11+
tooltip,
12+
tooltipPlacement,
13+
children,
14+
toggleLauncher,
15+
className,
16+
...propTypes
17+
}) => {
18+
const classes = classNames(
19+
'applauncher-pf dropdown',
20+
{
21+
'applauncher-pf-block-list': grid
22+
},
23+
{ open }
24+
);
25+
return (
26+
<li className={classes}>
27+
<ApplicationLauncherToggle
28+
tooltip={tooltip}
29+
tooltipPlacement={tooltipPlacement}
30+
onClick={() => toggleLauncher()}
31+
/>
32+
<Dropdown.Menu className="dropdown-menu-right">{children}</Dropdown.Menu>
33+
</li>
34+
);
35+
};
36+
37+
ApplicationLauncher.propTypes = {
38+
/** Additional element css classes */
39+
className: PropTypes.string,
40+
/** Children Node */
41+
children: PropTypes.node.isRequired,
42+
/** Toggle Tooltip */
43+
tooltip: PropTypes.string,
44+
/** tooltipPlacement */
45+
tooltipPlacement: PropTypes.string,
46+
/** Application Launcher Type (Default List) */
47+
grid: PropTypes.bool,
48+
/** open bool */
49+
open: PropTypes.bool,
50+
/** Toggle launcher func */
51+
toggleLauncher: PropTypes.func
52+
};
53+
ApplicationLauncher.defaultProps = {
54+
className: '',
55+
tooltip: '',
56+
tooltipPlacement: 'left',
57+
toggleLauncher: noop,
58+
grid: false,
59+
open: false
60+
};
61+
62+
export default ApplicationLauncher;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { storiesOf } from '@storybook/react';
2+
import { withKnobs } from '@storybook/addon-knobs';
3+
import {
4+
NavApplicationLauncherStory,
5+
WrapperNavApplicationLauncherStory
6+
} from './Stories/index';
7+
import { name } from '../../../package.json';
8+
9+
const stories = storiesOf(`${name}/ApplicationLauncher`, module);
10+
stories.addDecorator(withKnobs);
11+
12+
NavApplicationLauncherStory(stories);
13+
WrapperNavApplicationLauncherStory(stories);
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+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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+
tooltipPlacement,
12+
title,
13+
icon,
14+
noIcons,
15+
className,
16+
...props
17+
}) => {
18+
const classes = classNames('applauncher-pf-item', className);
19+
20+
if (tooltip !== null) {
21+
return (
22+
<OverlayTrigger
23+
overlay={<Tooltip id="tooltip">{tooltip}</Tooltip>}
24+
placement={tooltipPlacement}
25+
trigger={['hover', 'focus']}
26+
rootClose={false}
27+
>
28+
<li className={classes} role="menuitem">
29+
<a className="applauncher-pf-link" href="#" onClick={e => onClick(e)}>
30+
{!noIcons && (
31+
<Icon
32+
type="pf"
33+
name={icon}
34+
className="applauncher-pf-link-icon"
35+
/>
36+
)}
37+
<span className="applauncher-pf-link-title">{title}</span>
38+
</a>
39+
</li>
40+
</OverlayTrigger>
41+
);
42+
}
43+
return (
44+
<li className={classes} role="menuitem">
45+
<a className="applauncher-pf-link" href="#" onClick={e => onClick(e)}>
46+
{!noIcons && (
47+
<Icon type="pf" name={icon} className="applauncher-pf-link-icon" />
48+
)}
49+
<span className="applauncher-pf-link-title">{title}</span>
50+
</a>
51+
</li>
52+
);
53+
};
54+
ApplicationLauncherItem.propTypes = {
55+
/** Additional element css classes */
56+
className: PropTypes.string,
57+
/** onClick func */
58+
onClick: PropTypes.func,
59+
/** Title String */
60+
title: PropTypes.string.isRequired,
61+
/** Icon Type */
62+
icon: PropTypes.string.isRequired,
63+
/** App Tooltip */
64+
tooltip: PropTypes.string,
65+
/** Tooltip Placement */
66+
tooltipPlacement: PropTypes.string,
67+
/** No Icons Bool */
68+
noIcons: PropTypes.bool
69+
};
70+
ApplicationLauncherItem.defaultProps = {
71+
className: '',
72+
onClick: null,
73+
noIcons: false,
74+
tooltipPlacement: 'left',
75+
tooltip: null
76+
};
77+
export default ApplicationLauncherItem;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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 = ({ tooltip, onClick, tooltipPlacement }) => {
9+
if (tooltip)
10+
return (
11+
<OverlayTrigger
12+
placement={tooltipPlacement}
13+
id="applauncher-pf-block-list"
14+
overlay={<Tooltip id="tooltip">{tooltip}</Tooltip>}
15+
>
16+
<Button onClick={onClick} bsStyle="link" className="nav-item-iconic">
17+
<Icon
18+
className="fa fa-th applauncher-pf-icon"
19+
aria-describedby="tooltip"
20+
name=""
21+
/>
22+
</Button>
23+
</OverlayTrigger>
24+
);
25+
return (
26+
<Button onClick={onClick} bsStyle="link" className="nav-item-iconic">
27+
<Icon
28+
className="fa fa-th applauncher-pf-icon"
29+
aria-describedby="tooltip"
30+
name=""
31+
/>
32+
</Button>
33+
);
34+
};
35+
ApplicationLauncherToggle.propTypes = {
36+
/** onClick func */
37+
onClick: PropTypes.func,
38+
/** tooltipPlacement */
39+
tooltipPlacement: PropTypes.string,
40+
/** Toggle Tooltip */
41+
tooltip: PropTypes.string
42+
};
43+
ApplicationLauncherToggle.defaultProps = {
44+
onClick: null,
45+
tooltipPlacement: 'bottom',
46+
tooltip: ''
47+
};
48+
49+
export default ApplicationLauncherToggle;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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+
{ true: 'Grid', false: 'List' },
19+
'true'
20+
);
21+
const iconBool = boolean('Icons', true);
22+
23+
const story = (
24+
<nav className="navbar navbar-pf-vertical">
25+
<nav className="collapse navbar-collapse">
26+
<ul className="nav navbar-nav navbar-right navbar-iconic">
27+
<ApplicationLauncher
28+
grid={type === 'true'}
29+
tooltipPlacement="left"
30+
open
31+
>
32+
<ApplicationLauncherItem
33+
icon="storage-domain"
34+
title="Recteque"
35+
tooltip="Tooltip!"
36+
tooltipPlacement="left"
37+
onClick={handleClick}
38+
noIcons={!iconBool}
39+
/>
40+
<ApplicationLauncherItem
41+
icon="virtual-machine"
42+
title="No Tooltip"
43+
onClick={handleClick}
44+
noIcons={!iconBool}
45+
/>
46+
<ApplicationLauncherItem
47+
icon="domain"
48+
title="Lorem"
49+
tooltip="Tooltip!"
50+
tooltipPlacement="left"
51+
onClick={handleClick}
52+
noIcons={!iconBool}
53+
/>
54+
<ApplicationLauncherItem
55+
icon="home"
56+
title="Home"
57+
tooltip="Tooltip!"
58+
tooltipPlacement="left"
59+
onClick={handleClick}
60+
noIcons={!iconBool}
61+
/>
62+
</ApplicationLauncher>
63+
</ul>
64+
</nav>
65+
</nav>
66+
);
67+
return inlineTemplate({
68+
title: 'ApplicationLauncher',
69+
documentationLink: `${
70+
DOCUMENTATION_URL.PATTERNFLY_ORG_APPLICATION_FRAMEWORK
71+
}launcher/`,
72+
story
73+
});
74+
});
75+
};
76+
77+
export default NavApplicationLauncherStory;

0 commit comments

Comments
 (0)