Skip to content

Commit

Permalink
Add ColorControl. Create initial UI with mock state
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Q committed Feb 6, 2020
1 parent 8b5cbf0 commit 921c99f
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 48 deletions.
106 changes: 106 additions & 0 deletions packages/components/src/color-control/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/**
* External dependencies
*/
import colorize from 'tinycolor2';
import classnames from 'classnames';
import { noop } from 'lodash';
/**
* WordPress dependencies
*/
import { useState, useCallback } from '@wordpress/element';
import { compose, withInstanceId } from '@wordpress/compose';

/**
* Internal dependencies
*/
import BaseControl from '../base-control';
import ColorPicker from '../color-picker';
import Dropdown from '../dropdown';

import {
ControlContainer,
ControlWrapper,
ColorSwatch,
ColorLabel,
} from './styles/color-control-styles';

function BaseColorControl( {
className,
instanceId,
label,
value = 'black',
onChange = noop,
...props
} ) {
const [ isFocused, setIsFocused ] = useState( false );
const [ isOpen, setIsOpen ] = useState( false );

// TODO: Add derived prop/controlled hook to manage state
const [ color, setColor ] = useState( toColor( value ) );

const handleOnChange = ( nextColor ) => {
setColor( nextColor );
onChange( nextColor );
};

const renderToggle = useCallback(
( { isOpen: isOpenProp, onToggle } ) => {
setIsOpen( isOpenProp );
return (
<ColorSwatch
aria-expanded={ isOpenProp }
onBlur={ () => setIsFocused( false ) }
onFocus={ () => setIsFocused( true ) }
style={ { backgroundColor: color } }
onClick={ onToggle }
/>
);
},
[ color ]
);

const renderContent = useCallback(
() => (
<ColorPicker
color={ color }
onChangeComplete={ ( nextColor ) =>
handleOnChange( nextColor.hex )
}
disableAlpha
/>
),
[ color ]
);

const classes = classnames( 'components-color-control', className );
const id = `inspector-color-control-${ instanceId }`;
const isFocusedOrOpen = isFocused || isOpen;

return (
<ControlWrapper className={ classes }>
<BaseControl label={ label } id={ id } { ...props }>
<ControlContainer
isFocused={ isFocusedOrOpen }
className="components-color-control__container"
>
<Dropdown
className="components-color-control__swatch-picker"
noArrow={ true }
position="middle left"
renderToggle={ renderToggle }
renderContent={ renderContent }
/>
<ColorLabel className="components-color-control__label">
{ color }
</ColorLabel>
</ControlContainer>
</BaseControl>
</ControlWrapper>
);
}

function toColor( color ) {
return colorize( color ).toHexString();
}

export default compose( [ withInstanceId ] )( BaseColorControl );
25 changes: 25 additions & 0 deletions packages/components/src/color-control/stories/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* External dependencies
*/
import styled from '@emotion/styled';

/**
* Internal dependencies
*/
import ColorControl from '../';

export default { title: 'Components/ColorControl', component: ColorControl };

export const _default = () => {
return (
<Wrapper>
<ColorControl />
</Wrapper>
);
};

const Wrapper = styled.div`
padding: 40px;
margin-left: auto;
width: 250px;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* External dependencies
*/
import { css } from '@emotion/core';
import styled from '@emotion/styled';

/**
* Internal dependencies
*/
import { color } from '../../utils/colors';

export const ControlWrapper = styled.div``;

const containerFocus = ( { isFocused } ) => {
if ( ! isFocused ) return '';

return css`
border: 1px solid ${color( 'blue.medium.focus' )};
box-shadow: 0 0 0 1px ${color( 'blue.medium.focus' )};
`;
};

export const ControlContainer = styled.div`
align-items: center;
border-radius: 2px;
border: 1px solid ${color( 'lightGray.600' )};
box-sizing: border-box;
display: flex;
height: 36px;
overflow: hidden;
max-width: 110px;
${containerFocus};
`;

export const ColorSwatch = styled.button`
appearance: none;
border: none;
border-right: 1px solid ${color( 'lightGray.600' )};
box-sizing: border-box;
cursor: pointer;
display: block;
height: 36px;
outline: none;
width: 36px;
&:focus {
outline: none;
}
`;

export const ColorLabel = styled.div`
box-sizing: border-box;
padding: 4px 8px;
width: 72px;
font-size: 12px;
`;
1 change: 1 addition & 0 deletions packages/components/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export { default as CardMedia } from './card/media';
export { default as CheckboxControl } from './checkbox-control';
export { default as ClipboardButton } from './clipboard-button';
export { default as ColorIndicator } from './color-indicator';
export { default as ColorControl } from './color-control';
export { default as ColorPalette } from './color-palette';
export { default as ColorPicker } from './color-picker';
export { default as CustomSelectControl } from './custom-select-control';
Expand Down
71 changes: 71 additions & 0 deletions packages/edit-site/src/components/sidebar/global-styles-panel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { useState } from '@wordpress/element';

import {
ColorControl,
Panel,
PanelBody,
RangeControl,
} from '@wordpress/components';

export default function GlobalStylesPanel() {
// TODO: Replace with data/actions from wp.data
const [ fontSize, setFontSize ] = useState( 16 );
const [ fontScale, setFontScale ] = useState( 1.2 );
const [ lineHeight, setLineHeight ] = useState( 1.5 );

const [ textColor, setTextColor ] = useState( '#000000' );
const [ backgroundColor, setBackgroundColor ] = useState( '#ffffff' );
const [ primaryColor, setPrimaryColor ] = useState( '#0000ff' );

return (
<Panel header={ __( 'Global Styles' ) }>
<PanelBody title={ __( 'Typography' ) } initialOpen={ false }>
<RangeControl
label={ __( 'Font Size' ) }
value={ fontSize }
min={ 10 }
max={ 30 }
step={ 1 }
onChange={ setFontSize }
/>
<RangeControl
label={ __( 'Font Scale' ) }
value={ fontScale }
min={ 1.1 }
max={ 1.4 }
step={ 0.025 }
onChange={ setFontScale }
/>
<RangeControl
label={ __( 'Line Height' ) }
value={ lineHeight }
min={ 1 }
max={ 2 }
step={ 0.1 }
onChange={ setLineHeight }
/>
</PanelBody>
<PanelBody title={ __( 'Colors' ) } initialOpen={ false }>
<ColorControl
label={ __( 'Text' ) }
value={ textColor }
onChange={ setTextColor }
/>
<ColorControl
label={ __( 'Background' ) }
value={ backgroundColor }
onChange={ setBackgroundColor }
/>
<ColorControl
label={ __( 'Primary' ) }
value={ primaryColor }
onChange={ setPrimaryColor }
/>
</PanelBody>
</Panel>
);
}
46 changes: 0 additions & 46 deletions packages/edit-site/src/components/sidebar/global-styles.js

This file was deleted.

4 changes: 2 additions & 2 deletions packages/edit-site/src/components/sidebar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import GlobalStyles from './global-styles';
import GlobalStylesPanel from './global-styles-panel';

const { Slot: InspectorSlot, Fill: InspectorFill } = createSlotFill(
'EditSiteSidebarInspector'
Expand All @@ -21,7 +21,7 @@ function Sidebar() {
aria-label={ __( 'Site editor advanced settings.' ) }
tabIndex="-1"
>
<GlobalStyles />
<GlobalStylesPanel />
<Panel header={ __( 'Inspector' ) }>
<InspectorSlot bubblesVirtually />
</Panel>
Expand Down

0 comments on commit 921c99f

Please sign in to comment.