Skip to content

Commit c6e95d9

Browse files
authored
fix: Layout issues when resizing Cloud Config parameter dialog (parse-community#3241)
1 parent b596a32 commit c6e95d9

4 files changed

Lines changed: 64 additions & 29 deletions

File tree

src/components/JsonEditor/JsonEditor.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
pointer-events: none;
4343
background: transparent;
4444
color: #555572;
45-
overflow: auto;
45+
overflow: hidden;
4646

4747
code {
4848
display: block;
@@ -90,7 +90,7 @@
9090
.inputLayer {
9191
display: block;
9292
width: 100%;
93-
min-width: 100%;
93+
min-width: calc(var(--modal-min-width) * (1 - var(--modal-label-ratio)));
9494
background: transparent;
9595
color: transparent;
9696
caret-color: #333;

src/components/MultiSelect/MultiSelect.react.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export default class MultiSelect extends React.Component {
8181
render() {
8282
let popover = null;
8383
if (this.state.open) {
84-
const width = this.dropdownRef.current.clientWidth;
84+
const width = this.props.menuWidth || this.dropdownRef.current.clientWidth;
8585

8686
const classes = [styles.menu];
8787
if (this.props.dense) {

src/dashboard/Data/Config/ConfigConflictDiff.scss

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
* the root directory of this source tree.
77
*/
88
.container {
9+
contain: inline-size;
910
width: 100%;
10-
min-width: 100%;
11+
min-width: 0;
1112
overflow: auto;
12-
height: 200px;
13+
height: 80px;
1314
min-height: 80px;
14-
resize: both;
15+
resize: vertical;
1516
text-align: left;
1617
}
1718

src/dashboard/Data/Config/ConfigDialog.react.js

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Dropdown from 'components/Dropdown/Dropdown.react';
1010
import Field from 'components/Field/Field.react';
1111
import FileInput from 'components/FileInput/FileInput.react';
1212
import GeoPointInput from 'components/GeoPointInput/GeoPointInput.react';
13+
import Icon from 'components/Icon/Icon.react';
1314
import Label from 'components/Label/Label.react';
1415
import Modal from 'components/Modal/Modal.react';
1516
import NonPrintableHighlighter, { hasNonPrintableChars, getNonPrintableCharsFromJson, hasNonAlphanumericChars, getNonAlphanumericCharsFromJson, getRegexValidation, getRegexValidationFromJson } from 'components/NonPrintableHighlighter/NonPrintableHighlighter.react';
@@ -18,6 +19,8 @@ import Parse from 'parse';
1819
import React from 'react';
1920
import TextInput from 'components/TextInput/TextInput.react';
2021
import Toggle from 'components/Toggle/Toggle.react';
22+
import Popover from 'components/Popover/Popover.react';
23+
import Position from 'lib/Position';
2124
import Button from 'components/Button/Button.react';
2225
import JsonEditor from 'components/JsonEditor/JsonEditor.react';
2326
import validateNumeric from 'lib/validateNumeric';
@@ -120,6 +123,7 @@ export default class ConfigDialog extends React.Component {
120123

121124
constructor(props) {
122125
super();
126+
this.optionsRef = React.createRef();
123127
this.state = {
124128
value: null,
125129
type: 'String',
@@ -129,6 +133,7 @@ export default class ConfigDialog extends React.Component {
129133
wordWrap: false,
130134
showDiff: false,
131135
confirmOverride: false,
136+
optionsMenuOpen: false,
132137
error: null,
133138
syntaxColors: null,
134139
};
@@ -335,6 +340,14 @@ export default class ConfigDialog extends React.Component {
335340
});
336341
}
337342

343+
updateOptionsMenuPos = () => {
344+
if (this.optionsRef.current) {
345+
const pos = Position.inWindow(this.optionsRef.current);
346+
pos.y -= 4;
347+
this.setState({ optionsMenuPos: pos });
348+
}
349+
};
350+
338351
formatValue() {
339352
const { value, error } = ConfigDialog.formatJSON(this.state.value);
340353
this.setState({ value, error });
@@ -566,37 +579,58 @@ export default class ConfigDialog extends React.Component {
566579
onClick={this.compactValue.bind(this)}
567580
disabled={!this.canFormatValue()}
568581
/>
569-
<label style={{ display: 'flex', alignItems: 'center', gap: '4px', cursor: 'pointer' }}>
570-
<Toggle
571-
type={Toggle.Types.HIDE_LABELS}
572-
value={this.state.wordWrap}
573-
onChange={wordWrap => this.setState({ wordWrap })}
574-
additionalStyles={{ margin: '0px' }}
575-
colorLeft="#cbcbcb"
576-
colorRight="#00db7c"
577-
/>
578-
<span style={{ color: this.state.wordWrap ? '#333' : '#999' }}>Wrap</span>
579-
</label>
580582
{this.state.error && (
581583
<span style={{ color: '#d73a49', fontSize: '13px' }}>{this.state.error}</span>
582584
)}
583585
</>
584586
)}
585-
{isDiffableType && isExistingParam && (
586-
<label style={{ display: 'flex', alignItems: 'center', gap: '4px', cursor: 'pointer' }}>
587-
<Toggle
588-
type={Toggle.Types.HIDE_LABELS}
589-
value={this.state.showDiff}
590-
onChange={showDiff => this.setState({ showDiff })}
591-
additionalStyles={{ margin: '0px' }}
592-
colorLeft="#cbcbcb"
593-
colorRight="#00db7c"
587+
{(isJsonType || (isDiffableType && isExistingParam)) && (
588+
<div ref={this.optionsRef}>
589+
<Button
590+
value="Options &#9662;"
591+
onClick={() => {
592+
const node = this.optionsRef.current;
593+
const pos = Position.inWindow(node);
594+
pos.y -= 4; // small gap above button
595+
this.setState({ optionsMenuOpen: !this.state.optionsMenuOpen, optionsMenuPos: pos });
596+
}}
594597
/>
595-
<span style={{ color: this.state.showDiff ? '#333' : '#999' }}>Diff</span>
596-
</label>
598+
{this.state.optionsMenuOpen && this.state.optionsMenuPos && (
599+
<Popover
600+
fixed={true}
601+
position={this.state.optionsMenuPos}
602+
onExternalClick={() => { document.activeElement?.blur(); this.setState({ optionsMenuOpen: false }); }}
603+
>
604+
<div style={{ background: '#fff', border: '1px solid #e1e4e8', borderRadius: '4px', boxShadow: '0 3px 12px rgba(0,0,0,0.15)', padding: '4px 0', minWidth: '130px', transform: 'translateY(-100%)' }}>
605+
{isJsonType && (
606+
<div
607+
onClick={() => { document.activeElement?.blur(); this.setState({ wordWrap: !this.state.wordWrap, optionsMenuOpen: false }); }}
608+
style={{ display: 'flex', alignItems: 'center', padding: '8px 12px', cursor: 'pointer', fontSize: '14px', color: '#333', gap: '8px' }}
609+
onMouseEnter={e => e.currentTarget.style.background = '#f6f8fa'}
610+
onMouseLeave={e => e.currentTarget.style.background = 'transparent'}
611+
>
612+
<span style={{ width: '12px', display: 'inline-block' }}>{this.state.wordWrap && <Icon name="check" width={12} height={12} fill="#00db7c" />}</span>
613+
<span>Word wrap</span>
614+
</div>
615+
)}
616+
{isDiffableType && isExistingParam && (
617+
<div
618+
onClick={() => { document.activeElement?.blur(); this.setState({ showDiff: !this.state.showDiff, optionsMenuOpen: false }); }}
619+
style={{ display: 'flex', alignItems: 'center', padding: '8px 12px', cursor: 'pointer', fontSize: '14px', color: '#333', gap: '8px' }}
620+
onMouseEnter={e => e.currentTarget.style.background = '#f6f8fa'}
621+
onMouseLeave={e => e.currentTarget.style.background = 'transparent'}
622+
>
623+
<span style={{ width: '12px', display: 'inline-block' }}>{this.state.showDiff && <Icon name="check" width={12} height={12} fill="#00db7c" />}</span>
624+
<span>Diff view</span>
625+
</div>
626+
)}
627+
</div>
628+
</Popover>
629+
)}
630+
</div>
597631
)}
598632
</div>
599-
<div style={{ display: 'flex', gap: '12px', marginLeft: '20px' }}>
633+
<div style={{ display: 'flex', gap: '12px' }}>
600634
<Button value="Cancel" onClick={this.props.onCancel} />
601635
<Button
602636
primary={true}

0 commit comments

Comments
 (0)