Skip to content

Commit

Permalink
AlignmentMatrixControl: simplify styles and markup (#64827)
Browse files Browse the repository at this point in the history
* Simplify icon active cell computation

* AlignmentMatrixControl: simplify styles

* AlignmentMatrixControl.Icon: rewrite using SVG

* Do not use `size` prop on AlignmentMatrixControl.Icon in Storybook

* Cleanup

* CHANGELOG

* Do not type height and width explicitly

* Fix typo

* Inline computedWidth and computedHeight

* Restore getAlignmentIndex function, since it normalizes values internally

---

Co-authored-by: ciampo <[email protected]>
Co-authored-by: mirka <[email protected]>
  • Loading branch information
3 people authored Aug 27, 2024
1 parent d0337f2 commit 5773ae6
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 249 deletions.
2 changes: 2 additions & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
### Deprecations

- Deprecate `replace` from the options accepted by `useNavigator().goTo()` ([#64675](https://github.com/WordPress/gutenberg/pull/64675)).
- Soft deprecate `size` prop on `AlignmentMatrixControl.Icon` ([#64827](https://github.com/WordPress/gutenberg/pull/64827)).

### Enhancements

- `ColorPicker`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)).
- `CustomSelectControl V2`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)).
- `AlignmentMatrixControl.Icon`: rewrite entirely using SVG markup ([#64827](https://github.com/WordPress/gutenberg/pull/64827)).
- `DateTime`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)).
- `FormToggle`: Adopt radius scale ([#64693](https://github.com/WordPress/gutenberg/pull/64693)).
- `FormTokenField`: Remove unused border-radius ([#64693](https://github.com/WordPress/gutenberg/pull/64693)).
Expand Down
12 changes: 3 additions & 9 deletions packages/components/src/alignment-matrix-control/cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,17 @@ import { VisuallyHidden } from '../visually-hidden';
* Internal dependencies
*/
import { ALIGNMENT_LABEL } from './utils';
import {
Cell as CellView,
Point,
} from './styles/alignment-matrix-control-styles';
import { Cell as CellView, Point } from './styles';
import type { AlignmentMatrixControlCellProps } from './types';
import type { WordPressComponentProps } from '../context';

export default function Cell( {
id,
isActive = false,
value,
...props
}: WordPressComponentProps< AlignmentMatrixControlCellProps, 'span', false > ) {
const tooltipText = ALIGNMENT_LABEL[ value ];

return (
<Tooltip text={ tooltipText }>
<Tooltip text={ ALIGNMENT_LABEL[ value ] }>
<Composite.Item
id={ id }
render={ <CellView { ...props } role="gridcell" /> }
Expand All @@ -34,7 +28,7 @@ export default function Cell( {
otherwise it'll announce the content as "blank". So we use a visually
hidden element instead of aria-label. */ }
<VisuallyHidden>{ value }</VisuallyHidden>
<Point isActive={ isActive } role="presentation" />
<Point role="presentation" />
</Composite.Item>
</Tooltip>
);
Expand Down
78 changes: 48 additions & 30 deletions packages/components/src/alignment-matrix-control/icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,59 +3,77 @@
*/
import clsx from 'clsx';

/**
* WordPress dependencies
*/
import { Rect, SVG } from '@wordpress/primitives';

/**
* Internal dependencies
*/
import { ALIGNMENTS, getAlignmentIndex } from './utils';
import {
Root,
Cell,
Point,
} from './styles/alignment-matrix-control-icon-styles';
import type { AlignmentMatrixControlIconProps } from './types';
import type { WordPressComponentProps } from '../context';

const BASE_SIZE = 24;
const GRID_CELL_SIZE = 7;
const GRID_PADDING = ( BASE_SIZE - 3 * GRID_CELL_SIZE ) / 2;
const DOT_SIZE = 2;
const DOT_SIZE_SELECTED = 4;

function AlignmentMatrixControlIcon( {
className,
disablePointerEvents = true,
size = BASE_SIZE,
size,
width,
height,
style = {},
value = 'center',
...props
}: WordPressComponentProps< AlignmentMatrixControlIconProps, 'div', false > ) {
const alignIndex = getAlignmentIndex( value );
const scale = ( size / BASE_SIZE ).toFixed( 2 );

const classes = clsx(
'component-alignment-matrix-control-icon',
className
);

const styles = {
...style,
transform: `scale(${ scale })`,
};

}: WordPressComponentProps< AlignmentMatrixControlIconProps, 'svg', false > ) {
return (
<Root
{ ...props }
className={ classes }
disablePointerEvents={ disablePointerEvents }
<SVG
xmlns="http://www.w3.org/2000/svg"
viewBox={ `0 0 ${ BASE_SIZE } ${ BASE_SIZE }` }
width={ size ?? width ?? BASE_SIZE }
height={ size ?? height ?? BASE_SIZE }
role="presentation"
style={ styles }
className={ clsx(
'component-alignment-matrix-control-icon',
className
) }
style={ {
pointerEvents: disablePointerEvents ? 'none' : undefined,
...style,
} }
{ ...props }
>
{ ALIGNMENTS.map( ( align, index ) => {
const isActive = alignIndex === index;
const dotSize =
getAlignmentIndex( value ) === index
? DOT_SIZE_SELECTED
: DOT_SIZE;

return (
<Cell key={ align }>
<Point isActive={ isActive } />
</Cell>
<Rect
key={ align }
x={
GRID_PADDING +
( index % 3 ) * GRID_CELL_SIZE +
( GRID_CELL_SIZE - dotSize ) / 2
}
y={
GRID_PADDING +
Math.floor( index / 3 ) * GRID_CELL_SIZE +
( GRID_CELL_SIZE - dotSize ) / 2
}
width={ dotSize }
height={ dotSize }
fill="currentColor"
/>
);
} ) }
</Root>
</SVG>
);
}

Expand Down
29 changes: 10 additions & 19 deletions packages/components/src/alignment-matrix-control/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* External dependencies
*/
import clsx from 'clsx';
import { useStoreState } from '@ariakit/react';

/**
* WordPress dependencies
Expand All @@ -16,7 +15,7 @@ import { useInstanceId } from '@wordpress/compose';
import Cell from './cell';
import { Composite } from '../composite';
import { useCompositeStore } from '../composite/store';
import { Root, Row } from './styles/alignment-matrix-control-styles';
import { GridContainer, GridRow } from './styles';
import AlignmentMatrixControlIcon from './icon';
import { GRID, getItemId, getItemValue } from './utils';
import type { WordPressComponentProps } from '../context';
Expand Down Expand Up @@ -70,15 +69,13 @@ export function AlignmentMatrixControl( {
rtl: isRTL(),
} );

const activeId = useStoreState( compositeStore, 'activeId' );

const classes = clsx( 'component-alignment-matrix-control', className );

return (
<Composite
store={ compositeStore }
render={
<Root
<GridContainer
{ ...props }
aria-label={ label }
className={ classes }
Expand All @@ -89,20 +86,14 @@ export function AlignmentMatrixControl( {
}
>
{ GRID.map( ( cells, index ) => (
<Composite.Row render={ <Row role="row" /> } key={ index }>
{ cells.map( ( cell ) => {
const cellId = getItemId( baseId, cell );
const isActive = cellId === activeId;

return (
<Cell
id={ cellId }
isActive={ isActive }
key={ cell }
value={ cell }
/>
);
} ) }
<Composite.Row render={ <GridRow role="row" /> } key={ index }>
{ cells.map( ( cell ) => (
<Cell
id={ getItemId( baseId, cell ) }
key={ cell }
value={ cell }
/>
) ) }
</Composite.Row>
) ) }
</Composite>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,9 @@ export const Default = Template.bind( {} );
export const IconSubcomponent = () => {
return (
<HStack justify="flex-start">
<Icon icon={ <AlignmentMatrixControl.Icon value="top left" /> } />
<Icon
icon={
<AlignmentMatrixControl.Icon size={ 24 } value="top left" />
}
/>
<Icon
icon={
<AlignmentMatrixControl.Icon
size={ 24 }
value="center center"
/>
}
icon={ <AlignmentMatrixControl.Icon value="center center" /> }
/>
</HStack>
);
Expand Down
113 changes: 113 additions & 0 deletions packages/components/src/alignment-matrix-control/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/**
* External dependencies
*/
import styled from '@emotion/styled';
import { css } from '@emotion/react';

/**
* Internal dependencies
*/
import { COLORS, CONFIG } from '../utils';
import type {
AlignmentMatrixControlProps,
AlignmentMatrixControlIconProps,
} from './types';

// Grid structure

const rootBase = ( { size = 92 } ) => css`
direction: ltr;
display: grid;
grid-template-columns: repeat( 3, 1fr );
grid-template-rows: repeat( 3, 1fr );
box-sizing: border-box;
width: ${ size }px;
aspect-ratio: 1;
border-radius: ${ CONFIG.radiusMedium };
outline: none;
`;

export const GridContainer = styled.div< {
size?: AlignmentMatrixControlProps[ 'width' ];
disablePointerEvents?: AlignmentMatrixControlIconProps[ 'disablePointerEvents' ];
} >`
${ rootBase }
border: 1px solid transparent;
${ ( props ) =>
props.disablePointerEvents
? css``
: css`
cursor: pointer;
` }
`;

export const GridRow = styled.div`
grid-column: 1 / -1;
box-sizing: border-box;
display: grid;
grid-template-columns: repeat( 3, 1fr );
`;

// Cell
export const Cell = styled.span`
position: relative;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
margin: 0;
padding: 0;
appearance: none;
border: none;
outline: none;
`;

const POINT_SIZE = 6;
export const Point = styled.span`
display: block;
contain: strict;
box-sizing: border-box;
width: ${ POINT_SIZE }px;
aspect-ratio: 1;
margin: auto;
color: ${ COLORS.theme.gray[ 400 ] };
/* Use border instead of background color so that the point shows
in Windows High Contrast Mode */
border: ${ POINT_SIZE / 2 }px solid currentColor;
/* Highlight active item */
${ Cell }[data-active-item] & {
color: ${ COLORS.gray[ 900 ] };
transform: scale( calc( 5 / 3 ) );
}
/* Hover styles for non-active items */
${ Cell }:not([data-active-item]):hover & {
color: ${ COLORS.theme.accent };
}
/* Show an outline only when interacting with keyboard */
${ Cell }[data-focus-visible] & {
outline: 1px solid ${ COLORS.theme.accent };
outline-offset: 1px;
}
@media not ( prefers-reduced-motion ) {
transition-property: color, transform;
transition-duration: 120ms;
transition-timing-function: linear;
}
`;
Loading

0 comments on commit 5773ae6

Please sign in to comment.