コンテンツへスキップ

Toast

一時的に表示される簡潔なメッセージ。
vue
<script setup lang="ts">
import { ref } from 'vue'
import { ToastAction, ToastDescription, ToastProvider, ToastRoot, ToastTitle, ToastViewport } from 'radix-vue'

const open = ref(false)
const eventDateRef = ref(new Date())
const timerRef = ref(0)

function oneWeekAway() {
  const now = new Date()
  const inOneWeek = now.setDate(now.getDate() + 7)
  return new Date(inOneWeek)
}

function prettyDate(date: Date) {
  return new Intl.DateTimeFormat('en-US', { dateStyle: 'full', timeStyle: 'short' }).format(date)
}

function handleClick() {
  open.value = false
  window.clearTimeout(timerRef.value)
  timerRef.value = window.setTimeout(() => {
    eventDateRef.value = oneWeekAway()
    open.value = true
  }, 100)
}
</script>

<template>
  <ToastProvider>
    <button
      class="inline-flex items-center justify-center rounded font-medium text-[15px] px-[15px] leading-[35px] h-[35px] bg-white text-grass11 shadow-[0_2px_10px] shadow-blackA7 outline-none hover:bg-mauve3 focus:shadow-[0_0_0_2px] focus:shadow-black"
      @click="handleClick"
    >
      Add to calendar
    </button>

    <ToastRoot
      v-model:open="open"
      class="bg-white rounded-md shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] p-[15px] grid [grid-template-areas:_'title_action'_'description_action'] grid-cols-[auto_max-content] gap-x-[15px] items-center data-[state=open]:animate-slideIn data-[state=closed]:animate-hide data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=cancel]:translate-x-0 data-[swipe=cancel]:transition-[transform_200ms_ease-out] data-[swipe=end]:animate-swipeOut"
    >
      <ToastTitle class="[grid-area:_title] mb-[5px] font-medium text-slate12 text-[15px]">
        Scheduled: Catch up
      </ToastTitle>
      <ToastDescription as-child>
        <time
          class="[grid-area:_description] m-0 text-slate11 text-[13px] leading-[1.3]"
          :dateTime="eventDateRef.toISOString()"
        >
          {{ prettyDate(eventDateRef) }}
        </time>
      </ToastDescription>
      <ToastAction
        class="[grid-area:_action]"
        as-child
        alt-text="Goto schedule to undo"
      >
        <button class="inline-flex items-center justify-center rounded font-medium text-xs px-[10px] leading-[25px] h-[25px] bg-green2 text-green11 shadow-[inset_0_0_0_1px] shadow-green7 hover:shadow-[inset_0_0_0_1px] hover:shadow-green8 focus:shadow-[0_0_0_2px] focus:shadow-green8">
          Undo
        </button>
      </ToastAction>
    </ToastRoot>
    <ToastViewport class="[--viewport-padding:_25px] fixed bottom-0 right-0 flex flex-col p-[var(--viewport-padding)] gap-[10px] w-[390px] max-w-[100vw] m-0 list-none z-[2147483647] outline-none" />
  </ToastProvider>
</template>
  • 自動的に閉じます。
  • ホバー、フォーカス、ウィンドウのフォーカス喪失時に閉じることが一時停止します。
  • Toastビューポートにジャンプするためのホットキーをサポートします。
  • スワイプジェスチャーによる閉じ方をサポートします。
  • スワイプジェスチャーアニメーション用のCSS変数を公開します。
  • 制御可能または非制御可能です。

インストール

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

sh
$ npm add radix-vue

構成

コンポーネントをインポートします。

vue
<script setup lang="ts">
import { ToastAction, ToastClose, ToastDescription, ToastProvider, ToastRoot, ToastTitle, ToastViewport } from 'radix-vue'
</script>

<template>
  <ToastProvider>
    <ToastRoot>
      <ToastTitle />
      <ToastDescription />
      <ToastAction />
      <ToastClose />
    </ToastRoot>

    <ToastViewport />
  </ToastProvider>
</template>

APIリファレンス

プロバイダー

ToastとToastビューポートをラップするプロバイダー。通常はアプリケーションをラップします。

プロパティデフォルト
duration
5000
number

各Toastが表示されるミリ秒数。

label
'Notification'
string

各Toastの作者によるローカライズされたラベル。スクリーンリーダーユーザーが中断をToastに関連付けるのに役立ちます。

swipeDirection
'right'
'right' | 'left' | 'up' | 'down'

Toastを閉じるべきポインターのスワイプ方向。

swipeThreshold
50
number

閉じ動作がトリガーされる前にスワイプが通過する必要があるピクセル数。

ビューポート

Toastが表示される固定領域。ユーザーはホットキーを押してビューポートにジャンプできます。キーボードユーザー向けにホットキーの検出可能性を確保するのは、ユーザーの責任です。

プロパティデフォルト
as
'ol'
AsTag | Component

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

asChild
boolean

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

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

hotkey
['F8']
string[]

Toastビューポートにフォーカスを移動するキーボードショートカットとして使用するキー。

label
'Notifications ({hotkey})'
string | ((hotkey: string) => string)

ページのランドマークをナビゲートする際にスクリーンリーダーユーザーにコンテキストを提供するためのToastビューポートの作者によるローカライズされたラベル。利用可能な{hotkey}プレースホルダーは自動的に置き換えられます。または、カスタム関数を使用してラベルを生成することもできます。

ルート

自動的に閉じられるToast。ユーザーの応答を得るために開いたままにしておくべきではありません。

プロパティデフォルト
as
'li'
AsTag | Component

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

asChild
boolean

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

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

defaultOpen
true
boolean

最初にレンダリングされたときのダイアログの開いている状態。開いている状態を制御する必要がない場合に使用します。

duration
number

Toastが表示されるミリ秒数。ToastProviderに与えられた値を上書きします。

forceMount
boolean

より多くの制御が必要な場合にマウントを強制するために使用します。Vueアニメーションライブラリでアニメーションを制御する場合に役立ちます。

open
boolean

ダイアログの制御された開いている状態。v-model:openとしてバインドできます。

type
'foreground'
'foreground' | 'background'

アクセシビリティのためにToastの感度を制御します。

ユーザーアクションの結果であるToastの場合は、foregroundを選択します。バックグラウンドタスクから生成されたToastにはbackgroundを使用する必要があります。

Emitペイロード
escapeKeyDown
[event: KeyboardEvent]

Escapeキーが押されたときに呼び出されるイベントハンドラー。event.preventDefaultを呼び出すことで、防止できます。

pause
[]

破棄タイマーが一時停止されたときに呼び出されるイベントハンドラー。これは、ポインターがビューポート上に移動したとき、ビューポートにフォーカスが当たったとき、またはウィンドウのフォーカスが失われたときに発生します。

resume
[]

破棄タイマーが再開されたときに呼び出されるイベントハンドラー。これは、ポインターがビューポートから離れたとき、ビューポートのフォーカスが失われたとき、またはウィンドウにフォーカスが当たったときに発生します。

swipeCancel
[event: SwipeEvent]
swipeEnd
[event: SwipeEvent]

スワイプ操作の最後に呼び出されるイベントハンドラー。event.preventDefaultを呼び出すことで、防止できます。

swipeMove
[event: SwipeEvent]

スワイプ操作中に呼び出されるイベントハンドラー。event.preventDefaultを呼び出すことで、防止できます。

swipeStart
[event: SwipeEvent]

スワイプ操作の開始時に呼び出されるイベントハンドラー。event.preventDefaultを呼び出すことで、防止できます。

update:open
[value: boolean]

開いている状態が変更されたときに呼び出されるイベントハンドラー

スロット (デフォルト)ペイロード
open
boolean

現在の開いている状態

remaining
number

残りの時間 (ミリ秒)

duration
number

Toastが表示される総時間 (ミリ秒)

データ属性
[data-state]"open" | "closed"
[data-swipe]"start" | "move" | "cancel" | "end"
[data-swipe-direction]"up" | "down" | "left" | "right"
CSS変数説明
--radix-toast-swipe-move-x
水平方向にスワイプしたときのToastのオフセット位置
--radix-toast-swipe-move-y
垂直方向にスワイプしたときのToastのオフセット位置
--radix-toast-swipe-end-x
水平方向にスワイプした後のToastのオフセット終了位置
--radix-toast-swipe-end-y
垂直方向にスワイプした後のToastのオフセット終了位置

タイトル

Toastのオプションのタイトル

プロパティデフォルト
as
'div'
AsTag | Component

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

asChild
boolean

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

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

説明

Toastメッセージ。

プロパティデフォルト
as
'div'
AsTag | Component

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

asChild
boolean

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

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

アクション

無視しても安全なアクション。ユーザーが時間制限の結果として予期しない副作用のあるタスクを完了する必要がないようにするためです。

ユーザーの応答を得る必要がある場合は、代わりにToastとしてスタイル設定された"AlertDialog"をビューポートにポータルします。

プロパティデフォルト
altText*
string

アクションを実行する代替方法の簡単な説明。スクリーンリーダーユーザーがボタンに簡単/迅速に移動できない場合のため。

as
'div'
AsTag | Component

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

asChild
boolean

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

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

閉じる

ユーザーが期間が経過する前にToastを閉じることができるボタン。

プロパティデフォルト
as
'button'
AsTag | Component

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

asChild
boolean

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

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

カスタムホットキー

keycode.infoから各キーのevent.code値を使用して、デフォルトのホットキーを上書きします。

html
<ToastProvider>
  ...
  <ToastViewport :hotkey="['altKey', 'KeyT']" />
</ToastProvider>

カスタム期間

プロバイダーの値を上書きするために、Toastの期間をカスタマイズします。

vue
<ToastRoot :duration="3000">
  <ToastDescription>Saved!</ToastDescription>
</ToastRoot>

Toastの複製

ユーザーがボタンをクリックするたびにToastを表示する必要がある場合、状態を使用して同じToastの複数のインスタンスをレンダリングします(下記参照)。または、独自の命令型APIを作成するために、部分を抽象化することもできます。

html
<div>
  <form @submit="count++">
    ...
    <button>save</button>
  </form>

  <ToastRoot v-for="(_, index) in count" :key="index">
    <ToastDescription>Saved!</ToastDescription>
  </ToastRoot>
</div>

スワイプジェスチャーのアニメーション

--radix-toast-swipe-move-[x|y]--radix-toast-swipe-end-[x|y]のCSS変数をdata-swipe="[start|move|cancel|end]"属性と組み合わせて、閉じるジェスチャーをアニメーション化します。例を以下に示します。

html
<ToastProvider swipeDirection="right">
  <ToastRoot class="ToastRoot">...</ToastRoot>
  <ToastViewport />
</ToastProvider>
css
/* styles.css */
.ToastRoot[data-swipe='move'] {
  transform: translateX(var(--radix-toast-swipe-move-x));
}
.ToastRoot[data-swipe='cancel'] {
  transform: translateX(0);
  transition: transform 200ms ease-out;
}
.ToastRoot[data-swipe='end'] {
  animation: slideRight 100ms ease-out;
}

@keyframes slideRight {
  from {
    transform: translateX(var(--radix-toast-swipe-end-x));
  }
  to {
    transform: translateX(100%);
  }
}

アクセシビリティ

aria-liveの要件に準拠しています。

感度

typeプロパティを使用して、スクリーンリーダー向けのToastの感度を制御します。

ユーザーアクションの結果であるToastの場合は、foregroundを選択します。バックグラウンドタスクから生成されたToastにはbackgroundを使用する必要があります。

フォアグラウンド

フォアグラウンドのToastはすぐにアナウンスされます。補助技術は、フォアグラウンドのToastが表示されたときに、以前にキューに入れられたメッセージをクリアすることを選択する場合があります。同時に異なるフォアグラウンドのToastを積み重ねることは避けてください。

背景

背景トーストは、次の適切な機会にアナウンスされます。例えば、スクリーンリーダーが現在の文の読み上げを終えた時などです。キューに入れられたメッセージはクリアされないため、ユーザーインタラクションへの応答としてこれらを多用すると、スクリーンリーダーユーザーにとって遅延のあるユーザーエクスペリエンスに感じられる可能性があります。

html
<ToastRoot type="foreground">
  <ToastDescription>File removed successfully.</ToastDescription>
  <ToastClose>Dismiss</ToastClose>
</ToastRoot>

<ToastRoot type="background">
  <ToastDescription>We've just released Radix 1.0.</ToastDescription>
  <ToastClose>Dismiss</ToastClose>
</ToastRoot>

代替アクション

ActionaltText プロパティを使用して、スクリーンリーダーユーザーに対してトーストのアクションを実行する代替方法を指示します。

アプリケーション内の恒久的な場所でユーザーにアクションを実行させるように指示するか、独自のホットキーロジックを実装できます。後者を実装する場合は、foreground タイプを使用してすぐにアナウンスし、ユーザーに十分な時間を与えるために期間を長くします。

html
<ToastRoot type="background">
  <ToastTitle>Upgrade Available!</ToastTitle>
  <ToastDescription>We've just released Radix 1.0.</ToastDescription>
  <ToastAction altText="Goto account settings to upgrade">
    Upgrade
  </ToastAction>
  <ToastClose>Dismiss</ToastClose>
</ToastRoot>

<ToastRoot type="foreground" :duration="10000">
  <ToastDescription>File removed successfully.</ToastDescription>
  <ToastAction altText="Undo (Alt+U)">
    Undo <kbd>Alt</kbd>+<kbd>U</kbd>
  </ToastAction>
  <ToastClose>Dismiss</ToastClose>
</ToastRoot>

閉じるアイコンボタン

アイコン(またはフォントアイコン)を提供する場合は、スクリーンリーダーユーザーのために正しくラベル付けすることを忘れないでください。

html
<ToastRoot type="foreground">
  <ToastDescription>Saved!</ToastDescription>
  <ToastClose aria-label="Close">
    <span aria-hidden>×</span>
  </ToastClose>
</ToastRoot>

キーボード操作

キー説明
F8
トーストビューポートにフォーカスします。
Tab
フォーカスを次のフォーカス可能な要素に移動します。
Shift + Tab
フォーカスを前のフォーカス可能な要素に移動します。
Space
ToastAction または ToastClose にフォーカスがある場合、トーストを閉じます。
Enter
ToastAction または ToastClose にフォーカスがある場合、トーストを閉じます。
Esc
Toast にフォーカスがある場合、トーストを閉じます。

カスタムAPI

抽象的な部分

プリミティブな部分を独自のコンポーネントに抽象化することで、独自のAPIを作成します。

使用方法

vue
<script setup lang="ts">
import Toast from './your-toast.vue'
</script>

<template>
  <Toast
    title="Upgrade available"
    content="We've just released Radix 3.0!"
  >
    <button @click="handleUpgrade">
      Upgrade
    </button>
  </Toast>
</template>

実装

vue
// your-toast.vue
<script setup lang="ts">
import { ToastAction, ToastClose, ToastDescription, ToastRoot, ToastTitle } from 'radix-vue'

defineProps<{
  title: string
  content: string
}>()
</script>

<template>
  <ToastRoot>
    <ToastTitle v-if="title">
      {{ title }}
    </ToastTitle>
    <ToastDescription>{{ content }}</ToastDescription>
    <ToastAction
      as-child
      alt-text="toast"
    >
      <slot />
    </ToastAction>
    <ToastClose aria-label="Close">
      <span aria-hidden>×</span>
    </ToastClose>
  </ToastRoot>
</template>

命令型API

必要であれば、トーストの複製 を許可する独自の命令型APIを作成します。

使用方法

vue
<script setup lang="ts">
import Toast from './your-toast.vue'

const savedRef = ref<InstanceType<typeof Toast>>()
</script>

<template>
  <div>
    <form @submit="savedRef.publish()">
      ...
    </form>
    <Toast ref="savedRef">
      Saved successfully!
    </Toast>
  </div>
</template>

実装

vue
// your-toast.vue
<script setup lang="ts">
import { ToastClose, ToastDescription, ToastRoot, ToastTitle } from 'radix-vue'
import { ref } from 'vue'

const count = ref(0)

function publish() {
  count.value++
}

defineExpose({
  publish
})
</script>

<template>
  <ToastRoot
    v-for="index in count"
    :key="index"
  >
    <ToastDescription>
      <slot />
    </ToastDescription>
    <ToastClose>Dismiss</ToastClose>
  </ToastRoot>
</template>