diff --git a/src/constants/Categories.ts b/src/constants/Categories.ts index 387767d..95693af 100644 --- a/src/constants/Categories.ts +++ b/src/constants/Categories.ts @@ -32,6 +32,7 @@ export const CATEGORIES = [ 'Animated Content', 'Fade Content', 'Pixel Transition', + 'Ribbons', 'Glare Hover', 'Magnet Lines', 'Count Up', diff --git a/src/constants/Components.ts b/src/constants/Components.ts index 96716a7..7b7ea30 100644 --- a/src/constants/Components.ts +++ b/src/constants/Components.ts @@ -5,6 +5,7 @@ const animations = { 'glare-hover': () => import('../demo/Animations/GlareHoverDemo.vue'), 'magnet-lines': () => import('../demo/Animations/MagnetLinesDemo.vue'), 'click-spark': () => import('../demo/Animations/ClickSparkDemo.vue'), + 'ribbons': () => import('../demo/Animations/RibbonsDemo.vue'), 'metallic-paint': () => import('../demo/Animations/MetallicPaintDemo.vue'), 'magnet': () => import('../demo/Animations/MagnetDemo.vue'), 'cubes': () => import('../demo/Animations/CubesDemo.vue'), diff --git a/src/constants/code/Animations/ribbonsCode.ts b/src/constants/code/Animations/ribbonsCode.ts new file mode 100644 index 0000000..20ce4c0 --- /dev/null +++ b/src/constants/code/Animations/ribbonsCode.ts @@ -0,0 +1,28 @@ +import code from '@content/Animations/Ribbons/Ribbons.vue?raw'; +import type { CodeObject } from '../../../types/code'; + +export const ribbons: CodeObject = { + cli: `npx jsrepo add https://vue-bits.dev/ui/Animations/Ribbons`, + installation: `npm install ogl`, + usage: ` + +`, + code +}; diff --git a/src/content/Animations/Ribbons/Ribbons.vue b/src/content/Animations/Ribbons/Ribbons.vue new file mode 100644 index 0000000..e9626f3 --- /dev/null +++ b/src/content/Animations/Ribbons/Ribbons.vue @@ -0,0 +1,355 @@ + + + diff --git a/src/content/Backgrounds/Hyperspeed/Hyperspeed.vue b/src/content/Backgrounds/Hyperspeed/Hyperspeed.vue index 7d9284e..67cc449 100644 --- a/src/content/Backgrounds/Hyperspeed/Hyperspeed.vue +++ b/src/content/Backgrounds/Hyperspeed/Hyperspeed.vue @@ -469,7 +469,7 @@ class CarLights { const geometry = new THREE.TubeGeometry(curve, 40, 1, 8, false); const instanced = new THREE.InstancedBufferGeometry(); - // Copy geometry attributes + for (const key in geometry.attributes) { instanced.setAttribute(key, geometry.attributes[key]); } @@ -634,7 +634,7 @@ class LightsSticks { const options = this.options; const geometry = new THREE.PlaneGeometry(1, 1); const instanced = new THREE.InstancedBufferGeometry(); - // Copy geometry attributes + for (const key in geometry.attributes) { instanced.setAttribute(key, geometry.attributes[key]); } @@ -1038,17 +1038,14 @@ class App { this.onMouseUp = this.onMouseUp.bind(this); this.onWindowResize = this.onWindowResize.bind(this); - // Use ResizeObserver for better container tracking if (typeof ResizeObserver !== 'undefined') { const resizeObserver = new ResizeObserver(() => { this.onWindowResize(); }); resizeObserver.observe(container); - // Store reference for cleanup this.resizeObserver = resizeObserver; } else { - // Fallback to window resize window.addEventListener('resize', this.onWindowResize); } } @@ -1220,7 +1217,6 @@ class App { tick() { if (this.disposed || !this) return; - // Ensure renderer stays within container bounds const containerWidth = this.container.offsetWidth; const containerHeight = this.container.offsetHeight; diff --git a/src/content/TextAnimations/GlitchText/GlitchText.vue b/src/content/TextAnimations/GlitchText/GlitchText.vue index b511ba4..c2f1bca 100644 --- a/src/content/TextAnimations/GlitchText/GlitchText.vue +++ b/src/content/TextAnimations/GlitchText/GlitchText.vue @@ -40,7 +40,6 @@ const inlineStyles = computed( ); const baseClasses = [ - // Base styling 'text-white', 'font-black', 'whitespace-nowrap', @@ -50,7 +49,6 @@ const baseClasses = [ 'cursor-pointer', 'text-[clamp(2rem,10vw,8rem)]', - // Pseudo-elements base 'before:content-[attr(data-text)]', 'before:absolute', 'before:top-0', @@ -69,19 +67,16 @@ const baseClasses = [ ]; const normalGlitchClasses = [ - // After pseudo-element for normal mode 'after:left-[10px]', 'after:[text-shadow:var(--after-shadow,-10px_0_red)]', 'after:[animation:animate-glitch_var(--after-duration,3s)_infinite_linear_alternate-reverse]', - // Before pseudo-element for normal mode 'before:left-[-10px]', 'before:[text-shadow:var(--before-shadow,10px_0_cyan)]', 'before:[animation:animate-glitch_var(--before-duration,2s)_infinite_linear_alternate-reverse]' ]; const hoverOnlyClasses = [ - // Hide pseudo-elements by default 'before:content-[""]', 'before:opacity-0', 'before:[animation:none]', @@ -89,7 +84,6 @@ const hoverOnlyClasses = [ 'after:opacity-0', 'after:[animation:none]', - // Show and animate on hover 'hover:before:content-[attr(data-text)]', 'hover:before:opacity-100', 'hover:before:left-[-10px]', diff --git a/src/demo/Animations/RibbonsDemo.vue b/src/demo/Animations/RibbonsDemo.vue new file mode 100644 index 0000000..08f21a1 --- /dev/null +++ b/src/demo/Animations/RibbonsDemo.vue @@ -0,0 +1,226 @@ + + + + +