@cssninja/nuxt-toaster

中文文档
0.5.0发布于 2025/07/18MITTypeScriptES Module近 30 天下载 3947

🔔 A simple toaster (notifier) handler for Nuxt.js

原始使用文档
文档目录12 节
  1. Features
  2. Installation
  3. Basic Usage
  4. Show a toast
  5. Show a toast with a custom component
  6. Configuration
  7. Using ninjaToaster.show options
  8. Using toaster app config
  9. Using a custom plugin
  10. Theming
  11. Minimal CSS theme
  12. Development

@cssninja/nuxt-toaster

🔔 A simple toaster (notifier) handler for Nuxt.js

npm

Features

  • 🔧 Unstyled by default
  • 🧩 Render any component as a toast
  • 🎨 Fully customizable
  • 🪄 Simple to use

Installation

  1. Add @cssninja/nuxt-toaster dependency to your project
# Using pnpm
pnpm add -D @cssninja/nuxt-toaster

# Using yarn
pnpm add -D @cssninja/nuxt-toaster

# Using npm
npm install --save-dev @cssninja/nuxt-toaster
  1. Add @cssninja/nuxt-toaster to the modules section of nuxt.config.js
export default defineNuxtConfig({
  modules: [
    '@cssninja/nuxt-toaster'
  ]
})

Basic Usage

Show a toast

// get the ninjaToaster instance
const { $nt } = useNuxtApp()

// show a toast with a string as content
$nt.show('Hello world')

Show a toast with a custom component

// define or import a component
const MyToast = defineComponent({
  /* ... */
})

// get the ninjaToaster instance
const { $nt } = useNuxtApp()

// show a toast with render function as content
$nt.show(() => h(MyToast))

Configuration

Using ninjaToaster.show options

// get the ninjaToaster instance
const { $nt } = useNuxtApp()

$nt.show({
  /**
   * The content of the toast, can be a render function (a.k.a stateless component)
   * 
   * @type {string | number | Record<string, any> | (() => Component)}
   * @required
   */
  content: 'Hello world',

  /**
   * The duration of the toast
   * 
   * @default 5000
   */
  duration: 5000,

  /**
   * Pause the duration timer on hover, or focus
   * 
   * @default true
   */
  pauseOnHover: true,

  /**
   * Whereas the toast can be closed on click,
   * or on pressing Enter/Space keys when focused
   * 
   * @default true
   */
  dismissible: false,

  /**
   * Maximum number of toasts to show 
   * on the same `theme.containerId`
   * 
   * @default Infinity
   */
  maxToasts: 5,

  /**
   * Transition property for the toast
   * 
   * @see https://vuejs.org/api/built-in-components.html#transition
   */
  transition: {
    name: 'fadeIn',
  },

  /**
   * The theme used for the toast
   */
  theme: {
    /**
     * The container id where the toast will be rendered
     * If not exists, it will be created automatically
     * 
     * @default 'nt-container'
     */
    containerId: 'nt-container',
    /**
     * The class name for the toaster container (applyed to toast container)
     * 
     * @type {string | string[]}
     * @default ''
     */
    containerClass: 'nt-container-class',
    /**
     * The class name for the toast wrapper (applyed to each toast)
     * 
     * @type {string | string[]}
     * @default ''
     */
    wrapperClass: 'nt-wrapper-class',
  }
})

This will create a toast with the following HTML structure:

<body>
  <!-- ... -->
  <div id="nt-container" class="nt-container-class">
    <div
      class="nt-wrapper-class"
      role="alert"
      tabindex="0"
    >
      Hello world
    </div>
  </div>
</body>

note: the theme property is used to customize the toaster behavior. Each theme.containerId will have their own context (e.g. the maxToasts will count how many toaster are visible in the container with matching id).

Using toaster app config

To avoid to repeat yourself, you can set defaults values for ninjaToaster.show method in the nuxt app.config.ts at the root of your project.

// app.config.ts
export default defineAppConfig({
  toaster: {
    // default options for ninjaToaster.show
  }
})

Using a custom plugin

By default, the module create an instance of ninjaToaster and inject it in the nuxt context in useNuxtApp().$nt.

You can create your own instance and inject it in the context by using a custom plugin. Here we are using tailwindcss to style the toast.

  1. Disable default plugin in nuxt.config.ts module options
// nuxt.config.ts
export default defineNuxtConfig({
  modules: [
    '@cssninja/nuxt-toaster'
  ],
  toaster: {
    // disable the default plugin 
    installPlugin: false
  }
})
  1. Create a custom toast component
<script setup lang="ts">
// components/MyToast.vue
const props = defineProps<{
  title: string
  message?: string
  type: 'info' | 'error'
}>()

const {
  isHovered,
  isActive,
  timer,
  duration,
  click,
  close,
} = useNinjaToasterState()

const {
  percent,
  endAt,
  closeIn
} = useNinjaToasterProgress()
</script>

<template>
  <div
    class="rounded p-4"
    :class="[
      props.type === 'info' && 'bg-indigo-600 text-indigo-500'
      props.type === 'error' && 'bg-rose-600 text-rose-500'
    ]"
  >
    <h1>{{ props.title }}</h1>
    <p v-if="props.message">{{ props.message }}</p>
    <button @click="close()">Close</button>
  </div>
</template>
  1. Create a custom plugin
// plugins/toaster.ts
import MyToast from '~/components/MyToast.vue'

interface ToasterOptions {
  message: string
  title?: string
}

export default defineNuxtPlugin(() => {
  // define or import a theme
  const theme = {
    containerId: 'nt-container-bottom-right',
    containerClass: [
      'absolute',
      'inset-0',
      'pointer-events-none',
      'p-4',
      'flex',
      'flex-col-reverse',
      'items-start',
      'gap-2'
    ],
    wrapperClass: [
      'pointer-events-auto',
      'cursor-pointer',
    ],
  }

  // set default show options here
  const nt = createNinjaToaster({
    theme,
    maxToasts: 5,
    transition: {
      enterActiveClass: 'transition duration-300 ease-out',
      enterFromClass: 'transform translate-x-full opacity-0',
      enterToClass: 'transform translate-x-0 opacity-100',
      leaveActiveClass: 'transition duration-300 ease-in',
      leaveFromClass: 'transform translate-x-0 opacity-100',
      leaveToClass: 'transform translate-x-full opacity-0'
    }
  })

  const toaster = {
    info (options: ToasterOptions) {
      nt.show(() => h(MyToast, {
        ...options,
        type: 'info'
      }))
    },
    async error (options: ToasterOptions) {
      // wait for the toast to be mounted
      const { el, close } = await nt.show(() => h(MyToastError, {
        ...options,
        type: 'error'
      }))

      // focus the toast once it's mounted
      el.focus()
    },
    close() {
      // close all toasts
      nt.closeAll()

      // or close toasts in a specific containerId
      nt.close('nt-container-bottom-right') 

      // or close toasts using a theme
      nt.close(theme)
    },
  }

  return {
    provide {
      toaster
    }
  }
})
  1. Use your toaster instance in your app
// pages/index.vue
const { $toaster } = useNuxtApp()

$toaster.info({
  title: 'Hello world',
  message: 'This is a toaster info message'
})
$toaster.error({
  title: 'Hello world',
  message: 'This is a toaster error message'
})

Theming

Minimal CSS theme

#nt-container {
  /* make container fit the screen */
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
  z-index: 100;
  pointer-events: none;

  /* position the toasts using flexbox */
  display: flex;
  
  /**
   * position all toasts in bottom of the screen 
   * - use "flex-direction: column;" to position in top screen
   */
  flex-direction: column-reverse;

  /**
   * align all toasts to the center
   * - use "align-items: start" to aling to the left
   * - use "align-items: end" to aling to the right
   */
  align-items: center;

  /* add some space between toasts and screen */
  padding: 2rem;
  gap: 1rem;
}

#nt-container [role='alert'] {
  /* allow toasts to be interactive */
  pointer-events: auto;

  /* add styles to toasts */
  padding: 1rem;
  border-radius: 0.5rem;
  background-color: #fff;
  box-shadow: 0 0 1rem rgba(0, 0, 0, 0.1);
}


@media (max-width: 767px) {
  #nt-container {
    /* fit toasts to screen on mobile */
    padding: 0;
  }
}

Development

  • Run npm run dev:prepare to generate type stubs.
  • Use npm run dev to start playground in development mode.

版本与发布记录

@cssninja/nuxt-toaster 共发布 21 个版本,首次发布于 2022/09/23;过去 12 个月发布了 0 个版本。

版本发布日期距今
0.5.0latest2025/07/181.3 年前
0.4.02025/07/181.3 年前
0.3.122023/04/273 年前
0.3.112023/04/153 年前
0.3.102023/03/263 年前
0.3.92023/03/263 年前

关于 @cssninja/nuxt-toaster 的常见问题

@cssninja/nuxt-toaster 是什么?

🔔 A simple toaster (notifier) handler for Nuxt.js

如何安装 @cssninja/nuxt-toaster?

在项目目录运行 npm install @cssninja/nuxt-toaster,或使用 pnpm add / yarn add / bun add。

@cssninja/nuxt-toaster 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@cssninja/nuxt-toaster 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@cssninja/nuxt-toaster 可以商用吗?

@cssninja/nuxt-toaster 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@cssninja/nuxt-toaster 的下载量有多少?

根据 npm 官方下载统计,@cssninja/nuxt-toaster 在 2026/10/11 – 2026/11/09 这 30 天内被下载 3,947 次,日均约 132 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@cssninja/nuxt-toaster 还在维护吗?

最新版本 0.5.0 发布于 2025/07/18(1.3 年前);至今共发布 21 个版本,其中过去 12 个月发布了 0 个;首次发布于 2022/09/23。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。