コンテンツにスキップ

タグ入力

アルファ
タグ入力は、テキスト入力の後に、入力内にタグをレンダリングします。
リンゴ
バナナ
vue
<script setup lang="ts">
import { ref } from 'vue'
import { TagsInputInput, TagsInputItem, TagsInputItemDelete, TagsInputItemText, TagsInputRoot } from 'radix-vue'
import { Icon } from '@iconify/vue'

const modelValue = ref(['Apple', 'Banana'])
</script>

<template>
  <TagsInputRoot
    v-model="modelValue"
    class="flex gap-2 items-center border p-2 rounded-lg w-full max-w-[480px] flex-wrap border-blackA7 bg-white"
  >
    <TagsInputItem
      v-for="item in modelValue"
      :key="item"
      :value="item"
      class="text-white flex shadow-md items-center justify-center gap-2 bg-green8 aria-[current=true]:bg-green9 rounded p-1"
    >
      <TagsInputItemText class="text-sm pl-1" />
      <TagsInputItemDelete class="p-0.5 rounded bg-transparent hover:bg-blackA4">
        <Icon icon="lucide:x" />
      </TagsInputItemDelete>
    </TagsInputItem>

    <TagsInputInput
      placeholder="Fruits..."
      class="text-sm focus:outline-none flex-1 rounded text-green9 bg-transparent placeholder:text-mauve9 px-1"
    />
  </TagsInputRoot>
</template>

機能

  • 制御することも、制御しないこともできます。
  • 完全なキーボードナビゲーション。
  • タグの数を制限します。
  • クリップボードから値を受け入れます。
  • すべてのタグ値をリセットするためのクリアボタン。

インストール

コマンドラインからコンポーネントをインストールします。

sh
$ npm add radix-vue

構造

すべてのパーツをインポートして、それらをまとめます。

vue
<script setup>
import { TagsInputClear, TagsInputDelete, TagsInputInput, TagsInputItem, TagsInputRoot, TagsInputText } from 'radix-vue'
</script>

<template>
  <TagsInputRoot>
    <TagsInputItem>
      <TagsInputItemText />
      <TagsInputItemDelete />
    </TagsInputItem>

    <TagsInputInput />
    <TagsInputClear />
  </TagsInputRoot>
</template>

APIリファレンス

ルート

すべてのタグ入力コンポーネントのパーツが含まれています。

プロパティデフォルト
addOnBlur
boolean

trueの場合、入力のフォーカスが外れたときにタグを追加できるようにします

addOnPaste
boolean

trueの場合、ペースト時にタグの追加を許可します。delimiterプロパティと連携して動作します。

addOnTab
boolean

trueの場合、タブキーを押したときにタグの追加を許可します

as
'div'
AsTag | コンポーネント

このコンポーネントがレンダリングする要素またはコンポーネント。asChildで上書きできます。

asChild
boolean

子として渡された要素に対して、デフォルトのレンダリング要素を変更し、そのプロパティと動作をマージします。

詳細については、コンポジションガイドをご覧ください。

convertValue
((value: string) => AcceptableInputValue)

入力値を希望の型に変換します。オブジェクトを値として使用し、TagsInputInputを使用する場合は必須です。

defaultValue
[]
AcceptableInputValue[]

追加する必要のあるタグの値。タグ入力の状態を制御する必要がない場合に使用します

delimiter
','
string

新しいタグの追加をトリガーする文字。また、@pasteイベントでタグを分割するために使用されます

dir
'ltr' | 'rtl'

該当する場合のコンボボックスの読み取り方向。
省略した場合、ConfigProviderからグローバルに継承するか、LTR(左から右)読み取りモードを想定します。

disabled
boolean

trueの場合、ユーザーがタグ入力と対話するのを防ぎます。

displayValue
value.toString()
((value: AcceptableInputValue) => string)

タグの値を表示します。接尾辞を追加したり、オブジェクトを値として使用する場合など、値に修正を適用する場合に便利です

duplicate
boolean

trueの場合、重複したタグを許可します。

id
string
max
0
number

タグの最大数。

modelValue
AcceptableInputValue[]

タグ入力の制御された値。v-modelとしてバインドできます。

name
string

名前/値のペアの一部として、所有フォームとともに送信されるタグ入力の名前。

required
boolean

trueの場合、所有フォームを送信する前に、ユーザーがタグ入力を追加する必要があることを示します。

Emitペイロード
invalid
[payload: AcceptableInputValue]

値が無効な場合に呼び出されるイベントハンドラー

update:modelValue
[payload: AcceptableInputValue[]]

値が変更されたときに呼び出されるイベントハンドラー

スロット(デフォルト)ペイロード
modelValue
string | Record<string, any>

現在の入力値

データ属性
[data-disabled]無効の場合に存在します
[data-focused]入力にフォーカスがある場合に存在します
[data-invalid]入力値が無効な場合に存在します

アイテム

タグを保持するコンポーネント。

プロパティデフォルト
as
'div'
AsTag | コンポーネント

このコンポーネントがレンダリングする要素またはコンポーネント。asChildで上書きできます。

asChild
boolean

子として渡された要素に対して、デフォルトのレンダリング要素を変更し、そのプロパティと動作をマージします。

詳細については、コンポジションガイドをご覧ください。

disabled
boolean

trueの場合、ユーザーがタグ入力と対話するのを防ぎます。

value*
string | Record<string, any>

タグに関連付けられた値

データ属性
[data-state]"active" | "inactive"
[data-disabled]無効の場合に存在します

ItemText

タグのテキスト部分。アクセシビリティにとって重要です。

プロパティデフォルト
as
'span'
AsTag | コンポーネント

このコンポーネントがレンダリングする要素またはコンポーネント。asChildで上書きできます。

asChild
boolean

子として渡された要素に対して、デフォルトのレンダリング要素を変更し、そのプロパティと動作をマージします。

詳細については、コンポジションガイドをご覧ください。

ItemDelete

関連付けられたタグを削除するボタン。

プロパティデフォルト
as
'button'
AsTag | コンポーネント

このコンポーネントがレンダリングする要素またはコンポーネント。asChildで上書きできます。

asChild
boolean

子として渡された要素に対して、デフォルトのレンダリング要素を変更し、そのプロパティと動作をマージします。

詳細については、コンポジションガイドをご覧ください。

データ属性
[data-state]"active" | "inactive"
[data-disabled]無効の場合に存在します

入力

タグ入力用の入力要素。

プロパティデフォルト
as
'input'
AsTag | コンポーネント

このコンポーネントがレンダリングする要素またはコンポーネント。asChildで上書きできます。

asChild
boolean

子として渡された要素に対して、デフォルトのレンダリング要素を変更し、そのプロパティと動作をマージします。

詳細については、コンポジションガイドをご覧ください。

autoFocus
boolean

マウント時に要素にフォーカスします。

maxLength
number

許可される最大文字数。

placeholder
string

空のタグ入力に使用するプレースホルダー文字。

データ属性
[data-invalid]入力値が無効な場合に存在します

クリア

すべてのタグを削除するボタン。

プロパティデフォルト
as
'button'
AsTag | コンポーネント

このコンポーネントがレンダリングする要素またはコンポーネント。asChildで上書きできます。

asChild
boolean

子として渡された要素に対して、デフォルトのレンダリング要素を変更し、そのプロパティと動作をマージします。

詳細については、コンポジションガイドをご覧ください。

データ属性
[data-disabled]無効の場合に存在します

コンボボックス付き

コンボボックスと組み合わせてタグ入力を構成できます。

リンゴ
vue
<script setup lang="ts">
import { ref, watch } from 'vue'
import { ComboboxAnchor, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxLabel, ComboboxRoot, ComboboxTrigger, ComboboxViewport, TagsInputInput, TagsInputItem, TagsInputItemDelete, TagsInputItemText, TagsInputRoot } from 'radix-vue'
import { Icon } from '@iconify/vue'

const searchTerm = ref('')
const values = ref(['Apple'])
const options = ['Apple', 'Banana', 'Blueberry', 'Grapes', 'Pineapple']

watch(values, () => {
  searchTerm.value = ''
}, { deep: true })
</script>

<template>
  <ComboboxRoot
    v-model="values"
    v-model:search-term="searchTerm"
    multiple
    class="my-4 mx-auto relative"
  >
    <ComboboxAnchor class="w-[400px] inline-flex items-center justify-between rounded-lg p-2 text-[13px] leading-none  gap-[5px] bg-white text-grass11 shadow-[0_2px_10px] shadow-black/10 hover:bg-mauve3 focus:shadow-[0_0_0_2px] focus:shadow-black data-[placeholder]:text-grass9 outline-none">
      <TagsInputRoot
        v-slot="{ modelValue: tags }"
        :model-value="values"
        delimiter=""
        class="flex gap-2 items-center rounded-lg flex-wrap"
      >
        <TagsInputItem
          v-for="item in tags"
          :key="item"
          :value="item"
          class="flex items-center justify-center gap-2 text-white bg-grass8 aria-[current=true]:bg-grass9 rounded px-2 py-1"
        >
          <TagsInputItemText class="text-sm" />
          <TagsInputItemDelete>
            <Icon icon="lucide:x" />
          </TagsInputItemDelete>
        </TagsInputItem>

        <ComboboxInput as-child>
          <TagsInputInput
            placeholder="Fruits..."
            class="focus:outline-none flex-1 rounded !bg-transparent  placeholder:text-mauve10 px-1"
            @keydown.enter.prevent
          />
        </ComboboxInput>
      </TagsInputRoot>

      <ComboboxTrigger>
        <Icon
          icon="radix-icons:chevron-down"
          class="h-4 w-4 text-grass11"
        />
      </ComboboxTrigger>
    </ComboboxAnchor>
    <ComboboxContent class="absolute z-10 w-full mt-2 bg-white overflow-hidden rounded shadow-[0px_10px_38px_-10px_rgba(22,_23,_24,_0.35),_0px_10px_20px_-15px_rgba(22,_23,_24,_0.2)] will-change-[opacity,transform] data-[side=top]:animate-slideDownAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade data-[side=left]:animate-slideRightAndFade">
      <ComboboxViewport class="p-[5px]">
        <ComboboxEmpty class="text-gray-400  text-xs font-medium text-center py-2" />

        <ComboboxGroup>
          <ComboboxLabel class="px-[25px] text-xs leading-[25px] text-mauve11">
            Fruits
          </ComboboxLabel>

          <ComboboxItem
            v-for="(option, index) in options"
            :key="index"
            class="text-[13px] leading-none text-grass11 rounded-[3px] flex items-center h-[25px] pr-[35px] pl-[25px] relative select-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:outline-none data-[highlighted]:bg-grass8 data-[highlighted]:text-grass1"
            :value="option"
          >
            <ComboboxItemIndicator
              class="absolute left-0 w-[25px] inline-flex items-center justify-center"
            >
              <Icon icon="radix-icons:check" />
            </ComboboxItemIndicator>
            <span>
              {{ option }}
            </span>
          </ComboboxItem>
        </ComboboxGroup>
      </ComboboxViewport>
    </ComboboxContent>
  </ComboboxRoot>
</template>

貼り付けの動作

add-on-pasteプロパティを渡すことで、貼り付け時にタグを自動的に追加できます。

vue
<script setup lang="ts">
import { TagsInputInput, TagsInputItem, TagsInputItemDelete, TagsInputItemText, TagsInputRoot } from 'radix-vue'
</script>

<template>
  <TagsInputRoot
    v-model="modelValue"
    add-on-paste
  >

  </TagsInputRoot>
</template>

アクセシビリティ

キーボード操作

キー説明
Delete
タグがアクティブな場合、それを削除し、右側のタグをアクティブに設定します。
Backspace
タグがアクティブな場合、それを削除し、左側のタグをアクティブに設定します。左側にタグがない場合は、次のタグにフォーカスするか、入力にフォーカスします。
ArrowRight
次のタグをアクティブに設定します。
ArrowLeft
前のタグをアクティブに設定します。
Home
最初のタグをアクティブに設定します
End
最後のタグをアクティブに設定します