vunor について
vunorは、Vue 3の画面を開発する人向けのUnoCSSテーマプリセットとコンポーネントライブラリです。CSS変数によるスコープとショートカットで両者のスタイルを統一でき、それぞれ単独でも使えます。
主な機能
- 01UnoCSSテーマプリセット
- 02Vue 3コンポーネントライブラリ
- 03カラーパレットと間隔トークン
- 04スコープベースのテーマ変数
- 05ショートカットによるスタイル設定
- 06Reka UIベースのアクセシブルなコンポーネント
活用シーン
- 01Vue画面の共通テーマ作成
- 02特定のサブツリーへの状態色の適用
- 03ショートカットによるコンポーネントのスタイル調整
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mav-rik/ vunor --skill vunorインストール後、Claude Code で/vunorを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/cards.mdcolors.mdcomponents.mdforms.mdrules.mdsetup.mdshortcuts.mdtheme.mdtypography.md詳細
Vunor
Vunor は、1 つのパッケージで 2 つの役割を果たします。
- UnoCSS デザインシステムプリセット(
presetVunor)。いくつかの数学的なパラメーターから、完全なテーマ(知覚的なカラーパレット、黄金比に基づくタイポグラフィとスペーシング、レイヤー化された背景、フォントを考慮したマージン補正)を導き出します。 - Vue 3 コンポーネントライブラリ。Reka UI を基盤に構築された、アクセシビリティに配慮した 30 個以上のコンポーネントを、UnoCSS クラスのみでスタイリングします(CSS ファイルはゼロ、スコープ付きスタイルもありません)。
2 つの要素は独立しています。プリセットはコンポーネントなしで動作し、コンポーネントは独自のコードに使用するものと同じショートカットシステムでスキンを変更できます。
メンタルモデル
3 つのレイヤーが積み重なっています。クラスを理解するには、上から順に読みます。
SEMANTIC CLASSES scope-primary, layer-0, surface-100, c8-filled, i8-filled, card
↓ expand to (UnoCSS shortcuts, deep-merged from defineShortcuts() objects)
LOW-LEVEL UTILITIES bg-current, current-bg-scope-color-500, h-fingertip, p-$m
↓ resolve to (UnoCSS rules from presetVunor)
CSS CUSTOM PROPERTIES --scope-color-500, --current-bg, --v-fingertip, --card-spacing
描画、サイズ設定、テーマ設定はすべて CSS 変数を通じて行われます。 ツリーの上位で scope-primary を一度設定すれば、すべての子孫の bg-current、c8-filled、surface-100 などにプライマリパレットが適用されます。サブツリーで scope-error を変更すれば、そのサブツリーが赤くなり、ほかのクラスは変わりません。
必須の基盤:スコープ
scope-{name} は、サブツリーで有効にするパレットを宣言します。有効なスコープがないと、色対応クラスには描画に使う値がありません。 Vunor のプリフライトは :root に scope-neutral を自動的に設定するため、すぐに使い始められます。また、標準のボーダー、レイヤー背景、通常時のテキストやアイコンなど、付随的な UI は落ち着いたニュートラルな色になります。
ページのデフォルトは scope-neutral にし、より強いスコープはアクセント要素にのみ適用することをおすすめします。
- ブランドカラーを使うインタラクティブ要素(プライマリボタン、フォーカスされた入力欄、アクティブなタブ、ブランドバナー)→
scope-primary(別のアクセントにはscope-secondary)。 - 状態を示す要素(エラーのある入力欄、破壊的な操作を行うボタン、検証メッセージ)→
scope-error。警告にはscope-warn、成功にはscope-goodを使います。
こうすることで、ページの外枠部分はニュートラルなまま保たれ、注意を向ける必要のある要素が目立ちます。
<body class="layer-0">
<header>…</header>
<button class="scope-primary c8-filled">Save</button>
<VuInput v-model="email" :error="emailError" />
<button class="scope-error c8-flat">Delete account</button>
</body>
有効な名前:primary、secondary、good、warn、error、grey、neutral。
クイックスタート
// uno.config.ts
import { defineConfig } from 'unocss'
import { presetVunor, vunorShortcuts } from 'vunor/theme'
export default defineConfig({
presets: [presetVunor({ palette: { colors: { primary: '#6B4EFF' } } })],
shortcuts: [vunorShortcuts()],
})
// vite.config.ts — add VunorVueResolver for auto-import of <VuFoo>
import Components from 'unplugin-vue-components/vite'
import { VunorVueResolver } from 'vunor/vite'
plugins: [vue(), UnoCSS(), Components({ resolvers: [VunorVueResolver] })]
// OR, for Nuxt 3
modules: ['vunor/nuxt']
<html class="scope-primary">
<body class="layer-0">
<VuCard level="h3">
<VuCardHeader>Hello</VuCardHeader>
<VuButton class="c8-filled">Save</VuButton>
</VuCard>
</body>
</html>
セットアップの全手順については、references/setup.md を参照してください。
このスキルの使い方
必要なリファレンスファイルだけを読み込みます。各ファイルは単独で利用できます。
| ファイル | 読み込むタイミング |
|---|---|
| references/setup.md | Vunor のインストール、Vite または Nuxt の設定、パッケージのエクスポート一覧の確認 |
| references/colors.md | scope-*、layer-*、surface-*、current-*、bg-current の使用、ライト/ダークの動作の理解 |
| references/theme.md | パレットの調整(鮮やかさ、彩度、フラットさ、layersDepth、lightest/darkest)、カスタムサーフェスの定義、fingertip、baseRadius、タイポグラフィ、アニメーションの設定 |
| references/typography.md | タイポグラフィユーティリティの選択、黄金比に基づくスペーシングトークンの使用、マージン補正 text-mt-*/text-mb-* の適用、fingertip-* によるタッチターゲットのサイズ設定 |
| references/cards.md | カードの構築:<VuCard>、card ショートカット、card-{level} ルール、--card-spacing、密度、角丸、ヘッダーのレベル |
| references/shortcuts.md | コンポーネントスタイルのカスタマイズや上書き、c8(クリック可能)システムと i8(入力)システムの理解、defineShortcuts/mergeVunorShortcuts/vunorShortcuts の使用 |
| references/rules.md | Vunor が提供する特定の UnoCSS ルールパターン(scope-*、current-*、card-*、fingertip-*、i8-*、icon-*、text-m*-*)の確認 |
| references/components.md | フォーム以外のコンポーネントの使用:VuCard、VuButton、VuDialog、VuTabs、VuMenu、VuPopover、VuAppLayout、VuAppToasts、VuIcon、VuLoadingIndicator、VuPagination、VuProgressBar |
| references/forms.md | フォームコンポーネントの使用:VuInput、VuSelect、VuCombobox、VuCheckbox、VuRadioGroup、VuSlider、VuDatePicker |
クイックリファレンス
// Preset & shortcuts
import { presetVunor, vunorShortcuts, defineShortcuts,
mergeVunorShortcuts, toUnoShortcut } from 'vunor/theme'
import type { TVunorPaletteOptions, TVunorPaletteColor,
TVunorMainPaletteAdvanced, TVunorLayerPaletteAdvanced,
TVunorSurfaceConfig, TVunorTheme,
TVunorShortcut } from 'vunor/theme'
// PI composables (provide/inject)
import { useInputPi, useInputProps, useInputBaseProps,
useCardPI } from 'vunor'
import { useProvideInject } from 'vunor/utils'
// Vue / Nuxt integration
import { VunorVueResolver } from 'vunor/vite' // unplugin-vue-components resolver
// nuxt.config: modules: ['vunor/nuxt']
// Components (auto-imported when resolver/module is set up)
// <VuButton>, <VuCard>, <VuCardHeader>, <VuCardInner>, <VuDialog>, <VuTabs>,
// <VuMenu>, <VuMenuItem>, <VuPopover>, <VuAppLayout>, <VuAppToasts>,
// <VuIcon>, <VuLoadingIndicator>, <VuInnerLoading>, <VuLabel>, <VuPagination>,
// <VuProgressBar>, <VuOverflowContainer>, <VuCalendar>,
// <VuInput>, <VuInputBase>, <VuSelect>, <VuCombobox>, <VuCheckbox>,
// <VuRadioGroup>, <VuSlider>, <VuDatePicker>, <VuDevTools>
セマンティッククラスのチートシート
<div class="scope-primary | scope-error | scope-good | scope-warn |
scope-secondary | scope-grey | scope-neutral">…</div>
<div class="layer-0">…</div>
<div class="surface-0">…</div>
<div class="surface-50 | surface-100 | … | surface-900">…</div>
<div class="current-bg-scope-color-500 current-text-white">
<span class="bg-current text-current">…</span>
</div>
<div class="bg-scope-color-500/50 text-scope-light-1">…</div>
<span class="text-current">primary</span>
<span class="text-current-muted">secondary / placeholder weight</span>
<span class="text-current-hl">accent (scope-color-500)</span>
<button class="border-current hover:border-current-hover hover:bg-current-hover">hover-step</button>
<button class="c8-filled | c8-flat | c8-outlined | c8-light | c8-chrome">…</button>
<div class="i8 i8-filled | i8-flat | i8-round">…</div>
<button class="scope-primary c8-filled btn">Save</button>
<button class="c8-flat btn btn-square"><span class="i--x btn-icon"/></button>
<input class="i8-bare h-fingertip-m px-$m" />
<div class="popup-card w-[14em]">
<button class="menu-item">Row</button>
</div>
<button class="disabled-soft" aria-disabled="true">…</button>
<VuCard level="h3" rounded dense>…</VuCard>
<p class="text-h1 text-mb-$m">Title</p>
<div class="p-$m gap-$s h-fingertip rounded-base">…</div>
基本ルール
- 色はハードコードしたパレット名ではなく、
scope-*で管理します。 ページのクロームはデフォルトでニュートラルです(:rootにはscope-neutralがプリフライトで設定されています)。scope-primary(またはscope-secondary)は、プライマリボタン、フォーカスされた入力欄、ブランドバナーなどのアクセント要素にのみ適用します。状態を表す場合は、ネガティブな状態や破壊的な操作にはscope-error、警告にはscope-warn、成功にはscope-goodに切り替えます。 - コンポーネント内では、固定色よりスコープ相対クラスを優先します。
bg-current、text-current、border-current、text-current-hl、bg-current/10、またはbg-scope-color-500を使い、bg-primary-500は使いません。こうすることで、親のスコープが変わると同じコンポーネントの色も自動的に変わります(<button class="c8-filled">はどのスコープでも機能しますが、<button class="bg-primary-500">は機能しません)。スコープに依存しない色が本当に必要な場合に限り、特定のパレット色(bg-primary-500、text-error-700)を使います。 <style>ブロックやスコープ付きスタイルは記述しないでください。 UnoCSS のユーティリティと Vunor のショートカットを組み合わせます。コンポーネントの外観をカスタマイズするには、vunorShortcuts(myOverrides)でそのショートカットをオーバーライドします。references/shortcuts.md を参照してください。- レイヤーとサーフェスは、ダークモードに自動対応します。ライトモードでは
--scope-light-*を、.dark/prefers-color-scheme: darkの場合は--scope-dark-*を読み取ります。レイヤー/サーフェスのユーティリティにdark:プレフィックスを追加しないでください。 - スペーシングトークンには
$プレフィックスを使います:p-$m、gap-$s、m-$l。通常のp-mは別のユーティリティ(UnoCSS 組み込み)です。 - タッチターゲットのデフォルト値は
--v-fingertip(3em)です。 ボタン/入力欄にはh-fingertipを使います。サブツリーごとにfingertip-xs|s|m|l|xlで上書きできます。 scope-{name}は変数を設定するだけです。 それ自体は何も描画しません。bg-current、layer-*、surface-*、c8-*、i8-*などと組み合わせてください。