はじめに
Vue 3でアプリを作るとき、UIライブラリ選びに悩んだことはありませんか。「Element Plusは定番だけど少し重い」「Vuetifyはマテリアルデザインが前提で自由が利かない」「かといって自前でコンポーネントを作り込む時間はない」——そんなジレンマを抱えている方は多いはずです。
そこで注目したいのがNaive UIです。Evan You氏(Vue.jsの作者)が「かなり良い(fairly interesting)」と紹介したことでも話題になったこのライブラリは、90以上のコンポーネントをすべてTypeScriptで提供し、CSSファイルのインポートすら不要という徹底ぶり。GitHubスターは18,000を超え、Vue 3時代の有力な選択肢として存在感を増しています。
この記事では、Naive UIの特徴からインストール、テーマカスタマイズ、実践的な管理画面の実装までを一気に解説します。
Naive UIとは
Naive UIは、自動運転企業TuSimple発のオープンソースとして開発されているVue 3専用のUIコンポーネントライブラリです。公式のキャッチコピーは「Fairly Complete, Theme Customizable, Uses TypeScript, Fast」。つまり「十分に揃っていて、テーマを自在に変えられて、TypeScript製で、速い」ことを掲げています。MITライセンスで、2026年7月時点の最新バージョンはv2.44.1です。
主な特徴
- 90以上のコンポーネント - ボタンやフォームはもちろん、データテーブル、ツリー、カレンダー、カルーセルまで網羅。すべてツリーシェイク可能なので、使った分だけがバンドルに含まれます
- フルTypeScript - ライブラリ全体がTypeScriptで書かれており、propsやイベントの型補完が完璧に効きます。しかもCSSのインポートが不要で、コンポーネントを
importするだけで動きます - 強力なテーマシステム - テーマ変数もTypeScriptオブジェクトとして定義。ダークモード対応は組み込み済みで、数行のコードで切り替えられます
- パフォーマンス重視 - セレクトやツリーなどの大量データを扱うコンポーネントには仮想リストが組み込まれており、数万件のデータでも軽快に動作します
インストール
npm、pnpm、yarnのいずれでもインストールできます。Vue 3のプロジェクトを前提とします。
# npm
npm install naive-ui
# pnpm
pnpm add naive-ui
# yarn
yarn add naive-ui
推奨フォントを使いたい場合は、あわせてvfontsを入れます。
npm install vfonts
基本的な使い方
Naive UIの気持ちよさは「importするだけで動く」ことにあります。CSSの読み込み設定は一切不要です。
<script setup lang="ts">
import { NButton, NSpace } from 'naive-ui'
</script>
<template>
<n-space>
<n-button>デフォルト</n-button>
<n-button type="primary">プライマリ</n-button>
<n-button type="success">サクセス</n-button>
<n-button type="error">エラー</n-button>
</n-space>
</template>
これだけでスタイル済みのボタンが表示されます。<style>ブロックも、main.tsでのCSS読み込みもありません。
ダークモードを数行で実現する
Naive UIのテーマはn-config-providerで一括制御します。ダークモードの切り替えはこれだけです。
<script setup lang="ts">
import { ref } from 'vue'
import { NConfigProvider, NButton, NCard, darkTheme } from 'naive-ui'
const isDark = ref(false)
</script>
<template>
<n-config-provider :theme="isDark ? darkTheme : null">
<n-card title="テーマ切り替えデモ">
<n-button @click="isDark = !isDark">
{{ isDark ? 'ライトモードへ' : 'ダークモードへ' }}
</n-button>
</n-card>
</n-config-provider>
</template>
darkThemeを渡すだけで、配下のすべてのコンポーネントが一斉にダークモードになります。CSSの上書き合戦とは無縁です。
ブランドカラーに合わせたテーマカスタマイズ
テーマ変数はTypeScriptオブジェクトで上書きできます。型が付いているので、変数名をエディタの補完で探せるのが地味に便利です。
<script setup lang="ts">
import { NConfigProvider, NButton, type GlobalThemeOverrides } from 'naive-ui'
const themeOverrides: GlobalThemeOverrides = {
common: {
primaryColor: '#18a058',
primaryColorHover: '#36ad6a',
borderRadius: '8px'
},
Button: {
textColorPrimary: '#ffffff'
}
}
</script>
<template>
<n-config-provider :theme-overrides="themeOverrides">
<n-button type="primary">ブランドカラーのボタン</n-button>
</n-config-provider>
</template>
自動インポートでさらに快適に
unplugin-vue-componentsを使えば、コンポーネントのimport文すら書かずに済みます。
npm install -D unplugin-vue-components unplugin-auto-import
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [NaiveUiResolver()]
})
]
})
これでテンプレートに<n-button>と書くだけで、必要なコンポーネントだけが自動でバンドルされます。
実践的なユースケース:管理画面のユーザー一覧を作る
Naive UIが最も輝くのは、管理画面やダッシュボードの開発です。ここでは「検索・ページネーション・操作ボタン付きのユーザー一覧」をn-data-tableで実装してみます。
<script setup lang="ts">
import { h, ref, computed } from 'vue'
import {
NButton, NCard, NDataTable, NInput, NSpace, NTag,
useMessage, type DataTableColumns
} from 'naive-ui'
interface User {
id: number
name: string
email: string
role: 'admin' | 'member'
}
const message = useMessage()
const keyword = ref('')
const users = ref<User[]>([
{ id: 1, name: '佐藤 花子', email: 'hanako@example.com', role: 'admin' },
{ id: 2, name: '鈴木 太郎', email: 'taro@example.com', role: 'member' },
{ id: 3, name: '田中 一郎', email: 'ichiro@example.com', role: 'member' }
])
const filteredUsers = computed(() =>
users.value.filter(
(u) => u.name.includes(keyword.value) || u.email.includes(keyword.value)
)
)
const columns: DataTableColumns<User> = [
{ title: '名前', key: 'name' },
{ title: 'メールアドレス', key: 'email' },
{
title: '権限',
key: 'role',
render: (row) =>
h(
NTag,
{ type: row.role === 'admin' ? 'warning' : 'default' },
{ default: () => (row.role === 'admin' ? '管理者' : 'メンバー') }
)
},
{
title: '操作',
key: 'actions',
render: (row) =>
h(
NButton,
{
size: 'small',
onClick: () => message.info(`${row.name} さんの詳細を表示します`)
},
{ default: () => '詳細' }
)
}
]
</script>
<template>
<n-card title="ユーザー管理">
<n-space vertical>
<n-input
v-model:value="keyword"
placeholder="名前またはメールで検索"
clearable
/>
<n-data-table
:columns="columns"
:data="filteredUsers"
:pagination="{ pageSize: 10 }"
/>
</n-space>
</n-card>
</template>
ポイントは3つあります。
- カラム定義に型が効く -
DataTableColumns<User>と書くだけで、keyにタイポがあれば即座にエラーになります - セルのカスタム描画 -
render関数とh()で、タグやボタンを含む複雑なセルも宣言的に書けます useMessageによるトースト通知 - コンポーネントのどこからでもメッセージを表示できます
なお、useMessageを使うには、アプリのルート付近をn-message-providerで包んでおく必要があります。
<!-- App.vue -->
<template>
<n-config-provider>
<n-message-provider>
<UserList />
</n-message-provider>
</n-config-provider>
</template>
管理画面でよく使うダイアログ(n-dialog-provider)や通知(n-notification-provider)も同じパターンで利用できます。
まとめ
Naive UIの魅力を振り返ってみましょう。
- 90以上のコンポーネントがツリーシェイク対応で揃っている
- フルTypeScriptで型補完が完璧、しかもCSSインポート不要
- ダークモードやテーマカスタマイズが数行で実現できる
- 仮想リスト内蔵で大量データにも強く、管理画面開発と相性抜群
Vue 3でこれから新規プロジェクトを始めるなら、Naive UIは間違いなく候補の筆頭に挙がるライブラリです。特に社内ツールや管理画面のように「デザインに凝るより、速く堅牢に作りたい」場面では、その真価を存分に発揮してくれます。
まずはnpm install naive-uiから、importするだけで動く快適さをぜひ体験してみてください。公式ドキュメント(naiveui.com)には全コンポーネントのライブデモが揃っているので、眺めるだけでも作りたいものが膨らんでくるはずです。