Skip to content

Commit

Permalink
Refactor to vanilla radio inputs, rewrite styles
Browse files Browse the repository at this point in the history
  • Loading branch information
ciampo committed Dec 7, 2024
1 parent 3f43307 commit e65ea97
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 100 deletions.
101 changes: 55 additions & 46 deletions packages/fields/src/components/create-template-part-modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,11 @@ import {
Icon,
BaseControl,
TextControl,
Flex,
FlexItem,
FlexBlock,
Button,
Modal,
__experimentalRadioGroup as RadioGroup,
__experimentalRadio as Radio,
__experimentalHStack as HStack,
__experimentalVStack as VStack,
} from '@wordpress/components';
import { useInstanceId } from '@wordpress/compose';
import { store as coreStore } from '@wordpress/core-data';
import { useDispatch, useSelect } from '@wordpress/data';
import { useState } from '@wordpress/element';
Expand All @@ -40,6 +34,13 @@ import {
useExistingTemplateParts,
} from './utils';

function getAreaRadioId( value: string ) {
return `fields-create-template-part-modal__area-option-${ value }`;
}
function getAreaRadioDescriptionId( value: string ) {
return `fields-create-template-part-modal__area-option-description-${ value }`;
}

type CreateTemplatePartModalContentsProps = {
defaultArea?: string;
blocks: any[];
Expand Down Expand Up @@ -122,7 +123,6 @@ export function CreateTemplatePartModalContents( {
const [ title, setTitle ] = useState( defaultTitle );
const [ area, setArea ] = useState( defaultArea );
const [ isSubmitting, setIsSubmitting ] = useState( false );
const instanceId = useInstanceId( CreateTemplatePartModal );

const defaultTemplatePartAreas = useSelect( ( select ) => {
const areas =
Expand Down Expand Up @@ -202,51 +202,60 @@ export function CreateTemplatePartModalContents( {
onChange={ setTitle }
required
/>
<BaseControl
__nextHasNoMarginBottom
label={ __( 'Area' ) }
id={ `fields-create-template-part-modal__area-selection-${ instanceId }` }
className="fields-create-template-part-modal__area-base-control"
>
<RadioGroup
label={ __( 'Area' ) }
className="fields-create-template-part-modal__area-radio-group"
id={ `fields-create-template-part-modal__area-selection-${ instanceId }` }
onChange={ ( value ) =>
value && typeof value === 'string'
? setArea( value )
: () => void 0
}
checked={ area }
<fieldset>
<BaseControl.VisualLabel
as="legend"
className="fields-create-template-part-modal__area-radio-group-label"
>
{ __( 'Area' ) }
</BaseControl.VisualLabel>
<div className="fields-create-template-part-modal__area-radio-group">
{ defaultTemplatePartAreas.map(
( { icon, label, area: value, description } ) => (
<Radio
__next40pxDefaultSize
key={ label }
value={ value }
className="fields-create-template-part-modal__area-radio"
<div
key={ value }
className="fields-create-template-part-modal__area-radio-wrapper"
>
<Flex align="start" justify="start">
<FlexItem>
<Icon icon={ icon } />
</FlexItem>
<FlexBlock className="fields-create-template-part-modal__option-label">
{ label }
<div>{ description }</div>
</FlexBlock>

<FlexItem className="fields-create-template-part-modal__checkbox">
{ area === value && (
<Icon icon={ check } />
) }
</FlexItem>
</Flex>
</Radio>
<input
type="radio"
id={ getAreaRadioId( value ) }
name="fields-create-template-part-modal__area"
value={ value }
checked={ area === value }
onChange={ () => {
setArea( value );
} }
aria-describedby={ getAreaRadioDescriptionId(
value
) }
/>
<Icon
icon={ icon }
className="fields-create-template-part-modal__area-radio-icon"
/>
<label
htmlFor={ getAreaRadioId( value ) }
className="fields-create-template-part-modal__area-radio-label"
>
{ label }
</label>
<Icon
icon={ check }
className="fields-create-template-part-modal__area-radio-checkmark"
/>
<p
className="fields-create-template-part-modal__area-radio-description"
id={ getAreaRadioDescriptionId(
value
) }
>
{ description }
</p>
</div>
)
) }
</RadioGroup>
</BaseControl>
</div>
</fieldset>
<HStack justify="right">
<Button
__next40pxDefaultSize
Expand Down
133 changes: 79 additions & 54 deletions packages/fields/src/components/create-template-part-modal/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,61 +3,86 @@
}

.fields-create-template-part-modal__area-radio-group {
width: 100%;
border: $border-width solid $gray-700;
border: $border-width solid $gray-600;
border-radius: $radius-small;
}

.fields-create-template-part-modal__area-radio-wrapper {
position: relative;
padding: $grid-unit-15;

display: grid;
align-items: center;
grid-template-columns: min-content 1fr min-content;
grid-gap: $grid-unit-05 $grid-unit-10;

color: $gray-900;

& + & {
border-top: $border-width solid $gray-600;
}

input[type="radio"] {
position: absolute;
opacity: 0;
}

&:has(input[type="radio"]:checked) {
// This is needed to make sure that the focus ring always renders on top
// of the sibling radio "wrapper"'s borders.
z-index: 1;
}

&:has(input[type="radio"]:not(:checked)):hover {
color: var(--wp-admin-theme-color);
}

// Pass-through pointer events, so that the corresponding radio input
// gets checked when clicking on the underlying label
> *:not(.fields-create-template-part-modal__area-radio-label) {
pointer-events: none;
}
}

.fields-create-template-part-modal__area-radio-label {
// Capture pointer clicks for the whole radio wrapper
&::before {
content: "";
position: absolute;
inset: 0;
}

input[type="radio"]:not(:checked) ~ &::before {
cursor: pointer;
}

input[type="radio"]:focus-visible ~ &::before {
outline: 4px solid transparent;
box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color);
}
}

.fields-create-template-part-modal__area-radio-icon,
.fields-create-template-part-modal__area-radio-checkmark {
fill: currentColor;
}

.fields-create-template-part-modal__area-radio-checkmark {
input[type="radio"]:not(:checked) ~ & {
opacity: 0;
}
}

.fields-create-template-part-modal__area-radio-description {
grid-column: 2 / 3;
margin: 0;

color: $gray-600;
font-size: $helptext-font-size;
line-height: normal;
text-wrap: pretty;

.components-button.fields-create-template-part-modal__area-radio {
display: block;
width: 100%;
height: 100%;
text-align: left;
padding: $grid-unit-15;

&,
&.is-secondary:hover,
&.is-primary:hover {
margin: 0;
background-color: inherit;
border-bottom: $border-width solid $gray-700;
border-radius: 0;

&:not(:focus) {
box-shadow: none;
}

&:focus {
border-bottom: $border-width solid $white;
}

&:last-of-type {
border-bottom: none;
}
}

&:not(:hover),
&[aria-checked="true"] {
color: $gray-900;
cursor: auto;

.fields-create-template-part-modal__option-label div {
color: $gray-600;
}
}

.fields-create-template-part-modal__option-label {
padding-top: $grid-unit-05;
white-space: normal;

div {
padding-top: $grid-unit-05;
font-size: $helptext-font-size;
}
}

.fields-create-template-part-modal__checkbox {
margin-left: auto;
min-width: $grid-unit-30;
}
input[type="radio"]:not(:checked):hover ~ & {
color: inherit;
}
}

0 comments on commit e65ea97

Please sign in to comment.