This is inheritance over composition, which goes against the design principle "composition over inheritance". What happens when you want a `` and you also want it to be disabled? Would you create a ``? What happens when your button has 5 props? Would you create 3125 different button components to support all combinations? I think this pattern is OK for some specific use cases, but this example kind of misses the mark. In our application, we have a button, which is used to reset filters in different places on a page. It is displayed with the same icon, the same text and the same color on 50+ pages - here the pattern makes sense. We create a `` component. I feel like such a scenario is a better use case for this pattern, but for the actual UI component itself, I want it to be as flexible as possible through composition of different props and slots.
CVA + Props + Attributes And a clean attribute which strips everything except exposed methods yet the user can set the slot. Never had an issue so far, 1 year and counting
@@hejloldetermig3850 Exactly as you said, this feels much more complicated when it comes to usage so I would be careful with components that have alot of variations and are used alot. I think this pattern would only really be useful with very complex components that have 2-3 variations that differ from each other a lot.
I guess the next logical thing will be to combine all 3 buttons into one but with the 3 buttons as subcomponents inside the button and a prop that switches between the components. Something like Test Button and then inside the button the component becomes visible with a if statement. The functionality what the button does is inside the sub button component. This is how I would do it.
This is definitely an improvement from the initial component. I like to have my cake and eat it too by making the normal use case be as simple as possible while allowing full customizability when needed. In my Vue components, this generally takes the form of a prop, with a sensible default value, which is rendered as the default slot content. This way, I can either pass nothing and use the default value, pass a prop to override, or take full advantage of the slot. You can take this further and apply similar patterns to make really robust components with simple, intuitive interfaces. My personal favorite model for great component design is the FormKit library
Thank you for this video. I like this pattern. However, I would prefer the naming to ButtonBase, ButtonBrief, ButtonDisabled. 1. The IDE would show them next to each other and 2. while programming my first thought is always I need a button and second which button do I need.
The SRP on the maximal level. But it makes things more complicated. This approach works pretty well with functions or even classes. But components should have consistency and work almost like those in an abstract Vuetify or any other UI library. There might be tons of scenarios for tables or modals, popups, etc.
Hi erik , good point that you mention but i get confuse , when you create a disable button , it is just for breif button not base button and if we have a various of buttons type, we have to create their disabled button??
I do it by creating a Button Element that is able to display states like disabled, plus various Color Styles. Then there is the basic style such as Border, Rounded Edges. This is stored in a style prop as the default. The font size as well as the spacing within is also stored as a layout prop. The labeling as well as optional icons are passed on to the button via a slot. Icon left, right or in the middle without wording. If you are building a large number of buttons that can be grouped visually, we build a superordinate component. There we store the style as a map, literal or JSON and switch the respective variant via prop.
Hi Eric , I think this is not a good pattern for this use case because a single relatively simple AppBtn cmp can take all of the needed use cases very easily including : loading , disable , color , size & icons. It's better to create a single button with not much of a code. the icons are just props because I'm holding all of them as and the svg that contain all of them is in the app root. each Icon is with currentColor value and there is really not much code to get all of those use cases . this is for a button! for other components which are more complex I think the pattern that u suggested will work better.
I really like those kinds of abstractions, and i am using them in my daily coding, but when it comes to performance, i have a case where i have to render list of more than 10000 items it comes to an issue when using multiple nested components inside this list. What do you think about this case
Hi, nice idea. Maybe the example with disabled btn is not suitable. I usually want the disabled button in dynamic. If I will do ButtonDisabled I will have to add "if statements" for the disabled case.
I like how shadcn solves it, using CVA. A file to define the variants and then a slot. That gives a lot of versatility and keeps things clean. What variants does it allow? Just look at the file.
Kinda Reminds me a bit of Liskov Subtituiton Principle which is part of the SOLID principle, but not 100% since the button doesn't have the same emit name consistently with 3 buttons. I would say this pattern aren't necessarily wrong. It could feel redundant for sure 🙂
I would argue that is better still to use an object prop and parse the icon, divider,text ,color and state to the button component. That way I won't scratch my head finding the exact variance. for every use case.
ok - so where did you tore the abstracted button variants? In nuxt particularly I am having similar issue with folders and subfolders and increasingly longer....and longer component names.
ah I see your head was covering - you put BriefButton in root of components. I can see that getting very disorganized and good-names-dependent as yor projects and variants grow. For smaller projects I would recommend putting BreifButton in the Base folder where it would assume the name BaseBriefButton when using. Larger projects where you have several variants of several components...stilll looking for a good pattern.
That is a good point! I was thinking about putting it in the Base folder, but then I wanted only the fundamental components (BaseButton) in the base folder. Good point in larger projects, I'd probably have to rethink the directory structure.
This a very common issue and I'm still looking for the golden solution for this. In react you can collect all of your logic and keep it separate (like your video suggest) by named exports. I really like that but is that even possible in Vue?
in a way i miss the old days when you used 2-4 bootstrap classes(also have utility classes) not 20 and we didn't have to define a component most of the time you define utility small html components because of styling not because of functionality. For the functionality ones or you want to break your component into partials that's a different story
It would be MUCH easier and better organized to keep all logic inside of the component. ‹BaseButton variant="primary" outline disabled /›. And inside of the component you keep computed property which applies all needed classes and does all logic. This approach is mostly used in UI libraries.
I agree, inthis button case certainly… else everyone will do a different approach. With a bit of documentation it is not hard. With the other way maybe harder. With a form, and form elements, yes…
is it only me ,this way to write code in your app not good nor flexible ...?? i think if you need to create a base component it should handle all things and have flexible api ..at least for me i should able to change ( icon ,label ,loading,disabled,custom classes) and going further with some extra functionlity like ( varaint,colort, as) and to be more flexible icons(trailing and leading ) and labels can be customized with specifc slots if needed
I also feel like a base button should do most things a button is expected to do, click, loading, disabled, custom classes ,etc and then variants can be ButtinIcon
Don't really see this pattern useful. Creating component for each state of button is not good. We prefer to add multiple props for single button component, that can change its color, size, view and so on.
Hello! I think the translation says here, that I'm using v-if. I'm not using a v-if, I'm showing a way to refactor a button component to be more re-usuable using the base pattern. Привет! Кажется, здесь в переводе сказано, что я использую v-if. Я не использую v-if, я показываю способ рефакторинга компонента кнопки, чтобы его можно было более повторно использовать, используя базовый шаблон.
I believe his intention was to explain that, in the presented example, there are two types of buttons: the base button and the disabled button. To manage these states, it would be necessary to use a `v-if` directive instead of just passing a property to the base component.
This is a bad approach. Just stick to the props, and if internally you need more space, make internal components that don't get exposed to the developers.
I don't think this is good. It bloats the code too much using "v-if" to render two different components, for example, if you want a disabled button, instead of just passing a prop, you'll have to use "v-if" or "Component" to dynamically render the component. I think a good approach would be to create a BaseButton, then create other ones, but all in one component, and you change it inside the component accordingly to the prop changes. If you think a component is getting too big, always decouple it in more small components.
What patterns do you use?
FSD methodology
This is inheritance over composition, which goes against the design principle "composition over inheritance". What happens when you want a `` and you also want it to be disabled? Would you create a ``? What happens when your button has 5 props? Would you create 3125 different button components to support all combinations? I think this pattern is OK for some specific use cases, but this example kind of misses the mark. In our application, we have a button, which is used to reset filters in different places on a page. It is displayed with the same icon, the same text and the same color on 50+ pages - here the pattern makes sense. We create a `` component. I feel like such a scenario is a better use case for this pattern, but for the actual UI component itself, I want it to be as flexible as possible through composition of different props and slots.
CVA + Props + Attributes
And a clean attribute which strips everything except exposed methods yet the user can set the slot.
Never had an issue so far, 1 year and counting
@@hejloldetermig3850 Exactly as you said, this feels much more complicated when it comes to usage so I would be careful with components that have alot of variations and are used alot. I think this pattern would only really be useful with very complex components that have 2-3 variations that differ from each other a lot.
I guess the next logical thing will be to combine all 3 buttons into one but with the 3 buttons as subcomponents inside the button and a prop that switches between the components.
Something like Test Button and then inside the button the component becomes visible with a if statement. The functionality what the button does is inside the sub button component. This is how I would do it.
we have this issue at work. We start with a basic component and it eventually turns into a swiss army knife
This is definitely an improvement from the initial component. I like to have my cake and eat it too by making the normal use case be as simple as possible while allowing full customizability when needed. In my Vue components, this generally takes the form of a prop, with a sensible default value, which is rendered as the default slot content. This way, I can either pass nothing and use the default value, pass a prop to override, or take full advantage of the slot. You can take this further and apply similar patterns to make really robust components with simple, intuitive interfaces. My personal favorite model for great component design is the FormKit library
Thank you for this video. I like this pattern. However, I would prefer the naming to ButtonBase, ButtonBrief, ButtonDisabled. 1. The IDE would show them next to each other and 2. while programming my first thought is always I need a button and second which button do I need.
The SRP on the maximal level. But it makes things more complicated. This approach works pretty well with functions or even classes. But components should have consistency and work almost like those in an abstract Vuetify or any other UI library. There might be tons of scenarios for tables or modals, popups, etc.
thanks alot for all you do for the vue community
My pleasure!
Hi erik , good point that you mention but i get confuse , when you create a disable button , it is just for breif button not base button and if we have a various of buttons type, we have to create their disabled button??
I do it by creating a Button Element that is able to display states like disabled, plus various Color Styles. Then there is the basic style such as Border, Rounded Edges. This is stored in a style prop as the default. The font size as well as the spacing within is also stored as a layout prop.
The labeling as well as optional icons are passed on to the button via a slot. Icon left, right or in the middle without wording.
If you are building a large number of buttons that can be grouped visually, we build a superordinate component. There we store the style as a map, literal or JSON and switch the respective variant via prop.
Thanks, can I know how you're using these svgs?
Hi Eric , I think this is not a good pattern for this use case
because a single relatively simple AppBtn cmp can take all of the needed
use cases very easily including : loading , disable , color , size & icons.
It's better to create a single button with not much of a code.
the icons are just props because I'm holding all of them as and the svg that contain all of them is in the app root.
each Icon is with currentColor value and there is really not much code to get all of those use cases .
this is for a button!
for other components which are more complex I think the pattern that u suggested will work better.
I really like those kinds of abstractions, and i am using them in my daily coding, but when it comes to performance, i have a case where i have to render list of more than 10000 items it comes to an issue when using multiple nested components inside this list.
What do you think about this case
sounds like a case of pagination
@@goosybs the usecase prevents me from using pagination
Hi, nice idea. Maybe the example with disabled btn is not suitable.
I usually want the disabled button in dynamic.
If I will do ButtonDisabled I will have to add "if statements" for the disabled case.
Yeah it’s a little contrived but it works
I also agree, I think the base disabled button is junk.😅
I like how shadcn solves it, using CVA. A file to define the variants and then a slot. That gives a lot of versatility and keeps things clean. What variants does it allow? Just look at the file.
i prefer use props for disabled states
That works too
Love this video and would be great to see more!
Kinda Reminds me a bit of Liskov Subtituiton Principle which is part of the SOLID principle, but not 100% since the button doesn't have the same emit name consistently with 3 buttons. I would say this pattern aren't necessarily wrong. It could feel redundant for sure 🙂
I would argue that is better still to use an object prop and parse the icon, divider,text ,color and state to the button component. That way I won't scratch my head finding the exact variance. for every use case.
ok - so where did you tore the abstracted button variants? In nuxt particularly I am having similar issue with folders and subfolders and increasingly longer....and longer component names.
ah I see your head was covering - you put BriefButton in root of components. I can see that getting very disorganized and good-names-dependent as yor projects and variants grow. For smaller projects I would recommend putting BreifButton in the Base folder where it would assume the name BaseBriefButton when using. Larger projects where you have several variants of several components...stilll looking for a good pattern.
That is a good point! I was thinking about putting it in the Base folder, but then I wanted only the fundamental components (BaseButton) in the base folder. Good point in larger projects, I'd probably have to rethink the directory structure.
amazing video!!!
Thank you!!
This a very common issue and I'm still looking for the golden solution for this. In react you can collect all of your logic and keep it separate (like your video suggest) by named exports. I really like that but is that even possible in Vue?
Not really for named exports
@@ProgramWithErik so no option to have multiple components in the same file?
Slightly confused why DisabledButton is a component. Perhaps it was a bad example.
According to the html specification, nesting a div inside a button is considered bad practice, by the way.
frontend devs are rediscovering inheritance
in a way i miss the old days when you used 2-4 bootstrap classes(also have utility classes) not 20 and we didn't have to define a component
most of the time you define utility small html components because of styling not because of functionality. For the functionality ones or you want to break your component into partials that's a different story
It would be MUCH easier and better organized to keep all logic inside of the component. ‹BaseButton variant="primary" outline disabled /›. And inside of the component you keep computed property which applies all needed classes and does all logic. This approach is mostly used in UI libraries.
That is one way. I like this pattern though
I agree, inthis button case certainly… else everyone will do a different approach. With a bit of documentation it is not hard. With the other way maybe harder.
With a form, and form elements, yes…
dont think youre supposed to be putting divs in buttons. good video though i hadnt heard of these before
is it only me ,this way to write code in your app not good nor flexible ...?? i think if you need to create a base component it should handle all things and have flexible api ..at least for me i should able to change ( icon ,label ,loading,disabled,custom classes)
and going further with some extra functionlity like ( varaint,colort, as) and to be more flexible icons(trailing and leading ) and labels can be customized with specifc slots if needed
I also feel like a base button should do most things a button is expected to do, click, loading, disabled, custom classes ,etc and then variants can be ButtinIcon
Don't really see this pattern useful.
Creating component for each state of button is not good.
We prefer to add multiple props for single button component, that can change its color, size, view and so on.
Он предлагает использовать v-if DisabledButton, BaseButton.
А не пропсы.
Пример очень не удачный
Может и не удачный, но проблему классификации кнопок решает
Hello! I think the translation says here, that I'm using v-if. I'm not using a v-if, I'm showing a way to refactor a button component to be more re-usuable using the base pattern.
Привет! Кажется, здесь в переводе сказано, что я использую v-if. Я не использую v-if, я показываю способ рефакторинга компонента кнопки, чтобы его можно было более повторно использовать, используя базовый шаблон.
I believe his intention was to explain that, in the presented example, there are two types of buttons: the base button and the disabled button. To manage these states, it would be necessary to use a `v-if` directive instead of just passing a property to the base component.
@@ProgramWithErik I have no questions for you. I was talking about Michael Thyssen. Some of his examples in X sometimes seem strange
Your boss has to REALLY make up his mind before coming to you man! just saying. (thanks for the great explanation btw)
Looks awkward with the template at the top. I'm now so used to having the setup first.
I really thought this was the norm.
Using the slot was a stupid idea 💀 just make the icon and the separater optional props
This is a bad approach. Just stick to the props, and if internally you need more space, make internal components that don't get exposed to the developers.
Hard disagree. This is a great way of handling components
I don't think this is good. It bloats the code too much using "v-if" to render two different components, for example, if you want a disabled button, instead of just passing a prop, you'll have to use "v-if" or "Component" to dynamically render the component.
I think a good approach would be to create a BaseButton, then create other ones, but all in one component, and you change it inside the component accordingly to the prop changes.
If you think a component is getting too big, always decouple it in more small components.
Using dynamic components is better than using v-if for your use case. See the dynamic components part in the documentation.