Create a companion
Create one instance per mounted component or page. Pass a character pack, a local container and the size you want. The returned Pet is the handle for every later interaction.
Try it. It’s alive.LIVE DEMO
Drag the pet, or focus it and use arrow keys. Reduced motion follows your system settings.
Signature
ts
createPet(options?: PetOptions): Pet| Parameter or method | Behavior |
|---|---|
character / states | Character definition or named media states. |
width / height | Positive pixel dimensions; default 128 without a pack. |
container / bounds | Local element; bounds defaults to container when supplied, otherwise viewport. |
initialState | Must name a registered state; otherwise pack default, idle, or first state. |
bubble | Boolean or { enabled, closeButton }; enabled by default. |
How it works
Without a container the pet lives in the viewport. With a container it is clipped to that element and stays inside its stacking context. Give the container a real height. Imports are SSR-safe; createPet itself requires the browser DOM.
Use it in your project
Choose your stack. Each example includes setup and cleanup. For Vanilla, pass a mounted container at least 360px tall and keep the returned cleanup. Method names are identical across frameworks.
ts
import { createPet } from '@flowscape-ui/mimimo';
import { mochi } from '@flowscape-ui/mimimo-pet-mochi';
// Call after your container mounts.
export function mountCompanion(container: HTMLElement) {
const lifetime = new AbortController();
const pet = createPet({
character: mochi,
container,
anchor: 'center',
});
pet.addReaction('click', 'happy');
pet.say('Hello, friend!');
return () => {
lifetime.abort();
pet.destroy();
};
}
// Keep the returned cleanup and call it when the view is removed.tsx
'use client';
import { useEffect, useRef } from 'react';
import { createPet } from '@flowscape-ui/mimimo';
import { mochi } from '@flowscape-ui/mimimo-pet-mochi';
export default function Companion() {
const host = useRef<HTMLDivElement>(null);
useEffect(() => {
const container = host.current;
if (!container) return;
const lifetime = new AbortController();
const pet = createPet({
character: mochi,
container,
anchor: 'center',
});
pet.addReaction('click', 'happy');
pet.say('Hello, friend!');
return () => {
lifetime.abort();
pet.destroy();
};
}, []);
return <div ref={host} style={{ height: 360, position: 'relative' }} />;
}vue
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue';
import { createPet } from '@flowscape-ui/mimimo';
import { mochi } from '@flowscape-ui/mimimo-pet-mochi';
const host = ref<HTMLElement | null>(null);
let cleanup: (() => void) | undefined;
onMounted(() => {
const container = host.value;
if (!container) return;
const lifetime = new AbortController();
const pet = createPet({
character: mochi,
container,
anchor: 'center',
});
pet.addReaction('click', 'happy');
pet.say('Hello, friend!');
cleanup = () => {
lifetime.abort();
pet.destroy();
};
});
onBeforeUnmount(() => cleanup?.());
</script>
<template>
<div ref="host" style="height: 360px; position: relative" />
</template>