Skip to content

Commit a1409c3

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

16 files changed

+1156
-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.14.0",
3738
"recompose": "^0.26.0"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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+
open={open}
32+
/>
33+
<Dropdown.Menu className="dropdown-menu-right">{children}</Dropdown.Menu>
34+
</li>
35+
);
36+
};
37+
38+
ApplicationLauncher.propTypes = {
39+
/** Additional element css classes */
40+
className: PropTypes.string,
41+
/** Children Node */
42+
children: PropTypes.node.isRequired,
43+
/** Toggle Tooltip */
44+
tooltip: PropTypes.string,
45+
/** tooltipPlacement */
46+
tooltipPlacement: PropTypes.string,
47+
/** Application Launcher Type (Default List) */
48+
grid: PropTypes.bool,
49+
/** open bool */
50+
open: PropTypes.bool,
51+
/** Toggle launcher func */
52+
toggleLauncher: PropTypes.func
53+
};
54+
ApplicationLauncher.defaultProps = {
55+
className: '',
56+
tooltip: '',
57+
tooltipPlacement: 'left',
58+
toggleLauncher: noop,
59+
grid: false,
60+
open: false
61+
};
62+
63+
export default ApplicationLauncher;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { storiesOf } from '@storybook/react';
2+
import { withKnobs } from '@storybook/addon-knobs';
3+
import {
4+
storybookPackageName,
5+
STORYBOOK_CATEGORY
6+
} from 'storybook/constants/siteConstants';
7+
import {
8+
NavApplicationLauncherStory,
9+
WrapperNavApplicationLauncherStory
10+
} from './Stories/index';
11+
import { name } from '../../../package.json';
12+
13+
const stories = storiesOf(
14+
`${storybookPackageName(name)}/${
15+
STORYBOOK_CATEGORY.APPLICATION_FRAMEWORK
16+
}/Launcher`,
17+
module
18+
);
19+
stories.addDecorator(withKnobs);
20+
21+
NavApplicationLauncherStory(stories);
22+
WrapperNavApplicationLauncherStory(stories);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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 with tooltip 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('ApplicationLauncherItem without tooltip is working properly', () => {
42+
const component = mount(
43+
<ApplicationLauncherItem
44+
icon="pficon pficon-storage-domain"
45+
title="Recteque"
46+
onClick={handleClick}
47+
/>
48+
);
49+
50+
expect(component.render()).toMatchSnapshot();
51+
});
52+
53+
test('ApplicationLauncherToggle is working properly', () => {
54+
const component = mount(
55+
<ApplicationLauncherToggle tooltipPlacement="left" onClick={handleClick} />
56+
);
57+
58+
expect(component.render()).toMatchSnapshot();
59+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
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={title}>{tooltip}</Tooltip>}
24+
placement={tooltipPlacement}
25+
trigger={['hover', 'focus']}
26+
rootClose={false}
27+
>
28+
<li className={classes} role="presentation">
29+
<a
30+
className="applauncher-pf-link"
31+
href="#"
32+
onClick={e => onClick(e)}
33+
role="menuitem"
34+
>
35+
{!noIcons && (
36+
<Icon
37+
type="pf"
38+
name={icon}
39+
className="applauncher-pf-link-icon"
40+
/>
41+
)}
42+
<span className="applauncher-pf-link-title">{title}</span>
43+
</a>
44+
</li>
45+
</OverlayTrigger>
46+
);
47+
}
48+
return (
49+
<li className={classes} role="presentation">
50+
<a
51+
className="applauncher-pf-link"
52+
href="#"
53+
onClick={e => onClick(e)}
54+
role="menuitem"
55+
>
56+
{!noIcons && (
57+
<Icon type="pf" name={icon} className="applauncher-pf-link-icon" />
58+
)}
59+
<span className="applauncher-pf-link-title">{title}</span>
60+
</a>
61+
</li>
62+
);
63+
};
64+
ApplicationLauncherItem.propTypes = {
65+
/** Additional element css classes */
66+
className: PropTypes.string,
67+
/** onClick func */
68+
onClick: PropTypes.func,
69+
/** Title String */
70+
title: PropTypes.string.isRequired,
71+
/** Icon Type */
72+
icon: PropTypes.string.isRequired,
73+
/** App Tooltip */
74+
tooltip: PropTypes.string,
75+
/** Tooltip Placement */
76+
tooltipPlacement: PropTypes.string,
77+
/** No Icons Bool */
78+
noIcons: PropTypes.bool
79+
};
80+
ApplicationLauncherItem.defaultProps = {
81+
className: '',
82+
onClick: null,
83+
noIcons: false,
84+
tooltipPlacement: 'left',
85+
tooltip: null
86+
};
87+
export default ApplicationLauncherItem;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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 = ({
9+
open,
10+
tooltip,
11+
onClick,
12+
tooltipPlacement
13+
}) => {
14+
if (tooltip)
15+
return (
16+
<OverlayTrigger
17+
placement={tooltipPlacement}
18+
id="applauncher-pf-block-list"
19+
overlay={<Tooltip>{tooltip}</Tooltip>}
20+
>
21+
<Button
22+
onClick={onClick}
23+
bsStyle="link"
24+
className="nav-item-iconic dropdown-toggle"
25+
aria-describedby="tooltip"
26+
aria-expanded={open}
27+
>
28+
<Icon name="th applauncher-pf-icon" />
29+
</Button>
30+
</OverlayTrigger>
31+
);
32+
return (
33+
<Button
34+
onClick={onClick}
35+
bsStyle="link"
36+
className="nav-item-iconic dropdown-toggle"
37+
aria-expanded={open}
38+
>
39+
<Icon name="th applauncher-pf-icon" />
40+
<span className="dropdown-title">
41+
<span className="applauncher-pf-title">
42+
Application Launcher
43+
<span className="caret" aria-hidden="true" />
44+
</span>
45+
</span>
46+
</Button>
47+
);
48+
};
49+
ApplicationLauncherToggle.propTypes = {
50+
/** onClick func */
51+
onClick: PropTypes.func,
52+
/** tooltipPlacement */
53+
tooltipPlacement: PropTypes.string,
54+
/** Toggle Tooltip */
55+
tooltip: PropTypes.string,
56+
/** is Open bool */
57+
open: PropTypes.bool.isRequired
58+
};
59+
ApplicationLauncherToggle.defaultProps = {
60+
onClick: null,
61+
tooltipPlacement: 'bottom',
62+
tooltip: ''
63+
};
64+
65+
export default ApplicationLauncherToggle;
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/siteConstants';
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('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+
key="app1"
34+
icon="storage-domain"
35+
title="Recteque"
36+
tooltip="Tooltip!"
37+
tooltipPlacement="left"
38+
onClick={handleClick}
39+
noIcons={!iconBool}
40+
/>
41+
<ApplicationLauncherItem
42+
key="app2"
43+
icon="virtual-machine"
44+
title="No Tooltip"
45+
onClick={handleClick}
46+
noIcons={!iconBool}
47+
/>
48+
<ApplicationLauncherItem
49+
key="app3"
50+
icon="domain"
51+
title="Lorem"
52+
tooltip="Tooltip!"
53+
tooltipPlacement="left"
54+
onClick={handleClick}
55+
noIcons={!iconBool}
56+
/>
57+
<ApplicationLauncherItem
58+
key="app4"
59+
icon="home"
60+
title="Home"
61+
tooltip="Tooltip!"
62+
tooltipPlacement="left"
63+
onClick={handleClick}
64+
noIcons={!iconBool}
65+
/>
66+
</ApplicationLauncher>
67+
</ul>
68+
</nav>
69+
</nav>
70+
);
71+
return inlineTemplate({
72+
title: 'ApplicationLauncher',
73+
documentationLink: `${
74+
DOCUMENTATION_URL.PATTERNFLY_ORG_APPLICATION_FRAMEWORK
75+
}launcher/`,
76+
story
77+
});
78+
});
79+
};
80+
81+
export default NavApplicationLauncherStory;

0 commit comments

Comments
 (0)