Skip to content

Commit

Permalink
CreateTemplatePartModalContents: use native radio inputs (#67702)
Browse files Browse the repository at this point in the history
* Refactor to vanilla radio inputs, rewrite styles

* Remove unnecessary classname

* Apply instance ID to all ids and radio names

* Use darker shade of gray for description

---

Co-authored-by: ciampo <[email protected]>
Co-authored-by: mirka <[email protected]>
Co-authored-by: jameskoster <[email protected]>
Co-authored-by: jsnajdr <[email protected]>
Co-authored-by: tyxla <[email protected]>
  • Loading branch information
6 people authored Dec 16, 2024
1 parent 2eb82b4 commit bce0a50
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 99 deletions.
106 changes: 61 additions & 45 deletions packages/fields/src/components/create-template-part-modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,8 @@ import {
Icon,
BaseControl,
TextControl,
Flex,
FlexItem,
FlexBlock,
Button,
Modal,
__experimentalRadioGroup as RadioGroup,
__experimentalRadio as Radio,
__experimentalHStack as HStack,
__experimentalVStack as VStack,
} from '@wordpress/components';
Expand Down Expand Up @@ -40,6 +35,13 @@ import {
useExistingTemplateParts,
} from './utils';

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

type CreateTemplatePartModalContentsProps = {
defaultArea?: string;
blocks: any[];
Expand Down Expand Up @@ -201,52 +203,66 @@ 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">
{ __( 'Area' ) }
</BaseControl.VisualLabel>
<div className="fields-create-template-part-modal__area-radio-group">
{ ( defaultTemplatePartAreas ?? [] ).map( ( item ) => {
const icon = getTemplatePartIcon( item.icon );
return (
<Radio
__next40pxDefaultSize
key={ item.label }
value={ item.area }
className="fields-create-template-part-modal__area-radio"
<div
key={ item.area }
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">
{ item.label }
<div>{ item.description }</div>
</FlexBlock>

<FlexItem className="fields-create-template-part-modal__checkbox">
{ area === item.area && (
<Icon icon={ check } />
) }
</FlexItem>
</Flex>
</Radio>
<input
type="radio"
id={ getAreaRadioId(
item.area,
instanceId
) }
name={ `fields-create-template-part-modal__area-${ instanceId }` }
value={ item.area }
checked={ area === item.area }
onChange={ () => {
setArea( item.area );
} }
aria-describedby={ getAreaRadioDescriptionId(
item.area,
instanceId
) }
/>
<Icon
icon={ icon }
className="fields-create-template-part-modal__area-radio-icon"
/>
<label
htmlFor={ getAreaRadioId(
item.area,
instanceId
) }
className="fields-create-template-part-modal__area-radio-label"
>
{ item.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(
item.area,
instanceId
) }
>
{ item.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-700;
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;
}
}

1 comment on commit bce0a50

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected in bce0a50.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/12357437277
📝 Reported issues:

Please sign in to comment.