くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

Nuxt3でvue3-notificationをつかって通知する

BuefyからTailwind CSSに移行してるけど、
通知を自前で作る必要があるので、いろいろ試してみたときの備忘録。

通知関連のVueコンポーネントはいくつかあるけど、
Vue3対応でメンテナンスされているvue3-notificationを利用

使い方

まずはインストール

$ npm install --save @kyvg/vue3-notification

プラグインの作成

vueプラグインを使うので、~/pluginsディレクトリに、
ファイル(vue-notification.client.ts)を追加する。 client側のみで利用するので、.clientサフィックスで作成

// ~/plugins/vue-notification.client.ts
import Notifications, { notify } from "@kyvg/vue3-notification";

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(Notifications, {
    property: {
      // vue3-notificationのオプションはここで設定
    },
  });

  // $notifyで利用できるように、provideで渡す
  return { provide: { notify: notify } };
});

- vue-plugins | Plugins · Nuxt Directory Structure

型定義も追加

$notifyに型がつくように、型定義も拡張しておく。

// ~/types/vue.d.ts
import type { notify } from "@kyvg/vue3-notification";
declare module "#app" {
  interface NuxtApp {
    $notify: typeof notify;
  }
}

declare module "@vue/runtime-core" {
  interface ComponentCustomProperties {
    $notify: typeof notify;
  }
}

通知を表示するコンポーネントを追加

vue3-notificationでは、自動で追加するのではなく、
<notifications />コンポーネント内に追加される。

なので、通知を表示したい場所に、<notifications />を配置する。

<!-- ~/layouts/default.vue -->
<template>
  <main>
    <slot></slot>
  </main>

  <!-- 通知が表示されるコンポーネント -->
  <notifications width="100%" />
</template>

こんな感じで通知すればOK

this.$notify({ type: "success", text: "The operation completed" });

通知をグループに分ける

グループ名をつけて表示する位置を変えたり、
通知の位置を変更できるpropも用意されてる。

<notifications group="auth" position="top" />
<notifications group="app" position="bottom right" />
// グループ"auth"の方に通知する例
this.$notify({ group: "auth", text: "Wrong password, please try again" });

スタイルをカスタマイズする

通知の色などはtypeによって決まっているけど、
カスタムクラスを用意することでカスタマイズできる。

<notifications classes="my-notification" />

こんな感じで展開されるらしい。

<div class="vue-notification-wrapper">
  <div class="vue-notification-template my-notification">
    <div class="notification-title">Info</div>
    <div class="notification-content">You have been logged in</div>
  </div>
</div>

あとは、こんな感じにCSSを用意すればOK

// style of the notification itself
.my-notification {
  /*...*/

  // style for title line
  .notification-title {
    /*...*/
  }

  // style for content
  .notification-content {
    /*...*/
  }

  // additional styling hook when using`type` parameter, i.e. this.$notify({ type: 'success', message: 'Yay!' })
  &.success {
    /*...*/
  }
  &.info {
    /*...*/
  }
  &.error {
    /*...*/
  }
}

デフォルトのスタイルはこんな感じ

.vue-notification {
  // styling
  margin: 0 5px 5px;
  padding: 10px;
  font-size: 12px;
  color: #ffffff;

  // default (blue)
  background: #44a4fc;
  border-left: 5px solid #187fe7;

  // types (green, amber, red)
  &.success {
    background: #68cd86;
    border-left-color: #42a85f;
  }

  &.warn {
    background: #ffb648;
    border-left-color: #f48a06;
  }

  &.error {
    background: #e54d42;
    border-left-color: #b82e24;
  }
}

typeは、success / warn / errorのみだけど、
ここをカスタマイズすれば、infoなど独自のtypeも利用できる。

composableを活用する

通知するモジュールとしてuseNotifyを用意しておいても便利。

// ~/composables/useNotify.ts
export function useNotify() {
  const { $notify } = useNuxtApp();

  // 成功
  const success = (msg: string, group: string = "app") => {
    $notify({ group: group, type: "success", title: msg });
  };

  // エラー
  const error = (msg: string, group: string = "app") => {
    $notify({ group: group, type: "error", title: msg });
  };

  // 警告
  const warn = (msg: string, group: string = "app") => {
    $notify({ group: group, type: "error", title: msg });
  };

  // 情報
  const info = (msg: string, group: string = "app") => {
    $notify({ group: group, type: "info", title: msg });
  };

  return {
    notify: { success, error, warn, info },
  };
}

こんな感じで呼べばOK(*´ω`*)!!

<template>
  <notifications group="auth" position="top" />
  <notifications group="app" position="bottom right" />
</template>

<script lang="ts" setup>
const { notify } = useNotify();

notify.error("Error");
notify.error("Wrong password, please try again", "auth");
</script>

以上!! 便利(*´ω`*)!!

参考にしたサイト様