Skip to content

Commit

Permalink
CustomGradientPicker: Update Type and Angle controls (#23802)
Browse files Browse the repository at this point in the history
* Refactor AnglePickerControl styles

* Update SelectControl. Integrate new SelectControl with AnglePickerControl in GradientPicker

* Improve Gradient Select and radio control UI

* Update snapshots

* Update snapshot

* Update snapshot

* Add label for gradient picker type

* Fixed sizing.

* Improve focus.

* Harmonize spacing.

* Fix so swatches align with the gradient control below.

Co-authored-by: jasmussen <[email protected]>
  • Loading branch information
Q and jasmussen authored Aug 31, 2020
1 parent dc4a0b3 commit be09692
Show file tree
Hide file tree
Showing 23 changed files with 666 additions and 411 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
.block-editor-color-gradient-control {
&__color-indicator {
margin-bottom: $grid-unit-10;
.block-editor-color-gradient-control__color-indicator {
margin-bottom: $grid-unit-15;
}

&__button-tabs {
.block-editor-color-gradient-control__button-tabs {
display: block;
margin-bottom: $grid-unit-10;
margin-bottom: $grid-unit-15;
}
}

Expand Down
6 changes: 3 additions & 3 deletions packages/block-editor/src/components/gradient-picker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { pick } from 'lodash';
/**
* WordPress dependencies
*/
import { __experimentalGradientPicker } from '@wordpress/components';
import { __experimentalGradientPicker as GradientPicker } from '@wordpress/components';
import { useSelect } from '@wordpress/data';

function GradientPickerWithGradients( props ) {
Expand All @@ -19,7 +19,7 @@ function GradientPickerWithGradients( props ) {
[]
);
return (
<__experimentalGradientPicker
<GradientPicker
gradients={
props.gradients !== undefined ? props.gradient : gradients
}
Expand All @@ -37,7 +37,7 @@ export default function ( props ) {
const ComponentToUse =
props.gradients !== undefined &&
props.disableCustomGradients !== undefined
? __experimentalGradientPicker
? GradientPicker
: GradientPickerWithGradients;
return <ComponentToUse { ...props } />;
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Basic rendering should render with required props 1`] = `"<fieldset class=\\"block-editor-responsive-block-control\\"><legend class=\\"block-editor-responsive-block-control__title\\">Padding</legend><div class=\\"block-editor-responsive-block-control__inner\\"><div class=\\"components-base-control components-toggle-control block-editor-responsive-block-control__toggle\\"><div class=\\"components-base-control__field\\"><span class=\\"components-form-toggle is-checked\\"><input class=\\"components-form-toggle__input\\" id=\\"inspector-toggle-control-0\\" type=\\"checkbox\\" aria-describedby=\\"inspector-toggle-control-0__help\\" checked=\\"\\"><span class=\\"components-form-toggle__track\\"></span><span class=\\"components-form-toggle__thumb\\"></span></span><label for=\\"inspector-toggle-control-0\\" class=\\"components-toggle-control__label\\">Use the same padding on all screensizes.</label></div><p id=\\"inspector-toggle-control-0__help\\" class=\\"components-base-control__help\\">Toggle between using the same value for all screen sizes or using a unique value per screen size.</p></div><div class=\\"block-editor-responsive-block-control__group\\"><div class=\\"components-base-control\\"><div class=\\"components-base-control__field\\"><label class=\\"components-base-control__label\\" for=\\"inspector-select-control-0\\"><span aria-describedby=\\"rbc-desc-0\\">All</span><span class=\\"components-visually-hidden\\" id=\\"rbc-desc-0\\">Controls the padding property for All viewports.</span></label><select id=\\"inspector-select-control-0\\" class=\\"components-select-control__input\\"><option value=\\"\\">Please select</option><option value=\\"small\\">Small</option><option value=\\"medium\\">Medium</option><option value=\\"large\\">Large</option></select></div></div><p id=\\"all\\">All is used here for testing purposes to ensure we have access to details about the device.</p></div></div></fieldset>"`;
exports[`Basic rendering should render with required props 1`] = `"<fieldset class=\\"block-editor-responsive-block-control\\"><legend class=\\"block-editor-responsive-block-control__title\\">Padding</legend><div class=\\"block-editor-responsive-block-control__inner\\"><div class=\\"components-base-control components-toggle-control block-editor-responsive-block-control__toggle\\"><div class=\\"components-base-control__field\\"><span class=\\"components-form-toggle is-checked\\"><input class=\\"components-form-toggle__input\\" id=\\"inspector-toggle-control-0\\" type=\\"checkbox\\" aria-describedby=\\"inspector-toggle-control-0__help\\" checked=\\"\\"><span class=\\"components-form-toggle__track\\"></span><span class=\\"components-form-toggle__thumb\\"></span></span><label for=\\"inspector-toggle-control-0\\" class=\\"components-toggle-control__label\\">Use the same padding on all screensizes.</label></div><p id=\\"inspector-toggle-control-0__help\\" class=\\"components-base-control__help\\">Toggle between using the same value for all screen sizes or using a unique value per screen size.</p></div><div class=\\"block-editor-responsive-block-control__group\\"><div class=\\"components-base-control\\"><div class=\\"components-base-control__field\\"><div class=\\"components-flex components-select-control e1cr7zh10 css-sbt0p2-Flex-Root eboqfv50\\"><div class=\\"components-flex__item e1cr7zh14 css-d373l0-Item-LabelWrapper eboqfv51\\"><label for=\\"inspector-select-control-0\\" class=\\"components-input-control__label css-7tv4lf-Text-BaseLabel e1cr7zh13\\"><span aria-describedby=\\"rbc-desc-0\\">All</span><span class=\\"components-visually-hidden\\" id=\\"rbc-desc-0\\">Controls the padding property for All viewports.</span></label></div><div class=\\"components-input-control__container css-99mm9s-Container e1cr7zh11\\"><select class=\\"components-select-control__input css-hwcz8s-Select e12x0a390\\" id=\\"inspector-select-control-0\\"><option value=\\"\\">Please select</option><option value=\\"small\\">Small</option><option value=\\"medium\\">Medium</option><option value=\\"large\\">Large</option></select><span class=\\"components-input-control__suffix css-1lym30p-Suffix e1cr7zh19\\"><div class=\\"css-s55r1c-DownArrowWrapper e12x0a391\\"><svg viewBox=\\"0 0 24 24\\" xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"18\\" height=\\"18\\" role=\\"img\\" aria-hidden=\\"true\\" focusable=\\"false\\"><path d=\\"M17 9.4L12 14 7 9.4l-1 1.2 6 5.4 6-5.4z\\"></path></svg></div></span><fieldset aria-hidden=\\"true\\" class=\\"components-input-control__backdrop css-15qcvxb-Fieldset e1cr7zh15\\"></fieldset></div></div></div></div><p id=\\"all\\">All is used here for testing purposes to ensure we have access to details about the device.</p></div></div></fieldset>"`;
93 changes: 93 additions & 0 deletions packages/components/src/angle-picker-control/angle-circle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* WordPress dependencies
*/
import { useEffect, useRef } from '@wordpress/element';
import { __experimentalUseDragging as useDragging } from '@wordpress/compose';

/**
* Internal dependencies
*/
import {
CircleRoot,
CircleIndicatorWrapper,
CircleIndicator,
} from './styles/angle-picker-control-styles';

function AngleCircle( { value, onChange, ...props } ) {
const angleCircleRef = useRef();
const angleCircleCenter = useRef();
const previousCursorValue = useRef();

const setAngleCircleCenter = () => {
const rect = angleCircleRef.current.getBoundingClientRect();
angleCircleCenter.current = {
x: rect.x + rect.width / 2,
y: rect.y + rect.height / 2,
};
};

const changeAngleToPosition = ( event ) => {
const { x: centerX, y: centerY } = angleCircleCenter.current;
// Prevent (drag) mouse events from selecting and accidentally
// triggering actions from other elements.
event.preventDefault();

onChange( getAngle( centerX, centerY, event.clientX, event.clientY ) );
};

const { startDrag, isDragging } = useDragging( {
onDragStart: ( event ) => {
setAngleCircleCenter();
changeAngleToPosition( event );
},
onDragMove: changeAngleToPosition,
onDragEnd: changeAngleToPosition,
} );

useEffect( () => {
if ( isDragging ) {
if ( previousCursorValue.current === undefined ) {
previousCursorValue.current = document.body.style.cursor;
}
document.body.style.cursor = 'grabbing';
} else {
document.body.style.cursor = previousCursorValue.current || null;
previousCursorValue.current = undefined;
}
}, [ isDragging ] );

return (
/* eslint-disable jsx-a11y/no-static-element-interactions */
<CircleRoot
ref={ angleCircleRef }
onMouseDown={ startDrag }
className="components-angle-picker-control__angle-circle"
style={ isDragging ? { cursor: 'grabbing' } : undefined }
{ ...props }
>
<CircleIndicatorWrapper
style={
value ? { transform: `rotate(${ value }deg)` } : undefined
}
className="components-angle-picker-control__angle-circle-indicator-wrapper"
>
<CircleIndicator className="components-angle-picker-control__angle-circle-indicator" />
</CircleIndicatorWrapper>
</CircleRoot>
/* eslint-enable jsx-a11y/no-static-element-interactions */
);
}

function getAngle( centerX, centerY, pointX, pointY ) {
const y = pointY - centerY;
const x = pointX - centerX;

const angleInRadians = Math.atan2( y, x );
const angleInDeg = Math.round( angleInRadians * ( 180 / Math.PI ) ) + 90;
if ( angleInDeg < 0 ) {
return 360 + angleInDeg;
}
return angleInDeg;
}

export default AngleCircle;
150 changes: 54 additions & 96 deletions packages/components/src/angle-picker-control/index.js
Original file line number Diff line number Diff line change
@@ -1,116 +1,74 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import { useRef } from '@wordpress/element';
import {
useInstanceId,
__experimentalUseDragging as useDragging,
} from '@wordpress/compose';
import { __ } from '@wordpress/i18n';
import { useInstanceId } from '@wordpress/compose';

/**
* Internal dependencies
*/
import BaseControl from '../base-control';

function getAngle( centerX, centerY, pointX, pointY ) {
const y = pointY - centerY;
const x = pointX - centerX;

const angleInRadians = Math.atan2( y, x );
const angleInDeg = Math.round( angleInRadians * ( 180 / Math.PI ) ) + 90;
if ( angleInDeg < 0 ) {
return 360 + angleInDeg;
}
return angleInDeg;
}

const AngleCircle = ( { value, onChange, ...props } ) => {
const angleCircleRef = useRef();
const angleCircleCenter = useRef();

const setAngleCircleCenter = () => {
const rect = angleCircleRef.current.getBoundingClientRect();
angleCircleCenter.current = {
x: rect.x + rect.width / 2,
y: rect.y + rect.height / 2,
};
};

const changeAngleToPosition = ( event ) => {
const { x: centerX, y: centerY } = angleCircleCenter.current;
// Prevent (drag) mouse events from selecting and accidentally
// triggering actions from other elements.
event.preventDefault();

onChange( getAngle( centerX, centerY, event.clientX, event.clientY ) );
};

const { startDrag, isDragging } = useDragging( {
onDragStart: ( event ) => {
setAngleCircleCenter();
changeAngleToPosition( event );
},
onDragMove: changeAngleToPosition,
onDragEnd: changeAngleToPosition,
} );
return (
/* eslint-disable jsx-a11y/no-static-element-interactions */
<div
ref={ angleCircleRef }
onMouseDown={ startDrag }
className="components-angle-picker-control__angle-circle"
style={ isDragging ? { cursor: 'grabbing' } : undefined }
{ ...props }
>
<div
style={
value ? { transform: `rotate(${ value }deg)` } : undefined
}
className="components-angle-picker-control__angle-circle-indicator-wrapper"
>
<span className="components-angle-picker-control__angle-circle-indicator" />
</div>
</div>
/* eslint-enable jsx-a11y/no-static-element-interactions */
);
};
import { FlexBlock } from '../flex';
import NumberControl from '../number-control';
import AngleCircle from './angle-circle';
import {
Root,
NumberControlWrapper,
} from './styles/angle-picker-control-styles';

export default function AnglePickerControl( {
className,
id: idProp,
value,
onChange,
label = __( 'Angle' ),
label,
...props
} ) {
const instanceId = useInstanceId( AnglePickerControl );
const inputId = `components-angle-picker-control__input-${ instanceId }`;
const instanceId = useInstanceId(
AnglePickerControl,
'components-angle-picker-control__input'
);
const id = idProp || instanceId;

const handleOnNumberChange = ( unprocessedValue ) => {
const inputValue =
unprocessedValue !== '' ? parseInt( unprocessedValue, 10 ) : 0;
onChange( inputValue );
};

const classes = classnames( 'components-angle-picker-control', className );

return (
<BaseControl
className={ classes }
id={ id }
label={ label }
id={ inputId }
className="components-angle-picker-control"
{ ...props }
>
<AngleCircle
value={ value }
onChange={ onChange }
aria-hidden="true"
/>
<input
className="components-angle-picker-control__input-field"
type="number"
id={ inputId }
onChange={ ( event ) => {
const unprocessedValue = event.target.value;
const inputValue =
unprocessedValue !== ''
? parseInt( event.target.value, 10 )
: 0;
onChange( inputValue );
} }
value={ value }
min={ 0 }
max={ 360 }
step="1"
/>
<Root gap={ 3 }>
<NumberControlWrapper>
<NumberControl
className="components-angle-picker-control__input-field"
id={ id }
max={ 360 }
min={ 0 }
onChange={ handleOnNumberChange }
step="1"
value={ value }
/>
</NumberControlWrapper>
<FlexBlock>
<AngleCircle
aria-hidden="true"
value={ value }
onChange={ onChange }
/>
</FlexBlock>
</Root>
</BaseControl>
);
}
43 changes: 0 additions & 43 deletions packages/components/src/angle-picker-control/style.scss

This file was deleted.

Loading

0 comments on commit be09692

Please sign in to comment.