Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BoxControl: update design #56665

Merged
merged 37 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
910badb
Change to vertical formatting without width constraints
brookewp Nov 29, 2023
bdf1157
Add RangeControl to input controls
brookewp Nov 29, 2023
5eb20cc
Only show Icon for AllInputControl
brookewp Nov 29, 2023
e3c63de
Add RangeControl to AllInputControl
brookewp Nov 30, 2023
5dcef43
Clean up styles and match SpacingInputControl
brookewp Dec 1, 2023
695bba7
Add changes to InputControls to AxialInputControls
brookewp Dec 2, 2023
c0a8d7f
Update styles based on design input
brookewp Dec 2, 2023
6b78cf1
Fix issue where changing input didn’t affect rangecontrol
brookewp Dec 2, 2023
94db809
Add labels to sliders
brookewp Dec 2, 2023
ac87f8e
Add unit tests for slider
brookewp Dec 2, 2023
c9ac4b5
Update changelog
brookewp Dec 2, 2023
6076058
Update function name and add limitations to slider based on units
brookewp Dec 8, 2023
11b46d6
Add right margin to prevent slider thumb from being cut off
brookewp Dec 8, 2023
8fa41ab
Update slider’s initial position to check for a value
brookewp Dec 11, 2023
f1c9be2
Replace Tooltip with component
brookewp Dec 12, 2023
ec4985c
Use Grid for better semantics and a11y
brookewp Dec 12, 2023
a9ae993
Add id for slider aria labels
brookewp Dec 12, 2023
2494cdb
Implement changes from PR feedback
brookewp Dec 14, 2023
0a041fc
Adjust grid
brookewp Dec 14, 2023
8dc9b1c
Update column sizing
brookewp Dec 14, 2023
a57f3e2
Fix value by using `allValue` again
brookewp Dec 14, 2023
b28c652
Refactor to remove duplicate onChange based on feedback
brookewp Dec 14, 2023
7fbbe43
Fix mapped ids
brookewp Dec 15, 2023
73b65eb
Update naming based on feedback
brookewp Jan 3, 2024
f2bdae4
Fix id and key
brookewp Jan 3, 2024
7cdab78
Remove unused border radius logic
brookewp Jan 3, 2024
187ae8a
Update margin to include RTL
brookewp Jan 3, 2024
9121904
Remove unused hover functions for previously replaced visualizer
brookewp Jan 3, 2024
b5f546e
Replace custom UnitControl with standard
brookewp Jan 3, 2024
6287be9
Fix all input label
brookewp Jan 3, 2024
25cf3f6
Update naming in tests
brookewp Jan 8, 2024
3f9ec19
Add mixed label and test
brookewp Jan 8, 2024
178ff28
Restore Mixed placeholder
brookewp Jan 9, 2024
a780070
Remove unnecessary function
brookewp Jan 9, 2024
ced9711
Update naming
brookewp Jan 9, 2024
6dc8d44
Add labels to slider
brookewp Jan 10, 2024
505ac98
Fix label in test
brookewp Jan 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
- `Tabs`: do not render hidden content ([#57046](https://github.com/WordPress/gutenberg/pull/57046)).
- `Tabs`: improve hover and text alignment styles ([#57275](https://github.com/WordPress/gutenberg/pull/57275)).
- `Tabs`: make sure `Tab`s are associated to the right `TabPanel`s, regardless of the order they're rendered in ([#57033](https://github.com/WordPress/gutenberg/pull/57033)).
- `BoxControl`: Update design ([#56665](https://github.com/WordPress/gutenberg/pull/56665)).

## 25.14.0 (2023-12-13)

Expand Down
87 changes: 53 additions & 34 deletions packages/components/src/box-control/all-input-control.tsx
Original file line number Diff line number Diff line change
@@ -1,86 +1,105 @@
/**
* WordPress dependencies
*/
import { useInstanceId } from '@wordpress/compose';
/**
* Internal dependencies
*/
import type { UnitControlProps } from '../unit-control/types';
import { FlexedRangeControl, UnitControl } from './styles/box-control-styles';
import { HStack } from '../h-stack';
import type { BoxControlInputControlProps } from './types';
import UnitControl from './unit-control';
import { parseQuantityAndUnitFromRawValue } from '../unit-control';
import {
LABELS,
applyValueToSides,
getAllValue,
isValuesMixed,
isValuesDefined,
CUSTOM_VALUE_SETTINGS,
} from './utils';

const noop = () => {};

export default function AllInputControl( {
onChange = noop,
onFocus = noop,
onHoverOn = noop,
onHoverOff = noop,
values,
sides,
selectedUnits,
setSelectedUnits,
...props
}: BoxControlInputControlProps ) {
const inputId = useInstanceId( AllInputControl, 'box-control-input-all' );

const allValue = getAllValue( values, selectedUnits, sides );
const hasValues = isValuesDefined( values );
const isMixed = hasValues && isValuesMixed( values, selectedUnits, sides );
const allPlaceholder = isMixed ? LABELS.mixed : undefined;

const [ parsedQuantity, parsedUnit ] =
parseQuantityAndUnitFromRawValue( allValue );

const handleOnFocus: React.FocusEventHandler< HTMLInputElement > = (
event
) => {
onFocus( event, { side: 'all' } );
};

const handleOnChange: UnitControlProps[ 'onChange' ] = ( next ) => {
const onValueChange = ( next?: string ) => {
const isNumeric = next !== undefined && ! isNaN( parseFloat( next ) );
const nextValue = isNumeric ? next : undefined;
const nextValues = applyValueToSides( values, nextValue, sides );

onChange( nextValues );
};

const unitControlOnChange: UnitControlProps[ 'onChange' ] = ( next ) => {
onValueChange( next );
};

const sliderOnChange = ( next?: number ) => {
onValueChange(
next !== undefined ? [ next, parsedUnit ].join( '' ) : undefined
);
};

// Set selected unit so it can be used as fallback by unlinked controls
// when individual sides do not have a value containing a unit.
const handleOnUnitChange: UnitControlProps[ 'onUnitChange' ] = ( unit ) => {
const newUnits = applyValueToSides( selectedUnits, unit, sides );
setSelectedUnits( newUnits );
};

const handleOnHoverOn = () => {
onHoverOn( {
top: true,
bottom: true,
left: true,
right: true,
} );
};

const handleOnHoverOff = () => {
onHoverOff( {
top: false,
bottom: false,
left: false,
right: false,
} );
};

return (
<UnitControl
{ ...props }
disableUnits={ isMixed }
isOnly
value={ allValue }
onChange={ handleOnChange }
onUnitChange={ handleOnUnitChange }
onFocus={ handleOnFocus }
onHoverOn={ handleOnHoverOn }
onHoverOff={ handleOnHoverOff }
placeholder={ allPlaceholder }
/>
<HStack>
<UnitControl
{ ...props }
mirka marked this conversation as resolved.
Show resolved Hide resolved
className="component-box-control__unit-control"
disableUnits={ isMixed }
id={ inputId }
isPressEnterToChange
value={ allValue }
onChange={ unitControlOnChange }
mirka marked this conversation as resolved.
Show resolved Hide resolved
onUnitChange={ handleOnUnitChange }
onFocus={ handleOnFocus }
placeholder={ allPlaceholder }
label={ LABELS.all }
hideLabelFromVision
/>

<FlexedRangeControl
__nextHasNoMarginBottom
aria-controls={ inputId }
mirka marked this conversation as resolved.
Show resolved Hide resolved
onChange={ sliderOnChange }
min={ 0 }
max={ CUSTOM_VALUE_SETTINGS[ parsedUnit ?? 'px' ]?.max ?? 10 }
step={
CUSTOM_VALUE_SETTINGS[ parsedUnit ?? 'px' ]?.step ?? 0.1
}
value={ parsedQuantity ?? 0 }
withInputField={ false }
/>
</HStack>
);
}
144 changes: 75 additions & 69 deletions packages/components/src/box-control/axial-input-controls.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
/**
* WordPress dependencies
*/
import { useInstanceId } from '@wordpress/compose';
/**
* Internal dependencies
*/
import { parseQuantityAndUnitFromRawValue } from '../unit-control/utils';
import UnitControl from './unit-control';
import { LABELS } from './utils';
import { Layout } from './styles/box-control-styles';
import Tooltip from '../tooltip';
import { CUSTOM_VALUE_SETTINGS, LABELS } from './utils';
import {
FlexedBoxControlIcon,
FlexedRangeControl,
InputWrapper,
UnitControl,
} from './styles/box-control-styles';
import type { BoxControlInputControlProps } from './types';

const groupedSides = [ 'vertical', 'horizontal' ] as const;
Expand All @@ -13,14 +22,17 @@ type GroupedSide = ( typeof groupedSides )[ number ];
export default function AxialInputControls( {
onChange,
onFocus,
onHoverOn,
onHoverOff,
values,
selectedUnits,
setSelectedUnits,
sides,
...props
}: BoxControlInputControlProps ) {
const generatedId = useInstanceId(
AxialInputControls,
`box-control-input`
);

const createHandleOnFocus =
( side: GroupedSide ) =>
( event: React.FocusEvent< HTMLInputElement > ) => {
Expand All @@ -30,43 +42,7 @@ export default function AxialInputControls( {
onFocus( event, { side } );
};

const createHandleOnHoverOn = ( side: GroupedSide ) => () => {
if ( ! onHoverOn ) {
return;
}
if ( side === 'vertical' ) {
onHoverOn( {
top: true,
bottom: true,
} );
}
if ( side === 'horizontal' ) {
onHoverOn( {
left: true,
right: true,
} );
}
};

const createHandleOnHoverOff = ( side: GroupedSide ) => () => {
if ( ! onHoverOff ) {
return;
}
if ( side === 'vertical' ) {
onHoverOff( {
top: false,
bottom: false,
} );
}
if ( side === 'horizontal' ) {
onHoverOff( {
left: false,
right: false,
} );
}
};

const createHandleOnChange = ( side: GroupedSide ) => ( next?: string ) => {
const handleOnValueChange = ( side: GroupedSide, next?: string ) => {
if ( ! onChange ) {
return;
}
Expand Down Expand Up @@ -109,16 +85,8 @@ export default function AxialInputControls( {
? groupedSides.filter( ( side ) => sides.includes( side ) )
: groupedSides;

const first = filteredSides[ 0 ];
const last = filteredSides[ filteredSides.length - 1 ];
const only = first === last && first;

return (
<Layout
gap={ 0 }
align="top"
className="component-box-control__vertical-horizontal-input-controls"
>
<>
{ filteredSides.map( ( side ) => {
const [ parsedQuantity, parsedUnit ] =
parseQuantityAndUnitFromRawValue(
Expand All @@ -128,26 +96,64 @@ export default function AxialInputControls( {
side === 'vertical'
? selectedUnits.top
: selectedUnits.left;

const inputId = [ generatedId, side ].join( '-' );

return (
<UnitControl
{ ...props }
isFirst={ first === side }
isLast={ last === side }
isOnly={ only === side }
value={ [
parsedQuantity,
selectedUnit ?? parsedUnit,
].join( '' ) }
onChange={ createHandleOnChange( side ) }
onUnitChange={ createHandleOnUnitChange( side ) }
onFocus={ createHandleOnFocus( side ) }
onHoverOn={ createHandleOnHoverOn( side ) }
onHoverOff={ createHandleOnHoverOff( side ) }
label={ LABELS[ side ] }
key={ side }
/>
<InputWrapper key={ side }>
<FlexedBoxControlIcon side={ side } sides={ sides } />
<Tooltip placement="top-end" text={ LABELS[ side ] }>
<UnitControl
{ ...props }
className="component-box-control__unit-control"
id={ inputId }
isPressEnterToChange
value={ [
parsedQuantity,
selectedUnit ?? parsedUnit,
].join( '' ) }
onChange={ ( newValue ) =>
handleOnValueChange( side, newValue )
}
onUnitChange={ createHandleOnUnitChange(
side
) }
onFocus={ createHandleOnFocus( side ) }
label={ LABELS[ side ] }
hideLabelFromVision
key={ side }
/>
</Tooltip>
<FlexedRangeControl
__nextHasNoMarginBottom
aria-controls={ inputId }
aria-labelledby={ inputId }
brookewp marked this conversation as resolved.
Show resolved Hide resolved
onChange={ ( newValue ) =>
handleOnValueChange(
side,
newValue !== undefined
? [
newValue,
selectedUnit ?? parsedUnit,
].join( '' )
: undefined
)
}
min={ 0 }
max={
CUSTOM_VALUE_SETTINGS[ selectedUnit ?? 'px' ]
?.max ?? 10
}
step={
CUSTOM_VALUE_SETTINGS[ selectedUnit ?? 'px' ]
?.step ?? 0.1
}
value={ parsedQuantity ?? 0 }
withInputField={ false }
/>
</InputWrapper>
);
} ) }
</Layout>
</>
);
}
Loading
Loading