Skip to main content
Back to contributions
Pull Request
Merged
55.9K

Vue components support arbitrary HTML attributes

withastro/astro

Fixed TypeScript typings so Vue components properly accept HTML attributes like class and style via $attrs fallthrough

The Problem

Vue components have a built-in mechanism called $attrs fallthrough that allows arbitrary HTML attributes to pass through to child elements. This works automatically when a Vue component has a single root element, or can be explicitly controlled using the $attrs object.

However, Astro’s language tools weren’t aware of this Vue feature. When developers tried to pass standard HTML attributes like class, style, or id to Vue components in .astro files, TypeScript would throw false errors even though the code worked perfectly at runtime.

For example, this valid code would trigger TypeScript errors:

---
import MyVueComponent from './MyVueComponent.vue';
---

<!-- This works at runtime but TypeScript complained -->
<MyVueComponent class="my-styles" id="hero-section" />

The issue was labeled as a “good first issue” and had been open since October 2022, affecting developers who wanted to style Vue components using standard HTML attributes in their Astro projects.

The Solution

I implemented a type helper system that extends Vue component props to include HTML attributes and Astro client directives. The solution follows the same pattern already established in Astro’s Svelte integration.

The fix introduces a PropsWithHTMLAttributes<T> type that combines:

  • Component-specific props (T) - the props explicitly defined in the Vue component
  • Standard HTML attributes from astroHTML.JSX.HTMLAttributes - class, style, id, data-*, etc.
  • Astro client directives (AstroClientDirectives) - client:load, client:visible, etc.

Here’s the core type definition that makes this work:

// vue-shims.d.ts
type PropsWithHTMLAttributes<T> = T &
  astroHTML.JSX.HTMLAttributes &
  AstroClientDirectives;

The editor.cts file was then updated to automatically wrap all generated Vue component props with this new helper type, ensuring TypeScript recognizes that Vue components can accept any valid HTML attribute.

Files Changed

FileChange
packages/integrations/vue/vue-shims.d.tsNew file defining the PropsWithHTMLAttributes<T> type
packages/integrations/vue/src/editor.ctsUpdated to wrap Vue props with HTML attributes type
packages/integrations/vue/package.jsonAdded export for the new type definitions
packages/integrations/vue/test/toTsx.test.jsAdded test coverage with astro check validation

Timeline

DateEvent
Oct 5, 2022Issue #14686 opened by @Princesseuh
Dec 13, 2025Analyzed root cause and submitted PR #15016
Dec 17, 2025Rebased branch to resolve mixed commit history
Jan 7, 2026PR approved and merged by @Princesseuh

Impact

This fix benefits all Astro developers using Vue components who want to:

  • Apply CSS classes directly to Vue components
  • Add inline styles for quick customizations
  • Use data attributes for JavaScript interactions
  • Set accessibility attributes like aria-* and role
  • Use Astro’s client directives for partial hydration

The solution aligns Vue’s TypeScript support with the existing Svelte integration pattern, ensuring a consistent developer experience across Astro’s framework integrations.