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

SelectControl: Pass through options props #64211

Merged
merged 3 commits into from
Aug 5, 2024
Merged

SelectControl: Pass through options props #64211

merged 3 commits into from
Aug 5, 2024

Conversation

mirka
Copy link
Member

@mirka mirka commented Aug 2, 2024

Prerequisite for #63815

What?

In SelectControl, pass through any extra props defined in options to the underlying <option> element.

Why?

To support any additional option attributes, for example aria-label.

Testing Instructions

In Storybook, pass some additional option attributes and see what gets rendered in HTML.

✅ Unit test passes

@mirka mirka added [Type] Enhancement A suggestion for improvement. [Package] Components /packages/components labels Aug 2, 2024
@mirka mirka self-assigned this Aug 2, 2024
@@ -26,6 +26,22 @@ function useUniqueId( idProp?: string ) {
return idProp || id;
}

function SelectOptions( {
Copy link
Member Author

Choose a reason for hiding this comment

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

Extracted this out from the main component function because we need to pick props from the options.map and the names are going to conflict with the main component props.

options: NonNullable< SelectControlProps[ 'options' ] >;
} ) {
return options.map( ( { id, label, value, ...optionProps }, index ) => {
const key = id || `${ label }-${ value }-${ index }`;
Copy link
Member Author

Choose a reason for hiding this comment

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

As a key, ${ label }-${ value }-${ index } seems functionally equivalent to index 🤔 Doesn't seem particularly intentional, either (#6122). I'm not touching this in this PR though.

Comment on lines +20 to +21
it( 'should render its children', async () => {
const user = userEvent.setup();
Copy link
Member Author

Choose a reason for hiding this comment

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

Cleaned up some typos.

Comment on lines -37 to -49
id?: string;
/**
* Whether or not the option should have the disabled attribute.
*
* @default false
*/
disabled?: boolean;
/**
* Whether or not the option should be hidden.
*
* @default false
*/
hidden?: boolean;
Copy link
Member Author

Choose a reason for hiding this comment

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

Removing these explicit types since they are included in React.OptionHTMLAttributes.

Comment on lines -25 to -26
onBlur?: ( event: FocusEvent< HTMLSelectElement > ) => void;
onFocus?: ( event: FocusEvent< HTMLSelectElement > ) => void;
Copy link
Member Author

Choose a reason for hiding this comment

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

Removing these explicit event listener props since they are mixed in here:

function UnforwardedSelectControl(
props: WordPressComponentProps< SelectControlProps, 'select', false >,
ref: React.ForwardedRef< HTMLSelectElement >

This will remove them from the props table and auto-generated code snippets in Storybook, which is good because we have no reason to explicitly show onBlur and onFocus.

@mirka mirka marked this pull request as ready for review August 2, 2024 17:40
@mirka mirka requested a review from ajitbohra as a code owner August 2, 2024 17:40
Copy link

github-actions bot commented Aug 2, 2024

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: mirka <0mirka00@git.wordpress.org>
Co-authored-by: tyxla <tyxla@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@mirka mirka requested a review from a team August 2, 2024 17:41
Copy link
Member

@tyxla tyxla left a comment

Choose a reason for hiding this comment

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

LGTM 👍

Love the extra SelectControlBaseProps.options prop type cleanup 👏

The only thing I'd do would be to change the value description to be a bit more specific for multiple/single.

Comment on lines +66 to +70
/**
* The value of the selected option.
*
* If `multiple` is true, the `value` should be an array with the values of the selected options.
*/
Copy link
Member

Choose a reason for hiding this comment

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

Does it make sense to make this more specific, so it's clear it's for a single select? TypeScript can often see if the component has multiple or not and can determine which description to display in the IDE properly:

Screenshot 2024-08-05 at 16 14 25
Screenshot 2024-08-05 at 16 14 43

Copy link
Member Author

Choose a reason for hiding this comment

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

I'd love to, but I've been avoiding writing different descriptions for "conditional" props, because they don't work well with the Storybook props table. They simply get concatenated when they differ:

Concatenated description in Storybook props table

Copy link
Member

Choose a reason for hiding this comment

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

That's not a great reason for the type description verbosity TBH 😞 I wish Storybook could handle that in a more clever way. Are we the first to have that problem? Seems like this is similar to what we need: storybookjs/storybook#21281

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't necessarily dislike this limitation though. I think it is useful to know that a prop is conditionally polymorphic.

Comment on lines +93 to +97
/**
* The value of the selected option.
*
* If `multiple` is true, the `value` should be an array with the values of the selected options.
*/
Copy link
Member

Choose a reason for hiding this comment

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

As above: Does it make sense to make this more multiple-specific, so it's clear that it's always an array of values and not a single value since it's only when the select field is a multiple select one?

@mirka mirka merged commit 650eb7f into trunk Aug 5, 2024
64 checks passed
@mirka mirka deleted the select-option-props branch August 5, 2024 17:14
@github-actions github-actions bot added this to the Gutenberg 19.0 milestone Aug 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Components /packages/components [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants