Installation

Learn how to install and configure Pohon UI in your Vue application, compatible with both plain Vite and Inertia.
Pohon UI is styled with UnoCSS. If your project uses Tailwind CSS, use Nuxt UI instead, which also works in plain Vue.

Setup

Add to a Vue project

Install the Pohon UI package

pnpm add pohon-ui unocss @vinicunca/unocss-preset

Add the Pohon UI Vite plugin in your vite.config.ts

import vue from '@vitejs/plugin-vue';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    UnoCSS(),
    vue(),
    ui()
  ]
});
Pohon UI registers unplugin-auto-import and unplugin-vue-components, which will generate auto-imports.d.ts and components.d.ts type declaration files. You will likely want to gitignore these, and add them to your tsconfig.
tsconfig.app.json
{
  "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "auto-imports.d.ts", "components.d.ts"]
}
.gitignore
# Auto-generated type declarations
auto-imports.d.ts
components.d.ts
These declaration files are only written when Vite runs. The default create-vuebuild script runs vue-tsc in parallel with vite build (run-p type-check "build-only {@}"), so on a clean checkout type-checking can start before the files exist and fail with errors like Cannot find name 'useToast'. Run the type-check after the build instead so the declarations are generated first.
package.json
{
  "scripts": {
    "build": "run-s build-only type-check"
  }
}
Internally, Pohon UI relies on custom aliases to resolve the theme types. If you're using TypeScript, add these aliases to your tsconfig files to enable auto-completion in your vite.config.ts.
tsconfig.node.json
{
  "compilerOptions": {
    "paths": {
      "#build/ui": [
        "./node_modules/.pohon-ui/ui"
      ]
    }
  }
}
tsconfig.app.json
{
  "compilerOptions": {
    "paths": {
      "#build/ui/*": [
        "./node_modules/.pohon-ui/ui/*"
      ]
    }
  }
}

Use the Pohon UI Vue plugin

import ui from 'pohon-ui/vue-plugin';
import { createApp } from 'vue';
import { createRouter, createWebHistory } from 'vue-router';
import App from './App.vue';

const app = createApp(App);

const router = createRouter({
  routes: [],
  history: createWebHistory()
});

app.use(router);
app.use(ui);

app.mount('#app');

Configure UnoCSS

uno.config.ts
import { presetVinicunca } from '@vinicunca/unocss-preset';
import { pohonColors } from 'pohon-ui/unocss';
import { defineConfig } from 'unocss';

export default defineConfig({
  presets: [presetVinicunca()],
  theme: { colors: pohonColors },
});

Import virtual:uno.css in your Vue or Inertia entrypoint before mounting the application:

src/main.ts
import 'virtual:uno.css';

Wrap your app with App component

<template>
  <PApp>
    <RouterView />
  </PApp>
</template>
The App component sets up global config and is required for Toast, Tooltip and programmatic overlays.

Add the isolate class to your root container

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Pohon UI</title>
  </head>
  <body>
    <div id="app" class="isolate"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>
This ensures styles are scoped to your app and prevents issues with overlays and stacking contexts.

Explore working examples

See the Nuxt playground and Vue playground for complete Pohon UI setups.

Options

You can customize Pohon UI by providing options in your vite.config.ts.

prefix

Use the prefix option to change the prefix of the components.

  • Default: P
vite.config.ts
import vue from '@vitejs/plugin-vue';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    UnoCSS(),
    vue(),
    ui({
      prefix: 'Nuxt'
    })
  ]
});

ui

Use the ui option to provide configuration for Pohon UI. This is the Vue equivalent of the ui key in Nuxt's app.config.ts.

vite.config.ts
import vue from '@vitejs/plugin-vue';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    UnoCSS(),
    vue(),
    ui({
      ui: {
        colors: {
          primary: 'green',
          neutral: 'slate'
        }
      }
    })
  ]
});

dts

Use the dts option to enable or disable the generation of declaration files for auto-imported components and composables.

  • Default: true
vite.config.ts
import vue from '@vitejs/plugin-vue';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    UnoCSS(),
    vue(),
    ui({
      dts: false
    })
  ]
});

icon

Use the icon option to set default props for the Icon component (size, mode, customize) and to configure build-time icon bundling through clientBundle. Bundling of Pohon UI's own icons is enabled by default when their collection is installed. Set clientBundle: false to opt out.

  • Default: {}
vite.config.ts
import vue from '@vitejs/plugin-vue';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    UnoCSS(),
    vue(),
    ui({
      icon: {
        mode: 'svg',
        clientBundle: {
          scan: true
        }
      }
    })
  ]
});
Learn more about icon collections and client bundling in the Icons documentation.

colorMode

Use the colorMode option to enable or disable the color mode integration from @vueuse/core.

  • Default: true
vite.config.ts
import vue from '@vitejs/plugin-vue';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    UnoCSS(),
    vue(),
    ui({
      colorMode: false
    })
  ]
});

theme.colors

Use the theme.colors option to define the dynamic color aliases used to generate components theme.

  • Default: ['primary', 'secondary', 'success', 'info', 'warning', 'error']
vite.config.ts
import vue from '@vitejs/plugin-vue';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    UnoCSS(),
    vue(),
    ui({
      theme: {
        colors: ['primary', 'error']
      }
    })
  ]
});
Each alias adds a color variant to every component theme that has one, whether your app uses it or not. Trim the list to the aliases you actually use, and keep error if you use forms since validation styles rely on it. primary is always included.The --ui-color-<alias>-* shades themselves are not generated: define them in your CSS (see CSS Variables).
Learn more about color customization and theming in the Theme section.

theme.transitions

Use the theme.transitions option to enable or disable transitions on components.

  • Default: true
vite.config.ts
import vue from '@vitejs/plugin-vue';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    UnoCSS(),
    vue(),
    ui({
      theme: {
        transitions: false
      }
    })
  ]
});
This option adds the transition-colors class on components with hover or active states.

theme.unstyled

Use the theme.unstyled option to remove all default theme classes from components, keeping only their structure and the classes you provide through class, ui or app.config.ui.

  • Default: false
vite.config.ts
import vue from '@vitejs/plugin-vue';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    UnoCSS(),
    vue(),
    ui({
      theme: {
        unstyled: true
      }
    })
  ]
});
This strips structural classes too (positioning, transitions, flex/grid), not just cosmetic ones. Layout-heavy components like Modal, Drawer or Calendar will need you to re-supply their layout, similar to PrimeVue's unstyled mode.

theme.defaultVariants

Use the theme.defaultVariants option to override the default color and size variants for components.

Only defaults that are exactly primary or md are replaced, so Avatar keeps color: 'neutral' and Separator keeps size: 'xs'.

  • Default: { color: 'primary', size: 'md' }
vite.config.ts
import vue from '@vitejs/plugin-vue';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    UnoCSS(),
    vue(),
    ui({
      theme: {
        defaultVariants: {
          color: 'neutral',
          size: 'sm'
        }
      }
    })
  ]
});

prose

Use the prose option to enable Pohon UI Prose components and their theme.

  • Default: false
vite.config.ts
import vue from '@vitejs/plugin-vue';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    UnoCSS(),
    vue(),
    ui({
      prose: true
    })
  ]
});

autoImport

Use the autoImport option to disable composable auto-imports or to customize unplugin-auto-import options.

  • Default: {}
vite.config.ts
import vue from '@vitejs/plugin-vue';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    UnoCSS(),
    vue(),
    ui({
      autoImport: false
    })
  ]
});
When disabled, you can still import composables explicitly from pohon-ui/composables.

components

Use the components option to disable component auto-imports or to customize unplugin-vue-components options.

  • Default: {}
vite.config.ts
import vue from '@vitejs/plugin-vue';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    UnoCSS(),
    vue(),
    ui({
      components: false
    })
  ]
});
When disabled, you can still import components explicitly, e.g. import Button from 'pohon-ui/components/Button.vue' or import ProseCode from 'pohon-ui/components/prose/Code.vue'.

router

Use the router option to configure routing integration. This is useful for applications that don't use vue-router, such as Electron apps, MPAs, or frameworks like Inertia.js or Hybridly.

  • Default: true
ValueDescription
trueUses vue-router for navigation with RouterLink component.
falseDisables routing integration, links render as plain <a> tags.
'inertia'Uses Inertia.js for navigation with its Link component.
vite.config.ts
import vue from '@vitejs/plugin-vue';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    UnoCSS(),
    vue(),
    ui({
      router: false
    })
  ]
});
You can provide custom navigation logic for frameworks like Hybridly by setting router: false in the Vite config and passing a function when installing the Vue plugin:
src/main.ts
import { router } from 'hybridly';
import ui from 'pohon-ui/vue-plugin';

app.use(ui, {
  router: (event, { href, external }) => {
    if (external) {
      return;
    }

    event.preventDefault();

    router.navigate({ url: href });
  }
});
When set to false or 'inertia', vue-router is not required as a dependency.

scanPackages

Use the scanPackages option to specify additional npm packages that should be scanned for components using Pohon UI. This is useful when you have a shared component library that uses Pohon UI components internally.

vite.config.ts
import vue from '@vitejs/plugin-vue';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    UnoCSS(),
    vue(),
    ui({
      scanPackages: ['@my-org/ui-components']
    })
  ]
});
By default, only pohon-ui is scanned. Use this option when your external packages contain Vue components that use Pohon UI.

root

Use the root option to override the directory where Pohon UI generates its .pohon-ui directory (containing the theme templates). By default it uses Vite's root, but in setups like electron-vite the renderer's root points to a sub-directory (e.g. src/renderer), so the templates land in src/renderer/node_modules/.pohon-ui where UnoCSS doesn't scan them, causing theme classes like bg-background, ring-border and divide-border to be missing.

electron.vite.config.ts
import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'electron-vite';
import ui from 'pohon-ui/vite';
import UnoCSS from 'unocss/vite';

export default defineConfig({
  renderer: {
    root: 'src/renderer',
    plugins: [
      vue(),
      ui({
        root: __dirname
      })
    ]
  }
});
Point root at your project root so the generated .pohon-ui directory ends up in a node_modules that UnoCSS scans.

Continuous releases

Pohon UI uses pkg.pr.new for continuous preview releases, providing developers with instant access to the latest features and bug fixes without waiting for official releases.

Automatic preview releases are created for all commits and PRs to the main branch. Use them by replacing your package version with the specific commit hash or PR number.

package.json
{
  "dependencies": {
-   "pohon-ui": "^2.0.0-rc",
+   "pohon-ui": "https://pkg.pr.new/pohon-ui@4c96909",
  }
}
pkg.pr.new will automatically comment on PRs with the installation URL, making it easy to test changes.