Skip to content

feat(vue-router): add styles support on head#7320

Open
romulovalez wants to merge 1 commit intoTanStack:mainfrom
romulovalez:fix/vue-router-styles-augmentation
Open

feat(vue-router): add styles support on head#7320
romulovalez wants to merge 1 commit intoTanStack:mainfrom
romulovalez:fix/vue-router-styles-augmentation

Conversation

@romulovalez
Copy link
Copy Markdown

@romulovalez romulovalez commented May 2, 2026

Summary

Closes #7318.

  • Add the missing styles field to the Vue RouteMatchExtensions module augmentation in packages/vue-router/src/Matches.tsx, alongside meta, links, scripts, and headScripts — bringing Vue to parity with the React and Solid counterparts.
  • Wire up the runtime in packages/vue-router/src/headContentUtils.tsx so head().styles declared on routes is actually rendered (mirroring the existing headScripts pattern, then included in the final uniqBy output).

Test plan

  • pnpm --filter @tanstack/vue-router test:unit (45 files, 783 tests, 0 type errors). The existing route.test.tsx styles and styles w/loader tests now exercise the typed field end-to-end.

Summary by CodeRabbit

  • New Features
    • Added support for route-level style definitions in Vue Router, allowing styles to be automatically managed and applied through route configurations.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 2, 2026

📝 Walkthrough

Walkthrough

This PR adds a styles field to Vue Router's RouteMatchExtensions type and implements processing logic in useTags to transform style entries into managed <style> VDOM tags, bringing Vue feature parity with React and Solid implementations.

Changes

Style Tag Support in Vue Router

Layer / File(s) Summary
Data Shape
packages/vue-router/src/Matches.tsx
RouteMatchExtensions module augmentation extended with optional styles field to hold style metadata alongside meta, links, scripts, and headScripts.
Core Implementation
packages/vue-router/src/headContentUtils.tsx
useTags composable now processes match.styles by flattening entries, extracting children, and mapping each into a RouterManagedTag <style> element; results are merged with existing managed tags and deduped by uniqBy.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A hop, a skip, through stylesheets we go,
Vue Router now shines with deferred head glow,
Managed style tags in flattened array,
Bringing parity—hooray, hooray! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The pull request adds the styles field to RouteMatchExtensions module augmentation in Matches.tsx and implements runtime rendering in headContentUtils.tsx. However, the typed field differs from the linked issue requirement. Update the styles field type to match issue #7318 exactly: styles?: Array<(Vue.ComponentOptions['style'] & { key?: string }) | undefined> instead of the current Array<Vue.ComponentOptions['style'] | undefined>.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(vue-router): add styles support on head' clearly and concisely describes the main change: adding styles support to the Vue router head functionality.
Out of Scope Changes check ✅ Passed All changes in the pull request are directly related to adding styles support to Vue router head functionality, aligning with issue #7318 requirements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 2, 2026

Bundle Size Benchmarks

  • Commit: 51029a0df9eb
  • Measured at: 2026-05-02T08:03:41.694Z
  • Baseline source: history:51029a0df9eb
  • Dashboard: bundle-size history
Scenario Current (gzip) Delta vs baseline Raw Brotli Trend
react-router.minimal 87.15 KiB 0 B (0.00%) 273.94 KiB 75.70 KiB ███▁▁▁▁▁▁▁▁
react-router.full 90.68 KiB 0 B (0.00%) 285.45 KiB 78.71 KiB ███▁▁▁▁▁▁▁▁
solid-router.minimal 35.38 KiB 0 B (0.00%) 106.25 KiB 31.81 KiB ███▁▁▁▁▁▁▁▁
solid-router.full 40.10 KiB 0 B (0.00%) 120.46 KiB 36.04 KiB ███▁▁▁▁▁▁▁▁
vue-router.minimal 53.15 KiB 0 B (0.00%) 151.39 KiB 47.73 KiB ███▁▁▁▁▁▁▁▁
vue-router.full 58.31 KiB +30 B (+0.05%) 167.70 KiB 52.27 KiB ███▁▁▁▁▁▁▁▁▂
react-start.minimal 101.76 KiB 0 B (0.00%) 322.10 KiB 87.97 KiB ███▁▁▁▁▁▁▁▁
react-start.full 105.19 KiB 0 B (0.00%) 332.43 KiB 90.96 KiB ███▁▁▁▁▁▁▁▁
react-start.rsbuild.minimal 99.33 KiB 0 B (0.00%) 316.47 KiB 85.46 KiB █▂▂▁▁▁▁▁▁▁▁
react-start.rsbuild.full 102.63 KiB 0 B (0.00%) 326.90 KiB 88.28 KiB █▂▂▁▁▁▁▁▁▁▁
solid-start.minimal 49.40 KiB 0 B (0.00%) 152.08 KiB 43.60 KiB ███▁▁▁▁▁▁▁▁
solid-start.full 55.20 KiB 0 B (0.00%) 168.98 KiB 48.51 KiB ███▁▁▁▁▁▁▁▁

Trend sparkline is historical gzip bytes ending with this PR measurement; lower is better.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/vue-router/src/Matches.tsx`:
- Line 31: The styles property is incorrectly typed as
Vue.ComponentOptions['style']; change it to represent HTML <style> element
attributes with optional key and children for content (matching how
headContentUtils.tsx destructures match.styles and React uses
React.JSX.IntrinsicElements['style']). Update the declaration of styles in
Matches.tsx to an array of the HTML/style attribute type (e.g.
JSX.IntrinsicElements['style'] or HTML attributes for a style element) with & {
key?: string; children?: string } (and allow undefined entries) so deduplication
keying and style content typing are correct.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6e8a9361-2175-4ed5-95ce-4b368f44fafe

📥 Commits

Reviewing files that changed from the base of the PR and between 51029a0 and e24f3ac.

📒 Files selected for processing (2)
  • packages/vue-router/src/Matches.tsx
  • packages/vue-router/src/headContentUtils.tsx

Comment thread packages/vue-router/src/Matches.tsx
@romulovalez
Copy link
Copy Markdown
Author

I will fix nonce support in another follow-up PR

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.

feat(vue-router): add styles to Vue RouteMatchExtensions augmentation

1 participant