Skip to content

Commit

Permalink
Better looking checkboxes (#3345)
Browse files Browse the repository at this point in the history
Also showing icon only on hover on control headers
  • Loading branch information
mistercrunch committed Aug 21, 2017
1 parent e79adbb commit 2546457
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@ const propTypes = {
icon: PropTypes.string,
className: PropTypes.string,
onClick: PropTypes.func,
placement: PropTypes.string,
};
const defaultProps = {
icon: 'question-circle-o',
icon: 'info-circle',
className: 'text-muted',
placement: 'right',
};

export default function InfoTooltipWithTrigger({ label, tooltip, icon, className, onClick }) {
export default function InfoTooltipWithTrigger({
label, tooltip, icon, className, onClick, placement }) {
return (
<OverlayTrigger
placement="right"
placement={placement}
overlay={<Tooltip id={`${slugify(label)}-tooltip`}>{tooltip}</Tooltip>}
>
<i
Expand Down
11 changes: 10 additions & 1 deletion superset/assets/javascripts/explore/components/Control.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const defaultProps = {
export default class Control extends React.PureComponent {
constructor(props) {
super(props);
this.state = { hovered: false };
this.validate = this.validate.bind(this);
this.onChange = this.onChange.bind(this);
}
Expand All @@ -65,6 +66,9 @@ export default class Control extends React.PureComponent {
onChange(value, errors) {
this.validateAndSetValue(value, errors);
}
setHover(hovered) {
this.setState({ hovered });
}
validateAndSetValue(value, errors) {
let validationErrors = this.props.validationErrors;
let currentErrors = this.validate(value);
Expand Down Expand Up @@ -96,9 +100,14 @@ export default class Control extends React.PureComponent {
const ControlType = controlMap[this.props.type];
const divStyle = this.props.hidden ? { display: 'none' } : null;
return (
<div style={divStyle}>
<div
style={divStyle}
onMouseEnter={this.setHover.bind(this, true)}
onMouseLeave={this.setHover.bind(this, false)}
>
<ControlType
onChange={this.onChange}
hovered={this.state.hovered}
{...this.props}
/>
</div>
Expand Down
120 changes: 69 additions & 51 deletions superset/assets/javascripts/explore/components/ControlHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,74 +10,92 @@ const propTypes = {
renderTrigger: PropTypes.bool,
rightNode: PropTypes.node,
leftNode: PropTypes.node,
onClick: PropTypes.func,
hovered: PropTypes.bool,
};

const defaultProps = {
validationErrors: [],
renderTrigger: false,
hovered: false,
};

export default function ControlHeader({
label, description, validationErrors, renderTrigger, leftNode, rightNode }) {
const hasError = (validationErrors.length > 0);
return (
<div>
<div className="pull-left">
<ControlLabel>
{hasError ?
<strong className="text-danger">{label}</strong> :
<span>{label}</span>
}
{' '}
{(validationErrors.length > 0) &&
export default class ControlHeader extends React.Component {
renderOptionalIcons() {
if (this.props.hovered) {
return (
<span>
{this.props.description &&
<span>
<OverlayTrigger
placement="right"
overlay={
<Tooltip id={'error-tooltip'}>
{validationErrors.join(' ')}
</Tooltip>
}
>
<i className="fa fa-exclamation-circle text-danger" />
</OverlayTrigger>
<InfoTooltipWithTrigger
label="descr"
tooltip={this.props.description}
placement="top"
/>
{' '}
</span>
}
{description &&
{this.props.renderTrigger &&
<span>
<InfoTooltipWithTrigger label={label} tooltip={description} />
<InfoTooltipWithTrigger
label="bolt"
tooltip={this.props.description}
placement="top"
icon="bolt"
/>
{' '}
</span>
}
{renderTrigger &&
<span>
<OverlayTrigger
placement="right"
overlay={
<Tooltip id={'rendertrigger-tooltip'}>
Takes effect on chart immediatly
</Tooltip>
}
>
<i className="fa fa-bolt text-muted" />
</OverlayTrigger>
{' '}
</span>);
}
return null;
}
render() {
const labelClass = (this.props.validationErrors.length > 0) ? 'text-danger' : '';
return (
<div
className="ControlHeader"
>
<div className="pull-left">
<ControlLabel>
{this.props.leftNode &&
<span>{this.props.leftNode}</span>
}
<span
onClick={this.props.onClick}
className={labelClass}
style={{ cursor: this.props.onClick ? 'pointer' : '' }}
>
{this.props.label}
</span>
}
{leftNode &&
<span>{leftNode}</span>
}
</ControlLabel>
</div>
{rightNode &&
<div className="pull-right">
{rightNode}
{' '}
{(this.props.validationErrors.length > 0) &&
<span>
<OverlayTrigger
placement="top"
overlay={
<Tooltip id={'error-tooltip'}>
{this.props.validationErrors.join(' ')}
</Tooltip>
}
>
<i className="fa fa-exclamation-circle text-danger" />
</OverlayTrigger>
{' '}
</span>
}
{this.renderOptionalIcons()}
</ControlLabel>
</div>
}
<div className="clearfix" />
</div>
);
{this.props.rightNode &&
<div className="pull-right">
{this.props.rightNode}
</div>
}
<div className="clearfix" />
</div>
);
}
}

ControlHeader.propTypes = propTypes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Checkbox } from 'react-bootstrap';
import ControlHeader from '../ControlHeader';

const propTypes = {
Expand All @@ -24,11 +23,16 @@ export default class CheckboxControl extends React.Component {
return (
<ControlHeader
{...this.props}
onClick={this.onToggle.bind(this)}
leftNode={
<Checkbox
checked={this.props.value}
onChange={this.onToggle.bind(this)}
/>
<span>
<i
className={`fa fa-check ${this.props.value ? 'text-primary' : 'text-transparent'}`}
onClick={this.onToggle.bind(this)}
style={{ border: '1px solid #aaa', borderRadius: '2px', cursor: 'pointer' }}
/>
&nbsp;&nbsp;
</span>
}
/>
);
Expand Down
2 changes: 1 addition & 1 deletion superset/assets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"react-addons-css-transition-group": "^15.6.0",
"react-addons-shallow-compare": "^15.4.2",
"react-alert": "^1.0.14",
"react-bootstrap": "^0.31.0",
"react-bootstrap": "^0.31.2",
"react-bootstrap-table": "^3.1.7",
"react-dom": "^15.5.1",
"react-gravatar": "^2.6.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable no-unused-expressions */
import React from 'react';
import { Checkbox } from 'react-bootstrap';
import sinon from 'sinon';
import { expect } from 'chai';
import { describe, it, beforeEach } from 'mocha';
Expand Down Expand Up @@ -28,6 +27,6 @@ describe('CheckboxControl', () => {
expect(controlHeader).to.have.lengthOf(1);

const headerWrapper = controlHeader.shallow();
expect(headerWrapper.find(Checkbox)).to.have.length(1);
expect(headerWrapper.find('i.fa-check')).to.have.length(1);
});
});
3 changes: 3 additions & 0 deletions superset/assets/stylesheets/superset.less
Original file line number Diff line number Diff line change
Expand Up @@ -329,3 +329,6 @@ iframe {
border: none;
width: 100%;
}
.text-transparent {
color: transparent;
}

0 comments on commit 2546457

Please sign in to comment.