minazuki-ui
vue/nuxt用のUIコンポーネントライブラリ
※nuxt ^3 ※vue ^3.5
v1 からのアップグレードでテーマ設定オプションが変更されています。詳細は docs/MIGRATION.md を参照してください。
リソース
reset cssとして@acab/reset.cssを導入しています。 そのため、本ライブラリ読み込みにおいて、上記のreset cssが読み込まれます。
また、各種色やサイズはCSS変数にて管理されています。 詳細はこちらを参照してください。
バリデーションに関してはzodのスキーマを用いてvee-validate(v4)にて行っています。
スタイルの基本方針
幅や余白はレスポンシブに準じつつ、8pxの倍数ルールを用いています。
use
pnpm i -D minazuki-ui zod
Nuxt(推奨: Nuxt Module)
nuxt.config.ts に追加するだけで、コンポーネント・コンポーザブルの auto-import、CSS 自動注入、SSR フラッシュ防止が自動で設定されます。
export default defineNuxtConfig({
modules: ['minazuki-ui/nuxt'],
minazukiUi: {
// デフォルトテーマ ID(省略可。default: 'light')
themeId: 'light',
// テーマ上書き(省略可)
theme: {
// Brand を Blue に変更する例
statuses: { brand: { hue: 'blue', chroma: 'blue' } }
}
}
});
Nuxt Module オプション
| オプション | 型 | デフォルト | 説明 |
|---|---|---|---|
autoImport |
boolean |
true |
コンポーネント・コンポーザブルの auto-import |
css |
boolean |
true |
minazuki-ui/dist/style.css の自動注入 |
themeId |
string |
'light' |
デフォルトテーマ ID('light' or 'dark') |
theme |
Record<string, unknown> |
{} |
テーマ上書き定義(MiThemeOverride 形式) |
cookieName |
string |
'themeId' |
テーマ保持用クッキー名 |
cookieMaxAge |
number |
31536000 |
クッキーの有効期限(秒) |
install |
boolean |
false |
app.use() で全コンポーネントをグローバル登録(Tree Shaking 無効) |
Nuxt(手動 Plugin)
Nuxt Module を使わない場合は手動で Plugin を設定します。
plugins/minazuki-ui.ts
import MinazukiUi from 'minazuki-ui';
import 'minazuki-ui/dist/style.css';
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(MinazukiUi);
});
基本入力モデル
useFormを使用(推奨)
バリデーションなどをzodスキーマにて設定が可能。 各種フォーム入力欄を設定する場合に用いる。
// script
import { useFormData } from 'minazuki-ui';
import { string, object } from 'zod';
const TEST_SCHEMA = object({
test: string().max(50).min(1)
}).required();
const { canSubmit, resetForm, setValues, setFieldValue } = useFormData(TEST_SCHEMA, { test: '初期値' });
setValues({
test: '親から複数の項目に対して、値をセット'
})
setFieldValue('test', '親から任意の項目に対して、値をセット')
// template
<MiField name="test" :schema="TEST_SCHEMA.shape.test" />
<MiButton :disabled="!canSubmit">投稿</MiButton>
v-modelを使用
zod schemaによる細かいバリデーション制御を行わず、親コンポーネント側で独自に行うケースか、 バリデーションを使用せずに手軽に使いたい場合に用いることができる。
// script
const model = ref<string>('初期値');
// template
<MiField v-model="model" />
バリデーションの日本語化
必要に応じて各プロジェクトで実施してください
pnpm i -D zod-i18n-map i18next vee-validate
plugins/zod-validate.ts
import { init } from 'i18next';
import { z } from 'zod';
import { zodI18nMap } from 'zod-i18n-map';
import translation from 'zod-i18n-map/locales/ja/zod.json';
const customErrorMap: z.ZodErrorMap = (issue, ctx) => {
switch (issue.code) {
case z.ZodIssueCode.invalid_literal:
if (issue.expected && !issue.received) {
return { message: 'チェックしてください。' };
}
break;
case z.ZodIssueCode.too_small:
if (issue.minimum === 1) {
return { message: 'この項目は必須項目です。' };
}
break;
case z.ZodIssueCode.invalid_type:
if ([null, undefined, ''].includes(ctx.data)) {
return { message: 'この項目は必須項目です。' };
}
break;
}
return zodI18nMap(issue, ctx);
};
export default defineNuxtPlugin(() => {
// zod
init({
lng: 'ja',
resources: {
ja: { zod: translation }
}
});
z.setErrorMap(customErrorMap);
});
テーマ設定
Nuxt Module を使う場合は nuxt.config.ts の minazukiUi.theme に設定します(上記参照)。
手動 Plugin の場合は app.use() の第2引数に MiThemeOverride を渡します。
plugins/minazuki-ui.ts
import MinazukiUi from 'minazuki-ui';
import 'minazuki-ui/dist/style.css';
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(MinazukiUi, {
themeId: 'light',
theme: {
// Primitive: 色相角度やベース彩度を変更すると全段階に影響
primitives: {
hues: { teal: 200 },
chromas: { teal: 0.12 }
},
// Status: 役割の紐付け先を変更
statuses: {
brand: { hue: 'blue', chroma: 'blue' }
},
// UI: 個別トークンを上書き(文字列で light/dark 共通、ペアで個別指定)
ui: {
link: { light: '#cc3300', dark: '#ff6644' }
}
}
});
});
SSRでのダークモード初期フラッシュ対策
Nuxt Module を使う場合はクッキー管理が自動で行われます(追加設定不要)。
手動 Plugin を使う場合は、SSR 側が localStorage を参照できないため、クッキーを使って明示的に対処してください。
plugins/minazuki-ui.ts
import MinazukiUi, { useTheme } from 'minazuki-ui';
import type { ThemeId } from 'minazuki-ui';
import { watch } from 'vue';
import 'minazuki-ui/dist/style.css';
export default defineNuxtPlugin((nuxtApp) => {
const themeCookie = useCookie<ThemeId>('themeId', { default: () => 'light' });
const { currentTheme } = useTheme();
// app.use の前に設定することで install 内の setTheme がクッキー値を使って SSR を描画する
currentTheme.value = themeCookie.value === 'dark' ? 'dark' : 'light';
nuxtApp.vueApp.use(MinazukiUi);
// テーマ変更をクッキーに同期(次回リクエスト時の SSR も正しいテーマで描画される)
watch(currentTheme, (newTheme) => {
themeCookie.value = newTheme;
});
});
コマンド
| コマンド | 機能 |
|---|---|
| pnpm dev | ホームページ起動 |
| pnpm sb | storybookの起動 |