Skip to content

Commit 6ba853f

Browse files
gleknerdlabaj
authored andcommitted
feat(BreadcrumbSwitcher): creating a BreadcrumbSwitcher component (#1109)
1 parent de66f67 commit 6ba853f

16 files changed

+775
-2
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
@switcher-max-height: 400px;
2+
@switcher-max-width: 200px;
3+
@switcher-min-width: 200px;
4+
5+
#breadcrumb-switcher-popover {
6+
z-index: 1000 !important;
7+
8+
.popover-content {
9+
display: flex;
10+
flex-direction: column;
11+
padding-left: 0;
12+
padding-right: 0;
13+
max-height: @switcher-max-height;
14+
overflow: hidden;
15+
max-width: @switcher-max-width;
16+
min-width: @switcher-max-width;
17+
18+
.input-search {
19+
position: relative;
20+
left: 0;
21+
margin-left: auto;
22+
margin-right: auto;
23+
24+
input {
25+
padding: 0 25px 0 25px;
26+
width: 180px;
27+
}
28+
29+
.fa-search {
30+
color: @color-pf-blue-400;
31+
position: absolute;
32+
top: 7px;
33+
left: 8px;
34+
z-index: 99;
35+
}
36+
37+
.fa-close {
38+
cursor: pointer;
39+
position: absolute;
40+
top: 7px;
41+
right: 10px;
42+
z-index: 99;
43+
}
44+
}
45+
46+
.breadcrumb-switcher-popover-error {
47+
text-indent: 10px;
48+
color: @color-pf-red-100;
49+
}
50+
51+
.list-group-item {
52+
padding: 5px 10px 5px 10px;
53+
54+
&:hover {
55+
background-color: @color-pf-blue-25;
56+
}
57+
58+
&.active {
59+
background-color: @color-pf-blue-400;
60+
}
61+
}
62+
63+
.no-border {
64+
border: none;
65+
}
66+
67+
.pager {
68+
margin: 0 10px;
69+
70+
a {
71+
width: 22px;
72+
}
73+
74+
.fa {
75+
margin-left: -2px;
76+
}
77+
}
78+
79+
.scrollable-list {
80+
margin-top: 5px;
81+
margin-bottom: 10px;
82+
83+
&.list-group {
84+
border-top: 0;
85+
}
86+
}
87+
}
88+
89+
.breadcrumb-switcher-popover-loading {
90+
margin-top: 10px;
91+
}
92+
}

packages/patternfly-3/patternfly-react/less/patternfly-react.less

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
@import 'charts';
66
@import 'utilization-bar';
77
@import 'breadcrumb';
8+
@import 'breadcrumbswitcher';
89
@import 'label-remove';
910
@import 'modeless-overlay';
1011
@import 'notificationdrawer';

packages/patternfly-3/patternfly-react/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
"react-c3js": "^0.1.20",
3737
"react-click-outside": "^3.0.1",
3838
"react-collapse": "^4.0.3",
39+
"react-debounce-input": "^3.2.0",
40+
"react-ellipsis-with-tooltip": "^1.0.8",
3941
"react-fontawesome": "^1.6.1",
4042
"react-motion": "^0.5.2",
4143
"reactabular-table": "^8.14.0",
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
$switcher-max-height: 400px;
2+
$switcher-max-width: 200px;
3+
$switcher-min-width: 200px;
4+
5+
#breadcrumb-switcher-popover {
6+
z-index: 1000 !important;
7+
8+
.popover-content {
9+
display: flex;
10+
flex-direction: column;
11+
padding-left: 0;
12+
padding-right: 0;
13+
max-height: $switcher-max-height;
14+
overflow: hidden;
15+
max-width: $switcher-max-width;
16+
min-width: $switcher-max-width;
17+
18+
.input-search {
19+
position: relative;
20+
left: 0;
21+
margin-left: auto;
22+
margin-right: auto;
23+
24+
input {
25+
padding: 0 25px 0 25px;
26+
width: 180px;
27+
}
28+
29+
.fa-search {
30+
color: $color-pf-blue-400;
31+
position: absolute;
32+
top: 7px;
33+
left: 8px;
34+
z-index: 99;
35+
}
36+
37+
.fa-close {
38+
cursor: pointer;
39+
position: absolute;
40+
top: 7px;
41+
right: 10px;
42+
z-index: 99;
43+
}
44+
}
45+
46+
.breadcrumb-switcher-popover-error {
47+
text-indent: 10px;
48+
color: $color-pf-red-100;
49+
}
50+
51+
.list-group-item {
52+
padding: 5px 10px 5px 10px;
53+
54+
&:hover {
55+
background-color: $color-pf-blue-25;
56+
}
57+
58+
&.active {
59+
background-color: $color-pf-blue-400;
60+
}
61+
}
62+
63+
.no-border {
64+
border: none;
65+
}
66+
67+
.pager {
68+
margin: 0 10px;
69+
70+
a {
71+
width: 22px;
72+
}
73+
74+
.fa {
75+
margin-left: -2px;
76+
}
77+
}
78+
79+
.scrollable-list {
80+
margin-top: 5px;
81+
margin-bottom: 10px;
82+
83+
&.list-group {
84+
border-top: 0;
85+
}
86+
}
87+
}
88+
89+
.breadcrumb-switcher-popover-loading {
90+
margin-top: 10px;
91+
}
92+
}

packages/patternfly-3/patternfly-react/sass/patternfly-react/_patternfly-react.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@
1717
@import 'expand-collapse';
1818
@import 'login-page';
1919
@import 'dual-list-selector';
20+
@import 'breadcrumbswitcher-popover';
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
export const resources = [
2+
{ id: '1', name: 'Host 1', url: '#' },
3+
{ id: '2', name: 'Host 2', url: '#' },
4+
{ id: '3', name: 'Host 3 with a very very very very very long name', url: '#' },
5+
{
6+
id: '4',
7+
name: 'Host 4',
8+
url: undefined,
9+
onClick: Function.prototype
10+
},
11+
{
12+
id: '5',
13+
name: 'Host 5',
14+
url: '#',
15+
onClick: undefined
16+
}
17+
];
18+
19+
export const switcherProps = {
20+
searchDebounceTimeout: 250,
21+
currentPage: 2,
22+
totalPages: 3,
23+
resources
24+
};
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import React, { Component } from 'react';
2+
import ReactDOM from 'react-dom';
3+
import PropTypes from 'prop-types';
4+
import classNames from 'classnames';
5+
import { Overlay } from '../Overlay';
6+
7+
import { noop } from '../../common/helpers';
8+
9+
import BreadcrumbSwitcherPopover from './components/BreadcrumbSwitcherPopover';
10+
import BreadcrumbSwitcherToggler from './components/BreadcrumbSwitcherToggler';
11+
12+
class BreadcrumbSwitcher extends Component {
13+
componentDidUpdate(prevProps) {
14+
const { open, onOpen } = this.props;
15+
16+
if (open === true && prevProps.open === false) {
17+
onOpen();
18+
}
19+
}
20+
21+
render() {
22+
const {
23+
className,
24+
open,
25+
onOpen,
26+
currentPage,
27+
totalPages,
28+
isLoading,
29+
isPaginated,
30+
hasError,
31+
resources,
32+
onTogglerClick,
33+
onHide,
34+
onNextPageClick,
35+
onPrevPageClick,
36+
onSearchChange,
37+
searchValue,
38+
onSearchClear,
39+
searchDebounceTimeout,
40+
onResourceClick,
41+
...props
42+
} = this.props;
43+
const classes = classNames('breadcrumb-switcher', className);
44+
45+
return (
46+
<div className={classes} {...props}>
47+
<BreadcrumbSwitcherToggler
48+
id="switcher"
49+
onClick={() => onTogglerClick()}
50+
ref={ref => {
51+
this.togglerRef = ref;
52+
}}
53+
/>
54+
55+
<Overlay
56+
rootClose
57+
show={open}
58+
container={this}
59+
placement="bottom"
60+
onHide={onHide}
61+
// TODO: try to remove the `ReactDOM.findDOMNode`
62+
// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-find-dom-node.md
63+
// react-bootstrap still have it in their docs: https://react-bootstrap.github.io/components/overlays/
64+
// eslint-disable-next-line react/no-find-dom-node
65+
target={() => ReactDOM.findDOMNode(this.togglerRef)}
66+
>
67+
<BreadcrumbSwitcherPopover
68+
id="breadcrumb-switcher-popover"
69+
loading={isLoading}
70+
isPaginated={isPaginated}
71+
hasError={hasError}
72+
onSearchChange={onSearchChange}
73+
resources={resources}
74+
onNextPageClick={onNextPageClick}
75+
onPrevPageClick={onPrevPageClick}
76+
currentPage={currentPage}
77+
totalPages={totalPages}
78+
searchValue={searchValue}
79+
onSearchClear={onSearchClear}
80+
searchDebounceTimeout={searchDebounceTimeout}
81+
onResourceClick={onResourceClick}
82+
/>
83+
</Overlay>
84+
</div>
85+
);
86+
}
87+
}
88+
89+
BreadcrumbSwitcher.propTypes = {
90+
/** className */
91+
className: PropTypes.string,
92+
/** search box value */
93+
searchValue: PropTypes.string,
94+
/** is switcher open bool */
95+
open: PropTypes.bool,
96+
/** searchDebounceTimeout */
97+
searchDebounceTimeout: PropTypes.number,
98+
/** current Page */
99+
currentPage: PropTypes.number,
100+
/** total Pages */
101+
totalPages: PropTypes.number,
102+
/** is Loadnig bool */
103+
isLoading: PropTypes.bool,
104+
/** is Paginated bool */
105+
isPaginated: PropTypes.bool,
106+
/** has Error bool */
107+
hasError: PropTypes.bool,
108+
/** Breadcrumb resources */
109+
resources: PropTypes.arrayOf(
110+
PropTypes.shape({
111+
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
112+
name: PropTypes.string.isRequired,
113+
href: PropTypes.string,
114+
onClick: PropTypes.func
115+
})
116+
),
117+
/** function() onTogglerClick func */
118+
onTogglerClick: PropTypes.func,
119+
/** function() onHide func */
120+
onHide: PropTypes.func,
121+
/** function() onOpen func */
122+
onOpen: PropTypes.func,
123+
/** function() onPrevPageClick func */
124+
onPrevPageClick: PropTypes.func,
125+
/** function() onNextPageClick func */
126+
onNextPageClick: PropTypes.func,
127+
/** function(resource) onResourceClick func */
128+
onResourceClick: PropTypes.func,
129+
/** function(newSearch) onSearchChange func */
130+
onSearchChange: PropTypes.func,
131+
/** function() onSearchClear func */
132+
onSearchClear: PropTypes.func
133+
};
134+
135+
BreadcrumbSwitcher.defaultProps = {
136+
className: '',
137+
searchValue: '',
138+
open: false,
139+
searchDebounceTimeout: 300,
140+
currentPage: 1,
141+
totalPages: 1,
142+
isLoading: false,
143+
isPaginated: true,
144+
hasError: false,
145+
resources: [],
146+
onTogglerClick: noop,
147+
onHide: noop,
148+
onOpen: noop,
149+
onResourceClick: noop,
150+
onPrevPageClick: noop,
151+
onNextPageClick: noop,
152+
onSearchChange: noop,
153+
onSearchClear: noop
154+
};
155+
156+
export default BreadcrumbSwitcher;

0 commit comments

Comments
 (0)