Переглянути джерело

mol-plugin-ui: general refactoring & code improvements

David Sehnal 5 роки тому
батько
коміт
f2a6e63a20

+ 1 - 1
src/mol-plugin-ui/controls/action-menu.tsx

@@ -184,7 +184,7 @@ class Section extends React.PureComponent<SectionProps, SectionState> {
     get multiselectHeader() {
         const { header, hasCurrent } = this.state;
 
-        return <div className='msp-control-group-header msp-flex-row' style={{ marginTop: '1px' }}>
+        return <div className='msp-flex-row msp-control-group-header'>
             <Button icon={this.state.isExpanded ? 'collapse' : 'expand'} flex noOverflow onClick={this.toggleExpanded}>
                 {hasCurrent ? <b>{header?.label}</b> : header?.label}
             </Button>

+ 9 - 16
src/mol-plugin-ui/controls/color.tsx

@@ -11,7 +11,7 @@ import { camelCaseToWords, stringToWords } from '../../mol-util/string';
 import * as React from 'react';
 import { _Props, _State } from '../base';
 import { ParamProps } from './parameters';
-import { TextInput, Button } from './common';
+import { TextInput, Button, ControlRow } from './common';
 import { DefaultColorSwatch } from '../../mol-util/color/swatches';
 
 export class CombinedColorControl extends React.PureComponent<ParamProps<PD.Color>, { isExpanded: boolean }> {
@@ -50,23 +50,16 @@ export class CombinedColorControl extends React.PureComponent<ParamProps<PD.Colo
     render() {
         const label = this.props.param.label || camelCaseToWords(this.props.name);
         return <>
-            <div className='msp-control-row'>
-                <span title={this.props.param.description}>{label}</span>
-                <div>
-                    <Button onClick={this.toggleExpanded} inline className='msp-combined-color-button' style={{ background: Color.toStyle(this.props.value) }} />
-                </div>
-            </div>
+            <ControlRow title={this.props.param.description}
+                label={label}
+                control={<Button onClick={this.toggleExpanded} inline className='msp-combined-color-button' style={{ background: Color.toStyle(this.props.value) }} />} />
             {this.state.isExpanded && <div className='msp-control-offset'>
                 {this.swatch()}
-                <div className='msp-control-row'>
-                    <span>RGB</span>
-                    <div>
-                        <TextInput onChange={this.onChangeText} value={this.props.value}
-                            fromValue={formatColorRGB} toValue={getColorFromString} isValid={isValidColorString}
-                            className='msp-form-control' onEnter={this.props.onEnter} blurOnEnter={true} blurOnEscape={true}
-                            placeholder='e.g. 127 127 127' delayMs={250} />
-                    </div>
-                </div>
+                <ControlRow label='RGB'
+                    control={<TextInput onChange={this.onChangeText} value={this.props.value}
+                        fromValue={formatColorRGB} toValue={getColorFromString} isValid={isValidColorString}
+                        className='msp-form-control' onEnter={this.props.onEnter} blurOnEnter={true} blurOnEscape={true}
+                        placeholder='e.g. 127 127 127' delayMs={250} />} />
             </div>}
         </>;
     }

+ 31 - 16
src/mol-plugin-ui/controls/common.tsx

@@ -123,7 +123,7 @@ export class TextInput<T = string> extends React.PureComponent<TextInputProps<T>
         this.setState({ value: formatted }, () => this.triggerChanged(formatted, converted));
     }
 
-    onKeyUp  = (e: React.KeyboardEvent<HTMLInputElement>) => {
+    onKeyUp = (e: React.KeyboardEvent<HTMLInputElement>) => {
         if (e.charCode === 27 || e.keyCode === 27 /* esc */) {
             if (this.props.blurOnEscape && this.input.current) {
                 this.input.current.blur();
@@ -237,17 +237,15 @@ export class ExpandableControlRow extends React.Component<{
         const { label, pivot, controls } = this.props;
         // TODO: fix the inline CSS
         return <>
-            <div className='msp-control-row'>
-                <span>
-                    {label}
-                    <button className='msp-btn-link msp-btn-icon msp-control-group-expander' onClick={this.toggleExpanded} title={`${this.state.isExpanded ? 'Less' : 'More'} options`}
-                        style={{ background: 'transparent', textAlign: 'left', padding: '0' }}>
-                        <Icon name={this.state.isExpanded ? 'minus' : 'plus'} style={{ display: 'inline-block' }} />
-                    </button>
-                </span>
-                <div>{pivot}</div>
-                {this.props.colorStripe && <div className='msp-expandable-group-color-stripe' style={{ backgroundColor: Color.toStyle(this.props.colorStripe) }} /> }
-            </div>
+            <ControlRow label={<>
+                {label}
+                <button className='msp-btn-link msp-btn-icon msp-control-group-expander' onClick={this.toggleExpanded} title={`${this.state.isExpanded ? 'Less' : 'More'} options`}
+                    style={{ background: 'transparent', textAlign: 'left', padding: '0' }}>
+                    <Icon name={this.state.isExpanded ? 'minus' : 'plus'} style={{ display: 'inline-block' }} />
+                </button>
+            </>} control={pivot}>
+                {this.props.colorStripe && <div className='msp-expandable-group-color-stripe' style={{ backgroundColor: Color.toStyle(this.props.colorStripe) }} />}
+            </ControlRow>
             {this.state.isExpanded && <div className='msp-control-offset'>
                 {controls}
             </div>}
@@ -255,7 +253,7 @@ export class ExpandableControlRow extends React.Component<{
     }
 }
 
-export function SectionHeader(props: { icon?: IconName, title: string | JSX.Element, desc?: string}) {
+export function SectionHeader(props: { icon?: IconName, title: string | JSX.Element, desc?: string }) {
     return <div className='msp-section-header'>
         {props.icon && <Icon name={props.icon} />}
         {props.title} <small>{props.desc}</small>
@@ -360,11 +358,10 @@ export class ToggleButton extends React.PureComponent<ToggleButtonProps> {
         const props = this.props;
         const label = props.label;
         const className = props.isSelected ? `${props.className || ''} msp-control-current` : props.className;
-        return <button onClick={this.onClick} title={this.props.title}
+        return <Button icon={this.props.icon} onClick={this.onClick} title={this.props.title}
             disabled={props.disabled} style={props.style} className={className}>
-            <Icon name={this.props.icon} />
             {label && this.props.isSelected ? <b>{label}</b> : label}
-        </button>;
+        </Button>;
     }
 }
 
@@ -389,4 +386,22 @@ export class ExpandGroup extends React.PureComponent<{ header: string, headerSty
                     </div>)}
         </>;
     }
+}
+
+export type ControlRowProps = {
+    title?: string,
+    label?: React.ReactNode,
+    control?: React.ReactNode,
+    className?: string,
+    children?: React.ReactNode
+}
+
+export function ControlRow(props: ControlRowProps) {
+    let className = 'msp-control-row';
+    if (props.className) className += ' ' + props.className;
+    return <div className={className}>
+        <span className='msp-control-row-label' title={props.title}>{props.label}</span>
+        <div className='msp-control-row-ctrl'>{props.control}</div>
+        {props.children}
+    </div>;
 }

+ 32 - 64
src/mol-plugin-ui/controls/parameters.tsx

@@ -19,7 +19,7 @@ import { camelCaseToWords } from '../../mol-util/string';
 import { PluginUIComponent, _Props, _State } from '../base';
 import { ActionMenu } from './action-menu';
 import { ColorOptions, ColorValueOption, CombinedColorControl } from './color';
-import { ControlGroup, ExpandGroup, IconButton, NumericInput, ToggleButton } from './common';
+import { ControlGroup, ExpandGroup, IconButton, NumericInput, ToggleButton, Button, ControlRow } from './common';
 import { Icon } from './icons';
 import { legendFor } from './legend';
 import LineGraphComponent from './line-graph/line-graph-component';
@@ -201,7 +201,7 @@ export class ParamHelp<L extends LegendData> extends React.PureComponent<{ legen
         const { legend, description } = this.props
         const Legend = legend && legendFor(legend)
 
-        return <div className='msp-control-row msp-help-text'>
+        return <div className='msp-help-text'>
             <div>
                 <div className='msp-help-description'><Icon name='help-circle' />{description}</div>
                 {Legend && <div className='msp-help-legend'><Legend legend={legend} /></div>}
@@ -225,7 +225,7 @@ export type ParamControl = React.ComponentClass<ParamProps<any>>
 function renderSimple(options: { props: ParamProps<any>, state: { showHelp: boolean }, control: JSX.Element, addOn: JSX.Element | null, toggleHelp: () => void }) {
     const { props, state, control, toggleHelp, addOn } = options;
 
-    const _className = ['msp-control-row'];
+    let _className = [];
     if (props.param.shortLabel) _className.push('msp-control-label-short')
     if (props.param.twoColumns) _className.push('msp-control-col-2')
     const className = _className.join(' ');
@@ -237,8 +237,10 @@ function renderSimple(options: { props: ParamProps<any>, state: { showHelp: bool
     const desc = props.param.description;
     const hasHelp = help.description || help.legend
     return <>
-        <div className={className}>
-            <span title={desc}>
+        <ControlRow
+            className={className}
+            title={desc}
+            label={<>
                 {label}
                 {hasHelp &&
                     <button className='msp-help msp-btn-link msp-btn-icon msp-control-group-expander' onClick={toggleHelp}
@@ -247,11 +249,9 @@ function renderSimple(options: { props: ParamProps<any>, state: { showHelp: bool
                         <Icon name={state.showHelp ? 'help-circle-collapse' : 'help-circle-expand'} />
                     </button>
                 }
-            </span>
-            <div>
-                {control}
-            </div>
-        </div>
+            </>}
+            control={control}
+        />
         {hasHelp && state.showHelp && <div className='msp-control-offset'>
             <ParamHelp legend={help.legend} description={help.description} />
         </div>}
@@ -324,14 +324,7 @@ export class LineGraphControl extends React.PureComponent<ParamProps<PD.LineGrap
     render() {
         const label = this.props.param.label || camelCaseToWords(this.props.name);
         return <>
-            <div className='msp-control-row'>
-                <span>{label}</span>
-                <div>
-                    <button onClick={this.toggleExpanded}>
-                        {`${this.state.message}`}
-                    </button>
-                </div>
-            </div>
+            <ControlRow label={label} control={<button onClick={this.toggleExpanded} disabled={this.props.isDisabled}>{`${this.state.message}`}</button>} />
             <div className='msp-control-offset' style={{ display: this.state.isExpanded ? 'block' : 'none' }}>
                 <LineGraphComponent
                     data={this.props.param.defaultValue}
@@ -356,14 +349,12 @@ export class NumberInputControl extends React.PureComponent<ParamProps<PD.Numeri
         const placeholder = this.props.param.label || camelCaseToWords(this.props.name);
         const label = this.props.param.label || camelCaseToWords(this.props.name);
         const p = getPrecision(this.props.param.step || 0.01)
-        return <div className='msp-control-row'>
-            <span title={this.props.param.description}>{label}</span>
-            <div>
-                <NumericInput
-                    value={parseFloat(this.props.value.toFixed(p))} onEnter={this.props.onEnter} placeholder={placeholder}
-                    isDisabled={this.props.isDisabled} onChange={this.update} />
-            </div>
-        </div>;
+        return <ControlRow
+            title={this.props.param.description}
+            label={label}
+            control={<NumericInput
+                value={parseFloat(this.props.value.toFixed(p))} onEnter={this.props.onEnter} placeholder={placeholder}
+                isDisabled={this.props.isDisabled} onChange={this.update} />} />;
     }
 }
 
@@ -520,15 +511,10 @@ export class IntervalControl extends React.PureComponent<ParamProps<PD.Interval>
         const p = getPrecision(this.props.param.step || 0.01)
         const value = `[${v[0].toFixed(p)}, ${v[1].toFixed(p)}]`;
         return <>
-            <div className='msp-control-row'>
-                <span>{label}</span>
-                <div>
-                    <button onClick={this.toggleExpanded}>{value}</button>
-                </div>
-            </div>
-            <div className='msp-control-offset' style={{ display: this.state.isExpanded ? 'block' : 'none' }}>
+            <ControlRow label={label} control={<button onClick={this.toggleExpanded} disabled={this.props.isDisabled}>{value}</button>} />
+            {this.state.isExpanded && <div className='msp-control-offset'>
                 <ParameterControls params={this.components} values={v} onChange={this.componentChange} onEnter={this.props.onEnter} />
-            </div>
+            </div>}
         </>;
     }
 }
@@ -725,15 +711,10 @@ export class Vec3Control extends React.PureComponent<ParamProps<PD.Vec3>, { isEx
         const p = getPrecision(this.props.param.step || 0.01)
         const value = `[${v[0].toFixed(p)}, ${v[1].toFixed(p)}, ${v[2].toFixed(p)}]`;
         return <>
-            <div className='msp-control-row'>
-                <span>{label}</span>
-                <div>
-                    <button onClick={this.toggleExpanded}>{value}</button>
-                </div>
-            </div>
-            <div className='msp-control-offset' style={{ display: this.state.isExpanded ? 'block' : 'none' }}>
+            <ControlRow label={label} control={<button onClick={this.toggleExpanded} disabled={this.props.isDisabled}>{value}</button>} />
+            {this.state.isExpanded && <div className='msp-control-offset'>
                 <ParameterControls params={this.components} values={v} onChange={this.componentChange} onEnter={this.props.onEnter} />
-            </div>
+            </div>}
         </>;
     }
 }
@@ -809,24 +790,17 @@ export class MultiSelectControl extends React.PureComponent<ParamProps<PD.MultiS
         const emptyLabel = this.props.param.emptyValue;
         const label = this.props.param.label || camelCaseToWords(this.props.name);
         return <>
-            <div className='msp-control-row'>
-                <span>{label}</span>
-                <div>
-                    <button onClick={this.toggleExpanded}>
-                        {current.length === 0 && emptyLabel ? emptyLabel : `${current.length} of ${this.props.param.options.length}`}
-                    </button>
-                </div>
-            </div>
-            <div className='msp-control-offset' style={{ display: this.state.isExpanded ? 'block' : 'none' }}>
+            <ControlRow label={label} control={<button onClick={this.toggleExpanded} disabled={this.props.isDisabled}>
+                {current.length === 0 && emptyLabel ? emptyLabel : `${current.length} of ${this.props.param.options.length}`}
+            </button>} />
+            {this.state.isExpanded && <div className='msp-control-offset'>
                 {this.props.param.options.map(([value, label]) => {
                     const sel = current.indexOf(value) >= 0;
-                    return <div key={value} className='msp-row'>
-                        <button onClick={this.toggle(value)} disabled={this.props.isDisabled}>
-                            <span style={{ float: sel ? 'left' : 'right' }}>{sel ? `✓ ${label}` : `${label} ✗`}</span>
-                        </button>
-                    </div>
+                    return <Button key={value} onClick={this.toggle(value)} disabled={this.props.isDisabled} style={{ marginTop: '1px' }}>
+                        <span style={{ float: sel ? 'left' : 'right' }}>{sel ? `✓ ${label}` : `${label} ✗`}</span>
+                    </Button>
                 })}
-            </div>
+            </div>}
         </>;
     }
 }
@@ -1120,13 +1094,7 @@ export class ObjectListControl extends React.PureComponent<ParamProps<PD.ObjectL
         const label = this.props.param.label || camelCaseToWords(this.props.name);
         const value = `${v.length} item${v.length !== 1 ? 's' : ''}`;
         return <>
-            <div className='msp-control-row'>
-                <span>{label}</span>
-                <div>
-                    <button onClick={this.toggleExpanded} disabled={this.props.isDisabled}>{value}</button>
-                </div>
-            </div>
-
+            <ControlRow label={label} control={<button onClick={this.toggleExpanded} disabled={this.props.isDisabled}>{value}</button>} />
             {this.state.isExpanded && <div className='msp-control-offset'>
                 {this.props.value.map((v, i) => <ObjectListItem key={i} param={this.props.param} value={v} index={i} actions={this.actions} isDisabled={this.props.isDisabled} />)}
                 <ControlGroup header='New Item'>

+ 12 - 23
src/mol-plugin-ui/skin/base/components/controls.scss

@@ -1,5 +1,4 @@
-
-.msp-row, .msp-control-row {
+.msp-control-row {
     position: relative;
     height: $row-height;
     background: $default-background;
@@ -13,10 +12,8 @@
         @extend .msp-btn;
         @extend .msp-btn-block;
     }
-}
 
-.msp-control-row {   
-    > span:first-child, > button.msp-control-button-label {
+    > span.msp-control-row-label, > button.msp-control-button-label {
         line-height: $row-height;
         display: block;
         width: $control-label-width + $control-spacing;
@@ -40,7 +37,7 @@
         background: $default-background;
     }
 
-    > div:nth-child(2) {
+    > div.msp-control-row-ctrl {
         position: absolute;
         left: $control-label-width + $control-spacing;
         top: 0;
@@ -52,7 +49,7 @@
         background: $msp-form-control-background;
     }
 
-    > .msp-select-row {
+    > .msp-flex-row {
         background: $default-background;
     }
 }
@@ -269,21 +266,6 @@
     margin-top: 1px;
 }
 
-.msp-control-subgroup {
-    margin-top: 1px;
-
-    .msp-control-row {
-        margin-left: $control-spacing !important;
-        > span {
-            width: $control-label-width !important;
-        }
-
-        > div:nth-child(2) {
-            left: $control-label-width !important;
-        }
-    }
-}
-
 .msp-control-group-expander {
     display: block;
     position: absolute;
@@ -324,6 +306,11 @@
 }
 
 .msp-row-text {
+    height: $row-height;
+    position: relative;
+    background: $default-background;
+    margin-top: 1px;
+
     > div {
         line-height: $row-height;
         text-align: center;
@@ -341,7 +328,9 @@
 }
 
 .msp-help-text {
-    height: auto !important;
+    position: relative;
+    background: $default-background;
+    margin-top: 1px;
 
     > div {
         padding: ($control-spacing / 2) $control-spacing;

+ 48 - 21
src/mol-plugin-ui/skin/base/components/temp.scss

@@ -56,12 +56,56 @@
     }
 }
 
-.msp-select-row {
+// .msp-select-row {
+//     display:flex;
+//     flex-direction:row;
+//     height: $row-height;
+//     width: inherit;
+//     background: $default-background;
+
+//     > select, > button {
+//         margin: 0;
+//         flex: 1 1 auto;
+//         margin-right: 1px;
+//         height: $row-height;
+
+//         text-align-last: center;
+//         // padding: 0 $control-spacing;
+//         overflow: hidden;
+//     }
+
+//     > select {
+//         background: none;
+
+//         > option[value = _] {
+//             display: none;
+//         }
+//     }
+
+//     > select:last-child, > button:last-child {
+//         margin-right: 0;
+//     }
+// }
+
+.msp-flex-row {
+    margin-top: 1px;
+    background: $default-background;
+
     display:flex;
     flex-direction:row;
-    height: $row-height;
     width: inherit;
-    background: $default-background;
+    height: $row-height;
+
+    > .msp-flex-item {
+        margin: 0;
+        flex: 1 1 auto;
+        margin-right: 1px;
+        overflow: hidden;
+    }
+
+    > .msp-flex-item:last-child {
+        margin-right: 0;
+    }
 
     > select, > button {
         margin: 0;
@@ -70,7 +114,7 @@
         height: $row-height;
 
         text-align-last: center;
-        padding: 0 $control-spacing;
+        // padding: 0 $control-spacing;
         overflow: hidden;
     }
 
@@ -87,23 +131,6 @@
     }
 }
 
-.msp-flex-row {
-    display:flex;
-    flex-direction:row;
-    width: inherit;
-
-    > .msp-flex-item {
-        margin: 0;
-        flex: 1 1 auto;
-        margin-right: 1px;
-        overflow: hidden;
-    }
-
-    > .msp-flex-item:last-child {
-        margin-right: 0;
-    }
-}
-
 .msp-state-list {
     list-style: none;
     margin-top: $control-spacing;

+ 1 - 1
src/mol-plugin-ui/skin/base/components/transformer.scss

@@ -134,7 +134,7 @@
 }
 
 .msp-transform-apply-wider {
-    left: $row-height + 1px;
+    margin-left: $row-height + 1px;
 }
 
 .msp-data-beh {

+ 13 - 14
src/mol-plugin-ui/state/common.tsx

@@ -12,7 +12,7 @@ import { PluginContext } from '../../mol-plugin/context';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { Subject } from 'rxjs';
 import { Icon, IconName } from '../controls/icons';
-import { ExpandGroup, ToggleButton } from '../controls/common';
+import { ExpandGroup, ToggleButton, Button } from '../controls/common';
 
 export { StateTransformParameters, TransformControlBase };
 
@@ -184,21 +184,21 @@ abstract class TransformControlBase<P, S extends TransformControlBase.ComponentS
     }
 
     renderApply() {
-        const showBack = this.isUpdate() && !(this.state.busy || this.state.isInitial);
+        // const showBack = this.isUpdate() && !(this.state.busy || this.state.isInitial);
         const canApply = this.canApply();
 
         return this.props.autoHideApply && !canApply
             ? null
             : <div className='msp-transform-apply-wrap'>
                 <button className='msp-btn msp-btn-block msp-form-control msp-transform-default-params' onClick={this.setDefault} disabled={this.state.busy} title='Set default params'><Icon name='cw' /></button>
-                {showBack && <button className='msp-btn msp-btn-block msp-form-control msp-transform-refresh msp-form-control' title='Refresh params' onClick={this.refresh} disabled={this.state.busy || this.state.isInitial}>
+                {/* {showBack && <Button className='msp-btn msp-btn-block msp-form-control msp-transform-refresh msp-form-control' title='Refresh params' onClick={this.refresh} disabled={this.state.busy || this.state.isInitial}>
                     <Icon name='back' /> Back
-                </button>}
-                <div className={`msp-transform-apply${!showBack ? ' msp-transform-apply-wider' : ''}`}>
-                    <button className={`msp-btn msp-btn-block msp-form-control msp-btn-commit msp-btn-commit-${canApply ? 'on' : 'off'}`} onClick={this.apply} disabled={!canApply}>
-                        {canApply && <Icon name='ok' />}
+                </Button>}
+                <div className={`msp-transform-apply${!showBack ? ' msp-transform-apply-wider' : ''}`}> */}
+                <div className={`msp-transform-apply-wider`}>
+                    <Button icon={canApply ? 'ok' : void 0} className={`msp-btn-commit msp-btn-commit-${canApply ? 'on' : 'off'}`} onClick={this.apply} disabled={!canApply}>
                         {this.props.applyLabel || this.applyText()}
-                    </button>
+                    </Button>
                 </div>
             </div>;
     }
@@ -223,10 +223,10 @@ abstract class TransformControlBase<P, S extends TransformControlBase.ComponentS
 
         const ctrl = <div className={wrapClass} style={{ marginBottom: this.props.noMargin ? 0 : void 0 }}>
             {display !== 'none' && !this.props.wrapInExpander && <div className='msp-transform-header'>
-                <button className={`msp-btn msp-btn-block msp-form-control`} onClick={this.toggleExpanded} title={display.description}>
+                <Button onClick={this.toggleExpanded} title={display.description}>
                     {!isEmpty && <Icon name={this.state.isCollapsed ? 'expand' : 'collapse'} />}
                     {display.name}
-                </button>
+                </Button>
             </div>}
             {!isEmpty && !this.state.isCollapsed && <>
                 <ParamEditor info={info} a={a} b={b} events={this.events} params={this.state.params} isDisabled={this.state.busy} />
@@ -244,11 +244,10 @@ abstract class TransformControlBase<P, S extends TransformControlBase.ComponentS
     renderSimple() {
         const info = this.getInfo();
         const canApply = this.canApply();
-        const apply = <div className='msp-control-row msp-select-row'>
-            <button disabled={this.state.busy || !canApply} onClick={this.apply}>
-                <Icon name={this.props.simpleApply?.icon} />
+        const apply = <div className='msp-flex-row'>
+            <Button icon={this.props.simpleApply?.icon} disabled={this.state.busy || !canApply} onClick={this.apply}>
                 {this.props.simpleApply?.header}
-            </button>
+            </Button>
             {!info.isEmpty && <ToggleButton icon='cog' label='' title='Options' toggle={this.toggleExpanded} isSelected={!this.state.isCollapsed} disabled={this.state.busy} style={{ flex: '0 0 40px', padding: 0 }} />}
         </div>
 

+ 1 - 1
src/mol-plugin-ui/structure/components.tsx

@@ -115,7 +115,7 @@ class ComponentEditorControls extends PurePluginUIComponent<{}, ComponentEditorC
             ? `Undo ${this.plugin.state.data.latestUndoLabel}`
             : 'Some mistakes of the past can be undone.';
         return <>
-            <div className='msp-control-row msp-select-row'>
+            <div className='msp-flex-row'>
                 <ToggleButton icon='bookmarks' label='Preset' toggle={this.togglePreset} isSelected={this.state.action === 'preset'} disabled={this.isDisabled} />
                 <ToggleButton icon='plus' label='Add' toggle={this.toggleAdd} isSelected={this.state.action === 'add'} disabled={this.isDisabled} />
                 <ToggleButton icon='cog' label='' title='Options' style={{ flex: '0 0 40px', padding: 0 }} toggle={this.toggleOptions} isSelected={this.state.action === 'options'} disabled={this.isDisabled} />

+ 1 - 1
src/mol-plugin-ui/structure/focus.tsx

@@ -186,7 +186,7 @@ export class StructureFocusControls extends PluginUIComponent<{}, StructureFocus
         }
 
         return <>
-            <div className='msp-control-row msp-select-row'>
+            <div className='msp-flex-row'>
                 <Button noOverflow onClick={this.focus} title={title} onMouseEnter={this.highlightCurrent} onMouseLeave={this.clearHighlights} disabled={this.isDisabled || !current}
                     style={{ textAlignLast: current ? 'left' : void 0 }}>
                     {label}

+ 1 - 1
src/mol-plugin-ui/structure/measurements.tsx

@@ -168,7 +168,7 @@ export class MeasurementControls extends PurePluginUIComponent<{}, { isBusy: boo
 
     render() {
         return <>
-            <div className='msp-control-row msp-select-row'>
+            <div className='msp-flex-row'>
                 <ToggleButton icon='plus' label='Add' toggle={this.toggleAdd} isSelected={this.state.action === 'add'} disabled={this.state.isBusy} />
                 <ToggleButton icon='cog' label='' title='Options' toggle={this.toggleOptions} isSelected={this.state.action === 'options'} disabled={this.state.isBusy} style={{ flex: '0 0 40px', padding: 0 }} />
             </div>

+ 2 - 2
src/mol-plugin-ui/structure/selection.tsx

@@ -134,7 +134,7 @@ export class StructureSelectionControls<P, S extends StructureSelectionControlsS
 
     get controls() {
         return <>
-            <div className='msp-control-row msp-select-row'>
+            <div className='msp-flex-row'>
                 <ToggleButton icon='union' title={ActionHeader.get('add')} toggle={this.toggleAdd} isSelected={this.state.action === 'add'} disabled={this.isDisabled} />
                 <ToggleButton icon='subtract' title={ActionHeader.get('remove')} toggle={this.toggleRemove} isSelected={this.state.action === 'remove'} disabled={this.isDisabled} />
                 <ToggleButton icon='intersect' title={ActionHeader.get('intersect')} toggle={this.toggleIntersect} isSelected={this.state.action === 'intersect'} disabled={this.isDisabled} />
@@ -167,7 +167,7 @@ export class StructureSelectionControls<P, S extends StructureSelectionControlsS
         return <>
             <ParameterControls params={StructureSelectionParams} values={this.values} onChangeValues={this.setProps} />
             {this.controls}
-            <div className='msp-control-row msp-select-row' style={{ margin: '6px 0' }}>
+            <div className='msp-flex-row' style={{ margin: '6px 0' }}>
                 <Button noOverflow onClick={this.focus} title='Click to Focus Selection' disabled={empty}
                     style={{ textAlignLast: !empty ? 'left' : void 0 }}>
                     {this.stats}

+ 1 - 1
src/mol-plugin-ui/viewport/help.tsx

@@ -39,7 +39,7 @@ export class BindingsHelp extends React.PureComponent<{ bindings: { [k: string]:
 
 class HelpText extends React.PureComponent {
     render() {
-        return <div className='msp-control-row msp-help-text'>
+        return <div className='msp-help-text'>
             <div>{this.props.children}</div>
         </div>
     }

+ 1 - 1
src/mol-plugin/behavior/dynamic/custom-props/rcsb/ui/assembly-symmetry.tsx

@@ -56,7 +56,7 @@ export class AssemblySymmetryControls extends CollapsableControls<{}, AssemblySy
     }
 
     renderNoSymmetries() {
-        return <div className='msp-control-row msp-row-text'>
+        return <div className='msp-row-text'>
             <div>No Symmetries for Assembly</div>
         </div>;
     }