Color picker for admin config

This commit is contained in:
Sean King
2020-08-02 14:41:26 -06:00
parent ba18c3a643
commit f398dde5cb
5 changed files with 160 additions and 5 deletions

View File

@@ -11,6 +11,7 @@ import {
TextInput,
Checkbox,
FileChooser,
ColorWithPicker,
} from 'soapbox/features/forms';
import StillImage from 'soapbox/components/still_image';
import {
@@ -177,7 +178,7 @@ class ConfigSoapbox extends ImmutablePureComponent {
}
handleBrandColorChange = e => {
this.setState({ brandColor: e.target.value });
this.setState({ brandColor: e.hex });
}
handleTextChange = e => {
@@ -284,10 +285,13 @@ class ConfigSoapbox extends ImmutablePureComponent {
</div>
</FieldsGroup>
<FieldsGroup>
<div>
<label htmlFor='brand_color'><FormattedMessage id='soapbox_settings.fields.brand_color_label' defaultMessage='Brand color' /></label><br /><br />
<input type='color' id='brand_color' name='brand_color' value={this.state.brandColor || '#0482d8'} onChange={this.handleBrandColorChange} /><br /><br />
<label>{ this.state.brandColor }</label>
<div className='fields-row__column fields-group'>
<ColorWithPicker
buttonId='brand_color'
label={<FormattedMessage id='soapbox_settings.fields.brand_color_label' defaultMessage='Brand color' />}
value={this.state.brandColor || '#0482d8'}
onChange={this.handleBrandColorChange}
/>
</div>
</FieldsGroup>
<FieldsGroup>

View File

@@ -3,6 +3,10 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { v4 as uuidv4 } from 'uuid';
import { SketchPicker } from 'react-color';
import Overlay from 'react-overlays/lib/Overlay';
import { isMobile } from '../../is_mobile';
import detectPassiveEvents from 'detect-passive-events';
const FormPropTypes = {
label: PropTypes.oneOfType([
@@ -12,6 +16,8 @@ const FormPropTypes = {
]),
};
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
export const InputContainer = (props) => {
const containerClass = classNames('input', {
'with_label': props.label,
@@ -153,6 +159,98 @@ export class RadioGroup extends ImmutablePureComponent {
}
export class ColorPicker extends React.PureComponent {
static propTypes = {
style: PropTypes.object,
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
onClose: PropTypes.func,
}
handleDocumentClick = e => {
if (this.node && !this.node.contains(e.target)) {
this.props.onClose();
}
}
componentDidMount() {
document.addEventListener('click', this.handleDocumentClick, false);
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleDocumentClick, false);
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
}
setRef = c => {
this.node = c;
}
render() {
const { style, value, onChange } = this.props;
let margin_left_picker = isMobile(window.innerWidth) ? '20px' : '12px';
return (
<div id='SketchPickerContainer' ref={this.setRef} style={{ ...style, marginLeft: margin_left_picker, position: 'absolute', zIndex: 1000 }}>
<SketchPicker color={value} disableAlpha onChange={onChange} />
</div>
);
}
}
export class ColorWithPicker extends ImmutablePureComponent {
static propTypes = {
buttonId: PropTypes.string.isRequired,
label: FormPropTypes.label,
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
}
onToggle = (e) => {
if (!e.key || e.key === 'Enter') {
if (this.state.active) {
this.onHidePicker();
} else {
this.onShowPicker(e);
}
}
}
state = {
active: false,
placement: null,
}
onHidePicker = () => {
this.setState({ active: false });
}
onShowPicker = ({ target }) => {
this.setState({ active: true });
this.setState({ placement: isMobile(window.innerWidth) ? 'bottom' : 'right' });
}
render() {
const { buttonId, label, value, onChange } = this.props;
const { active, placement } = this.state;
return (
<div className='label_input__color'>
<label>{label}</label>
<button id={buttonId} className='color-swatch' style={{ background: value }} value={value} onClick={this.onToggle} />
<Overlay show={active} placement={placement} target={this}>
<ColorPicker value={value} onChange={onChange} onClose={this.onHidePicker} />
</Overlay>
</div>
);
}
}
export class RadioItem extends ImmutablePureComponent {
static propTypes = {

View File

@@ -444,6 +444,19 @@ code {
}
.label_input {
&__color {
display: inline-flex;
font-size: 14px;
.color-swatch {
width: 32px;
height: 16px;
margin-left: 12px;
display: inline-block;
}
}
&__wrapper {
position: relative;
}