diff --git a/@xen-orchestra/web-core/docs/component-variants.md b/@xen-orchestra/web-core/docs/component-variants.md index 2f009dd6ab8..47780a57b8e 100644 --- a/@xen-orchestra/web-core/docs/component-variants.md +++ b/@xen-orchestra/web-core/docs/component-variants.md @@ -109,7 +109,7 @@ Then, we can define the props needed to handle the variants: ```ts // TS types here -const props = defineProps<{ +const { variant, accent, size, disabled } = defineProps<{ variant: ButtonVariant accent: ButtonAccent size: ButtonSize @@ -124,16 +124,12 @@ Given the props we defined above, and to match the class names convention, we ca A way to do it is as follows: ```ts -const classNames = computed(() => [ - toVariants({ - variant: props.variant, - accent: props.accent, - size: props.size, - disabled: props.disabled, - }), -]) +const classNames = computed(() => toVariants({ variant, accent, size, disabled })) ``` +> [!TIP] +> The `toVariants()` helper SHOULD be used in the script section of the component, and not in the template section (see [best practices](./guidelines/best-practices.md#component-should-not-use-functions-in-the-template-to-compute-states-or-values) for more information). + Let's take an example where we want to use the "Button" component with this DS variant: ``` diff --git a/@xen-orchestra/web-core/docs/guidelines/best-practices.md b/@xen-orchestra/web-core/docs/guidelines/best-practices.md index 93ffc2bdad1..9a6daba71cd 100644 --- a/@xen-orchestra/web-core/docs/guidelines/best-practices.md +++ b/@xen-orchestra/web-core/docs/guidelines/best-practices.md @@ -220,12 +220,66 @@ In this example, the first button will call `deleteMe(event)` and thus will alwa See also: [inline handlers](https://vuejs.org/guide/essentials/event-handling.html#inline-handlers) in Vue.js documentation. +## Component SHOULD NOT use functions in the template to compute states or values + +If using functions in the template to compute states or values, it will be called on every render, which can lead to performance issues. + +Use `computed` instead, which will cache the result, and only recompute when the dependencies change. + +❌ Bad + +```vue + + + +``` + +✅ Good + +```vue + + + +``` + +If you find yourself using this kind of functions in the template, maybe it's a good sign that a refactoring is needed (i.e., extracting the logic in a subcomponent). + +There are some exceptions, for example, when using `$t` for translations inside the template. + ## Components SHOULD have a Story > [!TIP] > For now, stories are stored in > `@xen-orchestra/lite/src/stories` and can only be written for XO Lite and XO Core components. +## Helpers and utilities SHOULD be used when necessary + +Some common utilities are already available in the projects, so be sure to check if there is already a helper or utility that can be used before reinventing the wheel. + +You'll find them in these directories: + +- Web Core: + - `@xen-orchestra/web-core/src/composables` + - `@xen-orchestra/web-core/src/utils` + - `@xen-orchestra/web-core/src/packages` +- XO 6: + - `@xen-orchestra/web/src/composables` + - `@xen-orchestra/web/src/utils` +- XO Lite: + - `@xen-orchestra/lite/src/composables` + ## VueUse SHOULD be used when necessary -Instead of recreating some functionality, [VueUse](https://vueuse.org) provides a lot of utilities for common use cases (e.g., accessing browser APIs, using local storage, etc.). +If you don't find what you need in our helpers, [VueUse](https://vueuse.org) provides a lot of utilities for common use cases (e.g., accessing browser APIs, using local storage, etc.).