npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vue-moodie

v1.0.0

Published

A customizable, animated mood-reactive mascot widget for Vue 3

Readme

vue-moodie

npm version license Vue 3 bundle size

A customizable, animated mood-reactive mascot widget for Vue 3.

Moodie is a little ghost-like creature that reacts to your app's state with expressions, speech bubbles, animations, hats, and more — all without any extra dependencies beyond Vue 3 itself.



Features

  • Mood systemhappy, sad, excited, scared, angry, neutral, sleeping, dead
  • Speech bubble — display any message above Moodie
  • Mouse tracking — eyes and body smoothly follow the cursor (lerp)
  • Idle & sleep — automatically falls asleep after inactivity
  • Animations — plane flight, bounce, peek, rope swing (triggered programmatically or via keyboard)
  • Hatscowboy, propeller, helmet, or none
  • Sizebaby, medium, adult
  • Color picker — built-in HUD with color presets + custom hex input
  • Kill / revive — tombstone animation when "killed", spring back to life on revive
  • Light theme — pulls on sunglasses and triggers a flash effect
  • Keyboard shortcutsShift+K kill, Shift+R revive, Shift+A animate, Shift+S size cycle, Shift+H hat cycle
  • useMoodie composable — drive Moodie's state from your own logic (sliders, sensors, API data)
  • MoodieHud — standalone HUD panel you can mount anywhere separately
  • No Vuetify, no Pinia, no extra dependencies — just Vue 3

Screenshots


Installation

npm install vue-moodie

Peer dependency: Vue 3 (^3.0.0) must already be installed.


Quick Start

Option A — Global plugin

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import VueMoodiePlugin from 'vue-moodie'
import 'vue-moodie/dist/vue-moodie.css'

createApp(App).use(VueMoodiePlugin).mount('#app')
<template>
  <VueMoodie mood="happy" message="Hello world!" />
</template>

Option B — Direct import (no plugin)

<script setup>
import { VueMoodie } from 'vue-moodie'
import 'vue-moodie/dist/vue-moodie.css'
</script>

<template>
  <VueMoodie
    color="#7c3aed"
    size="medium"
    hat="propeller"
    mood="excited"
    message="Let's go! 🚀"
    :follow-mouse="true"
    :show-hud="true"
  />
</template>

Option C — With useMoodie composable

Drive Moodie's state from your own data — perfect for sliders, API results, sensor feeds, etc.

<script setup>
import { ref } from 'vue'
import { VueMoodie, useMoodie } from 'vue-moodie'
import 'vue-moodie/dist/vue-moodie.css'

const { mood, message, react, celebrate, speak } = useMoodie()

const stressScore = ref(5)

function onSliderChange(val) {
  stressScore.value = val
  // react(value, max, higherIsBetter)
  react(val, 10, false)  // 10 = max, false = higher stress is worse
}

function onSuccess() {
  celebrate()
  speak('You did it! 🎉')
}
</script>

<template>
  <input type="range" min="0" max="10" v-model="stressScore" @input="onSliderChange($event.target.value)" />
  <VueMoodie :mood="mood" :message="message" />
</template>

Option D — Separate MoodieHud panel

Mount the HUD anywhere in your layout, independently of where Moodie lives:

<script setup>
import { ref } from 'vue'
import { VueMoodie, MoodieHud } from 'vue-moodie'
import 'vue-moodie/dist/vue-moodie.css'

const color = ref('#7c3aed')
const size  = ref('medium')
const hat   = ref('none')
const dead  = ref(false)
</script>

<template>
  <!-- Moodie in one part of the layout -->
  <VueMoodie
    :color="color"
    :size="size"
    :hat="hat"
    @kill="dead = true"
    @revive="dead = false"
  />

  <!-- HUD in another part of the layout (e.g. sidebar) -->
  <MoodieHud
    v-model:color="color"
    v-model:size="size"
    v-model:hat="hat"
    :is-dead="dead"
    @kill="dead = true"
    @revive="dead = false"
  />
</template>

API

VueMoodie Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | color | String | '#7c3aed' | Body fill color (hex) | | size | String | 'medium' | 'baby' | 'medium' | 'adult' | | hat | String | 'none' | 'none' | 'cowboy' | 'propeller' | 'helmet' | | mood | String | 'neutral' | 'neutral' | 'happy' | 'sad' | 'excited' | 'scared' | 'angry' | 'sleeping' | 'dead' | | message | String | '' | Text shown in the speech bubble (empty = hidden) | | lightTheme | Boolean | false | When true, Moodie pulls on sunglasses + flash animation | | idleTimeout | Number | 7000 | Milliseconds before Moodie falls asleep | | followMouse | Boolean | true | Enable/disable cursor tracking | | showHud | Boolean | true | Show/hide the built-in HUD control buttons |


VueMoodie Events

| Event | Payload | Description | |-------|---------|-------------| | kill | — | Emitted when Moodie is killed (via HUD or keyboard) | | revive | — | Emitted when Moodie is revived | | animation | String \| null | Emitted when an animation starts ('plane', 'bounce', 'peek', 'rope') or ends (null) |


MoodieHud Props & Events

| Prop | Type | Default | Description | |------|------|---------|-------------| | color | String | '#7c3aed' | Current body color | | size | String | 'medium' | Current size | | hat | String | 'none' | Current hat | | isDead | Boolean | false | Reflects kill/revive state |

Emits: update:color, update:size, update:hat, kill, revive — all compatible with v-model:*.


useMoodie() Composable

const {
  mood,        // Ref<string> — current mood
  message,     // Ref<string> — current speech bubble text
  lastChanged, // Ref<Date>   — timestamp of last state change

  react(value, max, higherIsBetter),  // Map numeric value to mood + message
  reactSlider(value, max, stressor),  // React with named stressor context
  celebrate(),                         // Set mood to 'excited' + party message
  setIdle(),                           // Set mood to 'neutral' + clear message
  speak(text),                         // Set message without changing mood
} = useMoodie()

react(value, max, higherIsBetter?)

Maps a numeric value to a mood automatically:

react(8, 10, false)   // high = bad → mood: 'angry', message: stress warning
react(9, 10, true)    // high = good → mood: 'excited', message: congrats
react(3, 10, false)   // low = good → mood: 'happy'

reactSlider(value, max, stressor)

Same as react but takes a named stressor string for context-aware messages:

reactSlider(4, 5, 'study_load')       // mood: 'scared', message: study pressure warning
reactSlider(1, 5, 'sleep_quality')    // mood: 'happy', message: great sleep!

Supported stressor names: headache, breathing_problem, noise_level, peer_pressure, bullying, study_load, future_career_concerns, sleep_quality.


Keyboard Shortcuts

When focus is anywhere in the page, these global shortcuts control Moodie:

| Shortcut | Action | |----------|--------| | Shift + K | Kill Moodie | | Shift + R | Revive Moodie | | Shift + A | Trigger random animation | | Shift + S | Cycle size (baby → medium → adult) | | Shift + H | Cycle hat (none → cowboy → propeller → helmet) |


UMD / CDN Usage

<link rel="stylesheet" href="https://unpkg.com/vue-moodie/dist/vue-moodie.css" />
<script src="https://unpkg.com/vue/dist/vue.global.js"></script>
<script src="https://unpkg.com/vue-moodie/dist/vue-moodie.umd.cjs"></script>

<div id="app">
  <vue-moodie mood="happy" message="Hi from CDN!" />
</div>

<script>
  const { createApp } = Vue
  createApp({}).use(VueMoodie.default).mount('#app')
</script>

Local Development

git clone https://github.com/gmijo47/vue-moodie.git
cd vue-moodie
npm install
npm run build    # outputs to dist/
npm run dev      # watch mode

To use a local build in another project:

// package.json of your project
{
  "dependencies": {
    "vue-moodie": "file:../vue-moodie"
  }
}

Or with a Vite alias:

// vite.config.js
import { resolve } from 'path'
export default {
  resolve: {
    alias: {
      'vue-moodie': resolve(__dirname, '../vue-moodie/src/index.js')
    }
  }
}

Bundle Size

| File | Size | Gzip | |------|------|------| | vue-moodie.es.js (ESM) | 32.76 kB | 8.84 kB | | vue-moodie.umd.cjs (UMD) | 29.27 kB | — | | vue-moodie.css | 9.35 kB | — |


License

MIT © gmijo47