Closed zernonia closed 8 months ago
I'm with even though it's not typed yet https://github.com/vuejs/core/pull/7444$attrs
However if we extend Props based on HTMLAttributes like shadcn, we will have two class prop when we hit Ctrl + Space
runtime-dom.d.ts
defineProps
see this SFC playground
Edit: external types error and vue props destructuring error with class
keyword in Button.vue
in SFC playground
Base on so1ve answer in Vue issue (How to import interface for defineProps)
imported external interface should not be extended so Vue can resolve the type
We should have an interface like this
- export interface ButtonHTMLAttributes extends HTMLAttributes {
+ export interface OnlyButtonHTMLAttributes {
autofocus?: Booleanish
disabled?: Booleanish
form?: string
formaction?: string
formenctype?: string
formmethod?: string
formnovalidate?: Booleanish
formtarget?: string
name?: string
type?: 'submit' | 'reset' | 'button'
value?: string | string[] | number
}
https://github.com/wooorm/html-element-attributes/blob/main/index.js
Because the default value of the inheritAttrs
attribute in the vue component is true, I think the processing of $attrs.class
can be ignored in components that are not explicitly set to inheritAttrs: false
😃
That Vue SFC playground sometimes acts inconsistently after editing :sob: for example, it's merge classes even if you use $attrs.class and v-bind="$attrs"
I think we should use useAttrs
to destructure the object to access the class
key
<script setup lang="ts">
import { useAttrs } from 'vue'
import { cn } from '@/lib/utils'
defineOptions({
inheritAttrs: false,
})
const { class: className, ...rest } = useAttrs() // not reactive only works on first render
</script>
<template>
<input type="text" :class="cn('flex h-9 w-full text-green-600', className ?? '')" v-bind="rest">
</template>
<script setup lang="ts">
import Input from './Input.vue'
</script>
<template>
<Input class="text-red-600"/> <!-- class output: "flex h-9 w-full text-red-600" -->
</template>
That Vue SFC playground sometime acts inconsistently ðŸ˜
<script setup lang="ts"> import { useAttrs } from 'vue' import { cn } from '@/lib/utils' defineOptions({ inheritAttrs: false, }) const { class: className, ...rest } = useAttrs() </script> <template> <input type="text" :class="cn('flex h-9 w-full', className ?? '')" v-bind="rest"> </template>
Hi, have we finalize the solution yet?
Hi, have we finalize the solution yet?
I can refactor all components to useAttrs
and after Vue 3.4 to defineAttrs
But before that, I need approval from Vue wizards :raised_hands: @ zernonia
Note that setting inheritAttrs: false
makes it harder to use e.g. Cypress. The recommended way to select elements for a test is by using data-cy="my-element", then getting it with cy.get('[data-cy="my-element"]').
If you inspecting some element, you would notice a duplicated class name mainly due to using
2.
approach mentioned below.For components in
registry
, you would see 2 different approach for passing the class name intocn
function.using
class
props.using inherited attributes
The reason I'm hesitating is because I don't like to declare
class
props in every component, using$attrs.class
seems much more intuitive. wdyt??