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

feat(admin-ui): Radio & RadioGroup component #4400

Merged
merged 14 commits into from
Nov 28, 2024

Conversation

leopuleo
Copy link
Contributor

Changes

This pull request adds the Radio and RadioGroup components to the @webiny/admin-ui package. Subsequent pull requests will develop the form variant and update the components within the @webiny/ui.

How Has This Been Tested?

Manually - Jest

@leopuleo leopuleo requested a review from adrians5j November 19, 2024 14:35
@leopuleo leopuleo self-assigned this Nov 19, 2024
Copy link
Member

@adrians5j adrians5j left a comment

Choose a reason for hiding this comment

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

Left some nitpick level comments.

But since we could always discuss these things / we have a lot work left to do, I guess just ignore whatever you feel is not worth discussing.

});
}

get id() {
Copy link
Member

Choose a reason for hiding this comment

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

Sometimes I wonder do we really need all these getters when they're just returning prop value. 🤔
I guess they're needed because we have private underscored versions of props.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Although it might seem excessive, having a RadioItem model is very beneficial, and the id getter serves as a good example.

While an id is not required when defining a radio item, it's crucial for consistency in various situations. Ensuring that each RadioItem has a valid id helps us avoid issues when interacting with or displaying items.

If an id isn't provided externally, the model can generate one internally, keeping everything uniform across the application.

@@ -0,0 +1,8 @@
import React from "react";
Copy link
Member

Choose a reason for hiding this comment

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

I saw in other file this import is not there, but here we use it.

Just mentioning this for consistency... but yeah.. nitpick.

id={id}
className={cn(
[
"group peer aspect-square h-4 w-4 rounded-xl mt-xxs",
Copy link
Member

Choose a reason for hiding this comment

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

h-4 w-4 used here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you! 👍

<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
<span
className={cn([
"h-2 w-2 rounded-xl",
Copy link
Member

Choose a reason for hiding this comment

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

h-2 w-2 used here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you! 👍

const DecoratableRadio = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Item>,
RadioProps
>(({ className, label, id, ...props }, ref) => {
Copy link
Member

Choose a reason for hiding this comment

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

Will the users need to pass id all the time in order to have label also clickable / act as if a user clicked on the radio button? 🤔

Can we generate this maybe in cases the user did not pass the ID?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This component is quite simple; it just receives props and renders the radio button. I modified the props interface to make the id property mandatory.

The id is passed from the RadioItem model, and we know that it will always be a string, even if the user does not provide it.

/**
* RadioItem
*/
type RadioProps = React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item> & {
Copy link
Member

Choose a reason for hiding this comment

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

I noticed you're using type in some of these.

Which is fine, but I believe we're generally leaning more towards using interface when possible. So in this case, we could do:

interface RadioProps extends React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item> {
   label: string | React.ReactNode;
}

Just mentioning it, it's a nitpick. Bu feel free to leave it if you want.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you, I have switched to interface in this component. I will implement the same change in other components as well.

makeAutoObservable(this);
}

public init = (params: RadioGroupPresenterParams<TValue>) => {
Copy link
Member

@adrians5j adrians5j Nov 27, 2024

Choose a reason for hiding this comment

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

Saw this before and wanted to share an alternative to having to instantiate a class and then call init on it. It would include having a static create class, which takes params and instantiates / inits. So basically:

// Instead of this...
const rgp = new RadioGroupPresenter();
rgp.init(params);

// ...this (the `static` create method creates a new instance of the class):
const rgp = RadioGroupPresenter.create(params);

Maybe I missed something though, and this is probably a bit subjective. Still wanted to share, can't hurt. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll spend some time experimenting with it; thank you for the suggestion. 😃


get vm() {
return {
items: this.items.map(item => RadioItemMapper.toFormatted(item))
Copy link
Member

Choose a reason for hiding this comment

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

Question I had here before... why is RadioItemMapper having the toFormatted fn. If it's a "mapper", shouldn't it have toMapped method instead?

Don't know what's the correct term/verb here: are we talking about a mapper or a formatter here? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It makes sense: the original idea was to have a RadioItemMapper class with multiple methods (toFormatted, toDto...).

I changed it to RadioItemFormatter with a single format method.

packages/admin-ui/src/Radio/RadioGroupPresenter.ts Outdated Show resolved Hide resolved
import { RadioItemDto } from "~/Radio/RadioItemDto";

interface RadioGroupPresenterParams<TValue = string> {
items: RadioItemDto[];
Copy link
Member

@adrians5j adrians5j Nov 27, 2024

Choose a reason for hiding this comment

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

Still on the fence whether this is really RadioItemDto. :D

Maybe RadioItemParams?

IDK, I guess LR videos effed my brain and hard-wired the DTO concept to gateway layer 😵 .

Copy link
Contributor Author

Choose a reason for hiding this comment

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

DTOs encapsulate and transfer data between application layers or components, so they are not wired to the gateway layer only.

Anyway, I changed RadioItemDto into RadioItemParams as you suggest. It makes sense 👍

@leopuleo leopuleo merged commit eedd04a into feat/new-admin-ui Nov 28, 2024
8 checks passed
@leopuleo leopuleo deleted the leo/feat/ui-radio-group branch December 5, 2024 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants