diff --git a/docs/content/docs/1.getting-started/2.installation/1.nuxt.md b/docs/content/docs/1.getting-started/2.installation/1.nuxt.md
index 015cfaeb51..4b7d99cc08 100644
--- a/docs/content/docs/1.getting-started/2.installation/1.nuxt.md
+++ b/docs/content/docs/1.getting-started/2.installation/1.nuxt.md
@@ -395,6 +395,45 @@ export default defineNuxtConfig({
})
```
+### `experimental.componentDetection` :badge{label="Soon"}
+
+Use the `experimental.componentDetection` option to enable automatic component detection for tree-shaking. This feature scans your source code to detect which components are actually used and only generates the necessary CSS for those components (including their dependencies).
+
+- Default: `false`{lang="ts-type"}
+- Type: `boolean | string[]`{lang="ts-type"}
+
+**Enable automatic detection:**
+
+```ts [nuxt.config.ts]
+export default defineNuxtConfig({
+ modules: ['@nuxt/ui'],
+ css: ['~/assets/css/main.css'],
+ ui: {
+ experimental: {
+ componentDetection: true
+ }
+ }
+})
+```
+
+**Include additional components for dynamic usage:**
+
+```ts [nuxt.config.ts]
+export default defineNuxtConfig({
+ modules: ['@nuxt/ui'],
+ css: ['~/assets/css/main.css'],
+ ui: {
+ experimental: {
+ componentDetection: ['Modal', 'Dropdown', 'Popover']
+ }
+ }
+})
+```
+
+::note
+When providing an array of component names, automatic detection is enabled and these components (along with their dependencies) are guaranteed to be included. This is useful for dynamic components like `` that can't be statically analyzed.
+::
+
## Continuous releases
Nuxt UI uses [pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new) for continuous preview releases, providing developers with instant access to the latest features and bug fixes without waiting for official releases.
diff --git a/src/module.ts b/src/module.ts
index f90557c984..b2f09604ca 100644
--- a/src/module.ts
+++ b/src/module.ts
@@ -76,6 +76,22 @@ export interface ModuleOptions {
* @defaultValue false
*/
content?: boolean
+
+ /**
+ * Experimental features
+ */
+ experimental?: {
+ /**
+ * Enable automatic component detection for tree-shaking
+ * Only generates theme files for components actually used in your app
+ * - `true`: Enable automatic detection
+ * - `string[]`: Enable detection and include additional components (useful for dynamic components)
+ * @defaultValue false
+ * @example true
+ * @example ['Modal', 'Dropdown']
+ */
+ componentDetection?: boolean | string[]
+ }
}
declare module '#app' {
diff --git a/src/templates.ts b/src/templates.ts
index 31898d56a7..cedb0905bd 100644
--- a/src/templates.ts
+++ b/src/templates.ts
@@ -1,8 +1,11 @@
import { fileURLToPath } from 'node:url'
-import { kebabCase } from 'scule'
+import { readFile } from 'node:fs/promises'
+import { join } from 'pathe'
+import { globSync } from 'tinyglobby'
+import { camelCase, kebabCase, pascalCase } from 'scule'
import { genExport } from 'knitwork'
import colors from 'tailwindcss/colors'
-import { addTemplate, addTypeTemplate, hasNuxtModule } from '@nuxt/kit'
+import { addTemplate, addTypeTemplate, hasNuxtModule, logger, updateTemplates } from '@nuxt/kit'
import type { Nuxt, NuxtTemplate, NuxtTypeTemplate } from '@nuxt/schema'
import type { Resolver } from '@nuxt/kit'
import type { ModuleOptions } from './module'
@@ -10,18 +13,137 @@ import * as theme from './theme'
import * as themeProse from './theme/prose'
import * as themeContent from './theme/content'
-export function buildTemplates(options: ModuleOptions) {
- return Object.entries(theme).reduce((acc, [key, component]) => {
- acc[key] = typeof component === 'function' ? component(options as Required) : component
- return acc
- }, {} as Record)
+/**
+ * Build a dependency graph of components by scanning their source files
+ */
+async function buildComponentDependencyGraph(componentDir: string, prefix: string): Promise