クロスプラットフォームおよびモバイルUI · 新しいリソース

Vant デザインシステム.

Vant 4で構築したモバイル向け住所選択フロー。実際のCSS変数、住所IDの管理、入力検証、テーマ切り替え、ローカルのみへの明示的な保存に対応。

OpenDesign ガイド9 章リファレンス項目34件オリジナルアプリケーションガイド
01

Vant デザインシステムのインターフェースプレビュー

受取人の選択、住所の編集、新しい入力内容の検証、ネイティブコンポーネントのテーマ切り替えを行います。

サンプルキットのお届け先完全な例を開く
Vue 3対応のNative Vant 4.10.2。用紙のイラストと周囲のレイアウトは独自制作です。· 実装リファレンス
02

Vant デザインシステムのデザインリファレンス

インストール済みのベーススタイルシートから読み込んだVant 4.10.2 CSS変数。プレビューではConfigProviderを使って独自のティール色をプライマリーカラーに設定しています。以下の既定のロールは、変更されていないことが明示されています。

既定のカラーのロール

ソース
名前 / ルール値 / 設定用途
--van-primary-colorvar(--van-blue)既定のアクションエイリアス。青は#1989faです。
--van-success-colorvar(--van-green)成功のエイリアス。緑は#07c160です。
--van-danger-colorvar(--van-red)危険のエイリアス。赤は#ee0a24です。
--van-warning-colorvar(--van-orange)警告のエイリアス。オレンジは#ff976aです。
--van-text-colorvar(--van-gray-8)メインテキストのエイリアス。gray-8は#323233です。
--van-text-color-2var(--van-gray-6)セカンダリテキストのエイリアス。gray-6は#969799です。
--van-border-colorvar(--van-gray-3)区切り線のエイリアス。gray-3は#ebedf0です。
--van-backgroundvar(--van-gray-1)ページの背景。gray-1は#f7f8faです。
--van-background-2var(--van-white)コンポーネントの背景。白は#fffです。

パディングスケール

ソース
名前 / ルール値 / 設定用途
--van-padding-base4px内部の微細なオフセット。
--van-padding-xs8px小さな内部間隔。
--van-padding-sm12px住所項目のパディング。
--van-padding-md16px標準的なページ内側の余白。
--van-padding-lg24pxセクション内側の余白。
--van-padding-xl32px大きなページ内側の余白。

タイポグラフィと形状

ソース
名前 / ルール値 / 設定用途
--van-font-size-xs10pxUIの既定の文字サイズ。
--van-font-size-sm12pxUIの既定の文字サイズ。
--van-font-size-md14pxUIの既定の文字サイズ。
--van-font-size-lg16pxUIの既定の文字サイズ。
--van-line-height-xs14px対応する行の高さのトークン。
--van-line-height-sm18px対応する行の高さのトークン。
--van-line-height-md20px対応する行の高さのトークン。
--van-line-height-lg22px対応する行の高さのトークン。
--van-radius-sm2px名前付きの角丸半径。
--van-radius-md4px名前付きの角丸半径。
--van-radius-lg8px名前付きの角丸半径。
--van-radius-max999px名前付きの角丸半径。
--van-disabled-opacity.5既定の無効状態の不透明度。
--van-duration-base.3s標準のトランジション時間。

住所リストとプレビューの調整

ソース
名前 / ルール値 / 設定用途
--van-address-list-padding12px 12px 80px公式の既定値では、下部の追加ボタン用にスペースを確保します。
themeVars.addressListPadding12pxこのプレビューでは固定の追加ボタンを非表示にするため、独自に調整しています。
themeVars.primaryColor#176b77 --van-primary-colorに割り当てた独自のプライマリーカラー設定。
--van-address-list-item-font-size13px公式の住所テキストサイズ。
--van-address-list-edit-icon-size20px公式の編集アイコンサイズ。タップ領域全体のサイズではありません。
03

Vant デザインシステム完全ガイド

実際のインターフェースで、このデザインシステムを選び、適用し、レビューするための実践ガイドです。

DESIGN-vant.md

詳しいガイダンス、実装の出発点、ソースへのリンクをまとめています。

ガイドをダウンロード

Vantデザインシステム:CSSのロールを明示したモバイルコンポーネント

CSSのロールを明示したモバイルコンポーネント

VantはVueのモバイルWebインターフェースを対象としています。AddressList、Field、CellGroupは、デスクトップの管理テーブルではなく、コンパクトな宛先住所の行とフォームのセルを提供します。サンプルキットのフローではこれらのネイティブコンポーネントを使用し、選択した配送先を独立した概要に表示します。

この OpenDesign ガイドから

プライマリーロールの既定値は青で、--van-primary-colorを通じて設定されます。成功、危険、警告の各ロールは、それぞれ別のカラー変数を参照します。この見本ではConfigProviderを使ってプライマリーカラーを#176b77に変更していますが、このティール色を公式のVantブランドカラーとはしていません。独自制作の用紙のイラストは装飾であり、コントロールの状態を示すものではありません。

関連する仕様を確認する

Vant デザインシステム:4ピクセル刻みのパディングスケールとコンパクトな文字サイズ

4ピクセル刻みのパディングスケールとコンパクトな文字サイズ

Vantは4、8、12、16、24、32ピクセルのパディング値を公開しています。これらはスクリーンショットから推測した値ではなく、実際のベース変数です。住所リストの項目には小さいパディングのトークンを使用し、フォームと注文概要を区別しやすくするため、プレビューの周囲にはさらに広いセクション間隔を設けています。

指定された文字サイズは10〜16ピクセルで、それぞれに対応する行の高さは14〜22ピクセルです。アドレスのテキストには、専用の13pxコンポーネント変数があります。モバイル製品では、コントロールの既定値より大きな本文テキストが必要になる場合があります。見本の見出しには独自の32pxサイズを使用し、ページのブレークポイントで27pxに縮小しています。

関連する仕様を確認する

Vant デザインシステム:Address IDでラジオ選択を制御

Address IDでラジオ選択を制御

AddressListには、id、name、tel、address、および任意のisDefaultを含むレコードのリストを渡します。v-modelの値で選択中のレコードを識別します。概要は現在のリストからそのIDに一致するレコードを検索して算出されるため、受取人を編集すると、別個の概要状態を持たずに表示中の配送先がすぐに更新されます。

利用できない倉庫はdisabled-listで渡し、無効状態を説明するテキストを明示します。状況を伝えるために表示は維持されますが、配送先として選択することはできません。Defaultバッジはレコードの既定状態を示すもので、現在の選択とは別です。別のラジオ項目を選んでも変わりません。

関連する仕様を確認する

Vant デザインシステム:下書きと保存済みレコードを分けて管理

下書きと保存済みレコードを分けて管理

編集イベントから住所レコードを受け取ります。編集可能なフィールドだけをリアクティブな下書きにコピーし、安定したIDは別に保持します。キャンセルすると、保存済みの住所を変更せずに下書きを非表示にします。保存時には、一致するレコードを置き換えるか、新しいレコードをローカルに追加した後、そのIDを選択します。

この見本では、下部ポップアップを開く代わりに、リストの下に編集画面をインライン表示します。これにより、埋め込みドキュメントでもサンプル全体を使いやすくなります。Vantは標準化された住所入力向けのAddressEditも提供しています。この例では、特定の国の行政区域データを前提としないサンプル住所を使用するため、FormとFieldを使っています。

  1. スタジオを選択し、編集を開く前に概要を確認してください。
  2. 受取人を変更してからキャンセルし、保存済みの行が変わっていないことを確認してください。
  3. エディターをもう一度開き、有効な値を保存して、選択中の概要を確認してください。

関連する仕様を確認する

Vant デザインシステム:Fieldのルールで送信イベントを制御

Fieldのルールで送信イベントを制御

Formではvalidate-trigger="onSubmit"を使用します。受取人のバリデーターは空白を取り除き、2文字以上の入力を必須とします。電話番号のバリデーターは、先頭のプラス記号を任意とし、数字、空白、丸括弧、ハイフンを一定の範囲で受け付けます。住所のバリデーターは、空白以外の文字を10文字以上必須とします。これらのチェックは仕組みを示すものであり、郵便上の確認や、あらゆる電話番号に対応する検証ではありません。

native-type="submit"を指定したプライマリButtonは、ネイティブフォームを送信します。Vantは、ルールを通過した場合にのみsubmitを発行します。エラーは該当するFieldの横に表示され、エラーへのスクロールによって無効なフィールドが画面内に表示されます。プレビューでは、編集開始時に最初の宛先入力欄にもフォーカスします。検証に失敗しても入力内容は保持されます。

関連する仕様を確認する

VantデザインシステムのConfigProviderはキャメルケースの値をCSS変数に対応付ける

ConfigProviderでキャメルケースの値をCSS変数に割り当てる

theme-varsオブジェクトには、primaryColor、buttonPrimaryBackground、buttonPrimaryBorderColor、addressListPaddingが含まれます。ConfigProviderはこれらの名前を対応する--van-*変数に割り当てます。この独立したドキュメントでは、ルートで宣言したエイリアスが変更後のプライマリロールを参照できるよう、プロバイダーにtheme-vars-scope="global"を指定しています。ロールとプライマリボタンの2つの値を上書きすることで、ネイティブアクションとラジオ選択の色を連動させています。

themeプロパティをlightとdarkで切り替えると、Vantのコンポーネントテーマが更新されます。ページ自体の背景色とテキスト色には、テーマ変数を使った宣言が別途必要です。プロバイダーを設定するだけでは、アプリケーション内のすべての要素に色は適用されません。装飾用の紙のサンプルは、どちらのテーマでも素材の色をそのまま保ちます。

関連する仕様を確認する

Vantデザインシステム:モバイル固定アクションには埋め込み時の判断が必要

モバイル固定アクションには埋め込み時の判断が必要

AddressListは通常、固定の追加ボタン用に下部の余白を80ピクセル確保します。プレビューではshow-add-buttonをfalseにし、通常のインフローButtonを配置しています。また、addressListPaddingを12ピクセルに変更し、埋め込み例の中に固定アクションが浮いたり、理由のない空白が下部に残ったりしないようにしています。

画面が広い場合、リストと素材の概要を2列で表示します。元のブレークポイントである680pxを下回ると、縦並びになります。ネイティブのAddressListに設定されたheight:100%は明示的にheight:autoへリセットし、パネルが次のグリッド行に重ならず、内容に合わせて伸縮するようにしています。グローバルな最小ビューポート高は設定していないため、親ページは埋め込みドキュメントの高さをコンテンツに合わせて調整できます。狭い画面では住所名が折り返され、ページ幅が広がることはありません。

関連する仕様を確認する

Vantデザインシステム:見えるフォーカスと明示的なローカル結果

見えるフォーカスと明示的なローカル結果

Vantのベースリセットでは、デフォルトのフォーカスアウトラインが削除されます。併用するページスタイルシートで、ボタン、入力欄、テキストエリア、tab-index付きコントロールに、focus-visible時の3ピクセルのリングを戻しています。これはアプリケーション側で追加するものであり、ライブラリをインポートするだけでアクセシビリティ対応が完了するという意味ではありません。テーマ切り替えには、アクセシブルな名前と見えるラベルを付けています。

ステータス通知では、ローカルで保存したこと、または宛先を選択したことを伝えます。配送予約は行われていないことも明示します。この例には、購入手続き用のエンドポイント、ストレージ、外部への副作用はありません。実際の購入手続きでは、購入前にサーバー側で住所を検証し、配送可能かどうかを確認したうえで、最終確認を行う必要があります。

  • 利用できない住所は黙って削除せず、理由が見えるようにしてください。
  • 送信が無効だった場合も、ユーザーが該当項目を修正できるよう入力内容を保持してください。
  • 操作によって選択がローカルで変更されるだけなのか、実際に配送が予約されるのかを説明してください。

関連する仕様を確認する

Vantデザインシステム:ロケールとコンポーネントスタイルのインポート

ロケールとコンポーネントのスタイルをインポート

完全なSFCでは、コンポーネントをローカルでインポートします。エントリーファイルではLocale.useで英語ロケールを登録し、元のレイアウトスタイルシートより前にvant/lib/index.cssをインポートします。検証済みのパッケージはVue 3対応のVant 4.10.2です。英語ロケールのインポートに付けた.mjs拡張子は、インストール済みのESMファイルに合わせています。

単独で動作するプレビューでは、JavaScript、CSS、アイコンフォントをドキュメントにバンドルしています。バンドル済みのWOFF2フォントは残し、未使用のリモートWOFFフォールバックは削除しているため、サードパーティへのフォントリクエストに依存しません。本番アプリケーションでは、ホストされたデモのURLをそのまま使うのではなく、独自のバンドラーとアセットポリシーを使用してください。

関連する仕様を確認する

Vantデザインシステムのコンポーネント例

住所の選択と検証付き編集

AddressList、Form、Field、ConfigProvider、制御された入力ドラフトを使った完全なVue SFC。

vue
<script setup>
import {ref,reactive,computed,nextTick} from 'vue';
import {ConfigProvider,AddressList,Button,Form,Field,CellGroup,Tag,Switch,NoticeBar} from 'vant';
const list=ref([{id:'studio',name:'Alex Morgan',tel:'+44 20 7946 0101',address:'Studio 4, 18 Paper Street, London',isDefault:true},{id:'workshop',name:'Jules Chen',tel:'+44 20 7946 0122',address:'Workshop B, 52 Clay Road, London'}]);
const disabledList=[{id:'archive',name:'Sam Rivera',tel:'+44 20 7946 0133',address:'Old warehouse, 8 Mill Lane, London'}];
const chosen=ref('studio'),editing=ref(false),editingId=ref(null),notice=ref(''),dark=ref(false),formRef=ref();
const draft=reactive({name:'',tel:'',address:''});
const selected=computed(()=>list.value.find(x=>x.id===chosen.value));
const themeVars={primaryColor:'#176b77',addressListPadding:'12px',buttonPrimaryBackground:'#176b77',buttonPrimaryBorderColor:'#176b77'};
async function edit(item){editingId.value=item?.id||null;Object.assign(draft,item?{name:item.name,tel:item.tel,address:item.address}:{name:'',tel:'',address:''});editing.value=true;notice.value='';await nextTick();formRef.value?.resetValidation();document.querySelector('[name="recipient"]')?.focus();}
function save(){const value={id:editingId.value||`local-${Date.now()}`,name:draft.name.trim(),tel:draft.tel.trim(),address:draft.address.trim()};if(editingId.value)list.value=list.value.map(x=>x.id===editingId.value?{...x,...value}:x);else list.value.push(value);chosen.value=value.id;editing.value=false;notice.value='Address saved in this local preview.';}
function confirm(){notice.value=`Selected ${selected.value.name} at ${selected.value.address}. No delivery was booked.`;}
const nonempty=v=>v.trim().length>=2;
const phone=v=>/^\+?[\d ()-]{7,22}$/.test(v.trim());
</script>
<template><ConfigProvider theme-vars-scope="global" :theme="dark?'dark':'light'" :theme-vars="themeVars"><main class="delivery" :class="{dark}"><header><div><p class="eyebrow">VANT · MOBILE COMMERCE</p><h1>A destination for your sample kit.</h1><p class="intro">Choose a studio, update a recipient or add a local address.</p></div><label class="mode"><span>Dark</span><Switch v-model="dark" size="22px" aria-label="Dark theme" /></label></header><div class="columns"><section class="address-panel" aria-label="Delivery addresses"><div class="section-heading"><h2>Delivery address</h2><Tag plain type="primary">{{list.length}} available</Tag></div><AddressList v-model="chosen" :list="list" :disabled-list="disabledList" disabled-text="Outside the sample delivery area" default-tag-text="Default" :show-add-button="false" @edit="edit" @select="notice=''" /><div class="actions"><Button plain block type="primary" @click="edit()">Add a local address</Button></div></section><aside><section class="kit"><div class="paper-samples" aria-hidden="true"><i></i><i></i><i></i></div><p class="eyebrow">MATERIAL LIBRARY</p><h2>Paper & pigment kit</h2><p>Six paper stocks. Three print finishes. One place to compare them.</p><dl><div><dt>Recipient</dt><dd>{{selected?.name}}</dd></div><div><dt>Destination</dt><dd>{{selected?.address}}</dd></div></dl><Button block type="primary" @click="confirm">Use this address</Button><p class="local-note">Selection only. Nothing is purchased or shipped.</p></section></aside></div><section v-if="editing" class="editor"><h2>{{editingId?'Edit recipient':'Add an address'}}</h2><Form ref="formRef" validate-trigger="onSubmit" label-align="top" scroll-to-error @submit="save"><CellGroup inset><Field v-model="draft.name" name="recipient" label="Recipient" placeholder="Full name" :rules="[{validator:nonempty,message:'Enter at least two characters.'}]" /><Field v-model="draft.tel" name="telephone" type="tel" label="Telephone" placeholder="+44 20 7946 0100" :rules="[{validator:phone,message:'Use 7–22 characters: digits, spaces, +, brackets or hyphens.'}]" /><Field v-model="draft.address" name="address" type="textarea" rows="2" autosize label="Address" placeholder="Building, street and city" :rules="[{validator:v=>v.trim().length>=10,message:'Enter a complete address of at least ten characters.'}]" /></CellGroup><div class="form-actions"><Button type="primary" native-type="submit">Save locally</Button><Button native-type="button" @click="editing=false">Cancel</Button></div></Form></section><NoticeBar v-if="notice" wrapable :scrollable="false" color="var(--van-primary-color)" background="var(--van-background-2)" class="result" role="status">{{notice}}</NoticeBar></main></ConfigProvider></template>

コードリファレンス

  • 選択値には、配列内の位置ではなく住所IDを使います。
  • 固定のAddressList追加ボタンは非表示にし、インフローButtonから編集画面を開きます。
  • Formの送信処理は、Fieldのバリデーターを通過した後にのみ実行されます。

レスポンシブなページと見えるフォーカス

元のデスクトップ向け2分割レイアウトは、モバイルでは配送の流れに合わせたレイアウトに切り替わります。

CSS
*{box-sizing:border-box}body{margin:0;background:#f7f8fa;color:#323233}.delivery{padding:32px;max-width:1080px;margin:auto;background:var(--van-background);color:var(--van-text-color)}.delivery.dark{background:var(--van-background);color:var(--van-text-color)}header{display:flex;align-items:flex-start;justify-content:space-between;gap:24px;margin-bottom:32px}.eyebrow{font-size:11px;font-weight:600;letter-spacing:.12em;color:var(--van-text-color-2)}h1{font-size:32px;line-height:1.2;margin:12px 0;max-width:550px}h2{font-size:18px;line-height:24px;margin:0 0 12px}.intro{font-size:15px;line-height:24px;color:var(--van-text-color-2)}.mode{display:flex;gap:8px;align-items:center;font-size:12px}.columns{display:grid;grid-template-columns:1.25fr 1fr;gap:24px}.section-heading{display:flex;justify-content:space-between;align-items:center;padding:0 12px}.section-heading h2{margin:0}.actions{padding:0 12px}.kit{background:var(--van-background-2);padding:24px;border-radius:8px}.kit p{line-height:1.6}.paper-samples{height:130px;position:relative;display:flex;align-items:center;justify-content:center;margin-bottom:24px;background:#e9edef;border-radius:4px;overflow:hidden}.paper-samples i{height:90px;width:90px;background:#d6b59b;box-shadow:0 4px 8px #0001;transform:rotate(-12deg);margin-right:-25px}.paper-samples i:nth-child(2){background:#efdfbe;transform:rotate(2deg)}.paper-samples i:nth-child(3){background:#94adb1;transform:rotate(16deg)}dl{font-size:14px;line-height:20px;margin:24px 0}dl div{display:grid;grid-template-columns:90px 1fr;margin:12px 0;gap:12px}dt{color:var(--van-text-color-2)}dd{margin:0}.local-note{font-size:12px;color:var(--van-text-color-2);margin-bottom:0}.editor{max-width:640px;margin-top:32px}.editor h2{margin-left:16px}.form-actions{display:flex;gap:12px;margin:16px}.result{margin-top:24px;border-radius:8px}button:focus-visible,input:focus-visible,textarea:focus-visible,[tabindex]:focus-visible{outline:3px solid #176b77!important;outline-offset:3px}@media(max-width:680px){.delivery{padding:24px 12px}.columns{grid-template-columns:1fr}header{gap:8px;margin-bottom:24px}h1{font-size:27px}.mode{padding-top:4px}.kit{padding:20px}.paper-samples{height:110px}.van-address-item__name{white-space:normal}}

.delivery .van-address-list{height:auto}

コードリファレンス

  • コンポーネントの寸法はVantに基づきます。680pxのページブレークポイントはアプリケーション側で設定したものです。
  • ベースリセットでデフォルトのアウトラインが削除されるため、プレビューではフォーカスリングが見えるように戻しています。
04

Vantデザインシステムのエージェント設定

実装の出発点

Vue 3とVant 4.10.2で検証済みです。この例では、メモリ内の状態以外に住所を保存しません。

JavaScript
// Create the project first:
// npm create vite@latest vant-specimen -- --template vue
// cd vant-specimen && npm install
// In a Vite Vue 3 project:
// npm install [email protected]
// Save the complete SFC as App.vue and the supplied layout as style.css.
import {createApp} from 'vue';
import {Locale} from 'vant';
import enUS from 'vant/es/locale/lang/en-US.mjs';
import 'vant/lib/index.css';
import './style.css';
import App from './App.vue';
Locale.use('en-US',enUS);
createApp(App).mount('#app');
// index.html must contain <div id="app"></div>.
// Keep the template index.html and replace its entry with the code above.
// npm run dev

あなたのプロジェクト向けプロンプト

AI エージェント用プロンプト
Vant 4.10.2のsample-kitにある住所セレクターをベースにしてください。住所の追加や変更では、ネイティブのAddressListとForm/Fieldによる編集フローを維持し、フィールドの検証と選択中の住所の状態も保持してください。Localeの設定、en-USモジュール、ConfigProviderのテーマスコープ、コンテンツの高さに合わせたAddressListの調整も維持してください。キャンセル時に既存の住所を置き換えてはいけません。検証に成功した場合にのみ、ローカルの住所コレクションを更新します。この住所のみを扱う例に、支払いや配送時間帯の確定を示す表現を追加しないでください。
05

Vantデザインシステム:参照元と対象範囲

Vant 4.10.2。デフォルトのデザイントークンと元のページ独自の設定を区別しています。サンプルの住所は架空のもので、選択と編集はローカルで行われます。