diff --git a/src/components/common/PreviewText.vue b/src/components/common/PreviewText.vue
new file mode 100644
index 0000000..f62cdf4
--- /dev/null
+++ b/src/components/common/PreviewText.vue
@@ -0,0 +1,33 @@
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
diff --git a/src/constants/Categories.ts b/src/constants/Categories.ts
index 1fe5c08..aa641b0 100644
--- a/src/constants/Categories.ts
+++ b/src/constants/Categories.ts
@@ -22,7 +22,8 @@ export const CATEGORIES = [
'True Focus',
'Scroll Float',
'Scroll Reveal',
- 'Rotating Text'
+ 'Rotating Text',
+ 'Glitch Text'
]
},
{
diff --git a/src/constants/Components.ts b/src/constants/Components.ts
index ab2deab..b911a4f 100644
--- a/src/constants/Components.ts
+++ b/src/constants/Components.ts
@@ -27,7 +27,8 @@ const textAnimations = {
'true-focus': () => import("../demo/TextAnimations/TrueFocusDemo.vue"),
'scroll-float': () => import("../demo/TextAnimations/ScrollFloatDemo.vue"),
'scroll-reveal': ()=> import("../demo/TextAnimations/ScrollRevealDemo.vue"),
- 'rotating-text': ()=> import("../demo/TextAnimations/RotatingTextDemo.vue")
+ 'rotating-text': ()=> import("../demo/TextAnimations/RotatingTextDemo.vue"),
+ 'glitch-text': () => import("../demo/TextAnimations/GlitchTextDemo.vue"),
};
const components = {
diff --git a/src/constants/code/TextAnimations/glitchTextCode.ts b/src/constants/code/TextAnimations/glitchTextCode.ts
new file mode 100644
index 0000000..0c92253
--- /dev/null
+++ b/src/constants/code/TextAnimations/glitchTextCode.ts
@@ -0,0 +1,19 @@
+import code from '@/content/TextAnimations/GlitchText/GlitchText.vue?raw';
+import type { CodeObject } from '../../../types/code';
+
+export const glitchText: CodeObject = {
+ cli: `npx jsrepo add https://vue-bits.dev/ui/TextAnimations/GlitchText`,
+ usage: `
+
+
+
+`,
+ code
+};
diff --git a/src/content/TextAnimations/GlitchText/GlitchText.css b/src/content/TextAnimations/GlitchText/GlitchText.css
new file mode 100644
index 0000000..faff805
--- /dev/null
+++ b/src/content/TextAnimations/GlitchText/GlitchText.css
@@ -0,0 +1,120 @@
+.glitch {
+ color: #fff;
+ font-size: clamp(2rem, 10vw, 8rem);
+ white-space: nowrap;
+ font-weight: 900;
+ position: relative;
+ margin: 0 auto;
+ user-select: none;
+ cursor: pointer;
+}
+
+.glitch::after,
+.glitch::before {
+ content: attr(data-text);
+ position: absolute;
+ top: 0;
+ color: #fff;
+ background-color: #060010;
+ overflow: hidden;
+ clip-path: inset(0 0 0 0);
+}
+
+.glitch:not(.enable-on-hover)::after {
+ left: 10px;
+ text-shadow: var(--after-shadow, -10px 0 red);
+ animation: animate-glitch var(--after-duration, 3s) infinite linear alternate-reverse;
+}
+.glitch:not(.enable-on-hover)::before {
+ left: -10px;
+ text-shadow: var(--before-shadow, 10px 0 cyan);
+ animation: animate-glitch var(--before-duration, 2s) infinite linear alternate-reverse;
+}
+
+.glitch.enable-on-hover::after,
+.glitch.enable-on-hover::before {
+ content: '';
+ opacity: 0;
+ animation: none;
+}
+
+.glitch.enable-on-hover:hover::after {
+ content: attr(data-text);
+ opacity: 1;
+ left: 10px;
+ text-shadow: var(--after-shadow, -10px 0 red);
+ animation: animate-glitch var(--after-duration, 3s) infinite linear alternate-reverse;
+}
+.glitch.enable-on-hover:hover::before {
+ content: attr(data-text);
+ opacity: 1;
+ left: -10px;
+ text-shadow: var(--before-shadow, 10px 0 cyan);
+ animation: animate-glitch var(--before-duration, 2s) infinite linear alternate-reverse;
+}
+
+@keyframes animate-glitch {
+ 0% {
+ clip-path: inset(20% 0 50% 0);
+ }
+ 5% {
+ clip-path: inset(10% 0 60% 0);
+ }
+ 10% {
+ clip-path: inset(15% 0 55% 0);
+ }
+ 15% {
+ clip-path: inset(25% 0 35% 0);
+ }
+ 20% {
+ clip-path: inset(30% 0 40% 0);
+ }
+ 25% {
+ clip-path: inset(40% 0 20% 0);
+ }
+ 30% {
+ clip-path: inset(10% 0 60% 0);
+ }
+ 35% {
+ clip-path: inset(15% 0 55% 0);
+ }
+ 40% {
+ clip-path: inset(25% 0 35% 0);
+ }
+ 45% {
+ clip-path: inset(30% 0 40% 0);
+ }
+ 50% {
+ clip-path: inset(20% 0 50% 0);
+ }
+ 55% {
+ clip-path: inset(10% 0 60% 0);
+ }
+ 60% {
+ clip-path: inset(15% 0 55% 0);
+ }
+ 65% {
+ clip-path: inset(25% 0 35% 0);
+ }
+ 70% {
+ clip-path: inset(30% 0 40% 0);
+ }
+ 75% {
+ clip-path: inset(40% 0 20% 0);
+ }
+ 80% {
+ clip-path: inset(20% 0 50% 0);
+ }
+ 85% {
+ clip-path: inset(10% 0 60% 0);
+ }
+ 90% {
+ clip-path: inset(15% 0 55% 0);
+ }
+ 95% {
+ clip-path: inset(25% 0 35% 0);
+ }
+ 100% {
+ clip-path: inset(30% 0 40% 0);
+ }
+}
diff --git a/src/content/TextAnimations/GlitchText/GlitchText.vue b/src/content/TextAnimations/GlitchText/GlitchText.vue
new file mode 100644
index 0000000..934c41e
--- /dev/null
+++ b/src/content/TextAnimations/GlitchText/GlitchText.vue
@@ -0,0 +1,47 @@
+
+
+ {{ children }}
+
+
+
+
diff --git a/src/demo/TextAnimations/GlitchTextDemo.vue b/src/demo/TextAnimations/GlitchTextDemo.vue
new file mode 100644
index 0000000..56e709f
--- /dev/null
+++ b/src/demo/TextAnimations/GlitchTextDemo.vue
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+