Skip to content

Commit ce11507

Browse files
authored
Merge pull request #260 from data-driven-forms/pf4-menu-portaling
fix(pf4 select): Added prop that enables select menu portaling
2 parents d660080 + 0a2415e commit ce11507

File tree

4 files changed

+120
-94
lines changed

4 files changed

+120
-94
lines changed

packages/pf4-component-mapper/src/form-fields/select/select-styles.scss

Lines changed: 99 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -59,115 +59,121 @@
5959
}
6060
}
6161
}
62+
}
6263

63-
.ddorg__pf4-component-mapper__select__menu {
64-
cursor: pointer;
65-
border-radius: 0;
66-
z-index: 2;
67-
}
68-
69-
.ddorg__pf4-component-mapper__select__menu--option {
70-
display: flex;
71-
align-items: center;
64+
/**
65+
* Move menu styles out of select scope to enable using it while using portaling for context menu
66+
* !important is used to override global styles comming from react-select
67+
* z-index of menu has to be > 400 to show over pf4-modal
68+
*/
7269

73-
&.focused {
74-
background-color: var(--pf-global--Color--light-200);
75-
}
70+
.ddorg__pf4-component-mapper__select__menu {
71+
cursor: pointer;
72+
border-radius: 0 !important;
73+
z-index: 1000 !important;
74+
}
7675

77-
svg {
78-
width: 0.6em;
79-
margin-right: 10px;
80-
fill: var(--pf-global--active-color--100);
81-
}
76+
.ddorg__pf4-component-mapper__select__menu--option {
77+
display: flex;
78+
align-items: center;
8279

83-
div.pf-c-check {
84-
padding-left: 1rem;
85-
& + .ddorg__pf4-component-mapper__select__option {
86-
padding-left: 0;
87-
}
88-
}
80+
&.focused {
81+
background-color: var(--pf-global--Color--light-200);
8982
}
9083

91-
.ddorg__pf4-component-mapper__select__menu--option div {
92-
background: transparent;
93-
cursor: pointer;
94-
color: var(--pf-global--Color--300);
84+
svg {
85+
width: 0.6em;
86+
margin-right: 10px;
87+
fill: var(--pf-global--active-color--100);
9588
}
9689

97-
.ddorg__pf4-component-mapper__select__single-value {
98-
padding-left: 8px;
90+
div.pf-c-check {
91+
padding-left: 1rem;
92+
& + .ddorg__pf4-component-mapper__select__option {
93+
padding-left: 0;
94+
}
9995
}
96+
}
10097

101-
.ddorg__pf4-component-mapper__select__multivalue--container {
102-
display: flex;
103-
flex-direction: row;
104-
flex-wrap: nowrap;
105-
align-items: center;
106-
box-sizing: border-box;
107-
line-height: 24px;
108-
position: relative;
109-
margin-right: 4px;
110-
font-size: 12px;
111-
max-height: 26px;
112-
113-
> .ddorg__pf4-component-mapper__select__multivalue--remove {
114-
display: flex;
115-
116-
svg {
117-
fill: var(--pf-global--Color--400);
118-
}
98+
.ddorg__pf4-component-mapper__select__menu--option div {
99+
background: transparent;
100+
cursor: pointer;
101+
color: var(--pf-global--Color--300);
102+
}
119103

120-
> :hover {
121-
background: transparent;
122-
svg {
123-
fill: var(--pf-global--Color--dark-100);
124-
}
125-
}
126-
}
104+
.ddorg__pf4-component-mapper__select__single-value {
105+
padding-left: 8px;
106+
}
107+
108+
.ddorg__pf4-component-mapper__select__multivalue--container {
109+
display: flex;
110+
flex-direction: row;
111+
flex-wrap: nowrap;
112+
align-items: center;
113+
box-sizing: border-box;
114+
line-height: 24px;
115+
position: relative;
116+
margin-right: 4px;
117+
font-size: 12px;
118+
max-height: 26px;
119+
120+
> .ddorg__pf4-component-mapper__select__multivalue--remove {
121+
display: flex;
122+
123+
svg {
124+
fill: var(--pf-global--Color--400);
125+
}
127126

128-
&::before {
129-
position: absolute;
130-
top: 0;
131-
right: 0;
132-
bottom: 0;
133-
left: 0;
134-
content: "";
135-
border: var(--pf-global--BorderWidth--sm) solid var(--pf-global--Color--dark-200);
136-
border-radius: 3px;
137-
pointer-events: none;
127+
> :hover {
128+
background: transparent;
129+
svg {
130+
fill: var(--pf-global--Color--dark-100);
138131
}
139132
}
133+
}
140134

141-
.ddorg__pf4-component-mapper__select__value--container {
142-
display: flex;
143-
padding-left: 8px;
144-
align-items: center;
145-
flex-wrap: wrap;
146-
max-width: calc(100% - 70px);
147-
148-
.ddorg__pf4-component-mapper__select__multivalue--container {
149-
align-items: initial;
150-
.ddorg__pf4-component-mapper__select__multi-value__label {
151-
max-width: 240px;
152-
overflow: hidden;
153-
text-overflow: ellipsis;
154-
display: inline-block;
155-
}
135+
&::before {
136+
position: absolute;
137+
top: 0;
138+
right: 0;
139+
bottom: 0;
140+
left: 0;
141+
content: "";
142+
border: var(--pf-global--BorderWidth--sm) solid var(--pf-global--Color--dark-200);
143+
border-radius: 3px;
144+
pointer-events: none;
145+
}
146+
}
147+
148+
.ddorg__pf4-component-mapper__select__value--container {
149+
display: flex;
150+
padding-left: 8px;
151+
align-items: center;
152+
flex-wrap: wrap;
153+
max-width: calc(100% - 70px);
154+
155+
.ddorg__pf4-component-mapper__select__multivalue--container {
156+
align-items: initial;
157+
.ddorg__pf4-component-mapper__select__multi-value__label {
158+
max-width: 240px;
159+
overflow: hidden;
160+
text-overflow: ellipsis;
161+
display: inline-block;
156162
}
163+
}
157164

158-
.ddorg__pf4-component-mapper__select__value--container-chipgroup {
159-
padding: 4px 6px;
160-
font-size: 12px;
161-
background-color: var(--pf-global--BorderColor--300);
162-
border: var(--pf-global--BorderWidth--sm) solid var(--pf-global--BorderColor--300);
163-
margin: 0;
164-
max-height: 26px;
165-
&:hover{
166-
border-color: var(--pf-global--Color--dark-100);
167-
}
168-
> span {
169-
color: var(--pf-global--Color--dark-100);
170-
}
165+
.ddorg__pf4-component-mapper__select__value--container-chipgroup {
166+
padding: 4px 6px;
167+
font-size: 12px;
168+
background-color: var(--pf-global--BorderColor--300);
169+
border: var(--pf-global--BorderWidth--sm) solid var(--pf-global--BorderColor--300);
170+
margin: 0;
171+
max-height: 26px;
172+
&:hover{
173+
border-color: var(--pf-global--Color--dark-100);
171174
}
172-
}
175+
> span {
176+
color: var(--pf-global--Color--dark-100);
177+
}
178+
}
173179
}

packages/pf4-component-mapper/src/form-fields/select/select.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export class Select extends React.Component {
6868
: () => this.props.noOptionsMessage;
6969

7070
render() {
71-
const { selectVariant, loadOptions, loadingMessage, noOptionsMessage, ... props } = this.props;
71+
const { selectVariant, loadOptions, loadingMessage, noOptionsMessage, menuIsPortal, ... props } = this.props;
7272
const { isLoading, allOptions } = this.state;
7373
const Select = selectProvider(selectVariant);
7474
const isSearchable = selectVariant === 'createable' || props.isSearchable;
@@ -83,6 +83,8 @@ export class Select extends React.Component {
8383
/>);
8484
}
8585

86+
const menuPortalTarget = menuIsPortal ? document.body : undefined;
87+
8688
return (
8789
<Select
8890
menuPlacement="auto"
@@ -97,9 +99,16 @@ export class Select extends React.Component {
9799
isFetching={ Object.values(this.state.promises).some(value => value) }
98100
noOptionsMessage={ this.renderNoOptionsMessage() }
99101
onInputChange={ this.onInputChange }
102+
menuPortalTarget={ menuPortalTarget }
100103
{ ...props }
101104
className={ `ddorg__pf4-component-mapper__select${props.isMulti ? ' multi-select' : ' single-select'}` }
102105
classNamePrefix="ddorg__pf4-component-mapper__select"
106+
styles={{
107+
menuPortal: provided => ({
108+
...provided,
109+
'z-index': 'initial',
110+
}),
111+
}}
103112
onChange={ (option) => {
104113
const o = !option && props.isMulti ? [] : option;
105114
return simpleValue
@@ -132,6 +141,7 @@ Select.propTypes = {
132141
loadingMessage: PropTypes.node,
133142
updatingMessage: PropTypes.node,
134143
noOptionsMessage: PropTypes.func,
144+
menuIsPortal: PropTypes.bool,
135145
};
136146

137147
Select.defaultProps = {
@@ -142,6 +152,7 @@ Select.defaultProps = {
142152
loadingMessage: 'Loading...',
143153
updatingMessage: 'Loading data...',
144154
options: [],
155+
menuIsPortal: false,
145156
};
146157

147158
const DataDrivenSelect = ({ multi, ...props }) => (

packages/pf4-component-mapper/src/tests/select/select.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ describe('<Select />', () => {
130130
showMoreLabel: 'more',
131131
simpleValue: true,
132132
updatingMessage: 'Loading data...',
133+
menuIsPortal: false,
133134
value: [ 1, 2 ],
134135
loadingMessage: 'Loading...',
135136
});

packages/react-renderer-demo/src/app/src/doc-components/pf4-select.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
# Menu portaling
2+
3+
In order to show menu properly in dialogs like modals, you can use `menuIsPortal`. This will append menu as portal to body.
4+
5+
|prop name|type|description|
6+
|---------|----|-----------|
7+
|menuIsPortal|`bool`|Append menu to body instead of to select wrapper.See more [here](https://react-select.com/advanced#portaling)|
8+
19
# PF4 Async Select
210

311
PF4 Select allows to load the options asynchronously.

0 commit comments

Comments
 (0)