diff --git a/cspell.config.yaml b/cspell.config.yaml
index 991481955..fc2137edc 100644
--- a/cspell.config.yaml
+++ b/cspell.config.yaml
@@ -63,6 +63,7 @@ words:
- demodel
- devlogs
- directml
+ - dokidoki
- dotenvx
- DownloadLive2DSDK
- dtolnay
@@ -100,6 +101,7 @@ words:
- Kawaii
- kebabcase
- Keyyable
+ - kirakira
- kwaa
- lemonnekogh
- libsamplerate
@@ -159,6 +161,7 @@ words:
- pixi
- pixiv
- popmotion
+ - poppin
- PREFLIGHTS
- prereleased
- pretrained
diff --git a/packages/stage-ui/src/components/Widgets/PoppinText/PoppinText.web.story.vue b/packages/stage-ui/src/components/Widgets/PoppinText/PoppinText.web.story.vue
new file mode 100644
index 000000000..89eb844e2
--- /dev/null
+++ b/packages/stage-ui/src/components/Widgets/PoppinText/PoppinText.web.story.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/stage-ui/src/components/Widgets/PoppinText/PoppinText.web.vue b/packages/stage-ui/src/components/Widgets/PoppinText/PoppinText.web.vue
new file mode 100644
index 000000000..ccc2ce2b2
--- /dev/null
+++ b/packages/stage-ui/src/components/Widgets/PoppinText/PoppinText.web.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+ {{ cluster }}
+
+
+
diff --git a/packages/stage-ui/src/components/Widgets/PoppinText/animators/index.ts b/packages/stage-ui/src/components/Widgets/PoppinText/animators/index.ts
new file mode 100644
index 000000000..4c9e07193
--- /dev/null
+++ b/packages/stage-ui/src/components/Widgets/PoppinText/animators/index.ts
@@ -0,0 +1,3 @@
+export type Animator = (elements: HTMLElement[]) => (() => void)
+
+export * from './popup'
diff --git a/packages/stage-ui/src/components/Widgets/PoppinText/animators/popup.ts b/packages/stage-ui/src/components/Widgets/PoppinText/animators/popup.ts
new file mode 100644
index 000000000..ca0032660
--- /dev/null
+++ b/packages/stage-ui/src/components/Widgets/PoppinText/animators/popup.ts
@@ -0,0 +1,17 @@
+import type { Animator } from '.'
+
+import { createTimeline } from 'animejs'
+
+export const popupAnimator: Animator = (elements: HTMLElement[]) => {
+ const timeline = createTimeline({ loop: true })
+ .add(elements, {
+ translateY: ['1.1em', 0],
+ translateZ: 0,
+ duration: 750,
+ delay: (el, i) => 50 * i,
+ })
+
+ return () => {
+ timeline.remove(elements)
+ }
+}
diff --git a/packages/stage-ui/src/components/Widgets/index.ts b/packages/stage-ui/src/components/Widgets/index.ts
index f7e52285c..99a02673a 100644
--- a/packages/stage-ui/src/components/Widgets/index.ts
+++ b/packages/stage-ui/src/components/Widgets/index.ts
@@ -1,3 +1,4 @@
export * from './Dialogs'
export { default as PoppingSubtitles } from './PoppingSubtitles.web.vue'
+export { default as PoppinText } from './PoppinText/PoppinText.web.vue'
export * from './Toasters'