Merge branch 'main' into add-ascii-texts

This commit is contained in:
Max
2025-07-12 18:41:53 +02:00
committed by GitHub
239 changed files with 18121 additions and 8750 deletions

View File

@@ -6,11 +6,22 @@
<RefreshButton @click="forceRerender" />
<div :key="key" class="flex justify-center items-center">
<AnimatedContent :direction="direction" :delay="delay" :distance="distance" :reverse="reverse"
:duration="duration" :ease="ease" :initial-opacity="initialOpacity" :animate-opacity="animateOpacity"
:scale="scale" :threshold="threshold" @complete="() => console.log('✅ Animation Complete!')">
<AnimatedContent
:direction="direction"
:delay="delay"
:distance="distance"
:reverse="reverse"
:duration="duration"
:ease="ease"
:initial-opacity="initialOpacity"
:animate-opacity="animateOpacity"
:scale="scale"
:threshold="threshold"
@complete="() => console.log('✅ Animation Complete!')"
>
<div class="demo-content">
<h4>Animated Content</h4>
<p>It will animate in when it enters the viewport.</p>
</div>
</AnimatedContent>
@@ -18,29 +29,85 @@
</div>
<Customize>
<PreviewSelect title="Animation Direction" v-model="direction" :options="directionOptions"
@update:model-value="(val) => { direction = val as 'vertical' | 'horizontal'; forceRerender(); }" />
<PreviewSelect
title="Animation Direction"
v-model="direction"
:options="directionOptions"
@update:model-value="
val => {
direction = val as 'vertical' | 'horizontal';
forceRerender();
}
"
/>
<PreviewSelect title="Easing Function" v-model="ease" :options="easeOptions"
@update:model-value="(val) => { ease = val as string; forceRerender(); }" />
<PreviewSelect
title="Easing Function"
v-model="ease"
:options="easeOptions"
@update:model-value="
val => {
ease = val as string;
forceRerender();
}
"
/>
<PreviewSlider title="Distance" v-model="distance" :min="50" :max="300" :step="10"
@update:model-value="forceRerender" />
<PreviewSlider
title="Distance"
v-model="distance"
:min="50"
:max="300"
:step="10"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Duration" v-model="duration" :min="0.1" :max="3" :step="0.1" value-unit="s"
@update:model-value="forceRerender" />
<PreviewSlider
title="Duration"
v-model="duration"
:min="0.1"
:max="3"
:step="0.1"
value-unit="s"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Delay" v-model="delay" :min="0" :max="2" :step="0.1" value-unit="s"
@update:model-value="forceRerender" />
<PreviewSlider
title="Delay"
v-model="delay"
:min="0"
:max="2"
:step="0.1"
value-unit="s"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Initial Opacity" v-model="initialOpacity" :min="0" :max="1" :step="0.1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Initial Opacity"
v-model="initialOpacity"
:min="0"
:max="1"
:step="0.1"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Initial Scale" v-model="scale" :min="0.1" :max="2" :step="0.1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Initial Scale"
v-model="scale"
:min="0.1"
:max="2"
:step="0.1"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Threshold" v-model="threshold" :min="0.1" :max="1" :step="0.1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Threshold"
v-model="threshold"
:min="0.1"
:max="1"
:step="0.1"
@update:model-value="forceRerender"
/>
<PreviewSwitch title="Reverse Direction" v-model="reverse" @update:model-value="forceRerender" />
@@ -48,6 +115,7 @@
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['gsap']" />
</template>
@@ -63,44 +131,44 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import PreviewSelect from '../../components/common/PreviewSelect.vue'
import RefreshButton from '../../components/common/RefreshButton.vue'
import AnimatedContent from '../../content/Animations/AnimatedContent/AnimatedContent.vue'
import { animatedContent } from '@/constants/code/Animations/animatedContentCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import PreviewSelect from '../../components/common/PreviewSelect.vue';
import RefreshButton from '../../components/common/RefreshButton.vue';
import AnimatedContent from '../../content/Animations/AnimatedContent/AnimatedContent.vue';
import { animatedContent } from '@/constants/code/Animations/animatedContentCode';
import { useForceRerender } from '@/composables/useForceRerender';
const { rerenderKey: key, forceRerender } = useForceRerender()
const { rerenderKey: key, forceRerender } = useForceRerender();
const direction = ref<'vertical' | 'horizontal'>('vertical')
const distance = ref(100)
const delay = ref(0)
const reverse = ref(false)
const duration = ref(0.8)
const ease = ref('power3.out')
const initialOpacity = ref(0)
const animateOpacity = ref(true)
const scale = ref(1)
const threshold = ref(0.1)
const direction = ref<'vertical' | 'horizontal'>('vertical');
const distance = ref(100);
const delay = ref(0);
const reverse = ref(false);
const duration = ref(0.8);
const ease = ref('power3.out');
const initialOpacity = ref(0);
const animateOpacity = ref(true);
const scale = ref(1);
const threshold = ref(0.1);
const directionOptions = [
{ label: 'Vertical', value: 'vertical' },
{ label: 'Horizontal', value: 'horizontal' }
]
];
const easeOptions = [
{ label: 'Power3 Out', value: 'power3.out' },
{ label: 'Bounce Out', value: 'bounce.out' },
{ label: 'Elastic Out', value: 'elastic.out(1, 0.3)' }
]
];
const propData = [
{
@@ -169,7 +237,7 @@ const propData = [
default: '""',
description: 'Additional CSS classes for styling.'
}
]
];
</script>
<style scoped>
@@ -194,4 +262,4 @@ const propData = [
max-width: 25ch;
line-height: 1.6;
}
</style>
</style>

View File

@@ -3,13 +3,21 @@
<TabbedLayout>
<template #preview>
<div class="demo-container">
<ClickSpark :key="rerenderKey" :spark-color="sparkColor" :spark-size="sparkSize" :spark-radius="sparkRadius"
:spark-count="sparkCount" :duration="duration" :easing="easing" :extra-scale="extraScale"
class="click-spark-demo-area">
</ClickSpark>
<ClickSpark
:key="rerenderKey"
:spark-color="sparkColor"
:spark-size="sparkSize"
:spark-radius="sparkRadius"
:spark-count="sparkCount"
:duration="duration"
:easing="easing"
:extra-scale="extraScale"
class="click-spark-demo-area"
></ClickSpark>
<div
class="absolute inset-0 flex items-center justify-center pointer-events-none text-[4rem] font-[900] text-[#222] select-none">
class="absolute inset-0 flex items-center justify-center pointer-events-none text-[4rem] font-[900] text-[#222] select-none"
>
Click Around!
</div>
</div>
@@ -17,20 +25,50 @@
<Customize>
<PreviewColor title="Spark Color" v-model="sparkColor" @update:model-value="forceRerender" />
<PreviewSlider title="Spark Size" v-model="sparkSize" :min="5" :max="30" :step="1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Spark Size"
v-model="sparkSize"
:min="5"
:max="30"
:step="1"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Spark Radius" v-model="sparkRadius" :min="10" :max="50" :step="5"
@update:model-value="forceRerender" />
<PreviewSlider
title="Spark Radius"
v-model="sparkRadius"
:min="10"
:max="50"
:step="5"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Spark Count" v-model="sparkCount" :min="4" :max="20" :step="1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Spark Count"
v-model="sparkCount"
:min="4"
:max="20"
:step="1"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Duration (ms)" v-model="duration" :min="200" :max="1000" :step="50"
@update:model-value="forceRerender" />
<PreviewSlider
title="Duration (ms)"
v-model="duration"
:min="200"
:max="1000"
:step="50"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Extra Scale" v-model="extraScale" :min="0.5" :max="2" :step="0.1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Extra Scale"
v-model="extraScale"
:min="0.5"
:max="2"
:step="0.1"
@update:model-value="forceRerender"
/>
</Customize>
<PropTable :data="propData" />
@@ -48,26 +86,26 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewColor from '../../components/common/PreviewColor.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import ClickSpark from '../../content/Animations/ClickSpark/ClickSpark.vue'
import { clickSpark } from '@/constants/code/Animations/clickSparkCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewColor from '../../components/common/PreviewColor.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import ClickSpark from '../../content/Animations/ClickSpark/ClickSpark.vue';
import { clickSpark } from '@/constants/code/Animations/clickSparkCode';
import { useForceRerender } from '@/composables/useForceRerender';
const sparkColor = ref('#ffffff')
const sparkSize = ref(10)
const sparkRadius = ref(15)
const sparkCount = ref(8)
const duration = ref(400)
const easing = ref<"linear" | "ease-in" | "ease-out" | "ease-in-out">('ease-out')
const extraScale = ref(1)
const { rerenderKey, forceRerender } = useForceRerender()
const sparkColor = ref('#ffffff');
const sparkSize = ref(10);
const sparkRadius = ref(15);
const sparkCount = ref(8);
const duration = ref(400);
const easing = ref<'linear' | 'ease-in' | 'ease-out' | 'ease-in-out'>('ease-out');
const extraScale = ref(1);
const { rerenderKey, forceRerender } = useForceRerender();
const propData = [
{ name: 'sparkColor', type: 'string', default: "'#fff'", description: 'Color of the spark lines.' },
@@ -75,9 +113,14 @@ const propData = [
{ name: 'sparkRadius', type: 'number', default: '15', description: 'Distance sparks travel from the click center.' },
{ name: 'sparkCount', type: 'number', default: '8', description: 'Number of spark lines per click.' },
{ name: 'duration', type: 'number', default: '400', description: 'Animation duration in milliseconds.' },
{ name: 'easing', type: 'string', default: "'ease-out'", description: 'Easing function: "linear", "ease-in", "ease-out", or "ease-in-out".' },
{
name: 'easing',
type: 'string',
default: "'ease-out'",
description: 'Easing function: "linear", "ease-in", "ease-out", or "ease-in-out".'
},
{ name: 'extraScale', type: 'number', default: '1.0', description: 'Scale multiplier for spark distance and size.' }
]
];
</script>
<style scoped>

View File

@@ -3,22 +3,39 @@
<TabbedLayout>
<template #preview>
<h2 class="demo-title-extra">Default</h2>
<div class="demo-container relative">
<CountUp :key="keyDefault" :from="0" :to="100" separator="," direction="up" :duration="1"
class-name="count-up-text" />
<CountUp
:key="keyDefault"
:from="0"
:to="100"
separator=","
direction="up"
:duration="1"
class-name="count-up-text"
/>
<RefreshButton @click="forceRerenderDefault" />
</div>
<h2 class="demo-title-extra">Start Programatically</h2>
<div class="demo-container flex flex-col justify-center items-center relative min-h-[200px]">
<button class="bg-[#0b0b0b] cursor-pointer rounded-[10px] border border-[#222] text-white px-4 py-2 mb-4"
@click="setStartCounting(true)">
<button
class="bg-[#0b0b0b] cursor-pointer rounded-[10px] border border-[#222] text-white px-4 py-2 mb-4"
@click="setStartCounting(true)"
>
Count to 500!
</button>
<CountUp :key="keyProgramatically" :from="100" :to="500" :start-when="startCounting" :duration="5"
class-name="count-up-text" />
<CountUp
:key="keyProgramatically"
:from="100"
:to="500"
:start-when="startCounting"
:duration="5"
class-name="count-up-text"
/>
<RefreshButton v-if="startCounting" @click="forceRerenderProgramatically" />
</div>
@@ -38,27 +55,27 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import RefreshButton from '../../components/common/RefreshButton.vue'
import CountUp from '../../content/Animations/CountUp/CountUp.vue'
import { countup } from '@/constants/code/Animations/countUpCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import RefreshButton from '../../components/common/RefreshButton.vue';
import CountUp from '../../content/Animations/CountUp/CountUp.vue';
import { countup } from '@/constants/code/Animations/countUpCode';
import { useForceRerender } from '@/composables/useForceRerender';
const startCounting = ref(false)
const startCounting = ref(false);
const { rerenderKey: keyDefault, forceRerender: forceRerenderDefault } = useForceRerender()
const { rerenderKey: keyProgramatically, forceRerender: forceRerenderProgramatically } = useForceRerender()
const { rerenderKey: keyDefault, forceRerender: forceRerenderDefault } = useForceRerender();
const { rerenderKey: keyProgramatically, forceRerender: forceRerenderProgramatically } = useForceRerender();
const setStartCounting = (value: boolean) => {
startCounting.value = value
startCounting.value = value;
if (value) {
forceRerenderProgramatically()
forceRerenderProgramatically();
}
}
};
const propData = [
{
@@ -77,7 +94,8 @@ const propData = [
name: 'direction',
type: 'string',
default: '"up"',
description: 'Direction of the count; can be "up" or "down". When this is set to "down", "from" and "to" become reversed, in order to count down.'
description:
'Direction of the count; can be "up" or "down". When this is set to "down", "from" and "to" become reversed, in order to count down.'
},
{
name: 'delay',
@@ -101,7 +119,8 @@ const propData = [
name: 'startWhen',
type: 'boolean',
default: 'true',
description: 'A boolean to control whether the animation should start when the component is in view. It basically works like an if statement, if this is true, the count will start.'
description:
'A boolean to control whether the animation should start when the component is in view. It basically works like an if statement, if this is true, the count will start.'
},
{
name: 'separator',
@@ -121,7 +140,7 @@ const propData = [
default: '—',
description: 'Callback function that is called when the count animation ends.'
}
]
];
</script>
<style scoped>
@@ -129,4 +148,4 @@ const propData = [
min-height: 200px;
height: 200px;
}
</style>
</style>

View File

@@ -2,8 +2,14 @@
<TabbedLayout>
<template #preview>
<div class="relative demo-container h-[650px] overflow-hidden">
<Cubes :borderStyle="borderStyle" :gridSize="gridSize" :maxAngle="maxAngle" :radius="radius"
:autoAnimate="autoAnimate" :rippleOnClick="rippleOnClick" />
<Cubes
:borderStyle="borderStyle"
:gridSize="gridSize"
:maxAngle="maxAngle"
:radius="radius"
:autoAnimate="autoAnimate"
:rippleOnClick="rippleOnClick"
/>
</div>
<Customize>
@@ -21,6 +27,7 @@
</Customize>
<PropTable :data="propData" />
<Dependencies :dependencyList="['gsap']" />
</template>
@@ -35,117 +42,117 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSelect from '../../components/common/PreviewSelect.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSelect from '../../components/common/PreviewSelect.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import { cubes } from '../../constants/code/Animations/cubesCode'
import Cubes from '../../content/Animations/Cubes/Cubes.vue'
import { cubes } from '../../constants/code/Animations/cubesCode';
import Cubes from '../../content/Animations/Cubes/Cubes.vue';
const borderStyle = ref("2px dashed #A7EF9E")
const gridSize = ref(10)
const maxAngle = ref(45)
const radius = ref(3)
const autoAnimate = ref(true)
const rippleOnClick = ref(true)
const borderStyle = ref('2px dashed #A7EF9E');
const gridSize = ref(10);
const maxAngle = ref(45);
const radius = ref(3);
const autoAnimate = ref(true);
const rippleOnClick = ref(true);
const borderOptions = [
{ value: "2px dotted #fff", label: "Dotted White" },
{ value: "2px dashed #A7EF9E", label: "Dashed Green" },
{ value: "3px solid #fff", label: "Solid White" }
]
{ value: '2px dotted #fff', label: 'Dotted White' },
{ value: '2px dashed #A7EF9E', label: 'Dashed Green' },
{ value: '3px solid #fff', label: 'Solid White' }
];
const propData = [
{
name: "gridSize",
type: "number",
default: "10",
description: "The size of the grid (number of cubes per row/column)"
name: 'gridSize',
type: 'number',
default: '10',
description: 'The size of the grid (number of cubes per row/column)'
},
{
name: "cubeSize",
type: "number",
default: "undefined",
description: "Fixed size of each cube in pixels. If not provided, cubes will be responsive"
name: 'cubeSize',
type: 'number',
default: 'undefined',
description: 'Fixed size of each cube in pixels. If not provided, cubes will be responsive'
},
{
name: "maxAngle",
type: "number",
default: "45",
description: "Maximum rotation angle for the tilt effect in degrees"
name: 'maxAngle',
type: 'number',
default: '45',
description: 'Maximum rotation angle for the tilt effect in degrees'
},
{
name: "radius",
type: "number",
default: "3",
description: "Radius of the tilt effect (how many cubes around the cursor are affected)"
name: 'radius',
type: 'number',
default: '3',
description: 'Radius of the tilt effect (how many cubes around the cursor are affected)'
},
{
name: "easing",
type: "string",
name: 'easing',
type: 'string',
default: "'power3.out'",
description: "GSAP easing function for the tilt animation"
description: 'GSAP easing function for the tilt animation'
},
{
name: "duration",
type: "object",
default: "{ enter: 0.3, leave: 0.6 }",
description: "Animation duration for enter and leave effects"
name: 'duration',
type: 'object',
default: '{ enter: 0.3, leave: 0.6 }',
description: 'Animation duration for enter and leave effects'
},
{
name: "cellGap",
type: "number | object",
default: "undefined",
description: "Gap between cubes. Can be a number or object with row/col properties"
name: 'cellGap',
type: 'number | object',
default: 'undefined',
description: 'Gap between cubes. Can be a number or object with row/col properties'
},
{
name: "borderStyle",
type: "string",
name: 'borderStyle',
type: 'string',
default: "'1px solid #fff'",
description: "CSS border style for cube faces"
description: 'CSS border style for cube faces'
},
{
name: "faceColor",
type: "string",
name: 'faceColor',
type: 'string',
default: "'#060010'",
description: "Background color for cube faces"
description: 'Background color for cube faces'
},
{
name: "shadow",
type: "boolean | string",
default: "false",
description: "Shadow effect for cubes. Can be boolean or custom CSS shadow"
name: 'shadow',
type: 'boolean | string',
default: 'false',
description: 'Shadow effect for cubes. Can be boolean or custom CSS shadow'
},
{
name: "autoAnimate",
type: "boolean",
default: "true",
description: "Whether to automatically animate when user is idle"
name: 'autoAnimate',
type: 'boolean',
default: 'true',
description: 'Whether to automatically animate when user is idle'
},
{
name: "rippleOnClick",
type: "boolean",
default: "true",
description: "Whether to show ripple effect on click"
name: 'rippleOnClick',
type: 'boolean',
default: 'true',
description: 'Whether to show ripple effect on click'
},
{
name: "rippleColor",
type: "string",
name: 'rippleColor',
type: 'string',
default: "'#fff'",
description: "Color of the ripple effect"
description: 'Color of the ripple effect'
},
{
name: "rippleSpeed",
type: "number",
default: "2",
description: "Speed multiplier for the ripple animation"
name: 'rippleSpeed',
type: 'number',
default: '2',
description: 'Speed multiplier for the ripple animation'
}
]
];
</script>

View File

@@ -17,6 +17,7 @@
>
<div class="demo-content">
<h4>Fade Content</h4>
<p>It will fade in when it enters the viewport.</p>
</div>
</FadeContent>
@@ -25,17 +26,41 @@
<Customize>
<PreviewSwitch title="Enable Blur Effect" v-model="blur" @update:model-value="forceRerender" />
<PreviewSlider title="Duration (ms)" v-model="duration" :min="100" :max="3000" :step="100"
@update:model-value="forceRerender" />
<PreviewSlider
title="Duration (ms)"
v-model="duration"
:min="100"
:max="3000"
:step="100"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Delay (ms)" v-model="delay" :min="0" :max="1000" :step="50"
@update:model-value="forceRerender" />
<PreviewSlider
title="Delay (ms)"
v-model="delay"
:min="0"
:max="1000"
:step="50"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Threshold" v-model="threshold" :min="0.1" :max="1" :step="0.1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Threshold"
v-model="threshold"
:min="0.1"
:max="1"
:step="0.1"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Initial Opacity" v-model="initialOpacity" :min="0" :max="1" :step="0.1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Initial Opacity"
v-model="initialOpacity"
:min="0"
:max="1"
:step="0.1"
@update:model-value="forceRerender"
/>
</Customize>
<PropTable :data="propData" />
@@ -53,36 +78,41 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import RefreshButton from '../../components/common/RefreshButton.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import FadeContent from '../../content/Animations/FadeContent/FadeContent.vue'
import { fadeContent } from '@/constants/code/Animations/fadeContentCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import RefreshButton from '../../components/common/RefreshButton.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import FadeContent from '../../content/Animations/FadeContent/FadeContent.vue';
import { fadeContent } from '@/constants/code/Animations/fadeContentCode';
import { useForceRerender } from '@/composables/useForceRerender';
const blur = ref(true)
const duration = ref(1000)
const delay = ref(200)
const threshold = ref(0.1)
const initialOpacity = ref(0)
const easing = ref('ease-out')
const { rerenderKey, forceRerender } = useForceRerender()
const blur = ref(true);
const duration = ref(1000);
const delay = ref(200);
const threshold = ref(0.1);
const initialOpacity = ref(0);
const easing = ref('ease-out');
const { rerenderKey, forceRerender } = useForceRerender();
const propData = [
{ name: 'blur', type: 'boolean', default: 'false', description: 'Enable blur effect during fade animation.' },
{ name: 'duration', type: 'number', default: '1000', description: 'Animation duration in milliseconds.' },
{ name: 'easing', type: 'string', default: '"ease-out"', description: 'CSS easing function for the animation.' },
{ name: 'delay', type: 'number', default: '0', description: 'Delay before animation starts in milliseconds.' },
{ name: 'threshold', type: 'number', default: '0.1', description: 'Intersection threshold to trigger animation (0-1).' },
{
name: 'threshold',
type: 'number',
default: '0.1',
description: 'Intersection threshold to trigger animation (0-1).'
},
{ name: 'initialOpacity', type: 'number', default: '0', description: 'Initial opacity before animation (0-1).' },
{ name: 'className', type: 'string', default: '""', description: 'Additional CSS classes for styling.' }
]
];
</script>
<style scoped>
@@ -114,4 +144,4 @@ const propData = [
max-width: 25ch;
line-height: 1.6;
}
</style>
</style>

View File

@@ -4,12 +4,19 @@
<template #preview>
<div class="demo-container relative h-[600px] overflow-hidden">
<div class="flex justify-center items-center h-full">
<GlareHover background="#111" border-color="#222" border-radius="20px" width="400px" height="300px"
:glare-color="glareColor" :glare-opacity="glareOpacity" :glare-size="glareSize"
:transition-duration="transitionDuration" :play-once="playOnce">
<div class="text-center text-5xl font-black text-[#222] m-0">
Hover Me
</div>
<GlareHover
background="#111"
border-color="#222"
border-radius="20px"
width="400px"
height="300px"
:glare-color="glareColor"
:glare-opacity="glareOpacity"
:glare-size="glareSize"
:transition-duration="transitionDuration"
:play-once="playOnce"
>
<div class="text-center text-5xl font-black text-[#222] m-0">Hover Me</div>
</GlareHover>
</div>
</div>
@@ -21,8 +28,14 @@
<PreviewSlider title="Glare Size" v-model="glareSize" :min="100" :max="500" :step="25" value-unit="%" />
<PreviewSlider title="Transition Duration" v-model="transitionDuration" :min="200" :max="2000" :step="50"
value-unit="ms" />
<PreviewSlider
title="Transition Duration"
v-model="transitionDuration"
:min="200"
:max="2000"
:step="50"
value-unit="ms"
/>
<PreviewSwitch title="Play Once" v-model="playOnce" />
</Customize>
@@ -42,23 +55,23 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import PreviewColor from '../../components/common/PreviewColor.vue'
import GlareHover from '../../content/Animations/GlareHover/GlareHover.vue'
import { glareHover } from '@/constants/code/Animations/glareHoverCode'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import PreviewColor from '../../components/common/PreviewColor.vue';
import GlareHover from '../../content/Animations/GlareHover/GlareHover.vue';
import { glareHover } from '@/constants/code/Animations/glareHoverCode';
const glareColor = ref('#ffffff')
const glareOpacity = ref(0.3)
const glareSize = ref(300)
const transitionDuration = ref(800)
const playOnce = ref(false)
const glareColor = ref('#ffffff');
const glareOpacity = ref(0.3);
const glareSize = ref(300);
const transitionDuration = ref(800);
const playOnce = ref(false);
const propData = [
{
@@ -125,7 +138,7 @@ const propData = [
name: 'playOnce',
type: 'boolean',
default: 'false',
description: 'If true, the glare only animates on hover and doesn\'t return on mouse leave.'
description: "If true, the glare only animates on hover and doesn't return on mouse leave."
},
{
name: 'className',
@@ -139,5 +152,5 @@ const propData = [
default: '{}',
description: 'Additional inline styles.'
}
]
];
</script>

View File

@@ -3,34 +3,51 @@
<TabbedLayout>
<template #preview>
<h2 class="demo-title-extra">Container</h2>
<div class="demo-container">
<Magnet :key="rerenderKey" :padding="padding" :disabled="disabled" :magnetStrength="magnetStrength">
<div class="magnet-container">
Hover Me!
</div>
<div class="magnet-container">Hover Me!</div>
</Magnet>
</div>
<h2 class="demo-title-extra">Link</h2>
<div class="demo-container">
<Magnet :key="rerenderKey + 1" :padding="Math.floor(padding / 2)" :disabled="disabled"
:magnetStrength="magnetStrength">
<Magnet
:key="rerenderKey + 1"
:padding="Math.floor(padding / 2)"
:disabled="disabled"
:magnetStrength="magnetStrength"
>
<a href="https://github.com/DavidHDev/vue-bits" target="_blank" rel="noreferrer" class="magnet-link">
Star <span class="accent">Vue Bits</span> on GitHub!
Star
<span class="accent">Vue Bits</span>
on GitHub!
</a>
</Magnet>
</div>
<Customize>
<PreviewSwitch title="Disabled" v-model="disabled" @update:model-value="forceRerender" />
<PreviewSlider title="Padding" v-model="padding" :min="0" :max="300" :step="10" value-unit="px"
@update:model-value="forceRerender" />
<PreviewSlider
title="Padding"
v-model="padding"
:min="0"
:max="300"
:step="10"
value-unit="px"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Strength" v-model="magnetStrength" :min="1" :max="10" :step="1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Strength"
v-model="magnetStrength"
:min="1"
:max="10"
:step="1"
@update:model-value="forceRerender"
/>
</Customize>
<PropTable :data="propData" />
@@ -48,67 +65,67 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import Magnet from '../../content/Animations/Magnet/Magnet.vue'
import { magnet } from '@/constants/code/Animations/magnetCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import Magnet from '../../content/Animations/Magnet/Magnet.vue';
import { magnet } from '@/constants/code/Animations/magnetCode';
import { useForceRerender } from '@/composables/useForceRerender';
const disabled = ref(false)
const padding = ref(100)
const magnetStrength = ref(2)
const { rerenderKey, forceRerender } = useForceRerender()
const disabled = ref(false);
const padding = ref(100);
const magnetStrength = ref(2);
const { rerenderKey, forceRerender } = useForceRerender();
const propData = [
{
name: 'padding',
type: 'number',
default: '100',
description: 'Specifies the distance (in pixels) around the element that activates the magnet pull.',
description: 'Specifies the distance (in pixels) around the element that activates the magnet pull.'
},
{
name: 'disabled',
type: 'boolean',
default: 'false',
description: 'Disables the magnet effect when set to true.',
description: 'Disables the magnet effect when set to true.'
},
{
name: 'magnetStrength',
type: 'number',
default: '2',
description: 'Controls the strength of the pull; higher values reduce movement, lower values increase it.',
description: 'Controls the strength of the pull; higher values reduce movement, lower values increase it.'
},
{
name: 'activeTransition',
type: 'string',
default: '"transform 0.3s ease-out"',
description: 'CSS transition applied to the element when the magnet is active.',
description: 'CSS transition applied to the element when the magnet is active.'
},
{
name: 'inactiveTransition',
type: 'string',
default: '"transform 0.5s ease-in-out"',
description: 'CSS transition applied when the magnet is inactive (mouse out of range).',
description: 'CSS transition applied when the magnet is inactive (mouse out of range).'
},
{
name: 'wrapperClassName',
type: 'string',
default: '""',
description: 'Optional CSS class name for the outermost wrapper element.',
description: 'Optional CSS class name for the outermost wrapper element.'
},
{
name: 'innerClassName',
type: 'string',
default: '""',
description: 'Optional CSS class name for the moving (inner) element.',
description: 'Optional CSS class name for the moving (inner) element.'
}
]
];
</script>
<style scoped>

View File

@@ -3,13 +3,7 @@
<TabbedLayout>
<template #preview>
<div class="demo-container overflow-hidden flex justify-center pb-4 items-center">
<MagnetLines
:rows="10"
:columns="12"
container-size="40vmin"
line-width="2px"
line-height="30px"
/>
<MagnetLines :rows="10" :columns="12" container-size="40vmin" line-width="2px" line-height="30px" />
</div>
<PropTable :data="propData" />
@@ -27,12 +21,12 @@
</template>
<script setup lang="ts">
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import MagnetLines from '../../content/Animations/MagnetLines/MagnetLines.vue'
import { magnetLines } from '@/constants/code/Animations/magnetLinesCode'
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import MagnetLines from '../../content/Animations/MagnetLines/MagnetLines.vue';
import { magnetLines } from '@/constants/code/Animations/magnetLinesCode';
const propData = [
{
@@ -89,5 +83,5 @@ const propData = [
default: '{}',
description: 'Inline styles for the container.'
}
]
];
</script>

View File

@@ -0,0 +1,143 @@
<template>
<div class="metallic-paint-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container relative h-[500px] overflow-hidden">
<MetallicPaint
v-if="imageData"
:key="rerenderKey"
:image-data="imageData"
:params="{
edge,
patternBlur,
patternScale,
refraction,
speed,
liquid
}"
/>
</div>
<Customize>
<PreviewSlider
title="Edge"
v-model="edge"
:min="0"
:max="1"
:step="0.1"
@update:model-value="forceRerender"
/>
<PreviewSlider
title="Pattern Scale"
v-model="patternScale"
:min="1"
:max="5"
:step="0.1"
@update:model-value="forceRerender"
/>
<PreviewSlider
title="Pattern Blur"
v-model="patternBlur"
:min="0"
:max="0.1"
:step="0.001"
@update:model-value="forceRerender"
/>
<PreviewSlider
title="Refraction"
v-model="refraction"
:min="0"
:max="0.1"
:step="0.01"
@update:model-value="forceRerender"
/>
<PreviewSlider
title="Liquid"
v-model="liquid"
:min="0"
:max="1"
:step="0.01"
@update:model-value="forceRerender"
/>
<PreviewSlider
title="Speed"
v-model="speed"
:min="0"
:max="1"
:step="0.01"
@update:model-value="forceRerender"
/>
</Customize>
<PropTable :data="propData" />
</template>
<template #code>
<CodeExample :code-object="metallicPaint" />
</template>
<template #cli>
<CliInstallation :command="metallicPaint.cli" />
</template>
</TabbedLayout>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import MetallicPaint from '../../content/Animations/MetallicPaint/MetallicPaint.vue';
import { metallicPaint } from '@/constants/code/Animations/metallicPaintCode';
import { parseImage } from '../../content/Animations/MetallicPaint/parseImage';
import { useForceRerender } from '@/composables/useForceRerender';
import logo from '@/assets/logos/vue-bits-logo-small-dark.svg';
const imageData = ref<ImageData | null>(null);
const edge = ref(0);
const patternScale = ref(2);
const refraction = ref(0.015);
const patternBlur = ref(0.005);
const liquid = ref(0.07);
const speed = ref(0.3);
const { rerenderKey, forceRerender } = useForceRerender();
const propData = [
{
name: 'imageData',
type: 'ImageData',
default: 'none (required)',
description:
'The processed image data generated from the parseImage utility. This image data is used by the shader to create the liquid paper effect.'
},
{
name: 'params',
type: 'ShaderParams',
default: '',
description:
'An object to configure the shader effect. Properties include: patternScale, refraction, edge, patternBlur, liquid, speed'
}
];
onMounted(async () => {
try {
const response = await fetch(logo);
const blob = await response.blob();
const file = new File([blob], 'default.png', { type: blob.type });
const { imageData: processedImageData } = await parseImage(file);
imageData.value = processedImageData;
} catch (err) {
console.error('Error loading default image:', err);
}
});
</script>

View File

@@ -3,33 +3,60 @@
<TabbedLayout>
<template #preview>
<div
class="demo-container flex flex-col items-center justify-center min-h-[400px] max-h-[400px] relative overflow-hidden">
<PixelTransition :key="key" :grid-size="gridSize" :pixel-color="pixelColor"
:animation-step-duration="animationStepDuration" class-name="custom-pixel-card">
class="demo-container flex flex-col items-center justify-center min-h-[400px] max-h-[400px] relative overflow-hidden"
>
<PixelTransition
:key="key"
:grid-size="gridSize"
:pixel-color="pixelColor"
:animation-step-duration="animationStepDuration"
class-name="custom-pixel-card"
>
<template #firstContent>
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"
alt="Default" style="width: 100%; height: 100%; object-fit: cover;" />
<img
src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"
alt="Default"
style="width: 100%; height: 100%; object-fit: cover"
/>
</template>
<template #secondContent>
<div style="width: 100%; height: 100%; display: grid; place-items: center; background-color: #111;">
<p style="font-weight: 900; font-size: 3rem; color: #fff;">Meow!</p>
<div style="width: 100%; height: 100%; display: grid; place-items: center; background-color: #111">
<p style="font-weight: 900; font-size: 3rem; color: #fff">Meow!</p>
</div>
</template>
</PixelTransition>
<div class="mt-2 text-[#a6a6a6]">Psst, hover the card!</div>
</div>
<Customize>
<PreviewSlider title="Grid Size" v-model="gridSize" :min="2" :max="50" :step="1"
@update:model-value="forceRerender" width="200" />
<PreviewSlider
title="Grid Size"
v-model="gridSize"
:min="2"
:max="50"
:step="1"
@update:model-value="forceRerender"
width="200"
/>
<PreviewSlider title="Animation Duration" v-model="animationStepDuration" :min="0.1" :max="2" :step="0.1"
value-unit="s" @update:model-value="forceRerender" width="200" />
<PreviewSlider
title="Animation Duration"
v-model="animationStepDuration"
:min="0.1"
:max="2"
:step="0.1"
value-unit="s"
@update:model-value="forceRerender"
width="200"
/>
<PreviewColor title="Pixel Color" v-model="pixelColor" @update:model-value="forceRerender" />
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['gsap']" />
</template>
@@ -45,23 +72,23 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import PixelTransition from '../../content/Animations/PixelTransition/PixelTransition.vue'
import { pixelTransition } from '@/constants/code/Animations/pixelTransitionCode'
import { useForceRerender } from '@/composables/useForceRerender'
import PreviewColor from '../../components/common/PreviewColor.vue'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PixelTransition from '../../content/Animations/PixelTransition/PixelTransition.vue';
import { pixelTransition } from '@/constants/code/Animations/pixelTransitionCode';
import { useForceRerender } from '@/composables/useForceRerender';
import PreviewColor from '../../components/common/PreviewColor.vue';
const { rerenderKey: key, forceRerender } = useForceRerender()
const gridSize = ref(8)
const pixelColor = ref('#ffffff')
const animationStepDuration = ref(0.4)
const { rerenderKey: key, forceRerender } = useForceRerender();
const gridSize = ref(8);
const pixelColor = ref('#ffffff');
const animationStepDuration = ref(0.4);
const propData = [
{
@@ -112,7 +139,7 @@ const propData = [
default: '{}',
description: 'Optional inline styles for the container.'
}
]
];
</script>
<style scoped>

View File

@@ -0,0 +1,226 @@
<template>
<div class="ribbons-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container" style="height: 500px; position: relative">
<div class="hover-text">Hover Me.</div>
<Ribbons
:base-thickness="baseThickness"
:colors="colors"
:speed-multiplier="speedMultiplier"
:max-age="maxAge"
:enable-fade="enableFade"
:enable-shader-effect="enableWaves"
/>
</div>
<Customize>
<div class="count-controls">
<span class="count-label">Count</span>
<button @click="removeColor" :disabled="colors.length <= 1" class="count-button">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</button>
<span class="count-value">{{ colors.length }}</span>
<button @click="addColor" :disabled="colors.length >= 10" class="count-button">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</button>
</div>
<PreviewSlider title="Thickness" v-model="baseThickness" :min="1" :max="60" :step="1" />
<PreviewSlider title="Speed" v-model="speedMultiplier" :min="0.3" :max="0.7" :step="0.01" />
<PreviewSlider title="Max Age" v-model="maxAge" :min="300" :max="1000" :step="100" />
<PreviewSwitch title="Enable Fade" v-model="enableFade" />
<PreviewSwitch title="Enable Waves" v-model="enableWaves" />
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['ogl']" />
</template>
<template #code>
<CodeExample :code-object="ribbons" />
</template>
<template #cli>
<CliInstallation :command="ribbons.cli" />
</template>
</TabbedLayout>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import Ribbons from '../../content/Animations/Ribbons/Ribbons.vue';
import { ribbons } from '@/constants/code/Animations/ribbonsCode';
const baseThickness = ref(30);
const colors = ref(['#5227FF']);
const speedMultiplier = ref(0.5);
const maxAge = ref(500);
const enableFade = ref(false);
const enableWaves = ref(false);
const addColor = () => {
if (colors.value.length < 10) {
const newColor = `#${Math.floor(Math.random() * 16777215)
.toString(16)
.padStart(6, '0')}`;
colors.value.push(newColor);
}
};
const removeColor = () => {
if (colors.value.length > 1) {
colors.value.pop();
}
};
const propData = [
{
name: 'colors',
type: 'string[]',
default: "['#5227FF']",
description: 'An array of color strings to be used for the ribbons.'
},
{
name: 'baseSpring',
type: 'number',
default: '0.03',
description: 'Base spring factor for the physics controlling ribbon motion.'
},
{
name: 'baseFriction',
type: 'number',
default: '0.9',
description: 'Base friction factor that dampens the ribbon motion.'
},
{
name: 'baseThickness',
type: 'number',
default: '30',
description: 'The base thickness of the ribbons.'
},
{
name: 'offsetFactor',
type: 'number',
default: '0.02',
description: 'A factor to horizontally offset the starting positions of the ribbons.'
},
{
name: 'maxAge',
type: 'number',
default: '500',
description: 'Delay in milliseconds controlling how long the ribbon trails extend.'
},
{
name: 'pointCount',
type: 'number',
default: '50',
description: 'The number of points that make up each ribbon.'
},
{
name: 'speedMultiplier',
type: 'number',
default: '0.5',
description: 'Multiplier that adjusts how fast trailing points interpolate towards the head.'
},
{
name: 'enableFade',
type: 'boolean',
default: 'true',
description: 'If true, a fade effect is applied along the length of the ribbon.'
},
{
name: 'enableShaderEffect',
type: 'boolean',
default: 'true',
description: 'If true, an additional sine-wave shader effect is applied to the ribbons.'
},
{
name: 'effectAmplitude',
type: 'number',
default: '2',
description: 'The amplitude of the shader displacement effect.'
},
{
name: 'backgroundColor',
type: 'number[]',
default: '[0, 0, 0, 0]',
description: 'An RGBA array specifying the clear color for the renderer.'
}
];
</script>
<style scoped>
.hover-text {
position: absolute;
font-size: clamp(2rem, 6vw, 6rem);
font-weight: 900;
color: #222;
z-index: 1;
pointer-events: none;
}
.demo-container {
padding: 0;
overflow: hidden;
}
.count-controls {
display: flex;
gap: 1rem;
align-items: center;
margin-top: 1rem;
}
.count-label {
font-size: 0.875rem;
}
.count-button {
display: flex;
align-items: center;
justify-content: center;
width: 2.5rem;
height: 2.5rem;
background: #1b1b1b;
border: 1px solid #333;
border-radius: 10px;
color: #fff;
cursor: pointer;
transition: background-color 0.2s;
}
.count-button:hover:not(:disabled) {
background: #222;
}
.count-button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.count-value {
font-size: 0.875rem;
min-width: 1.5rem;
text-align: center;
}
</style>

View File

@@ -0,0 +1,154 @@
<template>
<div class="splash-cursor-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container">
<span class="text-6xl text-center text-[#222] font-black select-none">Move Your Cursor</span>
</div>
<Customize>
<PreviewSlider title="Simulation Resolution" v-model="simResolution" :min="64" :max="512" :step="32" />
<PreviewSlider title="Density Dissipation" v-model="densityDissipation" :min="1" :max="10" :step="0.5" />
<PreviewSlider title="Splat Force" v-model="splatForce" :min="1000" :max="15000" :step="1000" />
</Customize>
<PropTable :data="propData" />
</template>
<template #code>
<CodeExample :code-object="splashCursor" />
</template>
<template #cli>
<CliInstallation :command="splashCursor.cli" />
</template>
</TabbedLayout>
<SplashCursor
:key="rerenderKey"
:SIM_RESOLUTION="simResolution"
:DENSITY_DISSIPATION="densityDissipation"
:SPLAT_FORCE="splatForce"
/>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import SplashCursor from '../../content/Animations/SplashCursor/SplashCursor.vue';
import { splashCursor } from '@/constants/code/Animations/splashCursorCode';
import { useForceRerender } from '@/composables/useForceRerender';
const { rerenderKey, forceRerender } = useForceRerender();
const simResolution = ref(128);
const densityDissipation = ref(3.5);
const splatForce = ref(6000);
watch([simResolution, densityDissipation, splatForce], () => {
forceRerender();
});
const propData = [
{
name: 'SIM_RESOLUTION',
type: 'number',
default: '128',
description: 'Fluid simulation resolution for velocity fields.'
},
{
name: 'DYE_RESOLUTION',
type: 'number',
default: '1440',
description: 'Resolution of the color/dye texture.'
},
{
name: 'CAPTURE_RESOLUTION',
type: 'number',
default: '512',
description: 'Resolution used for certain capture operations (rarely changed).'
},
{
name: 'DENSITY_DISSIPATION',
type: 'number',
default: '3.5',
description: 'Rate at which color/density dissipates over time.'
},
{
name: 'VELOCITY_DISSIPATION',
type: 'number',
default: '2',
description: 'Rate at which velocity dissipates over time.'
},
{
name: 'PRESSURE',
type: 'number',
default: '0.1',
description: 'Base pressure for the fluid simulation.'
},
{
name: 'PRESSURE_ITERATIONS',
type: 'number',
default: '20',
description: 'Number of Jacobi iterations used for the pressure solver.'
},
{
name: 'CURL',
type: 'number',
default: '3',
description: 'Amount of vorticity/curl to apply for swirling effects.'
},
{
name: 'SPLAT_RADIUS',
type: 'number',
default: '0.2',
description: "Radius of the 'splat' effect when user interacts."
},
{
name: 'SPLAT_FORCE',
type: 'number',
default: '6000',
description: "Force of the fluid 'splat' on each interaction."
},
{
name: 'SHADING',
type: 'boolean',
default: 'true',
description: 'Toggles simple lighting/shading on the fluid.'
},
{
name: 'COLOR_UPDATE_SPEED',
type: 'number',
default: '10',
description: 'Frequency at which pointer colors are re-randomized.'
},
{
name: 'BACK_COLOR',
type: 'object',
default: '{ r: 0.5, g: 0, b: 0 }',
description: 'Base background color for the fluid. Not always used if TRANSPARENT is true.'
},
{
name: 'TRANSPARENT',
type: 'boolean',
default: 'true',
description: 'Determines if the canvas background should be rendered with alpha.'
}
];
</script>
<style scoped>
.demo-container {
overflow: hidden;
min-height: 300px;
padding: 0;
}
</style>

View File

@@ -3,35 +3,70 @@
<TabbedLayout>
<template #preview>
<div class="demo-container">
<Aurora :color-stops="colorStops" :amplitude="amplitude" :blend="blend" :speed="speed"
:intensity="intensity" class="w-full" />
<Aurora
:color-stops="colorStops"
:amplitude="amplitude"
:blend="blend"
:speed="speed"
:intensity="intensity"
class="w-full"
/>
</div>
<Customize>
<div class="space-y-2">
<h3 class="text-lg font-semibold text-gray-900 dark:text-gray-100">
Color Stops
</h3>
<h3 class="text-lg font-semibold text-gray-900 dark:text-gray-100">Color Stops</h3>
<div class="flex gap-4">
<PreviewColor v-for="(color, index) in colorStops" :key="index" :title="`Color ${index + 1}`"
:model-value="color" @update:model-value="(value) => updateColorStop(index, value)" />
<PreviewColor
v-for="(color, index) in colorStops"
:key="index"
:title="`Color ${index + 1}`"
:model-value="color"
@update:model-value="value => updateColorStop(index, value)"
/>
</div>
</div>
<PreviewSlider title="Amplitude" :model-value="amplitude" @update:model-value="amplitude = $event" :min="0"
:max="2" :step="0.1" />
<PreviewSlider
title="Amplitude"
:model-value="amplitude"
@update:model-value="amplitude = $event"
:min="0"
:max="2"
:step="0.1"
/>
<PreviewSlider title="Blend" :model-value="blend" @update:model-value="blend = $event" :min="0" :max="1"
:step="0.1" />
<PreviewSlider
title="Blend"
:model-value="blend"
@update:model-value="blend = $event"
:min="0"
:max="1"
:step="0.1"
/>
<PreviewSlider title="Speed" :model-value="speed" @update:model-value="speed = $event" :min="0" :max="3"
:step="0.1" />
<PreviewSlider
title="Speed"
:model-value="speed"
@update:model-value="speed = $event"
:min="0"
:max="3"
:step="0.1"
/>
<PreviewSlider title="Intensity" :model-value="intensity" @update:model-value="intensity = $event" :min="0"
:max="2" :step="0.1" />
<PreviewSlider
title="Intensity"
:model-value="intensity"
@update:model-value="intensity = $event"
:min="0"
:max="2"
:step="0.1"
/>
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['ogl']" />
</template>
@@ -47,39 +82,58 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import Aurora from '@/content/Backgrounds/Aurora/Aurora.vue'
import PreviewColor from '@/components/common/PreviewColor.vue'
import PreviewSlider from '@/components/common/PreviewSlider.vue'
import { aurora } from '@/constants/code/Backgrounds/auroraCode'
const colorStops = ref(['#171D22', '#7cff67', '#171D22'])
const amplitude = ref(1.0)
const blend = ref(0.5)
const speed = ref(1.0)
const intensity = ref(1.0)
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import Aurora from '@/content/Backgrounds/Aurora/Aurora.vue';
import PreviewColor from '@/components/common/PreviewColor.vue';
import PreviewSlider from '@/components/common/PreviewSlider.vue';
import { aurora } from '@/constants/code/Backgrounds/auroraCode';
const colorStops = ref(['#171D22', '#7cff67', '#171D22']);
const amplitude = ref(1.0);
const blend = ref(0.5);
const speed = ref(1.0);
const intensity = ref(1.0);
const updateColorStop = (index: number, color: string) => {
colorStops.value[index] = color
}
colorStops.value[index] = color;
};
const propData = [
{ name: 'colorStops', type: 'string[]', default: "['#171D22', '#7cff67', '#171D22']", description: 'Array of color stops for the aurora gradient.' },
{ name: 'amplitude', type: 'number', default: '1.0', description: 'Controls the height variation of the aurora effect.' },
{ name: 'blend', type: 'number', default: '0.5', description: 'Controls the blending/smoothness of the aurora effect.' },
{
name: 'colorStops',
type: 'string[]',
default: "['#171D22', '#7cff67', '#171D22']",
description: 'Array of color stops for the aurora gradient.'
},
{
name: 'amplitude',
type: 'number',
default: '1.0',
description: 'Controls the height variation of the aurora effect.'
},
{
name: 'blend',
type: 'number',
default: '0.5',
description: 'Controls the blending/smoothness of the aurora effect.'
},
{ name: 'speed', type: 'number', default: '1.0', description: 'Controls the animation speed of the aurora effect.' },
{ name: 'intensity', type: 'number', default: '1.0', description: 'Controls the overall intensity/opacity of the aurora effect.' },
{
name: 'intensity',
type: 'number',
default: '1.0',
description: 'Controls the overall intensity/opacity of the aurora effect.'
},
{ name: 'time', type: 'number', default: 'undefined', description: 'Optional time override for the animation.' },
{ name: 'className', type: 'string', default: '""', description: 'Additional CSS class names for styling.' },
{ name: 'style', type: 'CSSProperties', default: '{}', description: 'Inline styles for the component.' }
]
];
</script>
<style scoped>
@@ -87,4 +141,4 @@ const propData = [
overflow: hidden;
padding: 0;
}
</style>
</style>

View File

@@ -83,6 +83,7 @@
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['three']" />
</template>
@@ -98,26 +99,26 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '@/components/common/TabbedLayout.vue'
import PropTable from '@/components/common/PropTable.vue'
import Dependencies from '@/components/code/Dependencies.vue'
import CliInstallation from '@/components/code/CliInstallation.vue'
import CodeExample from '@/components/code/CodeExample.vue'
import Customize from '@/components/common/Customize.vue'
import Beams from '@/content/Backgrounds/Beams/Beams.vue'
import PreviewColor from '@/components/common/PreviewColor.vue'
import PreviewSlider from '@/components/common/PreviewSlider.vue'
import { beams } from '@/constants/code/Backgrounds/beamsCode'
import { ref } from 'vue';
import TabbedLayout from '@/components/common/TabbedLayout.vue';
import PropTable from '@/components/common/PropTable.vue';
import Dependencies from '@/components/code/Dependencies.vue';
import CliInstallation from '@/components/code/CliInstallation.vue';
import CodeExample from '@/components/code/CodeExample.vue';
import Customize from '@/components/common/Customize.vue';
import Beams from '@/content/Backgrounds/Beams/Beams.vue';
import PreviewColor from '@/components/common/PreviewColor.vue';
import PreviewSlider from '@/components/common/PreviewSlider.vue';
import { beams } from '@/constants/code/Backgrounds/beamsCode';
const beamWidth = ref(3)
const beamHeight = ref(30)
const beamNumber = ref(20)
const lightColor = ref('#ffffff')
const speed = ref(2)
const noiseIntensity = ref(1.75)
const scale = ref(0.2)
const rotation = ref(30)
const beamWidth = ref(3);
const beamHeight = ref(30);
const beamNumber = ref(20);
const lightColor = ref('#ffffff');
const speed = ref(2);
const noiseIntensity = ref(1.75);
const scale = ref(0.2);
const rotation = ref(30);
const propData = [
{
@@ -168,7 +169,7 @@ const propData = [
default: '0',
description: 'Rotation of the entire beams system in degrees.'
}
]
];
</script>
<style scoped>

View File

@@ -2,47 +2,108 @@
<div class="dot-grid-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container" style="height: 500px; overflow: hidden;">
<DotGrid :key="rerenderKey" :dot-size="dotSize" :gap="gap" :base-color="baseColor" :active-color="activeColor"
:proximity="proximity" :speed-trigger="speedTrigger" :shock-radius="shockRadius"
:shock-strength="shockStrength" :max-speed="maxSpeed" :resistance="resistance"
:return-duration="returnDuration" class-name="dot-grid-demo-canvas" />
<div class="demo-container" style="height: 500px; overflow: hidden">
<DotGrid
:key="rerenderKey"
:dot-size="dotSize"
:gap="gap"
:base-color="baseColor"
:active-color="activeColor"
:proximity="proximity"
:speed-trigger="speedTrigger"
:shock-radius="shockRadius"
:shock-strength="shockStrength"
:max-speed="maxSpeed"
:resistance="resistance"
:return-duration="returnDuration"
class-name="dot-grid-demo-canvas"
/>
</div>
<Customize>
<div class="color-controls">
<PreviewColor title="Base Color" v-model="baseColor" @update:model-value="forceRerender" />
<PreviewColor title="Active Color" v-model="activeColor" @update:model-value="forceRerender" />
</div>
<PreviewSlider title="Dot Size" v-model="dotSize" :min="2" :max="50" :step="1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Dot Size"
v-model="dotSize"
:min="2"
:max="50"
:step="1"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Gap" v-model="gap" :min="5" :max="100" :step="1" @update:model-value="forceRerender" />
<PreviewSlider title="Proximity" v-model="proximity" :min="50" :max="500" :step="10"
@update:model-value="forceRerender" />
<PreviewSlider
title="Proximity"
v-model="proximity"
:min="50"
:max="500"
:step="10"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Speed Trigger" v-model="speedTrigger" :min="50" :max="500" :step="10"
@update:model-value="forceRerender" />
<PreviewSlider
title="Speed Trigger"
v-model="speedTrigger"
:min="50"
:max="500"
:step="10"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Shock Radius" v-model="shockRadius" :min="50" :max="500" :step="10"
@update:model-value="forceRerender" />
<PreviewSlider
title="Shock Radius"
v-model="shockRadius"
:min="50"
:max="500"
:step="10"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Shock Strength" v-model="shockStrength" :min="1" :max="20" :step="1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Shock Strength"
v-model="shockStrength"
:min="1"
:max="20"
:step="1"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Max Speed" v-model="maxSpeed" :min="1000" :max="10000" :step="100"
@update:model-value="forceRerender" />
<PreviewSlider
title="Max Speed"
v-model="maxSpeed"
:min="1000"
:max="10000"
:step="100"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Resistance (Inertia)" v-model="resistance" :min="100" :max="2000" :step="50"
@update:model-value="forceRerender" />
<PreviewSlider
title="Resistance (Inertia)"
v-model="resistance"
:min="100"
:max="2000"
:step="50"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Return Duration (Inertia)" v-model="returnDuration" :min="0.1" :max="5" :step="0.1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Return Duration (Inertia)"
v-model="returnDuration"
:min="0.1"
:max="5"
:step="0.1"
@update:model-value="forceRerender"
/>
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['gsap']" />
</template>
@@ -58,47 +119,67 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import PreviewColor from '../../components/common/PreviewColor.vue'
import DotGrid from '../../content/Backgrounds/DotGrid/DotGrid.vue'
import { dotGrid } from '@/constants/code/Backgrounds/dotGridCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewColor from '../../components/common/PreviewColor.vue';
import DotGrid from '../../content/Backgrounds/DotGrid/DotGrid.vue';
import { dotGrid } from '@/constants/code/Backgrounds/dotGridCode';
import { useForceRerender } from '@/composables/useForceRerender';
const dotSize = ref(5)
const gap = ref(15)
const baseColor = ref('#333333')
const activeColor = ref('#27FF64')
const proximity = ref(120)
const speedTrigger = ref(100)
const shockRadius = ref(250)
const shockStrength = ref(5)
const maxSpeed = ref(5000)
const resistance = ref(750)
const returnDuration = ref(1.5)
const { rerenderKey, forceRerender } = useForceRerender()
const dotSize = ref(5);
const gap = ref(15);
const baseColor = ref('#333333');
const activeColor = ref('#27FF64');
const proximity = ref(120);
const speedTrigger = ref(100);
const shockRadius = ref(250);
const shockStrength = ref(5);
const maxSpeed = ref(5000);
const resistance = ref(750);
const returnDuration = ref(1.5);
const { rerenderKey, forceRerender } = useForceRerender();
const propData = [
{ name: 'dotSize', type: 'number', default: '16', description: 'Size of each dot in pixels.' },
{ name: 'gap', type: 'number', default: '32', description: 'Gap between each dot in pixels.' },
{ name: 'baseColor', type: 'string', default: "'#27FF64'", description: 'Base color of the dots.' },
{ name: 'activeColor', type: 'string', default: "'#27FF64'", description: 'Color of dots when hovered or activated.' },
{ name: 'proximity', type: 'number', default: '150', description: 'Radius around the mouse pointer within which dots react.' },
{ name: 'speedTrigger', type: 'number', default: '100', description: 'Mouse speed threshold to trigger inertia effect.' },
{
name: 'activeColor',
type: 'string',
default: "'#27FF64'",
description: 'Color of dots when hovered or activated.'
},
{
name: 'proximity',
type: 'number',
default: '150',
description: 'Radius around the mouse pointer within which dots react.'
},
{
name: 'speedTrigger',
type: 'number',
default: '100',
description: 'Mouse speed threshold to trigger inertia effect.'
},
{ name: 'shockRadius', type: 'number', default: '250', description: 'Radius of the shockwave effect on click.' },
{ name: 'shockStrength', type: 'number', default: '5', description: 'Strength of the shockwave effect on click.' },
{ name: 'maxSpeed', type: 'number', default: '5000', description: 'Maximum speed for inertia calculation.' },
{ name: 'resistance', type: 'number', default: '750', description: 'Resistance for the inertia effect.' },
{ name: 'returnDuration', type: 'number', default: '1.5', description: 'Duration for dots to return to their original position after inertia.' },
{
name: 'returnDuration',
type: 'number',
default: '1.5',
description: 'Duration for dots to return to their original position after inertia.'
},
{ name: 'className', type: 'string', default: "''", description: 'Additional CSS classes for the component.' },
{ name: 'style', type: 'object', default: '{}', description: 'Inline styles for the component.' }
]
];
</script>
<style scoped>
@@ -112,4 +193,4 @@ const propData = [
gap: 1rem;
margin-bottom: 1rem;
}
</style>
</style>

View File

@@ -0,0 +1,58 @@
<template>
<TabbedLayout>
<template #preview>
<div class="demo-container h-[600px]">
<GridMotion :items="images" />
</div>
<PropTable :data="propData" />
<Dependencies :dependency-list="['gsap']" />
</template>
<template #code>
<CodeExample :code-object="gridMotion" />
</template>
<template #cli>
<CliInstallation :command="gridMotion.cli" />
</template>
</TabbedLayout>
</template>
<script setup lang="ts">
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import PropTable from '../../components/common/PropTable.vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import GridMotion from '../../content/Backgrounds/GridMotion/GridMotion.vue';
import { gridMotion } from '../../constants/code/Backgrounds/gridMotionCode';
const propData = [
{
name: 'items',
type: 'array',
default: '[]',
description: 'An array of items to display in the grid. Each item can be a string, JSX element, or an image URL.'
},
{
name: 'gradientColor',
type: 'string',
default: 'black',
description: 'Controls the color of the radial gradient used as the background.'
}
];
const imageUrl =
'https://images.unsplash.com/photo-1748370987492-eb390a61dcda?q=80&w=1364&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D';
const numberOfImages = 30;
const images = Array.from({ length: numberOfImages }, () => imageUrl);
</script>
<style scoped>
.demo-container {
padding: 0;
overflow: hidden;
}
</style>

View File

@@ -0,0 +1,92 @@
<template>
<div class="hyperspeed-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container">
<div class="instruction-text">Click & Hold</div>
<Hyperspeed :effect-options="currentPreset" />
</div>
<Customize>
<PreviewSelect title="Animation Preset" :options="options" v-model="activePreset" />
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['three', 'postprocessing']" />
</template>
<template #code>
<CodeExample :code-object="hyperspeed" />
</template>
<template #cli>
<CliInstallation :command="hyperspeed.cli" />
</template>
</TabbedLayout>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSelect from '../../components/common/PreviewSelect.vue';
import Hyperspeed from '../../content/Backgrounds/Hyperspeed/Hyperspeed.vue';
import { hyperspeedPresets } from '../../content/Backgrounds/Hyperspeed/HyperspeedPresets';
import { hyperspeed } from '@/constants/code/Backgrounds/hyperspeedCode';
const activePreset = ref<string>('one');
const currentPreset = computed(() => {
return hyperspeedPresets[activePreset.value as keyof typeof hyperspeedPresets];
});
const propData = [
{
name: 'effectOptions',
type: 'object',
default: 'See the "code" tab for default values and presets.',
description:
'The highly customizable configuration object for the effect, controls things like colors, distortion, line properties, etc.'
}
];
const options = [
{ value: 'one', label: 'Cyberpunk' },
{ value: 'two', label: 'Akira' },
{ value: 'three', label: 'Golden' },
{ value: 'four', label: 'Split' },
{ value: 'five', label: 'Highway' },
{ value: 'six', label: 'Deep' }
];
</script>
<style scoped>
.hyperspeed-demo {
width: 100%;
}
.demo-container {
height: 600px;
overflow: hidden;
cursor: pointer;
padding: 0;
}
.instruction-text {
position: absolute;
top: 1.5rem;
left: 50%;
transform: translateX(-50%);
font-weight: 900;
font-size: 4rem;
color: #222;
z-index: 10;
pointer-events: none;
}
</style>

View File

@@ -14,13 +14,20 @@
<PreviewSlider :min="0" :max="2" :step="0.1" v-model="speed" title="Speed" @update:modelValue="forceRerender" />
<PreviewSlider :min="0" :max="0.5" :step="0.01" v-model="amplitude" title="Amplitude"
@update:modelValue="forceRerender" />
<PreviewSlider
:min="0"
:max="0.5"
:step="0.01"
v-model="amplitude"
title="Amplitude"
@update:modelValue="forceRerender"
/>
<PreviewSwitch v-model="mouseInteraction" title="Enable Mouse Interaction" @update:modelValue="forceRerender" />
</Customize>
<PropTable :data="propData" />
<Dependencies :dependencyList="['ogl']" />
</template>
@@ -35,52 +42,52 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import Iridescence from '../../content/Backgrounds/Iridescence/Iridescence.vue'
import { iridescence } from '../../constants/code/Backgrounds/iridescenceCode'
import { useForceRerender } from '../../composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import Iridescence from '../../content/Backgrounds/Iridescence/Iridescence.vue';
import { iridescence } from '../../constants/code/Backgrounds/iridescenceCode';
import { useForceRerender } from '../../composables/useForceRerender';
const colors = ref<[number, number, number]>([1, 1, 1])
const speed = ref(1)
const amplitude = ref(0.1)
const mouseInteraction = ref(true)
const colors = ref<[number, number, number]>([1, 1, 1]);
const speed = ref(1);
const amplitude = ref(0.1);
const mouseInteraction = ref(true);
const { rerenderKey: key, forceRerender } = useForceRerender()
const { rerenderKey: key, forceRerender } = useForceRerender();
const propData = [
{
name: "color",
type: "Array<number>",
default: "[1, 1, 1]",
description: "Base color as an array of RGB values (each between 0 and 1)."
name: 'color',
type: 'Array<number>',
default: '[1, 1, 1]',
description: 'Base color as an array of RGB values (each between 0 and 1).'
},
{
name: "speed",
type: "number",
default: "1.0",
description: "Speed multiplier for the animation."
name: 'speed',
type: 'number',
default: '1.0',
description: 'Speed multiplier for the animation.'
},
{
name: "amplitude",
type: "number",
default: "0.1",
description: "Amplitude for the mouse-driven effect."
name: 'amplitude',
type: 'number',
default: '0.1',
description: 'Amplitude for the mouse-driven effect.'
},
{
name: "mouseReact",
type: "boolean",
default: "true",
description: "Enable or disable mouse interaction with the shader."
name: 'mouseReact',
type: 'boolean',
default: 'true',
description: 'Enable or disable mouse interaction with the shader.'
}
]
];
</script>
<style scoped>
@@ -88,4 +95,4 @@ const propData = [
overflow: hidden;
padding: 0;
}
</style>
</style>

View File

@@ -31,11 +31,7 @@
:step="5"
/>
<PreviewSwitch
title="Smooth Animation"
:model-value="smooth"
@update:model-value="updateSmooth"
/>
<PreviewSwitch title="Smooth Animation" :model-value="smooth" @update:model-value="updateSmooth" />
<PreviewSwitch
title="Show Center Vignette"
@@ -51,6 +47,7 @@
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="[]" />
</template>
@@ -66,58 +63,88 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import LetterGlitch from '@/content/Backgrounds/LetterGlitch/LetterGlitch.vue'
import PreviewSlider from '@/components/common/PreviewSlider.vue'
import PreviewSwitch from '@/components/common/PreviewSwitch.vue'
import { letterGlitch } from '@/constants/code/Backgrounds/letterGlitchCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import LetterGlitch from '@/content/Backgrounds/LetterGlitch/LetterGlitch.vue';
import PreviewSlider from '@/components/common/PreviewSlider.vue';
import PreviewSwitch from '@/components/common/PreviewSwitch.vue';
import { letterGlitch } from '@/constants/code/Backgrounds/letterGlitchCode';
import { useForceRerender } from '@/composables/useForceRerender';
const smooth = ref(true)
const speed = ref(10)
const colors = ref(['#2b4539', '#61dca3', '#61b3dc'])
const showCenterVignette = ref(true)
const showOuterVignette = ref(false)
const smooth = ref(true);
const speed = ref(10);
const colors = ref(['#2b4539', '#61dca3', '#61b3dc']);
const showCenterVignette = ref(true);
const showOuterVignette = ref(false);
const { rerenderKey, forceRerender } = useForceRerender()
const { rerenderKey, forceRerender } = useForceRerender();
const randomHex = () => {
return '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0')
}
return (
'#' +
Math.floor(Math.random() * 16777215)
.toString(16)
.padStart(6, '0')
);
};
const randomizeColors = () => {
colors.value = [randomHex(), randomHex(), randomHex()]
forceRerender()
}
colors.value = [randomHex(), randomHex(), randomHex()];
forceRerender();
};
const updateSmooth = (value: boolean) => {
smooth.value = value
forceRerender()
}
smooth.value = value;
forceRerender();
};
const updateCenterVignette = (value: boolean) => {
showCenterVignette.value = value
forceRerender()
}
showCenterVignette.value = value;
forceRerender();
};
const updateOuterVignette = (value: boolean) => {
showOuterVignette.value = value
forceRerender()
}
showOuterVignette.value = value;
forceRerender();
};
const propData = [
{ name: 'glitchColors', type: 'string[]', default: "['#2b4539', '#61dca3', '#61b3dc']", description: 'Controls the colors of the letters rendered in the canvas.' },
{ name: 'glitchSpeed', type: 'number', default: '50', description: 'Controls the speed at which letters scramble in the animation.' },
{ name: 'centerVignette', type: 'boolean', default: 'false', description: 'When true, renders a radial gradient in the center of the container' },
{ name: 'outerVignette', type: 'boolean', default: 'true', description: 'When true, renders an inner radial gradient around the edges of the container.' },
{ name: 'smooth', type: 'boolean', default: 'true', description: 'When true, smoothens the animation of the letters for a more subtle feel.' }
]
{
name: 'glitchColors',
type: 'string[]',
default: "['#2b4539', '#61dca3', '#61b3dc']",
description: 'Controls the colors of the letters rendered in the canvas.'
},
{
name: 'glitchSpeed',
type: 'number',
default: '50',
description: 'Controls the speed at which letters scramble in the animation.'
},
{
name: 'centerVignette',
type: 'boolean',
default: 'false',
description: 'When true, renders a radial gradient in the center of the container'
},
{
name: 'outerVignette',
type: 'boolean',
default: 'true',
description: 'When true, renders an inner radial gradient around the edges of the container.'
},
{
name: 'smooth',
type: 'boolean',
default: 'true',
description: 'When true, smoothens the animation of the letters for a more subtle feel.'
}
];
</script>
<style scoped>

View File

@@ -3,28 +3,65 @@
<TabbedLayout>
<template #preview>
<div class="demo-container">
<Lightning :hue="hue" :x-offset="xOffset" :speed="speed" :intensity="intensity"
:size="size" class="w-full h-full" />
<Lightning
:hue="hue"
:x-offset="xOffset"
:speed="speed"
:intensity="intensity"
:size="size"
class="w-full h-full"
/>
</div>
<Customize>
<PreviewSlider title="Hue" :model-value="hue" @update:model-value="hue = $event" :min="0" :max="360"
:step="1" />
<PreviewSlider
title="Hue"
:model-value="hue"
@update:model-value="hue = $event"
:min="0"
:max="360"
:step="1"
/>
<PreviewSlider title="X Offset" :model-value="xOffset" @update:model-value="xOffset = $event" :min="-2"
:max="2" :step="0.1" />
<PreviewSlider
title="X Offset"
:model-value="xOffset"
@update:model-value="xOffset = $event"
:min="-2"
:max="2"
:step="0.1"
/>
<PreviewSlider title="Speed" :model-value="speed" @update:model-value="speed = $event" :min="0.5" :max="2"
:step="0.1" />
<PreviewSlider
title="Speed"
:model-value="speed"
@update:model-value="speed = $event"
:min="0.5"
:max="2"
:step="0.1"
/>
<PreviewSlider title="Intensity" :model-value="intensity" @update:model-value="intensity = $event" :min="0.1"
:max="2" :step="0.1" />
<PreviewSlider
title="Intensity"
:model-value="intensity"
@update:model-value="intensity = $event"
:min="0.1"
:max="2"
:step="0.1"
/>
<PreviewSlider title="Size" :model-value="size" @update:model-value="size = $event" :min="0.1" :max="3"
:step="0.1" />
<PreviewSlider
title="Size"
:model-value="size"
@update:model-value="size = $event"
:min="0.1"
:max="3"
:step="0.1"
/>
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="[]" />
</template>
@@ -40,30 +77,35 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import Lightning from '@/content/Backgrounds/Lightning/Lightning.vue'
import PreviewSlider from '@/components/common/PreviewSlider.vue'
import { lightning } from '@/constants/code/Backgrounds/lightningCode'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import Lightning from '@/content/Backgrounds/Lightning/Lightning.vue';
import PreviewSlider from '@/components/common/PreviewSlider.vue';
import { lightning } from '@/constants/code/Backgrounds/lightningCode';
const hue = ref(160)
const xOffset = ref(0)
const speed = ref(1)
const intensity = ref(1)
const size = ref(1)
const hue = ref(160);
const xOffset = ref(0);
const speed = ref(1);
const intensity = ref(1);
const size = ref(1);
const propData = [
{ name: 'hue', type: 'number', default: '230', description: 'Hue of the lightning in degrees (0 to 360).' },
{ name: 'xOffset', type: 'number', default: '0', description: 'Horizontal offset of the lightning in normalized units.' },
{
name: 'xOffset',
type: 'number',
default: '0',
description: 'Horizontal offset of the lightning in normalized units.'
},
{ name: 'speed', type: 'number', default: '1', description: 'Animation speed multiplier for the lightning.' },
{ name: 'intensity', type: 'number', default: '1', description: 'Brightness multiplier for the lightning.' },
{ name: 'size', type: 'number', default: '1', description: 'Scale factor for the bolt size.' }
]
];
</script>
<style scoped>

View File

@@ -3,10 +3,18 @@
<TabbedLayout>
<template #preview>
<div class="demo-container">
<Particles :key="rerenderKey" :particle-colors="[color]" :particle-count="particleCount"
:particle-spread="particleSpread" :speed="speed" :particle-base-size="baseSize"
:move-particles-on-hover="moveParticlesOnHover" :alpha-particles="alphaParticles"
:disable-rotation="disableRotation" class="w-full h-full" />
<Particles
:key="rerenderKey"
:particle-colors="[color]"
:particle-count="particleCount"
:particle-spread="particleSpread"
:speed="speed"
:particle-base-size="baseSize"
:move-particles-on-hover="moveParticlesOnHover"
:alpha-particles="alphaParticles"
:disable-rotation="disableRotation"
class="w-full h-full"
/>
</div>
<Customize>
@@ -14,29 +22,63 @@
<PreviewColor title="Color" :model-value="color" @update:model-value="updateColor" />
</div>
<PreviewSlider title="Count" :model-value="particleCount" @update:model-value="particleCount = $event"
:min="100" :max="1000" :step="100" />
<PreviewSlider
title="Count"
:model-value="particleCount"
@update:model-value="particleCount = $event"
:min="100"
:max="1000"
:step="100"
/>
<PreviewSlider title="Spread" :model-value="particleSpread" @update:model-value="particleSpread = $event"
:min="10" :max="100" :step="10" />
<PreviewSlider
title="Spread"
:model-value="particleSpread"
@update:model-value="particleSpread = $event"
:min="10"
:max="100"
:step="10"
/>
<PreviewSlider title="Speed" :model-value="speed" @update:model-value="speed = $event" :min="0" :max="2"
:step="0.1" />
<PreviewSlider
title="Speed"
:model-value="speed"
@update:model-value="speed = $event"
:min="0"
:max="2"
:step="0.1"
/>
<PreviewSlider title="Base Size" :model-value="baseSize" @update:model-value="baseSize = $event" :min="100"
:max="1000" :step="100" />
<PreviewSlider
title="Base Size"
:model-value="baseSize"
@update:model-value="baseSize = $event"
:min="100"
:max="1000"
:step="100"
/>
<PreviewSwitch title="Mouse Interaction" :model-value="moveParticlesOnHover"
@update:model-value="moveParticlesOnHover = $event" />
<PreviewSwitch
title="Mouse Interaction"
:model-value="moveParticlesOnHover"
@update:model-value="moveParticlesOnHover = $event"
/>
<PreviewSwitch title="Particle Transparency" :model-value="alphaParticles"
@update:model-value="alphaParticles = $event" />
<PreviewSwitch
title="Particle Transparency"
:model-value="alphaParticles"
@update:model-value="alphaParticles = $event"
/>
<PreviewSwitch title="Disable Rotation" :model-value="disableRotation"
@update:model-value="disableRotation = $event" />
<PreviewSwitch
title="Disable Rotation"
:model-value="disableRotation"
@update:model-value="disableRotation = $event"
/>
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['ogl']" />
</template>
@@ -52,49 +94,89 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import Particles from '@/content/Backgrounds/Particles/Particles.vue'
import PreviewSlider from '@/components/common/PreviewSlider.vue'
import PreviewSwitch from '@/components/common/PreviewSwitch.vue'
import PreviewColor from '@/components/common/PreviewColor.vue'
import { particles } from '@/constants/code/Backgrounds/particlesCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import Particles from '@/content/Backgrounds/Particles/Particles.vue';
import PreviewSlider from '@/components/common/PreviewSlider.vue';
import PreviewSwitch from '@/components/common/PreviewSwitch.vue';
import PreviewColor from '@/components/common/PreviewColor.vue';
import { particles } from '@/constants/code/Backgrounds/particlesCode';
import { useForceRerender } from '@/composables/useForceRerender';
const color = ref('#ffffff')
const particleCount = ref(200)
const particleSpread = ref(10)
const speed = ref(0.1)
const baseSize = ref(100)
const moveParticlesOnHover = ref(true)
const alphaParticles = ref(false)
const disableRotation = ref(false)
const color = ref('#ffffff');
const particleCount = ref(200);
const particleSpread = ref(10);
const speed = ref(0.1);
const baseSize = ref(100);
const moveParticlesOnHover = ref(true);
const alphaParticles = ref(false);
const disableRotation = ref(false);
const { rerenderKey, forceRerender } = useForceRerender()
const { rerenderKey, forceRerender } = useForceRerender();
const updateColor = (value: string) => {
color.value = value
forceRerender()
}
color.value = value;
forceRerender();
};
const propData = [
{ name: 'particleCount', type: 'number', default: '200', description: 'The number of particles to generate.' },
{ name: 'particleSpread', type: 'number', default: '10', description: 'Controls how far particles are spread from the center.' },
{
name: 'particleSpread',
type: 'number',
default: '10',
description: 'Controls how far particles are spread from the center.'
},
{ name: 'speed', type: 'number', default: '0.1', description: 'Speed factor controlling the animation pace.' },
{ name: 'particleColors', type: 'string[]', default: "['#ffffff']", description: 'An array of hex color strings used to color the particles.' },
{ name: 'moveParticlesOnHover', type: 'boolean', default: 'false', description: 'Determines if particles should move in response to mouse hover.' },
{ name: 'particleHoverFactor', type: 'number', default: '1', description: 'Multiplier for the particle movement when hovering.' },
{ name: 'alphaParticles', type: 'boolean', default: 'false', description: 'If true, particles are rendered with varying transparency; otherwise, as solid circles.' },
{
name: 'particleColors',
type: 'string[]',
default: "['#ffffff']",
description: 'An array of hex color strings used to color the particles.'
},
{
name: 'moveParticlesOnHover',
type: 'boolean',
default: 'false',
description: 'Determines if particles should move in response to mouse hover.'
},
{
name: 'particleHoverFactor',
type: 'number',
default: '1',
description: 'Multiplier for the particle movement when hovering.'
},
{
name: 'alphaParticles',
type: 'boolean',
default: 'false',
description: 'If true, particles are rendered with varying transparency; otherwise, as solid circles.'
},
{ name: 'particleBaseSize', type: 'number', default: '100', description: 'The base size of the particles.' },
{ name: 'sizeRandomness', type: 'number', default: '1', description: 'Controls the variation in particle sizes (0 means all particles have the same size).' },
{ name: 'cameraDistance', type: 'number', default: '20', description: 'Distance from the camera to the particle system.' },
{ name: 'disableRotation', type: 'boolean', default: 'false', description: 'If true, stops the particle system from rotating.' }
]
{
name: 'sizeRandomness',
type: 'number',
default: '1',
description: 'Controls the variation in particle sizes (0 means all particles have the same size).'
},
{
name: 'cameraDistance',
type: 'number',
default: '20',
description: 'Distance from the camera to the particle system.'
},
{
name: 'disableRotation',
type: 'boolean',
default: 'false',
description: 'If true, stops the particle system from rotating.'
}
];
</script>
<style scoped>

View File

@@ -0,0 +1,129 @@
<template>
<div class="shape-blur-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container">
<ShapeBlur
:variation="0"
:pixel-ratio-prop="pixelRatioProp"
:shape-size="shapeSize"
:roundness="roundness"
:border-size="borderSize"
:circle-size="circleSize"
:circle-edge="circleEdge"
class="shapeblur-demo"
/>
<div class="hover-text">Hover Me.</div>
</div>
<Customize>
<PreviewSlider title="Shape Size" v-model="shapeSize" :min="0.1" :max="2" :step="0.1" />
<PreviewSlider title="Roundness" v-model="roundness" :min="0" :max="1" :step="0.05" />
<PreviewSlider title="Border Size" v-model="borderSize" :min="0.01" :max="0.2" :step="0.005" />
<PreviewSlider title="Circle Size" v-model="circleSize" :min="0.1" :max="0.5" :step="0.01" />
<PreviewSlider title="Circle Edge" v-model="circleEdge" :min="0.1" :max="2" :step="0.1" />
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['three']" />
</template>
<template #code>
<CodeExample :code-object="shapeBlur" />
</template>
<template #cli>
<CliInstallation :command="shapeBlur.cli" />
</template>
</TabbedLayout>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import ShapeBlur from '../../content/Backgrounds/ShapeBlur/ShapeBlur.vue';
import { shapeBlur } from '@/constants/code/Backgrounds/shapeBlurCode';
const pixelRatioProp = ref(window.devicePixelRatio || 1);
const shapeSize = ref(1.0);
const roundness = ref(0.5);
const borderSize = ref(0.05);
const circleSize = ref(0.25);
const circleEdge = ref(1);
const propData = [
{
name: 'variation',
type: 'number',
default: '0',
description: 'Selects the shape variation (0-3) used by the shader.'
},
{
name: 'pixelRatioProp',
type: 'number',
default: '2',
description: 'Overrides the pixel ratio, typically set to the device pixel ratio.'
},
{
name: 'shapeSize',
type: 'number',
default: '1.2',
description: 'Controls the size of the shape.'
},
{
name: 'roundness',
type: 'number',
default: '0.4',
description: "Determines the roundness of the shape's corners."
},
{
name: 'borderSize',
type: 'number',
default: '0.05',
description: 'Sets the thickness of the border.'
},
{
name: 'circleSize',
type: 'number',
default: '0.3',
description: 'Determines the size of the hover circle effect.'
},
{
name: 'circleEdge',
type: 'number',
default: '0.5',
description: 'Controls the edge softness of the hover circle.'
}
];
</script>
<style scoped>
.hover-text {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-size: 6rem;
font-weight: 900;
z-index: 0;
color: #222;
pointer-events: none;
}
.demo-container {
overflow: hidden;
padding: 0;
}
</style>

View File

@@ -3,27 +3,58 @@
<TabbedLayout>
<template #preview>
<div class="demo-container">
<Silk :speed="speed" :scale="scale" :color="color" :noise-intensity="noiseIntensity" :rotation="rotation"
class="w-full h-full" />
<Silk
:speed="speed"
:scale="scale"
:color="color"
:noise-intensity="noiseIntensity"
:rotation="rotation"
class="w-full h-full"
/>
</div>
<Customize>
<PreviewSlider title="Speed" :model-value="speed" @update:model-value="speed = $event" :min="0" :max="10"
:step="0.1" />
<PreviewSlider
title="Speed"
:model-value="speed"
@update:model-value="speed = $event"
:min="0"
:max="10"
:step="0.1"
/>
<PreviewSlider title="Scale" :model-value="scale" @update:model-value="scale = $event" :min="0.1" :max="3"
:step="0.1" />
<PreviewSlider
title="Scale"
:model-value="scale"
@update:model-value="scale = $event"
:min="0.1"
:max="3"
:step="0.1"
/>
<PreviewSlider title="Noise Intensity" :model-value="noiseIntensity"
@update:model-value="noiseIntensity = $event" :min="0" :max="3" :step="0.1" />
<PreviewSlider
title="Noise Intensity"
:model-value="noiseIntensity"
@update:model-value="noiseIntensity = $event"
:min="0"
:max="3"
:step="0.1"
/>
<PreviewSlider title="Rotation" :model-value="rotation" @update:model-value="rotation = $event" :min="0"
:max="6.28" :step="0.1" />
<PreviewSlider
title="Rotation"
:model-value="rotation"
@update:model-value="rotation = $event"
:min="0"
:max="6.28"
:step="0.1"
/>
<PreviewColor title="Color" :model-value="color" @update:model-value="color = $event" />
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['ogl']" />
</template>
@@ -39,23 +70,23 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import Silk from '@/content/Backgrounds/Silk/Silk.vue'
import PreviewColor from '@/components/common/PreviewColor.vue'
import PreviewSlider from '@/components/common/PreviewSlider.vue'
import { silk } from '@/constants/code/Backgrounds/silkCode'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import Silk from '@/content/Backgrounds/Silk/Silk.vue';
import PreviewColor from '@/components/common/PreviewColor.vue';
import PreviewSlider from '@/components/common/PreviewSlider.vue';
import { silk } from '@/constants/code/Backgrounds/silkCode';
const speed = ref(5)
const scale = ref(1)
const color = ref('#7B7481')
const noiseIntensity = ref(1.5)
const rotation = ref(0)
const speed = ref(5);
const scale = ref(1);
const color = ref('#7B7481');
const noiseIntensity = ref(1.5);
const rotation = ref(0);
const propData = [
{ name: 'speed', type: 'number', default: '5', description: 'Animation speed multiplier' },
@@ -65,7 +96,7 @@ const propData = [
{ name: 'rotation', type: 'number', default: '0', description: 'Rotation angle in radians' },
{ name: 'className', type: 'string', default: '""', description: 'Additional CSS class names for styling.' },
{ name: 'style', type: 'CSSProperties', default: '{}', description: 'Inline styles for the component.' }
]
];
</script>
<style scoped>

View File

@@ -3,21 +3,31 @@
<template #preview>
<div class="relative min-h-[200px] demo-container overflow-hidden p-0">
<div class="w-full h-[500px] overflow-hidden">
<Squares :squareSize="size" :speed="speed" :direction="direction" :borderColor="borderColor"
:hoverFillColor="hoverColor" />
<Squares
:squareSize="size"
:speed="speed"
:direction="direction"
:borderColor="borderColor"
:hoverFillColor="hoverColor"
/>
</div>
</div>
<Customize>
<div class="flex items-center mb-6">
<span class="text-sm mr-2">Direction</span>
<div class="flex">
<button v-for="dir in directions" :key="dir.value" @click="direction = dir.value" :class="[
'px-3 py-2 text-xs h-8 text-white border-r border-[#333] cursor-pointer last:border-r-0',
direction === dir.value
? 'bg-[#222] hover:bg-[#222]'
: 'bg-[#111] hover:bg-[#111]'
]" class="first:rounded-l last:rounded-r">
<button
v-for="dir in directions"
:key="dir.value"
@click="direction = dir.value"
:class="[
'px-3 py-2 text-xs h-8 text-white border-r border-[#333] cursor-pointer last:border-r-0',
direction === dir.value ? 'bg-[#222] hover:bg-[#222]' : 'bg-[#111] hover:bg-[#111]'
]"
class="first:rounded-l last:rounded-r"
>
{{ dir.label }}
</button>
</div>
@@ -32,7 +42,6 @@
<PreviewColor v-model="hoverColor" title="Hover Color" />
</div>
</Customize>
<PropTable :data="propData" />
@@ -49,22 +58,22 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import PreviewColor from '../../components/common/PreviewColor.vue'
import PropTable from '../../components/common/PropTable.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import Squares from '../../content/Backgrounds/Squares/Squares.vue'
import { squares } from '../../constants/code/Backgrounds/squaresCode'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewColor from '../../components/common/PreviewColor.vue';
import PropTable from '../../components/common/PropTable.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import Squares from '../../content/Backgrounds/Squares/Squares.vue';
import { squares } from '../../constants/code/Backgrounds/squaresCode';
const direction = ref<'diagonal' | 'up' | 'right' | 'down' | 'left'>('diagonal')
const borderColor = ref('#333')
const hoverColor = ref('#27FF64')
const size = ref(40)
const speed = ref(0.5)
const direction = ref<'diagonal' | 'up' | 'right' | 'down' | 'left'>('diagonal');
const borderColor = ref('#333');
const hoverColor = ref('#27FF64');
const size = ref(40);
const speed = ref(0.5);
const directions = [
{ value: 'diagonal', label: 'Diagonal' },
@@ -72,40 +81,40 @@ const directions = [
{ value: 'right', label: 'Right' },
{ value: 'down', label: 'Down' },
{ value: 'left', label: 'Left' }
] as const
] as const;
const propData = [
{
name: "direction",
type: "string",
name: 'direction',
type: 'string',
default: "'right'",
description: "Direction of square animation. Options: 'diagonal', 'up', 'right', 'down', 'left'."
},
{
name: "speed",
type: "number",
default: "1",
description: "Animation speed multiplier."
name: 'speed',
type: 'number',
default: '1',
description: 'Animation speed multiplier.'
},
{
name: "borderColor",
type: "string",
name: 'borderColor',
type: 'string',
default: "'#999'",
description: "Color of the square borders."
description: 'Color of the square borders.'
},
{
name: "squareSize",
type: "number",
default: "40",
description: "Size of individual squares in pixels."
name: 'squareSize',
type: 'number',
default: '40',
description: 'Size of individual squares in pixels.'
},
{
name: "hoverFillColor",
type: "string",
name: 'hoverFillColor',
type: 'string',
default: "'#222'",
description: "Fill color when hovering over squares."
description: 'Fill color when hovering over squares.'
}
]
];
</script>
<style scoped>
@@ -113,4 +122,4 @@ const propData = [
overflow: hidden;
padding: 0;
}
</style>
</style>

View File

@@ -2,8 +2,12 @@
<TabbedLayout>
<template #preview>
<div class="relative demo-container h-[500px] overflow-hidden p-0">
<Threads :amplitude="amplitude" :distance="distance" :enableMouseInteraction="enableMouseInteraction"
:color="[1, 1, 1]" />
<Threads
:amplitude="amplitude"
:distance="distance"
:enableMouseInteraction="enableMouseInteraction"
:color="[1, 1, 1]"
/>
</div>
<Customize>
@@ -15,6 +19,7 @@
</Customize>
<PropTable :data="propData" />
<Dependencies :dependencyList="['ogl']" />
</template>
@@ -29,48 +34,48 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import Threads from '../../content/Backgrounds/Threads/Threads.vue'
import { threads } from '../../constants/code/Backgrounds/threadsCode'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import Threads from '../../content/Backgrounds/Threads/Threads.vue';
import { threads } from '../../constants/code/Backgrounds/threadsCode';
const amplitude = ref(1)
const distance = ref(0)
const enableMouseInteraction = ref(true)
const amplitude = ref(1);
const distance = ref(0);
const enableMouseInteraction = ref(true);
const propData = [
{
name: "color",
type: "[number, number, number]",
default: "[1, 1, 1]",
description: "Customizes the color of the lines (RGB)."
name: 'color',
type: '[number, number, number]',
default: '[1, 1, 1]',
description: 'Customizes the color of the lines (RGB).'
},
{
name: "amplitude",
type: "number",
default: "1",
description: "Adjusts the intensity of the wave effect on the lines."
name: 'amplitude',
type: 'number',
default: '1',
description: 'Adjusts the intensity of the wave effect on the lines.'
},
{
name: "distance",
type: "number",
default: "0",
description: "Controls the spacing between the lines. A value of 0 means no offset."
name: 'distance',
type: 'number',
default: '0',
description: 'Controls the spacing between the lines. A value of 0 means no offset.'
},
{
name: "enableMouseInteraction",
type: "boolean",
default: "false",
name: 'enableMouseInteraction',
type: 'boolean',
default: 'false',
description: "Enables smooth mouse hover effects that modulate the line's movement and amplitude."
}
]
];
</script>
<style scoped>
@@ -78,4 +83,4 @@ const propData = [
overflow: hidden;
padding: 0;
}
</style>
</style>

View File

@@ -7,8 +7,14 @@
</div>
<Customize>
<PreviewSlider title="Wave Speed X" :model-value="waveSpeedX" @update:model-value="waveSpeedX = $event"
:min="0" :max="0.1" :step="0.01" />
<PreviewSlider
title="Wave Speed X"
:model-value="waveSpeedX"
@update:model-value="waveSpeedX = $event"
:min="0"
:max="0.1"
:step="0.01"
/>
<div class="flex gap-4 items-center">
<PreviewColor title="Waves Color" :model-value="color" @update:model-value="color = $event" />
@@ -16,6 +22,7 @@
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="[]" />
</template>
@@ -31,36 +38,76 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import Waves from '@/content/Backgrounds/Waves/Waves.vue'
import PreviewSlider from '@/components/common/PreviewSlider.vue'
import PreviewColor from '@/components/common/PreviewColor.vue'
import { waves } from '@/constants/code/Backgrounds/wavesCode'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import Waves from '@/content/Backgrounds/Waves/Waves.vue';
import PreviewSlider from '@/components/common/PreviewSlider.vue';
import PreviewColor from '@/components/common/PreviewColor.vue';
import { waves } from '@/constants/code/Backgrounds/wavesCode';
const color = ref('#ffffff')
const waveSpeedX = ref(0.0125)
const color = ref('#ffffff');
const waveSpeedX = ref(0.0125);
const propData = [
{ name: 'lineColor', type: 'string', default: 'black', description: 'Defines the color of the wave lines drawn on the canvas.' },
{ name: 'backgroundColor', type: 'string', default: 'transparent', description: 'Sets the background color of the waves container.' },
{ name: 'waveSpeedX', type: 'number', default: '0.0125', description: 'Horizontal speed factor for the wave animation.' },
{ name: 'waveSpeedY', type: 'number', default: '0.005', description: 'Vertical speed factor for the wave animation.' },
{
name: 'lineColor',
type: 'string',
default: 'black',
description: 'Defines the color of the wave lines drawn on the canvas.'
},
{
name: 'backgroundColor',
type: 'string',
default: 'transparent',
description: 'Sets the background color of the waves container.'
},
{
name: 'waveSpeedX',
type: 'number',
default: '0.0125',
description: 'Horizontal speed factor for the wave animation.'
},
{
name: 'waveSpeedY',
type: 'number',
default: '0.005',
description: 'Vertical speed factor for the wave animation.'
},
{ name: 'waveAmpX', type: 'number', default: '32', description: 'Horizontal amplitude of each wave.' },
{ name: 'waveAmpY', type: 'number', default: '16', description: 'Vertical amplitude of each wave.' },
{ name: 'xGap', type: 'number', default: '10', description: 'Horizontal gap between individual wave lines.' },
{ name: 'yGap', type: 'number', default: '32', description: 'Vertical gap between points on each wave line.' },
{ name: 'friction', type: 'number', default: '0.925', description: 'Controls how quickly the cursor effect slows down.' },
{ name: 'tension', type: 'number', default: '0.005', description: 'Determines the "springiness" of the cursor effect on points.' },
{ name: 'maxCursorMove', type: 'number', default: '100', description: 'Limits how far each point can shift due to cursor movement.' },
{
name: 'friction',
type: 'number',
default: '0.925',
description: 'Controls how quickly the cursor effect slows down.'
},
{
name: 'tension',
type: 'number',
default: '0.005',
description: 'Determines the "springiness" of the cursor effect on points.'
},
{
name: 'maxCursorMove',
type: 'number',
default: '100',
description: 'Limits how far each point can shift due to cursor movement.'
},
{ name: 'style', type: 'object', default: '{}', description: 'Inline styles applied to the container element.' },
{ name: 'className', type: 'string', default: '""', description: 'Custom class name(s) applied to the container element.' }
]
{
name: 'className',
type: 'string',
default: '""',
description: 'Custom class name(s) applied to the container element.'
}
];
</script>
<style scoped>

View File

@@ -4,32 +4,46 @@
<template #preview>
<div class="demo-container h-[500px] overflow-hidden flex flex-col lg:flex-row relative">
<div
class="w-full lg:w-1/2 h-auto lg:h-full flex flex-col justify-center items-center lg:items-start text-center lg:text-left pt-8 lg:pt-0 pb-4 lg:pb-0 px-4 lg:px-4">
class="w-full lg:w-1/2 h-auto lg:h-full flex flex-col justify-center items-center lg:items-start text-center lg:text-left pt-8 lg:pt-0 pb-4 lg:pb-0 px-4 lg:px-4"
>
<h2 class="text-2xl md:text-3xl lg:text-4xl mb-4 font-medium leading-tight pl-0 lg:pl-24">
Card stacks have never
<span class="inline lg:block">looked so good</span>
</h2>
<p class="text-lg lg:text-xl mb-4 font-normal leading-tight text-gray-400 pl-0 lg:pl-24">
Just look at it go!
</p>
</div>
<div class="w-full lg:w-1/2 h-full lg:h-full relative">
<CardSwap :key="rerenderKey" :width="500" :height="400" :card-distance="cardDistance"
:vertical-distance="verticalDistance" :delay="delay" :skew-amount="skewAmount" :easing="easing"
:pause-on-hover="pauseOnHover" @card-click="handleCardClick">
<CardSwap
:key="rerenderKey"
:width="500"
:height="400"
:card-distance="cardDistance"
:vertical-distance="verticalDistance"
:delay="delay"
:skew-amount="skewAmount"
:easing="easing"
:pause-on-hover="pauseOnHover"
@card-click="handleCardClick"
>
<template #card-0>
<div class="border-b border-white bg-gradient-to-t from-[#222] to-[#0b0b0b]">
<div class="m-2 flex items-center">
<i class="pi pi-circle-fill mr-2"></i>
<span>Smooth</span>
</div>
</div>
<div class="relative p-2">
<video autoplay loop muted playsinline class="rounded-[15px] w-full h-full">
<source
src="https://cdn.dribbble.com/userupload/7053861/file/original-7956be57144058795db6bb24875bdab9.mp4"
type="video/mp4" />
type="video/mp4"
/>
Your browser does not support the video tag.
</video>
</div>
@@ -39,14 +53,17 @@
<div class="border-b border-white bg-gradient-to-t from-[#222] to-[#0b0b0b]">
<div class="m-2 flex items-center">
<i class="pi pi-code mr-2"></i>
<span>Reliable</span>
</div>
</div>
<div class="relative p-2">
<video autoplay loop muted playsinline class="rounded-[15px] w-full h-full">
<source
src="https://cdn.dribbble.com/userupload/7078020/file/original-b071e9063d9e3ba86a85a61b9d5a7c42.mp4"
type="video/mp4" />
type="video/mp4"
/>
Your browser does not support the video tag.
</video>
</div>
@@ -56,14 +73,17 @@
<div class="border-b border-white bg-gradient-to-t from-[#222] to-[#0b0b0b]">
<div class="m-2 flex items-center">
<i class="pi pi-sliders-h mr-2"></i>
<span>Customizable</span>
</div>
</div>
<div class="relative p-2">
<video autoplay loop muted playsinline class="rounded-[15px] w-full h-full">
<source
src="https://cdn.dribbble.com/userupload/7098541/file/original-0b063b12ca835421580e6034368ad95a.mp4"
type="video/mp4" />
type="video/mp4"
/>
Your browser does not support the video tag.
</video>
</div>
@@ -85,12 +105,15 @@
<button
class="text-xs bg-[#111] rounded-[10px] border border-[#333] hover:bg-[#222] text-white h-8 px-3 transition-colors"
@click="toggleEasing">
Easing: <span class="text-zinc-400">&nbsp;{{ easing }}</span>
@click="toggleEasing"
>
Easing:
<span class="text-zinc-400">&nbsp;{{ easing }}</span>
</button>
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['gsap']" />
</template>
@@ -106,91 +129,91 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import CardSwap from '../../content/Components/CardSwap/CardSwap.vue'
import { cardSwap } from '@/constants/code/Components/cardSwapCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import CardSwap from '../../content/Components/CardSwap/CardSwap.vue';
import { cardSwap } from '@/constants/code/Components/cardSwapCode';
import { useForceRerender } from '@/composables/useForceRerender';
const { rerenderKey, forceRerender } = useForceRerender()
const { rerenderKey, forceRerender } = useForceRerender();
const cardDistance = ref(60)
const verticalDistance = ref(70)
const delay = ref(5000)
const skewAmount = ref(6)
const easing = ref<'elastic' | 'linear'>('elastic')
const pauseOnHover = ref(false)
const cardDistance = ref(60);
const verticalDistance = ref(70);
const delay = ref(5000);
const skewAmount = ref(6);
const easing = ref<'elastic' | 'linear'>('elastic');
const pauseOnHover = ref(false);
const toggleEasing = () => {
easing.value = easing.value === 'elastic' ? 'linear' : 'elastic'
forceRerender()
}
easing.value = easing.value === 'elastic' ? 'linear' : 'elastic';
forceRerender();
};
const handleCardClick = (index: number) => {
console.log(`Card ${index} clicked`)
}
console.log(`Card ${index} clicked`);
};
const propData = [
{
name: "width",
type: "number | string",
default: "500",
description: "Width of the card container"
name: 'width',
type: 'number | string',
default: '500',
description: 'Width of the card container'
},
{
name: "height",
type: "number | string",
default: "400",
description: "Height of the card container"
name: 'height',
type: 'number | string',
default: '400',
description: 'Height of the card container'
},
{
name: "cardDistance",
type: "number",
default: "60",
description: "X-axis spacing between cards"
name: 'cardDistance',
type: 'number',
default: '60',
description: 'X-axis spacing between cards'
},
{
name: "verticalDistance",
type: "number",
default: "70",
description: "Y-axis spacing between cards"
name: 'verticalDistance',
type: 'number',
default: '70',
description: 'Y-axis spacing between cards'
},
{
name: "delay",
type: "number",
default: "5000",
description: "Milliseconds between card swaps"
name: 'delay',
type: 'number',
default: '5000',
description: 'Milliseconds between card swaps'
},
{
name: "pauseOnHover",
type: "boolean",
default: "false",
description: "Whether to pause animation on hover"
name: 'pauseOnHover',
type: 'boolean',
default: 'false',
description: 'Whether to pause animation on hover'
},
{
name: "onCardClick",
type: "(idx: number) => void",
default: "undefined",
description: "Callback function when a card is clicked"
name: 'onCardClick',
type: '(idx: number) => void',
default: 'undefined',
description: 'Callback function when a card is clicked'
},
{
name: "skewAmount",
type: "number",
default: "6",
description: "Degree of slope for top/bottom edges"
name: 'skewAmount',
type: 'number',
default: '6',
description: 'Degree of slope for top/bottom edges'
},
{
name: "easing",
name: 'easing',
type: "'linear' | 'elastic'",
default: "'elastic'",
description: "Animation easing type"
description: 'Animation easing type'
}
]
];
</script>

View File

@@ -3,13 +3,26 @@
<TabbedLayout>
<template #preview>
<div class="demo-container relative h-[500px] overflow-hidden flex items-center justify-center">
<Carousel :key="rerenderKey" :base-width="width" :autoplay="autoplay" :autoplay-delay="autoplayDelay"
:pause-on-hover="pauseOnHover" :loop="loop" :round="round" />
<Carousel
:key="rerenderKey"
:base-width="width"
:autoplay="autoplay"
:autoplay-delay="autoplayDelay"
:pause-on-hover="pauseOnHover"
:loop="loop"
:round="round"
/>
</div>
<Customize>
<PreviewSlider title="Width" v-model="width" :min="250" :max="330" :step="10"
@update:model-value="forceRerender" />
<PreviewSlider
title="Width"
v-model="width"
:min="250"
:max="330"
:step="10"
@update:model-value="forceRerender"
/>
<PreviewSwitch title="Round Variant" v-model="round" @update:model-value="forceRerender" />
@@ -17,14 +30,26 @@
<PreviewSwitch title="Autoplay" v-model="autoplay" @update:model-value="forceRerender" />
<PreviewSlider title="Delay" v-model="autoplayDelay" :min="1000" :max="4000" :step="1000"
:disabled="!autoplay" @update:model-value="forceRerender" />
<PreviewSlider
title="Delay"
v-model="autoplayDelay"
:min="1000"
:max="4000"
:step="1000"
:disabled="!autoplay"
@update:model-value="forceRerender"
/>
<PreviewSwitch title="Pause On Hover" v-model="pauseOnHover" :disabled="!autoplay"
@update:model-value="forceRerender" />
<PreviewSwitch
title="Pause On Hover"
v-model="pauseOnHover"
:disabled="!autoplay"
@update:model-value="forceRerender"
/>
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['motion-v']" />
</template>
@@ -40,77 +65,70 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import Carousel from '../../content/Components/Carousel/Carousel.vue'
import { carousel } from '@/constants/code/Components/carouselCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import Carousel from '../../content/Components/Carousel/Carousel.vue';
import { carousel } from '@/constants/code/Components/carouselCode';
import { useForceRerender } from '@/composables/useForceRerender';
const width = ref(300)
const autoplay = ref(false)
const autoplayDelay = ref(3000)
const pauseOnHover = ref(false)
const loop = ref(false)
const round = ref(false)
const width = ref(300);
const autoplay = ref(false);
const autoplayDelay = ref(3000);
const pauseOnHover = ref(false);
const loop = ref(false);
const round = ref(false);
const { rerenderKey, forceRerender } = useForceRerender()
const { rerenderKey, forceRerender } = useForceRerender();
const propData = [
{
name: "items",
type: "CarouselItem[]",
default: "DEFAULT_ITEMS",
description:
"An array of carousel items. Each item must include title, description, id, and icon."
name: 'items',
type: 'CarouselItem[]',
default: 'DEFAULT_ITEMS',
description: 'An array of carousel items. Each item must include title, description, id, and icon.'
},
{
name: "baseWidth",
type: "number",
default: "300",
description:
"Total width (in px) of the carousel container. Effective item width is baseWidth minus padding."
name: 'baseWidth',
type: 'number',
default: '300',
description: 'Total width (in px) of the carousel container. Effective item width is baseWidth minus padding.'
},
{
name: "autoplay",
type: "boolean",
default: "false",
description:
"Enables automatic scrolling to the next item at a fixed interval."
name: 'autoplay',
type: 'boolean',
default: 'false',
description: 'Enables automatic scrolling to the next item at a fixed interval.'
},
{
name: "autoplayDelay",
type: "number",
default: "3000",
description:
"Delay in milliseconds between automatic scrolls when autoplay is enabled."
name: 'autoplayDelay',
type: 'number',
default: '3000',
description: 'Delay in milliseconds between automatic scrolls when autoplay is enabled.'
},
{
name: "pauseOnHover",
type: "boolean",
default: "false",
description:
"Pauses the autoplay functionality when the carousel is hovered."
name: 'pauseOnHover',
type: 'boolean',
default: 'false',
description: 'Pauses the autoplay functionality when the carousel is hovered.'
},
{
name: "loop",
type: "boolean",
default: "false",
description:
"When true, the carousel loops seamlessly from the last item back to the first."
name: 'loop',
type: 'boolean',
default: 'false',
description: 'When true, the carousel loops seamlessly from the last item back to the first.'
},
{
name: "round",
type: "boolean",
default: "false",
description:
"When true, the carousel is rendered with a 1:1 aspect ratio and circular container/items."
name: 'round',
type: 'boolean',
default: 'false',
description: 'When true, the carousel is rendered with a 1:1 aspect ratio and circular container/items.'
}
]
];
</script>

View File

@@ -0,0 +1,155 @@
<template>
<div class="circular-gallery-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container h-[500px] p-0 overflow-hidden">
<CircularGallery
:key="rerenderKey"
:bend="bend"
:border-radius="borderRadius"
:scroll-speed="scrollSpeed"
:scroll-ease="scrollEase"
:text-color="textColor"
:font="font"
/>
</div>
<Customize>
<PreviewSlider
title="Bend Level"
v-model="bend"
:min="-10"
:max="10"
:step="1"
@update:model-value="forceRerender"
/>
<PreviewSlider
title="Border Radius"
v-model="borderRadius"
:min="0"
:max="0.5"
:step="0.01"
@update:model-value="forceRerender"
/>
<PreviewSlider
title="Scroll Speed"
v-model="scrollSpeed"
:min="0.5"
:max="5"
:step="0.1"
@update:model-value="forceRerender"
/>
<PreviewSlider
title="Scroll Ease"
v-model="scrollEase"
:min="0.01"
:max="0.15"
:step="0.01"
@update:model-value="forceRerender"
/>
<PreviewColor title="Text Color" v-model="textColor" @update:model-value="forceRerender" />
<PreviewSelect title="Font" v-model="font" :options="fontOptions" @update:model-value="forceRerender" />
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['ogl']" />
</template>
<template #code>
<CodeExample :code-object="circularGallery" />
</template>
<template #cli>
<CliInstallation :command="circularGallery.cli" />
</template>
</TabbedLayout>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewColor from '../../components/common/PreviewColor.vue';
import PreviewSelect from '../../components/common/PreviewSelect.vue';
import CircularGallery from '../../content/Components/CircularGallery/CircularGallery.vue';
import { circularGallery } from '@/constants/code/Components/circularGalleryCode';
import { useForceRerender } from '@/composables/useForceRerender';
const bend = ref(1);
const borderRadius = ref(0.05);
const scrollSpeed = ref(2);
const scrollEase = ref(0.05);
const textColor = ref('#ffffff');
const font = ref('bold 30px Figtree');
const { rerenderKey, forceRerender } = useForceRerender();
const fontOptions = [
{ label: 'Figtree Bold', value: 'bold 30px Figtree' },
{ label: 'Arial Bold', value: 'bold 30px Arial' },
{ label: 'Helvetica Bold', value: 'bold 30px Helvetica' },
{ label: 'Times Bold', value: 'bold 30px Times' },
{ label: 'Courier Bold', value: 'bold 30px Courier' },
{ label: 'Georgia Bold', value: 'bold 30px Georgia' }
];
const propData = [
{
name: 'items',
type: 'Array<{ image: string; text: string }>',
default: 'undefined',
description: 'List of items to display in the gallery. Each item should have an image URL and a text label.'
},
{
name: 'bend',
type: 'number',
default: '3',
description:
'Determines the curvature of the gallery layout. A negative value bends in one direction, a positive value in the opposite.'
},
{
name: 'textColor',
type: 'string',
default: '"#ffffff"',
description: 'Specifies the color of the text labels.'
},
{
name: 'borderRadius',
type: 'number',
default: '0.05',
description: 'Sets the border radius for the media items to achieve rounded corners.'
},
{
name: 'font',
type: 'string',
default: '"bold 30px Figtree"',
description: 'Font style for the text labels.'
},
{
name: 'scrollSpeed',
type: 'number',
default: '2',
description:
'Controls how much the gallery moves per scroll event. Lower values result in slower scrolling, higher values in faster scrolling.'
},
{
name: 'scrollEase',
type: 'number',
default: '0.05',
description:
'Controls the smoothness of scroll transitions. Lower values create smoother, more fluid motion, while higher values make it more responsive.'
}
];
</script>

View File

@@ -2,15 +2,18 @@
<div class="decay-card-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container" style="overflow: hidden;">
<div class="demo-container" style="overflow: hidden">
<DecayCard>
<div class="text-[2rem]">
Decay<br />Card
Decay
<br />
Card
</div>
</DecayCard>
</div>
<PropTable :data="propData" />
<Dependencies :dependency-list="['gsap']" />
</template>
@@ -26,13 +29,13 @@
</template>
<script setup lang="ts">
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import DecayCard from '../../content/Components/DecayCard/DecayCard.vue'
import { decayCard } from '@/constants/code/Components/decayCardCode'
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import DecayCard from '../../content/Components/DecayCard/DecayCard.vue';
import { decayCard } from '@/constants/code/Components/decayCardCode';
const propData = [
{
@@ -59,5 +62,5 @@ const propData = [
default: 'https://picsum.photos/300/400?grayscale',
description: 'Allows setting the background image of the card.'
}
]
];
</script>

View File

@@ -2,31 +2,73 @@
<div class="dock-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container" style="min-height: 400px; position: relative;">
<div class="demo-container" style="min-height: 400px; position: relative">
<div class="demo-content">
<Dock :key="rerenderKey" :items="items" :panel-height="panelHeight" :base-item-size="baseItemSize"
:magnification="magnification" :distance="200" :dock-height="256"
:spring="{ mass: 0.1, stiffness: 150, damping: 12 }" />
<Dock
:key="rerenderKey"
:items="items"
:panel-height="panelHeight"
:base-item-size="baseItemSize"
:magnification="magnification"
:distance="200"
:dock-height="256"
:spring="{ mass: 0.1, stiffness: 150, damping: 12 }"
/>
</div>
<div
class="absolute inset-0 flex items-center justify-center pointer-events-none text-[4rem] font-[900] text-[#222] select-none">
class="absolute inset-0 flex items-center justify-center pointer-events-none text-[4rem] font-[900] text-[#222] select-none"
>
Try It!
</div>
</div>
<Customize>
<PreviewSlider title="Background Height" :min="30" :max="200" :step="10" :model-value="panelHeight"
@update:model-value="(val: number) => { panelHeight = val; forceRerender(); }" />
<PreviewSlider
title="Background Height"
:min="30"
:max="200"
:step="10"
:model-value="panelHeight"
@update:model-value="
(val: number) => {
panelHeight = val;
forceRerender();
}
"
/>
<PreviewSlider title="Item Size" :min="20" :max="60" :step="10" :model-value="baseItemSize"
@update:model-value="(val: number) => { baseItemSize = val; forceRerender(); }" />
<PreviewSlider
title="Item Size"
:min="20"
:max="60"
:step="10"
:model-value="baseItemSize"
@update:model-value="
(val: number) => {
baseItemSize = val;
forceRerender();
}
"
/>
<PreviewSlider title="Magnification" :min="50" :max="100" :step="10" :model-value="magnification"
@update:model-value="(val: number) => { magnification = val; forceRerender(); }" />
<PreviewSlider
title="Magnification"
:min="50"
:max="100"
:step="10"
:model-value="magnification"
@update:model-value="
(val: number) => {
magnification = val;
forceRerender();
}
"
/>
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['motion-v']" />
</template>
@@ -42,96 +84,97 @@
</template>
<script setup lang="ts">
import { ref, h } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import Dock from '../../content/Components/Dock/Dock.vue'
import { dock } from '@/constants/code/Components/dockCode'
import { useToast } from 'primevue/usetoast'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref, h } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import Dock from '../../content/Components/Dock/Dock.vue';
import { dock } from '@/constants/code/Components/dockCode';
import { useToast } from 'primevue/usetoast';
import { useForceRerender } from '@/composables/useForceRerender';
const panelHeight = ref(68)
const baseItemSize = ref(50)
const magnification = ref(70)
const panelHeight = ref(68);
const baseItemSize = ref(50);
const magnification = ref(70);
const toast = useToast()
const { rerenderKey, forceRerender } = useForceRerender()
const toast = useToast();
const { rerenderKey, forceRerender } = useForceRerender();
const HomeIcon = () => h('i', { class: 'pi pi-home', style: { fontSize: '18px', color: 'white' } })
const ArchiveIcon = () => h('i', { class: 'pi pi-inbox', style: { fontSize: '18px', color: 'white' } })
const ProfileIcon = () => h('i', { class: 'pi pi-user', style: { fontSize: '18px', color: 'white' } })
const SettingsIcon = () => h('i', { class: 'pi pi-cog', style: { fontSize: '18px', color: 'white' } })
const HomeIcon = () => h('i', { class: 'pi pi-home', style: { fontSize: '18px', color: 'white' } });
const ArchiveIcon = () => h('i', { class: 'pi pi-inbox', style: { fontSize: '18px', color: 'white' } });
const ProfileIcon = () => h('i', { class: 'pi pi-user', style: { fontSize: '18px', color: 'white' } });
const SettingsIcon = () => h('i', { class: 'pi pi-cog', style: { fontSize: '18px', color: 'white' } });
const showAlert = (message: string) => {
toast.add({
severity: 'secondary',
summary: `${message} button was clicked`,
life: 3000
})
}
});
};
const items = [
{ icon: HomeIcon, label: 'Home', onClick: () => showAlert('Home') },
{ icon: ArchiveIcon, label: 'Archive', onClick: () => showAlert('Archive') },
{ icon: ProfileIcon, label: 'Profile', onClick: () => showAlert('Profile') },
{ icon: SettingsIcon, label: 'Settings', onClick: () => showAlert('Settings') },
]
{ icon: SettingsIcon, label: 'Settings', onClick: () => showAlert('Settings') }
];
const propData = [
{
name: "items",
type: "DockItemData[]",
default: "[]",
description: "Array of dock items. Each item should include an icon, label, onClick handler, and an optional className."
name: 'items',
type: 'DockItemData[]',
default: '[]',
description:
'Array of dock items. Each item should include an icon, label, onClick handler, and an optional className.'
},
{
name: "className",
type: "string",
name: 'className',
type: 'string',
default: '""',
description: "Additional CSS classes for the dock panel."
description: 'Additional CSS classes for the dock panel.'
},
{
name: "distance",
type: "number",
default: "200",
description: "Pixel distance used to calculate the magnification effect based on mouse proximity."
name: 'distance',
type: 'number',
default: '200',
description: 'Pixel distance used to calculate the magnification effect based on mouse proximity.'
},
{
name: "panelHeight",
type: "number",
default: "68",
description: "Height (in pixels) of the dock panel."
name: 'panelHeight',
type: 'number',
default: '68',
description: 'Height (in pixels) of the dock panel.'
},
{
name: "baseItemSize",
type: "number",
default: "50",
description: "The base size (in pixels) for each dock item."
name: 'baseItemSize',
type: 'number',
default: '50',
description: 'The base size (in pixels) for each dock item.'
},
{
name: "dockHeight",
type: "number",
default: "256",
description: "Maximum height (in pixels) of the dock container."
name: 'dockHeight',
type: 'number',
default: '256',
description: 'Maximum height (in pixels) of the dock container.'
},
{
name: "magnification",
type: "number",
default: "70",
description: "The magnified size (in pixels) applied to a dock item when hovered."
name: 'magnification',
type: 'number',
default: '70',
description: 'The magnified size (in pixels) applied to a dock item when hovered.'
},
{
name: "spring",
type: "SpringOptions",
default: "{ mass: 0.1, stiffness: 150, damping: 12 }",
description: "Configuration options for the spring animation."
name: 'spring',
type: 'SpringOptions',
default: '{ mass: 0.1, stiffness: 150, damping: 12 }',
description: 'Configuration options for the spring animation.'
}
]
];
</script>
<style scoped>
@@ -157,8 +200,8 @@ const propData = [
.demo-title {
font-size: 2rem;
font-weight: 900;
color: #271E37;
color: #271e37;
margin: 0;
text-align: center;
}
</style>
</style>

View File

@@ -10,6 +10,7 @@
<div class="demo-section">
<h2 class="demo-title-extra">Using Steps</h2>
<div class="demo-container relative min-h-[200px] flex items-center justify-center">
<ElasticSlider :is-stepped="true" :step-size="10" />
</div>
@@ -17,11 +18,13 @@
<div class="demo-section">
<h2 class="demo-title-extra">Custom Range & Icons</h2>
<div class="demo-container relative min-h-[200px] flex items-center justify-center">
<ElasticSlider :starting-value="500" :default-value="750" :max-value="1000">
<template #left-icon>
<i class="pi pi-thumbs-down text-xl"></i>
</template>
<template #right-icon>
<i class="pi pi-thumbs-up text-xl"></i>
</template>
@@ -44,12 +47,12 @@
</template>
<script setup lang="ts">
import TabbedLayout from '@/components/common/TabbedLayout.vue'
import PropTable from '@/components/common/PropTable.vue'
import CodeExample from '@/components/code/CodeExample.vue'
import CliInstallation from '@/components/code/CliInstallation.vue'
import ElasticSlider from '@/content/Components/ElasticSlider/ElasticSlider.vue'
import { elasticSlider } from '@/constants/code/Components/elasticSliderCode'
import TabbedLayout from '@/components/common/TabbedLayout.vue';
import PropTable from '@/components/common/PropTable.vue';
import CodeExample from '@/components/code/CodeExample.vue';
import CliInstallation from '@/components/code/CliInstallation.vue';
import ElasticSlider from '@/content/Components/ElasticSlider/ElasticSlider.vue';
import { elasticSlider } from '@/constants/code/Components/elasticSliderCode';
const propData = [
{
@@ -62,7 +65,7 @@ const propData = [
name: 'startingValue',
type: 'number',
default: '0',
description: 'The starting point for the slider\'s range, e.g., startingValue=100 allows the slider to start at 100.'
description: "The starting point for the slider's range, e.g., startingValue=100 allows the slider to start at 100."
},
{
name: 'maxValue',
@@ -91,16 +94,16 @@ const propData = [
{
name: 'leftIcon',
type: 'Component | string',
default: '\'-\'',
default: "'-'",
description: 'Custom Vue component or string to display on the left side of the slider.'
},
{
name: 'rightIcon',
type: 'Component | string',
default: '\'+\'',
default: "'+'",
description: 'Custom Vue component or string to display on the right side of the slider.'
}
]
];
</script>
<style scoped>
@@ -116,4 +119,4 @@ const propData = [
color: #fff;
margin-bottom: 0.5rem;
}
</style>
</style>

View File

@@ -2,11 +2,12 @@
<div class="flowing-menu-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container" style="height: 600px; overflow: hidden; padding: 100px 0;">
<div class="demo-container" style="height: 600px; overflow: hidden; padding: 100px 0">
<FlowingMenu :items="demoItems" />
</div>
<PropTable :data="propData" />
<Dependencies :dependency-list="['gsap']" />
</template>
@@ -22,13 +23,13 @@
</template>
<script setup lang="ts">
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import FlowingMenu from '../../content/Components/FlowingMenu/FlowingMenu.vue'
import { flowingMenu } from '@/constants/code/Components/flowingMenuCode'
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import FlowingMenu from '../../content/Components/FlowingMenu/FlowingMenu.vue';
import { flowingMenu } from '@/constants/code/Components/flowingMenuCode';
const propData = [
{
@@ -37,12 +38,12 @@ const propData = [
default: '[]',
description: 'An array of objects containing: link, text, image.'
}
]
];
const demoItems = [
{ link: '#', text: 'Mojave', image: 'https://picsum.photos/600/400?random=1' },
{ link: '#', text: 'Sonoma', image: 'https://picsum.photos/600/400?random=2' },
{ link: '#', text: 'Monterey', image: 'https://picsum.photos/600/400?random=3' },
{ link: '#', text: 'Sequoia', image: 'https://picsum.photos/600/400?random=4' }
]
];
</script>

View File

@@ -3,37 +3,83 @@
<TabbedLayout>
<template #preview>
<div class="demo-container relative h-[600px] overflow-hidden flex items-center justify-center">
<FlyingPosters :key="rerenderKey" :items="items" :plane-width="planeWidth" :plane-height="planeHeight"
:distortion="distortion" :scroll-ease="scrollEase" :camera-fov="cameraFov" :camera-z="cameraZ"
class="h-full w-full" />
<FlyingPosters
:key="rerenderKey"
:items="items"
:plane-width="planeWidth"
:plane-height="planeHeight"
:distortion="distortion"
:scroll-ease="scrollEase"
:camera-fov="cameraFov"
:camera-z="cameraZ"
class="h-full w-full"
/>
<div
class="absolute inset-0 flex items-center justify-center pointer-events-none text-[4rem] font-[900] text-[#222] select-none">
class="absolute inset-0 flex items-center justify-center pointer-events-none text-[4rem] font-[900] text-[#222] select-none"
>
Scroll.
</div>
</div>
<Customize>
<PreviewSlider title="Plane Width" v-model="planeWidth" :min="200" :max="400" :step="20"
@update:model-value="forceRerender" />
<PreviewSlider
title="Plane Width"
v-model="planeWidth"
:min="200"
:max="400"
:step="20"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Plane Height" v-model="planeHeight" :min="200" :max="400" :step="20"
@update:model-value="forceRerender" />
<PreviewSlider
title="Plane Height"
v-model="planeHeight"
:min="200"
:max="400"
:step="20"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Distortion" v-model="distortion" :min="0" :max="10" :step="0.5"
@update:model-value="forceRerender" />
<PreviewSlider
title="Distortion"
v-model="distortion"
:min="0"
:max="10"
:step="0.5"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Scroll Ease" v-model="scrollEase" :min="0.005" :max="0.05" :step="0.005"
@update:model-value="forceRerender" />
<PreviewSlider
title="Scroll Ease"
v-model="scrollEase"
:min="0.005"
:max="0.05"
:step="0.005"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Camera FOV" v-model="cameraFov" :min="30" :max="90" :step="5"
@update:model-value="forceRerender" />
<PreviewSlider
title="Camera FOV"
v-model="cameraFov"
:min="30"
:max="90"
:step="5"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Camera Z" v-model="cameraZ" :min="10" :max="40" :step="2"
@update:model-value="forceRerender" />
<PreviewSlider
title="Camera Z"
v-model="cameraZ"
:min="10"
:max="40"
:step="2"
@update:model-value="forceRerender"
/>
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['ogl']" />
</template>
@@ -49,26 +95,26 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import FlyingPosters from '../../content/Components/FlyingPosters/FlyingPosters.vue'
import { flyingPosters } from '@/constants/code/Components/flyingPostersCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import FlyingPosters from '../../content/Components/FlyingPosters/FlyingPosters.vue';
import { flyingPosters } from '@/constants/code/Components/flyingPostersCode';
import { useForceRerender } from '@/composables/useForceRerender';
const planeWidth = ref(320)
const planeHeight = ref(320)
const distortion = ref(3)
const scrollEase = ref(0.01)
const cameraFov = ref(45)
const cameraZ = ref(20)
const planeWidth = ref(320);
const planeHeight = ref(320);
const distortion = ref(3);
const scrollEase = ref(0.01);
const cameraFov = ref(45);
const cameraZ = ref(20);
const { rerenderKey, forceRerender } = useForceRerender()
const { rerenderKey, forceRerender } = useForceRerender();
const items = ref([
'https://picsum.photos/800/800?grayscale&random=1',
@@ -85,65 +131,63 @@ const items = ref([
'https://picsum.photos/800/800?grayscale&random=12',
'https://picsum.photos/800/800?grayscale&random=13',
'https://picsum.photos/800/800?grayscale&random=14',
'https://picsum.photos/800/800?grayscale&random=15',
])
'https://picsum.photos/800/800?grayscale&random=15'
]);
const propData = [
{
name: "items",
type: "string[]",
default: "[]",
name: 'items',
type: 'string[]',
default: '[]',
description:
"An array of image URLs to display in the 3D poster gallery. Each URL should point to a valid image resource."
'An array of image URLs to display in the 3D poster gallery. Each URL should point to a valid image resource.'
},
{
name: "planeWidth",
type: "number",
default: "320",
name: 'planeWidth',
type: 'number',
default: '320',
description:
"The width of each poster plane in pixels. This affects the visual size of the posters in the 3D space."
'The width of each poster plane in pixels. This affects the visual size of the posters in the 3D space.'
},
{
name: "planeHeight",
type: "number",
default: "320",
name: 'planeHeight',
type: 'number',
default: '320',
description:
"The height of each poster plane in pixels. This affects the visual size of the posters in the 3D space."
'The height of each poster plane in pixels. This affects the visual size of the posters in the 3D space.'
},
{
name: "distortion",
type: "number",
default: "3",
name: 'distortion',
type: 'number',
default: '3',
description:
"The amount of distortion effect applied to the posters during animation. Higher values create more dramatic effects."
'The amount of distortion effect applied to the posters during animation. Higher values create more dramatic effects.'
},
{
name: "scrollEase",
type: "number",
default: "0.01",
description:
"The easing factor for scroll animation. Lower values create smoother, more fluid scroll transitions."
name: 'scrollEase',
type: 'number',
default: '0.01',
description: 'The easing factor for scroll animation. Lower values create smoother, more fluid scroll transitions.'
},
{
name: "cameraFov",
type: "number",
default: "45",
name: 'cameraFov',
type: 'number',
default: '45',
description:
"The field of view for the 3D camera in degrees. A wider FOV shows more of the scene but with perspective distortion."
'The field of view for the 3D camera in degrees. A wider FOV shows more of the scene but with perspective distortion.'
},
{
name: "cameraZ",
type: "number",
default: "20",
name: 'cameraZ',
type: 'number',
default: '20',
description:
"The Z-axis position of the 3D camera. Higher values move the camera further back, showing more posters at once."
'The Z-axis position of the 3D camera. Higher values move the camera further back, showing more posters at once.'
},
{
name: "className",
type: "string",
name: 'className',
type: 'string',
default: "''",
description:
"Additional CSS classes to apply to the component container."
description: 'Additional CSS classes to apply to the component container.'
}
]
];
</script>

View File

@@ -2,7 +2,7 @@
<div class="glass-icons-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container" style="height: 500px; overflow: hidden;">
<div class="demo-container" style="height: 500px; overflow: hidden">
<GlassIcons :items="items" class="my-glass-icons" />
</div>
@@ -25,17 +25,17 @@
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import GlassIcons from '../../content/Components/GlassIcons/GlassIcons.vue'
import { glassIcons } from '@/constants/code/Components/glassIconsCode'
import { ref, computed } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import GlassIcons from '../../content/Components/GlassIcons/GlassIcons.vue';
import { glassIcons } from '@/constants/code/Components/glassIconsCode';
const colorful = ref(false)
const colorful = ref(false);
const items = computed(() => [
{ icon: 'pi pi-file', color: colorful.value ? 'blue' : '#444', label: 'Files' },
@@ -44,14 +44,15 @@ const items = computed(() => [
{ icon: 'pi pi-cloud', color: colorful.value ? 'indigo' : '#444', label: 'Weather' },
{ icon: 'pi pi-pencil', color: colorful.value ? 'orange' : '#444', label: 'Notes' },
{ icon: 'pi pi-chart-bar', color: colorful.value ? 'green' : '#444', label: 'Stats' }
])
]);
const propData = [
{
name: 'items',
type: 'GlassIconsItem[]',
default: '[]',
description: 'Array of items to render. Each item should include: an icon (string), a color (string), a label (string), and an optional customClass (string).'
description:
'Array of items to render. Each item should include: an icon (string), a color (string), a label (string), and an optional customClass (string).'
},
{
name: 'className',
@@ -59,5 +60,5 @@ const propData = [
default: "''",
description: 'Optional additional CSS class(es) to be added to the container.'
}
]
];
</script>

View File

@@ -2,7 +2,9 @@
<div class="gooey-nav-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container relative h-[500px] overflow-hidden bg-gradient-to-br from-purple-900 via-blue-900 to-indigo-900 flex items-center justify-center">
<div
class="demo-container relative h-[500px] overflow-hidden bg-gradient-to-br from-purple-900 via-blue-900 to-indigo-900 flex items-center justify-center"
>
<GooeyNav
:key="rerenderKey"
:items="navItems"
@@ -60,78 +62,78 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import GooeyNav from '../../content/Components/GooeyNav/GooeyNav.vue'
import { gooeyNav } from '@/constants/code/Components/gooeyNavCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import GooeyNav from '../../content/Components/GooeyNav/GooeyNav.vue';
import { gooeyNav } from '@/constants/code/Components/gooeyNavCode';
import { useForceRerender } from '@/composables/useForceRerender';
const particleCount = ref(15)
const timeVariance = ref(300)
const particleR = ref(100)
const { rerenderKey, forceRerender } = useForceRerender()
const particleCount = ref(15);
const timeVariance = ref(300);
const particleR = ref(100);
const { rerenderKey, forceRerender } = useForceRerender();
const navItems = [
{ label: "Home", href: null },
{ label: "About", href: null },
{ label: "Contact", href: null },
]
{ label: 'Home', href: null },
{ label: 'About', href: null },
{ label: 'Contact', href: null }
];
const propData = [
{
name: "items",
type: "GooeyNavItem[]",
default: "[]",
description: "Array of navigation items with label and href properties."
name: 'items',
type: 'GooeyNavItem[]',
default: '[]',
description: 'Array of navigation items with label and href properties.'
},
{
name: "animationTime",
type: "number",
default: "600",
description: "Duration (ms) of the main animation."
name: 'animationTime',
type: 'number',
default: '600',
description: 'Duration (ms) of the main animation.'
},
{
name: "particleCount",
type: "number",
default: "15",
description: "Number of bubble particles per transition."
name: 'particleCount',
type: 'number',
default: '15',
description: 'Number of bubble particles per transition.'
},
{
name: "particleDistances",
type: "[number, number]",
default: "[90, 10]",
description: "Outer and inner distances of bubble spread."
name: 'particleDistances',
type: '[number, number]',
default: '[90, 10]',
description: 'Outer and inner distances of bubble spread.'
},
{
name: "particleR",
type: "number",
default: "100",
description: "Radius factor influencing random particle rotation."
name: 'particleR',
type: 'number',
default: '100',
description: 'Radius factor influencing random particle rotation.'
},
{
name: "timeVariance",
type: "number",
default: "300",
description: "Random time variance (ms) for particle animations."
name: 'timeVariance',
type: 'number',
default: '300',
description: 'Random time variance (ms) for particle animations.'
},
{
name: "colors",
type: "number[]",
default: "[1, 2, 3, 1, 2, 3, 1, 4]",
description: "Color indices used when creating bubble particles."
name: 'colors',
type: 'number[]',
default: '[1, 2, 3, 1, 2, 3, 1, 4]',
description: 'Color indices used when creating bubble particles.'
},
{
name: "initialActiveIndex",
type: "number",
default: "0",
description: "Which item is selected on mount."
name: 'initialActiveIndex',
type: 'number',
default: '0',
description: 'Which item is selected on mount.'
}
]
];
</script>
<style>

View File

@@ -2,10 +2,19 @@
<div class="infinite-scroll-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container"
style="height: 500px; overflow: hidden; display: flex; justify-content: center; align-items: center;">
<InfiniteScroll :items="items" :is-tilted="isTilted" :tilt-direction="tiltDirection" :autoplay="autoplay"
:autoplay-speed="1" :autoplay-direction="autoplayDirection" :pause-on-hover="pauseOnHover" />
<div
class="demo-container"
style="height: 500px; overflow: hidden; display: flex; justify-content: center; align-items: center"
>
<InfiniteScroll
:items="items"
:is-tilted="isTilted"
:tilt-direction="tiltDirection"
:autoplay="autoplay"
:autoplay-speed="1"
:autoplay-direction="autoplayDirection"
:pause-on-hover="pauseOnHover"
/>
</div>
<Customize>
@@ -13,7 +22,7 @@
<PreviewSelect v-if="isTilted" title="Tilt Direction" :options="tiltOptions" v-model="tiltDirection" />
<hr style="margin: 1rem 0; border-color: #222;" />
<hr style="margin: 1rem 0; border-color: #222" />
<PreviewSwitch title="Autoplay" v-model="autoplay" />
@@ -25,6 +34,7 @@
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['gsap']" />
</template>
@@ -40,23 +50,23 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import PreviewSelect from '../../components/common/PreviewSelect.vue'
import InfiniteScroll from '../../content/Components/InfiniteScroll/InfiniteScroll.vue'
import { infiniteScroll } from '@/constants/code/Components/infiniteScrollCode'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import PreviewSelect from '../../components/common/PreviewSelect.vue';
import InfiniteScroll from '../../content/Components/InfiniteScroll/InfiniteScroll.vue';
import { infiniteScroll } from '@/constants/code/Components/infiniteScrollCode';
const isTilted = ref(true)
const tiltDirection = ref<'left' | 'right'>('left')
const autoplay = ref(true)
const autoplayDirection = ref<'up' | 'down'>('up')
const pauseOnHover = ref(true)
const isTilted = ref(true);
const tiltDirection = ref<'left' | 'right'>('left');
const autoplay = ref(true);
const autoplayDirection = ref<'up' | 'down'>('up');
const pauseOnHover = ref(true);
const items = [
{ content: 'Paragraph Item 2' },
@@ -72,17 +82,17 @@ const items = [
{ content: 'Paragraph Item 12' },
{ content: 'Text Item 13' },
{ content: 'Paragraph Item 14' }
]
];
const autoplayOptions = [
{ value: 'up', label: 'Up' },
{ value: 'down', label: 'Down' }
]
];
const tiltOptions = [
{ value: 'left', label: 'Left' },
{ value: 'right', label: 'Right' }
]
];
const propData = [
{
@@ -101,7 +111,8 @@ const propData = [
name: 'items',
type: 'array',
default: '[]',
description: 'Array of items with custom content. Each item should have a "content" property containing a string or Vue component.'
description:
'Array of items with custom content. Each item should have a "content" property containing a string or Vue component.'
},
{
name: 'itemMinHeight',
@@ -151,5 +162,5 @@ const propData = [
default: '"-0.5em"',
description: 'Negative margin to reduce spacing between items.'
}
]
];
</script>

View File

@@ -2,12 +2,22 @@
<div class="masonry-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container" style="height: 900px; overflow: hidden;">
<div class="demo-container" style="height: 900px; overflow: hidden">
<RefreshButton @refresh="forceRerender" />
<Masonry :key="rerenderKey" :items="sampleItems" :ease="ease" :duration="duration" :stagger="stagger"
:animate-from="animateFrom" :scale-on-hover="scaleOnHover" :hover-scale="hoverScale"
:blur-to-focus="blurToFocus" :color-shift-on-hover="colorShiftOnHover" class="masonry-demo-container" />
<Masonry
:key="rerenderKey"
:items="sampleItems"
:ease="ease"
:duration="duration"
:stagger="stagger"
:animate-from="animateFrom"
:scale-on-hover="scaleOnHover"
:hover-scale="hoverScale"
:blur-to-focus="blurToFocus"
:color-shift-on-hover="colorShiftOnHover"
class="masonry-demo-container"
/>
</div>
<Customize>
@@ -17,26 +27,50 @@
<PreviewSwitch title="Color Shift on Hover" v-model="colorShiftOnHover" @update:model-value="forceRerender" />
<PreviewSelect title="Animation Direction" v-model="animateFrom" :options="[
{ label: 'Bottom', value: 'bottom' },
{ label: 'Top', value: 'top' },
{ label: 'Left', value: 'left' },
{ label: 'Right', value: 'right' },
{ label: 'Center', value: 'center' },
{ label: 'Random', value: 'random' }
]" @update:model-value="forceRerender" />
<PreviewSelect
title="Animation Direction"
v-model="animateFrom"
:options="[
{ label: 'Bottom', value: 'bottom' },
{ label: 'Top', value: 'top' },
{ label: 'Left', value: 'left' },
{ label: 'Right', value: 'right' },
{ label: 'Center', value: 'center' },
{ label: 'Random', value: 'random' }
]"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Duration (s)" v-model="duration" :min="0.1" :max="2" :step="0.1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Duration (s)"
v-model="duration"
:min="0.1"
:max="2"
:step="0.1"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Stagger Delay (s)" v-model="stagger" :min="0.01" :max="0.2" :step="0.01"
@update:model-value="forceRerender" />
<PreviewSlider
title="Stagger Delay (s)"
v-model="stagger"
:min="0.01"
:max="0.2"
:step="0.01"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Hover Scale" v-model="hoverScale" :min="0.8" :max="1.2" :step="0.05"
@update:model-value="forceRerender" />
<PreviewSlider
title="Hover Scale"
v-model="hoverScale"
:min="0.8"
:max="1.2"
:step="0.05"
@update:model-value="forceRerender"
/>
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['gsap']" />
</template>
@@ -52,30 +86,30 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import RefreshButton from '../../components/common/RefreshButton.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import PreviewSelect from '../../components/common/PreviewSelect.vue'
import Masonry from '../../content/Components/Masonry/Masonry.vue'
import { masonry } from '@/constants/code/Components/masonryCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import RefreshButton from '../../components/common/RefreshButton.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSelect from '../../components/common/PreviewSelect.vue';
import Masonry from '../../content/Components/Masonry/Masonry.vue';
import { masonry } from '@/constants/code/Components/masonryCode';
import { useForceRerender } from '@/composables/useForceRerender';
const ease = ref('power3.out')
const duration = ref(0.6)
const stagger = ref(0.05)
const animateFrom = ref<'bottom' | 'top' | 'left' | 'right' | 'center' | 'random'>('bottom')
const scaleOnHover = ref(true)
const hoverScale = ref(0.95)
const blurToFocus = ref(true)
const colorShiftOnHover = ref(false)
const { rerenderKey, forceRerender } = useForceRerender()
const ease = ref('power3.out');
const duration = ref(0.6);
const stagger = ref(0.05);
const animateFrom = ref<'bottom' | 'top' | 'left' | 'right' | 'center' | 'random'>('bottom');
const scaleOnHover = ref(true);
const hoverScale = ref(0.95);
const blurToFocus = ref(true);
const colorShiftOnHover = ref(false);
const { rerenderKey, forceRerender } = useForceRerender();
const sampleItems = ref([
{ id: '1', img: 'https://picsum.photos/300/400?random=1&grayscale', url: 'https://picsum.photos', height: 400 },
@@ -92,20 +126,46 @@ const sampleItems = ref([
{ id: '12', img: 'https://picsum.photos/300/400?random=12&grayscale', url: 'https://picsum.photos', height: 400 },
{ id: '13', img: 'https://picsum.photos/300/470?random=13&grayscale', url: 'https://picsum.photos', height: 470 },
{ id: '14', img: 'https://picsum.photos/300/390?random=14&grayscale', url: 'https://picsum.photos', height: 390 },
{ id: '15', img: 'https://picsum.photos/300/510?random=15&grayscale', url: 'https://picsum.photos', height: 510 },
])
{ id: '15', img: 'https://picsum.photos/300/510?random=15&grayscale', url: 'https://picsum.photos', height: 510 }
]);
const propData = [
{ name: 'items', type: 'Item[]', default: '[]', description: 'Array of items to display in the masonry grid. Each item must have id, img, url, and height properties.' },
{
name: 'items',
type: 'Item[]',
default: '[]',
description:
'Array of items to display in the masonry grid. Each item must have id, img, url, and height properties.'
},
{ name: 'ease', type: 'string', default: '"power3.out"', description: 'GSAP easing function for animations.' },
{ name: 'duration', type: 'number', default: '0.6', description: 'Duration of the animation in seconds.' },
{ name: 'stagger', type: 'number', default: '0.05', description: 'Stagger delay between item animations in seconds.' },
{ name: 'animateFrom', type: 'string', default: '"bottom"', description: 'Direction items animate from: "bottom", "top", "left", "right", "center", or "random".' },
{
name: 'stagger',
type: 'number',
default: '0.05',
description: 'Stagger delay between item animations in seconds.'
},
{
name: 'animateFrom',
type: 'string',
default: '"bottom"',
description: 'Direction items animate from: "bottom", "top", "left", "right", "center", or "random".'
},
{ name: 'scaleOnHover', type: 'boolean', default: 'true', description: 'Whether items scale on hover.' },
{ name: 'hoverScale', type: 'number', default: '0.95', description: 'Scale factor when hovering over items.' },
{ name: 'blurToFocus', type: 'boolean', default: 'true', description: 'Whether items start blurred and focus on entrance.' },
{ name: 'colorShiftOnHover', type: 'boolean', default: 'false', description: 'Whether to show color overlay on hover.' },
]
{
name: 'blurToFocus',
type: 'boolean',
default: 'true',
description: 'Whether items start blurred and focus on entrance.'
},
{
name: 'colorShiftOnHover',
type: 'boolean',
default: 'false',
description: 'Whether to show color overlay on hover.'
}
];
</script>
<style scoped>

View File

@@ -3,19 +3,22 @@
<TabbedLayout>
<template #preview>
<div
class="demo-container relative min-h-[500px] max-h-[500px] overflow-hidden flex items-center justify-center">
class="demo-container relative min-h-[500px] max-h-[500px] overflow-hidden flex items-center justify-center"
>
<PixelCard :key="rerenderKey" :variant="selectedVariant">
<div class="absolute mix-blend-screen z-10 inset-0 flex items-center justify-center w-full h-full">
<h2 class="text-5xl font-black select-none text-[#222]">
Hover Me.
</h2>
<h2 class="text-5xl font-black select-none text-[#222]">Hover Me.</h2>
</div>
</PixelCard>
</div>
<Customize>
<PreviewSelect title="Animation Variant" :options="variantOptions" v-model="selectedVariant"
@update:model-value="forceRerender" />
<PreviewSelect
title="Animation Variant"
:options="variantOptions"
v-model="selectedVariant"
@update:model-value="forceRerender"
/>
</Customize>
<PropTable :data="propData" />
@@ -33,64 +36,64 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSelect from '../../components/common/PreviewSelect.vue'
import PixelCard from '../../content/Components/PixelCard/PixelCard.vue'
import { pixelCard } from '@/constants/code/Components/pixelCardCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSelect from '../../components/common/PreviewSelect.vue';
import PixelCard from '../../content/Components/PixelCard/PixelCard.vue';
import { pixelCard } from '@/constants/code/Components/pixelCardCode';
import { useForceRerender } from '@/composables/useForceRerender';
const selectedVariant = ref<'default' | 'blue' | 'yellow' | 'pink'>('default')
const { rerenderKey, forceRerender } = useForceRerender()
const selectedVariant = ref<'default' | 'blue' | 'yellow' | 'pink'>('default');
const { rerenderKey, forceRerender } = useForceRerender();
const variantOptions = [
{ value: 'default', label: 'Default' },
{ value: 'yellow', label: 'Yellow' },
{ value: 'blue', label: 'Blue' },
{ value: 'pink', label: 'Pink' }
]
];
const propData = [
{
name: "variant",
type: "string",
name: 'variant',
type: 'string',
default: '"default"',
description: "Defines the color scheme and animation style.",
options: "default | yellow | blue | pink"
description: 'Defines the color scheme and animation style.',
options: 'default | yellow | blue | pink'
},
{
name: "gap",
type: "number",
default: "varies by variant",
description: "Pixel grid gap size in pixels."
name: 'gap',
type: 'number',
default: 'varies by variant',
description: 'Pixel grid gap size in pixels.'
},
{
name: "speed",
type: "number",
default: "varies by variant",
description: "Animation speed modifier (lower is slower)."
name: 'speed',
type: 'number',
default: 'varies by variant',
description: 'Animation speed modifier (lower is slower).'
},
{
name: "colors",
type: "string",
name: 'colors',
type: 'string',
default: '"#f8fafc,#f1f5f9,#cbd5e1"',
description: "Comma-separated list of colors for the pixel effect."
description: 'Comma-separated list of colors for the pixel effect.'
},
{
name: "noFocus",
type: "boolean",
default: "false",
description: "If true, prevents animation from triggering on focus."
name: 'noFocus',
type: 'boolean',
default: 'false',
description: 'If true, prevents animation from triggering on focus.'
},
{
name: "className",
type: "string",
name: 'className',
type: 'string',
default: '""',
description: "Additional CSS class for the wrapper."
description: 'Additional CSS class for the wrapper.'
}
]
];
</script>

View File

@@ -2,22 +2,32 @@
<div class="profile-card-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container" style="height: 700px; overflow: hidden; position: relative;">
<ProfileCard :key="rerenderKey" name="Javi A. Torres" title="Software Engineer" handle="javicodes"
status="Online" contact-text="Contact Me" avatar-url="/assets/person.png"
:icon-url="showIcon ? '/assets/iconpattern.png' : ''" :show-user-info="showUserInfo"
:show-behind-gradient="showBehindGradient" grain-url="/assets/grain.webp"
:behind-gradient="customBehindGradient" :inner-gradient="customInnerGradient"
@contact-click="handleContactClick" />
<div class="demo-container" style="height: 700px; overflow: hidden; position: relative">
<ProfileCard
:key="rerenderKey"
name="Javi A. Torres"
title="Software Engineer"
handle="javicodes"
status="Online"
contact-text="Contact Me"
avatar-url="/assets/person.png"
:icon-url="showIcon ? '/assets/iconpattern.png' : ''"
:show-user-info="showUserInfo"
:show-behind-gradient="showBehindGradient"
grain-url="/assets/grain.webp"
:behind-gradient="customBehindGradient"
:inner-gradient="customInnerGradient"
@contact-click="handleContactClick"
/>
</div>
<Customize>
<button @click="generateRandomGradients" class="randomize-btn">
Randomize Colors
</button>
<button @click="generateRandomGradients" class="randomize-btn">Randomize Colors</button>
<PreviewSwitch title="Show Icon Pattern" v-model="showIcon" @update:model-value="forceRerender" />
<PreviewSwitch title="Show User Info" v-model="showUserInfo" @update:model-value="forceRerender" />
<PreviewSwitch title="Show BG Gradient" v-model="showBehindGradient" @update:model-value="forceRerender" />
</Customize>
@@ -36,40 +46,42 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import ProfileCard from '../../content/Components/ProfileCard/ProfileCard.vue'
import { profileCard } from '@/constants/code/Components/profileCardCode'
import { useToast } from 'primevue/usetoast'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import ProfileCard from '../../content/Components/ProfileCard/ProfileCard.vue';
import { profileCard } from '@/constants/code/Components/profileCardCode';
import { useToast } from 'primevue/usetoast';
import { useForceRerender } from '@/composables/useForceRerender';
const showIcon = ref(true)
const showUserInfo = ref(true)
const showBehindGradient = ref(true)
const customBehindGradient = ref("radial-gradient(farthest-side circle at var(--pointer-x) var(--pointer-y),hsla(266,100%,90%,var(--card-opacity)) 4%,hsla(266,50%,80%,calc(var(--card-opacity)*0.75)) 10%,hsla(266,25%,70%,calc(var(--card-opacity)*0.5)) 50%,hsla(266,0%,60%,0) 100%),radial-gradient(35% 52% at 55% 20%,#00ffaac4 0%,#073aff00 100%),radial-gradient(100% 100% at 50% 50%,#00c1ffff 1%,#073aff00 76%),conic-gradient(from 124deg at 50% 50%,#c137ffff 0%,#07c6ffff 40%,#07c6ffff 60%,#c137ffff 100%)")
const customInnerGradient = ref("linear-gradient(145deg,#60496e8c 0%,#71C4FF44 100%)")
const showIcon = ref(true);
const showUserInfo = ref(true);
const showBehindGradient = ref(true);
const customBehindGradient = ref(
'radial-gradient(farthest-side circle at var(--pointer-x) var(--pointer-y),hsla(266,100%,90%,var(--card-opacity)) 4%,hsla(266,50%,80%,calc(var(--card-opacity)*0.75)) 10%,hsla(266,25%,70%,calc(var(--card-opacity)*0.5)) 50%,hsla(266,0%,60%,0) 100%),radial-gradient(35% 52% at 55% 20%,#00ffaac4 0%,#073aff00 100%),radial-gradient(100% 100% at 50% 50%,#00c1ffff 1%,#073aff00 76%),conic-gradient(from 124deg at 50% 50%,#c137ffff 0%,#07c6ffff 40%,#07c6ffff 60%,#c137ffff 100%)'
);
const customInnerGradient = ref('linear-gradient(145deg,#60496e8c 0%,#71C4FF44 100%)');
const toast = useToast()
const { rerenderKey, forceRerender } = useForceRerender()
const toast = useToast();
const { rerenderKey, forceRerender } = useForceRerender();
const generateRandomGradients = () => {
const randomHue1 = Math.floor(Math.random() * 360)
const randomHue2 = Math.floor(Math.random() * 360)
const randomHue3 = Math.floor(Math.random() * 360)
const randomHue4 = Math.floor(Math.random() * 360)
const randomHue1 = Math.floor(Math.random() * 360);
const randomHue2 = Math.floor(Math.random() * 360);
const randomHue3 = Math.floor(Math.random() * 360);
const randomHue4 = Math.floor(Math.random() * 360);
const newBehindGradient = `radial-gradient(farthest-side circle at var(--pointer-x) var(--pointer-y),hsla(${randomHue1},100%,90%,var(--card-opacity)) 4%,hsla(${randomHue1},50%,80%,calc(var(--card-opacity)*0.75)) 10%,hsla(${randomHue1},25%,70%,calc(var(--card-opacity)*0.5)) 50%,hsla(${randomHue1},0%,60%,0) 100%),radial-gradient(35% 52% at 55% 20%,hsl(${randomHue2}, 100%, 70%) 0%,transparent 100%),radial-gradient(100% 100% at 50% 50%,hsl(${randomHue3}, 100%, 65%) 1%,transparent 76%),conic-gradient(from 124deg at 50% 50%,hsl(${randomHue4}, 100%, 70%) 0%,hsl(${randomHue2}, 100%, 70%) 40%,hsl(${randomHue2}, 100%, 70%) 60%,hsl(${randomHue4}, 100%, 70%) 100%)`
const newInnerGradient = `linear-gradient(145deg,hsla(${randomHue1}, 40%, 45%, 0.55) 0%,hsla(${randomHue3}, 60%, 70%, 0.27) 100%)`
const newBehindGradient = `radial-gradient(farthest-side circle at var(--pointer-x) var(--pointer-y),hsla(${randomHue1},100%,90%,var(--card-opacity)) 4%,hsla(${randomHue1},50%,80%,calc(var(--card-opacity)*0.75)) 10%,hsla(${randomHue1},25%,70%,calc(var(--card-opacity)*0.5)) 50%,hsla(${randomHue1},0%,60%,0) 100%),radial-gradient(35% 52% at 55% 20%,hsl(${randomHue2}, 100%, 70%) 0%,transparent 100%),radial-gradient(100% 100% at 50% 50%,hsl(${randomHue3}, 100%, 65%) 1%,transparent 76%),conic-gradient(from 124deg at 50% 50%,hsl(${randomHue4}, 100%, 70%) 0%,hsl(${randomHue2}, 100%, 70%) 40%,hsl(${randomHue2}, 100%, 70%) 60%,hsl(${randomHue4}, 100%, 70%) 100%)`;
const newInnerGradient = `linear-gradient(145deg,hsla(${randomHue1}, 40%, 45%, 0.55) 0%,hsla(${randomHue3}, 60%, 70%, 0.27) 100%)`;
customBehindGradient.value = newBehindGradient
customInnerGradient.value = newInnerGradient
forceRerender()
}
customBehindGradient.value = newBehindGradient;
customInnerGradient.value = newInnerGradient;
forceRerender();
};
const handleContactClick = () => {
toast.add({
@@ -77,8 +89,8 @@ const handleContactClick = () => {
summary: 'Contact Clicked!',
detail: 'Contact button was clicked',
life: 3000
})
}
});
};
const propData = [
{
@@ -139,25 +151,25 @@ const propData = [
name: 'name',
type: 'string',
default: '"Javi A. Torres"',
description: 'User\'s display name'
description: "User's display name"
},
{
name: 'title',
type: 'string',
default: '"Software Engineer"',
description: 'User\'s job title or role'
description: "User's job title or role"
},
{
name: 'handle',
type: 'string',
default: '"javicodes"',
description: 'User\'s handle or username (displayed with @ prefix)'
description: "User's handle or username (displayed with @ prefix)"
},
{
name: 'status',
type: 'string',
default: '"Online"',
description: 'User\'s current status'
description: "User's current status"
},
{
name: 'contactText',
@@ -177,7 +189,7 @@ const propData = [
default: 'undefined',
description: 'Callback function called when the contact button is clicked'
}
]
];
</script>
<style scoped>
@@ -204,4 +216,4 @@ const propData = [
width: 100%;
height: 100%;
}
</style>
</style>

View File

@@ -6,9 +6,9 @@
<SpotlightCard class-name="custom-spotlight-card">
<div class="flex h-full flex-col items-start justify-center">
<i class="pi pi-star-fill text-4xl mb-3 text-white"></i>
<h3 class="text-2xl font-semibold tracking-tight mb-1 text-white">
Boost Your Experience
</h3>
<h3 class="text-2xl font-semibold tracking-tight mb-1 text-white">Boost Your Experience</h3>
<p class="text-sm text-zinc-400">
Get exclusive benefits, features & 24/7 support as a permanent club member.
</p>
@@ -17,13 +17,14 @@
</div>
<h2 class="text-xl font-semibold text-white mb-4 mt-8">Custom Color</h2>
<div class="demo-container relative py-10">
<SpotlightCard class-name="custom-spotlight-card" spotlight-color="rgba(39, 255, 100, 0.326)">
<div class="flex h-full flex-col items-start justify-center">
<i class="pi pi-lock text-3xl mb-3 text-white"></i>
<h3 class="text-2xl font-semibold tracking-tight mb-1 text-white">
Enhanced Security
</h3>
<h3 class="text-2xl font-semibold tracking-tight mb-1 text-white">Enhanced Security</h3>
<p class="text-sm text-zinc-400">
Our state of the art software offers peace of mind through strict security measures.
</p>
@@ -46,27 +47,27 @@
</template>
<script setup lang="ts">
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import SpotlightCard from '../../content/Components/SpotlightCard/SpotlightCard.vue'
import { spotlightCard } from '@/constants/code/Components/spotlightCardCode'
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import SpotlightCard from '../../content/Components/SpotlightCard/SpotlightCard.vue';
import { spotlightCard } from '@/constants/code/Components/spotlightCardCode';
const propData = [
{
name: 'spotlightColor',
type: 'string',
default: 'rgba(255, 255, 255, 0.25)',
description: 'Controls the color of the radial gradient used for the spotlight effect.',
description: 'Controls the color of the radial gradient used for the spotlight effect.'
},
{
name: 'className',
type: 'string',
default: '',
description: 'Allows adding custom classes to the component.',
description: 'Allows adding custom classes to the component.'
}
]
];
</script>
<style>

View File

@@ -2,7 +2,7 @@
<div class="tilted-card-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container" style="min-height: 500px; position: relative; overflow: hidden;">
<div class="demo-container" style="min-height: 500px; position: relative; overflow: hidden">
<TiltedCard
image-src="https://i.scdn.co/image/ab67616d0000b273d9985092cd88bffd97653b58"
alt-text="Kendrick Lamar - GNX Album Cover"
@@ -19,42 +19,23 @@
:overlay-content="displayOverlayContent"
>
<template #overlay>
<p class="tilted-card-demo-text">
Kendrick Lamar - GNX
</p>
<p class="tilted-card-demo-text">Kendrick Lamar - GNX</p>
</template>
</TiltedCard>
</div>
<Customize>
<PreviewSlider
title="Rotate Amplitude"
v-model="rotateAmplitude"
:min="0"
:max="30"
:step="1"
/>
<PreviewSlider title="Rotate Amplitude" v-model="rotateAmplitude" :min="0" :max="30" :step="1" />
<PreviewSlider
title="Scale on Hover"
v-model="scaleOnHover"
:min="1"
:max="1.5"
:step="0.05"
/>
<PreviewSlider title="Scale on Hover" v-model="scaleOnHover" :min="1" :max="1.5" :step="0.05" />
<PreviewSwitch
title="Show Tooltip"
v-model="showTooltip"
/>
<PreviewSwitch title="Show Tooltip" v-model="showTooltip" />
<PreviewSwitch
title="Show Overlay Content"
v-model="displayOverlayContent"
/>
<PreviewSwitch title="Show Overlay Content" v-model="displayOverlayContent" />
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['motion-v']" />
</template>
@@ -70,22 +51,22 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import TiltedCard from '../../content/Components/TiltedCard/TiltedCard.vue'
import { tiltedCard } from '@/constants/code/Components/tiltedCardCode'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import TiltedCard from '../../content/Components/TiltedCard/TiltedCard.vue';
import { tiltedCard } from '@/constants/code/Components/tiltedCardCode';
const rotateAmplitude = ref(12)
const scaleOnHover = ref(1.05)
const showTooltip = ref(true)
const displayOverlayContent = ref(true)
const rotateAmplitude = ref(12);
const scaleOnHover = ref(1.05);
const showTooltip = ref(true);
const displayOverlayContent = ref(true);
const propData = [
{
@@ -166,7 +147,7 @@ const propData = [
default: 'false',
description: 'Whether to show overlay content (use overlay slot for content).'
}
]
];
</script>
<style scoped>
@@ -180,4 +161,4 @@ const propData = [
border-radius: 8px;
backdrop-filter: blur(10px);
}
</style>
</style>

View File

@@ -5,10 +5,22 @@
<div class="demo-container relative min-h-[400px] overflow-hidden">
<RefreshButton @refresh="forceRerender" />
<BlurText :key="rerenderKey" text="Isn't this so cool?!" :delay="delay"
class-name="text-3xl md:text-6xl font-bold text-center" :animate-by="animateBy" :direction="direction"
:threshold="threshold" :root-margin="rootMargin" :step-duration="stepDuration"
@animation-complete="() => { showCallback && showToast() }" />
<BlurText
:key="rerenderKey"
text="Isn't this so cool?!"
:delay="delay"
class-name="text-3xl md:text-6xl font-bold text-center"
:animate-by="animateBy"
:direction="direction"
:threshold="threshold"
:root-margin="rootMargin"
:step-duration="stepDuration"
@animation-complete="
() => {
showCallback && showToast();
}
"
/>
</div>
<Customize>
@@ -17,27 +29,51 @@
<div class="flex gap-4 flex-wrap">
<button
class="text-xs bg-[#0b0b0b] rounded-[10px] border border-[#1e3721] hover:bg-[#1e3721] text-white h-8 px-3 transition-colors"
@click="toggleAnimateBy">
Animate By: <span class="text-[#a1a1aa]">&nbsp;{{ animateBy }}</span>
@click="toggleAnimateBy"
>
Animate By:
<span class="text-[#a1a1aa]">&nbsp;{{ animateBy }}</span>
</button>
<button
class="text-xs bg-[#0b0b0b] rounded-[10px] border border-[#1e3721] hover:bg-[#1e3721] text-white h-8 px-3 transition-colors"
@click="toggleDirection">
Direction: <span class="text-[#a1a1aa]">&nbsp;{{ direction }}</span>
@click="toggleDirection"
>
Direction:
<span class="text-[#a1a1aa]">&nbsp;{{ direction }}</span>
</button>
</div>
<PreviewSlider title="Delay (ms)" v-model="delay" :min="50" :max="500" :step="10"
@update:model-value="forceRerender" />
<PreviewSlider
title="Delay (ms)"
v-model="delay"
:min="50"
:max="500"
:step="10"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Step Duration (s)" v-model="stepDuration" :min="0.1" :max="1" :step="0.05"
@update:model-value="forceRerender" />
<PreviewSlider
title="Step Duration (s)"
v-model="stepDuration"
:min="0.1"
:max="1"
:step="0.05"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Threshold" v-model="threshold" :min="0.1" :max="1" :step="0.1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Threshold"
v-model="threshold"
:min="0.1"
:max="1"
:step="0.1"
@update:model-value="forceRerender"
/>
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['motion-v']" />
</template>
@@ -53,61 +89,96 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import RefreshButton from '../../components/common/RefreshButton.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import BlurText from '../../content/TextAnimations/BlurText/BlurText.vue'
import { blurText } from '@/constants/code/TextAnimations/blurTextCode'
import { useToast } from 'primevue/usetoast'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import RefreshButton from '../../components/common/RefreshButton.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import BlurText from '../../content/TextAnimations/BlurText/BlurText.vue';
import { blurText } from '@/constants/code/TextAnimations/blurTextCode';
import { useToast } from 'primevue/usetoast';
import { useForceRerender } from '@/composables/useForceRerender';
const animateBy = ref<'words' | 'letters'>('words')
const direction = ref<'top' | 'bottom'>('top')
const delay = ref(200)
const stepDuration = ref(0.35)
const threshold = ref(0.1)
const rootMargin = ref('0px')
const showCallback = ref(true)
const toast = useToast()
const { rerenderKey, forceRerender } = useForceRerender()
const animateBy = ref<'words' | 'letters'>('words');
const direction = ref<'top' | 'bottom'>('top');
const delay = ref(200);
const stepDuration = ref(0.35);
const threshold = ref(0.1);
const rootMargin = ref('0px');
const showCallback = ref(true);
const toast = useToast();
const { rerenderKey, forceRerender } = useForceRerender();
const toggleAnimateBy = () => {
animateBy.value = animateBy.value === 'words' ? 'letters' : 'words'
forceRerender()
}
animateBy.value = animateBy.value === 'words' ? 'letters' : 'words';
forceRerender();
};
const toggleDirection = () => {
direction.value = direction.value === 'top' ? 'bottom' : 'top'
forceRerender()
}
direction.value = direction.value === 'top' ? 'bottom' : 'top';
forceRerender();
};
const showToast = () => {
toast.add({
severity: 'secondary',
summary: 'Animation Finished!',
life: 3000
})
}
});
};
const propData = [
{ name: 'text', type: 'string', default: '""', description: 'The text content to animate.' },
{ name: 'animateBy', type: 'string', default: '"words"', description: 'Determines whether to animate by "words" or "letters".' },
{ name: 'direction', type: 'string', default: '"top"', description: 'Direction from which the words/letters appear ("top" or "bottom").' },
{ name: 'delay', type: 'number', default: '200', description: 'Delay between animations for each word/letter (in ms).' },
{ name: 'stepDuration', type: 'number', default: '0.35', description: 'The time taken for each letter/word to animate (in seconds).' },
{ name: 'threshold', type: 'number', default: '0.1', description: 'Intersection threshold for triggering the animation.' },
{
name: 'animateBy',
type: 'string',
default: '"words"',
description: 'Determines whether to animate by "words" or "letters".'
},
{
name: 'direction',
type: 'string',
default: '"top"',
description: 'Direction from which the words/letters appear ("top" or "bottom").'
},
{
name: 'delay',
type: 'number',
default: '200',
description: 'Delay between animations for each word/letter (in ms).'
},
{
name: 'stepDuration',
type: 'number',
default: '0.35',
description: 'The time taken for each letter/word to animate (in seconds).'
},
{
name: 'threshold',
type: 'number',
default: '0.1',
description: 'Intersection threshold for triggering the animation.'
},
{ name: 'rootMargin', type: 'string', default: '"0px"', description: 'Root margin for the intersection observer.' },
{ name: 'className', type: 'string', default: '""', description: 'Additional class names to style the component.' },
{ name: 'animationFrom', type: 'object', default: 'undefined', description: 'Custom initial animation properties.' },
{ name: 'animationTo', type: 'array', default: 'undefined', description: 'Custom target animation properties array.' },
{
name: 'animationTo',
type: 'array',
default: 'undefined',
description: 'Custom target animation properties array.'
},
{ name: 'easing', type: 'function', default: '(t) => t', description: 'Custom easing function for the animation.' },
{ name: 'onAnimationComplete', type: 'function', default: 'undefined', description: 'Callback function triggered when all animations complete.' }
]
{
name: 'onAnimationComplete',
type: 'function',
default: 'undefined',
description: 'Callback function triggered when all animations complete.'
}
];
</script>

View File

@@ -3,24 +3,38 @@
<TabbedLayout>
<template #preview>
<div class="demo-container relative min-h-[400px] overflow-hidden flex items-center justify-center">
<CircularText :key="rerenderKey" text="VUE * BITS * IS * AWESOME * " :spin-duration="spinDuration"
:on-hover="onHover" class-name="text-blue-500" />
<CircularText
:key="rerenderKey"
text="VUE * BITS * IS * AWESOME * "
:spin-duration="spinDuration"
:on-hover="onHover"
class-name="text-blue-500"
/>
</div>
<Customize>
<div class="flex gap-4 flex-wrap">
<button
class="text-xs bg-[#0b0b0b] rounded-[10px] border border-[#1e3721] hover:bg-[#1e3721] text-white h-8 px-3 transition-colors"
@click="toggleOnHover">
On Hover: <span class="text-[#a1a1aa]">&nbsp;{{ onHover }}</span>
@click="toggleOnHover"
>
On Hover:
<span class="text-[#a1a1aa]">&nbsp;{{ onHover }}</span>
</button>
</div>
<PreviewSlider title="Spin Duration (s)" v-model="spinDuration" :min="1" :max="50" :step="1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Spin Duration (s)"
v-model="spinDuration"
:min="1"
:max="50"
:step="1"
@update:model-value="forceRerender"
/>
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['motion-v']" />
</template>
@@ -36,40 +50,45 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import CircularText from '../../content/TextAnimations/CircularText/CircularText.vue'
import { circularText } from '@/constants/code/TextAnimations/circularTextCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import CircularText from '../../content/TextAnimations/CircularText/CircularText.vue';
import { circularText } from '@/constants/code/TextAnimations/circularTextCode';
import { useForceRerender } from '@/composables/useForceRerender';
const onHover = ref<'slowDown' | 'speedUp' | 'pause' | 'goBonkers'>('speedUp')
const spinDuration = ref(20)
const { rerenderKey, forceRerender } = useForceRerender()
const onHover = ref<'slowDown' | 'speedUp' | 'pause' | 'goBonkers'>('speedUp');
const spinDuration = ref(20);
const { rerenderKey, forceRerender } = useForceRerender();
const hoverOptions: Array<'slowDown' | 'speedUp' | 'pause' | 'goBonkers'> = [
'slowDown',
'speedUp',
'pause',
'goBonkers'
]
];
const toggleOnHover = () => {
const currentIndex = hoverOptions.indexOf(onHover.value)
const nextIndex = (currentIndex + 1) % hoverOptions.length
onHover.value = hoverOptions[nextIndex]
forceRerender()
}
const currentIndex = hoverOptions.indexOf(onHover.value);
const nextIndex = (currentIndex + 1) % hoverOptions.length;
onHover.value = hoverOptions[nextIndex];
forceRerender();
};
const propData = [
{ name: 'text', type: 'string', default: '""', description: 'The text content to display in a circular pattern.' },
{ name: 'spinDuration', type: 'number', default: '20', description: 'Duration of one full rotation in seconds.' },
{ name: 'onHover', type: 'string', default: '"speedUp"', description: 'Hover behavior: "slowDown", "speedUp", "pause", or "goBonkers".' },
{
name: 'onHover',
type: 'string',
default: '"speedUp"',
description: 'Hover behavior: "slowDown", "speedUp", "pause", or "goBonkers".'
},
{ name: 'className', type: 'string', default: '""', description: 'Additional class names to style the component.' }
]
];
</script>

View File

@@ -3,26 +3,57 @@
<TabbedLayout>
<template #preview>
<div class="demo-container relative h-[500px] overflow-hidden p-0">
<CurvedLoop :key="rerenderKey" :marquee-text="marqueeText" :speed="speed" :curve-amount="curveAmount"
:interactive="interactive" />
<CurvedLoop
:key="rerenderKey"
:marquee-text="marqueeText"
:speed="speed"
:curve-amount="curveAmount"
:interactive="interactive"
/>
</div>
<Customize>
<div class="mb-4">
<label class="block text-sm font-medium mb-2">Marquee Text</label>
<input v-model="marqueeText" type="text" placeholder="Enter text..."
<input
v-model="marqueeText"
type="text"
placeholder="Enter text..."
class="w-[300px] px-3 py-2 bg-[#0b0b0b] border border-[#333] rounded-md text-white focus:outline-none focus:border-[#666]"
@input="forceRerender" />
@input="forceRerender"
/>
</div>
<PreviewSlider title="Speed" v-model="speed" :min="0" :max="10" :step="0.1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Speed"
v-model="speed"
:min="0"
:max="10"
:step="0.1"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Curve Amount" v-model="curveAmount" :min="-400" :max="400" :step="10" value-unit="px"
@update:model-value="forceRerender" />
<PreviewSlider
title="Curve Amount"
v-model="curveAmount"
:min="-400"
:max="400"
:step="10"
value-unit="px"
@update:model-value="forceRerender"
/>
<PreviewSwitch title="Draggable" :model-value="interactive"
@update:model-value="(val: boolean) => { interactive = val; forceRerender() }" />
<PreviewSwitch
title="Draggable"
:model-value="interactive"
@update:model-value="
(val: boolean) => {
interactive = val;
forceRerender();
}
"
/>
</Customize>
<PropTable :data="propData" />
@@ -40,24 +71,24 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import CurvedLoop from '../../content/TextAnimations/CurvedLoop/CurvedLoop.vue'
import { curvedLoop } from '@/constants/code/TextAnimations/curvedLoopCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import CurvedLoop from '../../content/TextAnimations/CurvedLoop/CurvedLoop.vue';
import { curvedLoop } from '@/constants/code/TextAnimations/curvedLoopCode';
import { useForceRerender } from '@/composables/useForceRerender';
const marqueeText = ref('Be ✦ Creative ✦ With ✦ Vue ✦ Bits ✦')
const speed = ref(2)
const curveAmount = ref(400)
const interactive = ref(true)
const marqueeText = ref('Be ✦ Creative ✦ With ✦ Vue ✦ Bits ✦');
const speed = ref(2);
const curveAmount = ref(400);
const interactive = ref(true);
const { rerenderKey, forceRerender } = useForceRerender()
const { rerenderKey, forceRerender } = useForceRerender();
const propData = [
{
@@ -96,5 +127,5 @@ const propData = [
default: 'true',
description: 'Whether the marquee can be dragged by the user'
}
]
];
</script>

View File

@@ -4,20 +4,52 @@
<template #preview>
<div class="demo-container relative py-6 overflow-hidden">
<RefreshButton @click="forceRerender" />
<div :key="key" class="pl-6 m-8 w-full flex flex-col justify-start items-start">
<DecryptedText :speed="speed" text="Ahoy, matey!" :max-iterations="maxIterations" :sequential="sequential"
:reveal-direction="revealDirection" parent-class-name="decrypted-text"
:use-original-chars-only="useOriginalCharsOnly" :animate-on="animateOn" />
<DecryptedText :speed="speed" text="Set yer eyes on this" :max-iterations="maxIterations"
:sequential="sequential" :reveal-direction="revealDirection" parent-class-name="decrypted-text"
:use-original-chars-only="useOriginalCharsOnly" :animate-on="animateOn" />
<DecryptedText :speed="speed" text="And try tinkerin' round'" :max-iterations="maxIterations"
:sequential="sequential" :reveal-direction="revealDirection" parent-class-name="decrypted-text"
:use-original-chars-only="useOriginalCharsOnly" :animate-on="animateOn" />
<DecryptedText :speed="speed" text="with these here props, arr!" :max-iterations="maxIterations"
:sequential="sequential" :reveal-direction="revealDirection" parent-class-name="decrypted-text"
:use-original-chars-only="useOriginalCharsOnly" :animate-on="animateOn"
@animation-complete="() => console.log('✅ Animation Finished!')" />
<DecryptedText
:speed="speed"
text="Ahoy, matey!"
:max-iterations="maxIterations"
:sequential="sequential"
:reveal-direction="revealDirection"
parent-class-name="decrypted-text"
:use-original-chars-only="useOriginalCharsOnly"
:animate-on="animateOn"
/>
<DecryptedText
:speed="speed"
text="Set yer eyes on this"
:max-iterations="maxIterations"
:sequential="sequential"
:reveal-direction="revealDirection"
parent-class-name="decrypted-text"
:use-original-chars-only="useOriginalCharsOnly"
:animate-on="animateOn"
/>
<DecryptedText
:speed="speed"
text="And try tinkerin' round'"
:max-iterations="maxIterations"
:sequential="sequential"
:reveal-direction="revealDirection"
parent-class-name="decrypted-text"
:use-original-chars-only="useOriginalCharsOnly"
:animate-on="animateOn"
/>
<DecryptedText
:speed="speed"
text="with these here props, arr!"
:max-iterations="maxIterations"
:sequential="sequential"
:reveal-direction="revealDirection"
parent-class-name="decrypted-text"
:use-original-chars-only="useOriginalCharsOnly"
:animate-on="animateOn"
@animation-complete="() => console.log('✅ Animation Finished!')"
/>
</div>
</div>
@@ -26,17 +58,48 @@
<PreviewSwitch title="Original Chars" v-model="useOriginalCharsOnly" @update:model-value="forceRerender" />
<PreviewSlider title="Speed" v-model="speed" :min="10" :max="200" :step="10" value-unit="ms"
@update:model-value="forceRerender" />
<PreviewSlider
title="Speed"
v-model="speed"
:min="10"
:max="200"
:step="10"
value-unit="ms"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Iterations" v-model="maxIterations" :min="1" :max="50" :step="1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Iterations"
v-model="maxIterations"
:min="1"
:max="50"
:step="1"
@update:model-value="forceRerender"
/>
<PreviewSelect title="Animation Trigger" v-model="animateOn" :options="animateOptions"
@update:model-value="(val) => { animateOn = val as 'view' | 'hover'; forceRerender(); }" />
<PreviewSelect
title="Animation Trigger"
v-model="animateOn"
:options="animateOptions"
@update:model-value="
val => {
animateOn = val as 'view' | 'hover';
forceRerender();
}
"
/>
<PreviewSelect title="Animation Direction" v-model="revealDirection" :options="directionOptions"
@update:model-value="(val) => { revealDirection = val as 'start' | 'end' | 'center'; forceRerender(); }" />
<PreviewSelect
title="Animation Direction"
v-model="revealDirection"
:options="directionOptions"
@update:model-value="
val => {
revealDirection = val as 'start' | 'end' | 'center';
forceRerender();
}
"
/>
</Customize>
<PropTable :data="propData" />
@@ -54,39 +117,39 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import PreviewSelect from '../../components/common/PreviewSelect.vue'
import RefreshButton from '../../components/common/RefreshButton.vue'
import DecryptedText from '../../content/TextAnimations/DecryptedText/DecryptedText.vue'
import { decryptedText } from '@/constants/code/TextAnimations/decryptedTextCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import PreviewSelect from '../../components/common/PreviewSelect.vue';
import RefreshButton from '../../components/common/RefreshButton.vue';
import DecryptedText from '../../content/TextAnimations/DecryptedText/DecryptedText.vue';
import { decryptedText } from '@/constants/code/TextAnimations/decryptedTextCode';
import { useForceRerender } from '@/composables/useForceRerender';
const { rerenderKey: key, forceRerender } = useForceRerender()
const { rerenderKey: key, forceRerender } = useForceRerender();
const speed = ref(60)
const maxIterations = ref(10)
const sequential = ref(true)
const useOriginalCharsOnly = ref(false)
const revealDirection = ref<'start' | 'end' | 'center'>('start')
const animateOn = ref<'view' | 'hover'>('view')
const speed = ref(60);
const maxIterations = ref(10);
const sequential = ref(true);
const useOriginalCharsOnly = ref(false);
const revealDirection = ref<'start' | 'end' | 'center'>('start');
const animateOn = ref<'view' | 'hover'>('view');
const animateOptions = [
{ label: 'View', value: 'view' },
{ label: 'Hover', value: 'hover' }
]
];
const directionOptions = [
{ label: 'Start', value: 'start' },
{ label: 'End', value: 'end' },
{ label: 'Center', value: 'center' }
]
];
const propData = [
{
@@ -149,7 +212,7 @@ const propData = [
default: '"hover"',
description: 'Trigger scrambling on hover or scroll-into-view.'
}
]
];
</script>
<style scoped>

View File

@@ -3,10 +3,15 @@
<TabbedLayout>
<template #preview>
<div class="demo-container relative h-[400px] overflow-hidden p-0 flex justify-center items-center">
<FallingText :key="key"
<FallingText
:key="key"
text="Vue Bits is a library of animated and interactive Vue components designed to streamline UI development and simplify your workflow."
:highlight-words="['Vue', 'Bits', 'animated', 'components', 'simplify']" :trigger="trigger"
:gravity="gravity" font-size="2rem" :mouse-constraint-stiffness="mouseConstraintStiffness" />
:highlight-words="['Vue', 'Bits', 'animated', 'components', 'simplify']"
:trigger="trigger"
:gravity="gravity"
font-size="2rem"
:mouse-constraint-stiffness="mouseConstraintStiffness"
/>
<div class="absolute z-0 text-[4rem] font-[900] text-[#222] select-none" v-if="!effectStarted">
{{ trigger === 'hover' ? 'Hover Me' : trigger === 'click' ? 'Click Me' : 'Auto Start' }}
@@ -14,17 +19,34 @@
</div>
<Customize>
<PreviewSelect title="Animation Trigger" v-model="trigger" :options="triggerOptions"
@update:model-value="forceRerender" />
<PreviewSelect
title="Animation Trigger"
v-model="trigger"
:options="triggerOptions"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Gravity" v-model="gravity" :min="0.1" :max="2" :step="0.01"
@update:model-value="forceRerender" />
<PreviewSlider
title="Gravity"
v-model="gravity"
:min="0.1"
:max="2"
:step="0.01"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Mouse Constraint Stiffness" v-model="mouseConstraintStiffness" :min="0.1" :max="2"
:step="0.1" @update:model-value="forceRerender" />
<PreviewSlider
title="Mouse Constraint Stiffness"
v-model="mouseConstraintStiffness"
:min="0.1"
:max="2"
:step="0.1"
@update:model-value="forceRerender"
/>
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['matter-js']" />
</template>
@@ -40,33 +62,33 @@
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import PreviewSelect from '../../components/common/PreviewSelect.vue'
import FallingText from '../../content/TextAnimations/FallingText/FallingText.vue'
import { fallingText } from '@/constants/code/TextAnimations/fallingTextCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref, computed } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSelect from '../../components/common/PreviewSelect.vue';
import FallingText from '../../content/TextAnimations/FallingText/FallingText.vue';
import { fallingText } from '@/constants/code/TextAnimations/fallingTextCode';
import { useForceRerender } from '@/composables/useForceRerender';
const { rerenderKey: key, forceRerender } = useForceRerender()
const { rerenderKey: key, forceRerender } = useForceRerender();
const gravity = ref(0.56)
const mouseConstraintStiffness = ref(0.9)
const trigger = ref<'hover' | 'click' | 'auto' | 'scroll'>('hover')
const gravity = ref(0.56);
const mouseConstraintStiffness = ref(0.9);
const trigger = ref<'hover' | 'click' | 'auto' | 'scroll'>('hover');
const effectStarted = computed(() => trigger.value === 'auto')
const effectStarted = computed(() => trigger.value === 'auto');
const triggerOptions = [
{ value: 'hover', label: 'Hover' },
{ value: 'click', label: 'Click' },
{ value: 'auto', label: 'Auto' },
{ value: 'scroll', label: 'Scroll' }
]
];
const propData = [
{
@@ -117,7 +139,7 @@ const propData = [
default: '"1rem"',
description: 'Font size applied to the text before it falls.'
}
]
];
</script>
<style scoped></style>

View File

@@ -4,23 +4,58 @@
<template #preview>
<div class="demo-container relative h-[500px] overflow-hidden">
<div class="flex flex-col items-center justify-center h-full">
<FuzzyText :key="`main-${rerenderKey}`" text="404" :base-intensity="baseIntensity"
:hover-intensity="hoverIntensity" :enable-hover="enableHover" :font-size="140" />
<FuzzyText
:key="`main-${rerenderKey}`"
text="404"
:base-intensity="baseIntensity"
:hover-intensity="hoverIntensity"
:enable-hover="enableHover"
:font-size="140"
/>
<div class="my-1" />
<FuzzyText :key="`sub-${rerenderKey}`" text="not found" :base-intensity="baseIntensity"
:hover-intensity="hoverIntensity" :enable-hover="enableHover" :font-size="70" font-family="Gochi Hand" />
<FuzzyText
:key="`sub-${rerenderKey}`"
text="not found"
:base-intensity="baseIntensity"
:hover-intensity="hoverIntensity"
:enable-hover="enableHover"
:font-size="70"
font-family="Gochi Hand"
/>
</div>
</div>
<Customize>
<PreviewSlider title="Base Intensity" v-model="baseIntensity" :min="0" :max="1" :step="0.01"
@update:model-value="forceRerender" />
<PreviewSlider
title="Base Intensity"
v-model="baseIntensity"
:min="0"
:max="1"
:step="0.01"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Hover Intensity" v-model="hoverIntensity" :min="0" :max="2" :step="0.01"
@update:model-value="forceRerender" />
<PreviewSlider
title="Hover Intensity"
v-model="hoverIntensity"
:min="0"
:max="2"
:step="0.01"
@update:model-value="forceRerender"
/>
<PreviewSwitch title="Enable Hover" :model-value="enableHover"
@update:model-value="(val: boolean) => { enableHover = val; forceRerender() }" />
<PreviewSwitch
title="Enable Hover"
:model-value="enableHover"
@update:model-value="
(val: boolean) => {
enableHover = val;
forceRerender();
}
"
/>
</Customize>
<PropTable :data="propData" />
@@ -38,23 +73,23 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import FuzzyText from '../../content/TextAnimations/FuzzyText/FuzzyText.vue'
import { fuzzyText } from '@/constants/code/TextAnimations/fuzzyTextCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import FuzzyText from '../../content/TextAnimations/FuzzyText/FuzzyText.vue';
import { fuzzyText } from '@/constants/code/TextAnimations/fuzzyTextCode';
import { useForceRerender } from '@/composables/useForceRerender';
const baseIntensity = ref(0.2)
const hoverIntensity = ref(0.5)
const enableHover = ref(true)
const baseIntensity = ref(0.2);
const hoverIntensity = ref(0.5);
const enableHover = ref(true);
const { rerenderKey, forceRerender } = useForceRerender()
const { rerenderKey, forceRerender } = useForceRerender();
const propData = [
{
@@ -67,7 +102,8 @@ const propData = [
name: 'fontSize',
type: 'number | string',
default: '"clamp(2rem, 8vw, 8rem)"',
description: 'Specifies the font size of the text. Accepts any valid CSS font-size value or a number (interpreted as pixels).'
description:
'Specifies the font size of the text. Accepts any valid CSS font-size value or a number (interpreted as pixels).'
},
{
name: 'fontWeight',
@@ -105,5 +141,5 @@ const propData = [
default: '0.5',
description: 'The fuzz intensity when the text is hovered.'
}
]
];
</script>

View File

@@ -0,0 +1,94 @@
<template>
<div class="glitchtext-demo">
<TabbedLayout>
<template #preview>
<div class="demo-container relative h-[500px] overflow-hidden">
<GlitchText
:children="text"
:speed="speed"
:enable-shadows="enableShadows"
:enable-on-hover="enableOnHover"
class-name="demo-glitch-text"
/>
</div>
<Customize>
<div class="mb-4">
<PreviewText title="Text" v-model="text" />
<PreviewSlider title="Refresh Delay" v-model="speed" :min="0.1" :max="5" :step="0.1" />
<PreviewSwitch title="Glitch Colors" v-model="enableShadows" />
<PreviewSwitch title="Glitch On Hover" v-model="enableOnHover" />
</div>
</Customize>
<PropTable :data="propData" />
</template>
<template #code>
<CodeExample :code-object="glitchText" />
</template>
<template #cli>
<CliInstallation :command="glitchText.cli" />
</template>
</TabbedLayout>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import GlitchText from '../../content/TextAnimations/GlitchText/GlitchText.vue';
import PropTable from '../../components/common/PropTable.vue';
import PreviewText from '../../components/common/PreviewText.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import { glitchText } from '@/constants/code/TextAnimations/glitchTextCode';
const text = ref('Vue Bits');
const speed = ref(0.5);
const enableShadows = ref(true);
const enableOnHover = ref(false);
watch(enableOnHover, newValue => {
text.value = newValue ? 'Hover Me' : 'Vue Bits';
});
const propData = [
{
name: 'children',
type: 'string',
default: '',
description: 'The text content that will display the glitch effect.'
},
{
name: 'speed',
type: 'number',
default: '0.5',
description: 'Multiplier for the animation speed. Higher values slow down the glitch effect.'
},
{
name: 'enableShadows',
type: 'boolean',
default: 'true',
description: 'Toggle the colored text shadows on the glitch pseudo-elements.'
},
{
name: 'enableOnHover',
type: 'boolean',
default: 'false',
description: 'If true, the glitch animation is only activated on hover.'
},
{
name: 'className',
type: 'string',
default: '',
description: 'Additional custom classes to apply to the component.'
}
];
</script>

View File

@@ -3,18 +3,29 @@
<TabbedLayout>
<template #preview>
<h2 class="demo-title-extra">Default</h2>
<div class="demo-container relative min-h-[150px] flex items-center justify-center">
<div class="demo-container">
<div class="text-[2rem]">
<GradientText text="Add a splash of color!" :colors="gradientPreview" :animation-speed="speed"
:show-border="false" />
<GradientText
text="Add a splash of color!"
:colors="gradientPreview"
:animation-speed="speed"
:show-border="false"
/>
</div>
</div>
<h2 class="demo-title-extra">Border Animation</h2>
<div class="demo-container relative min-h-[150px] flex items-center justify-center">
<div class="demo-container">
<div class="text-[2rem]">
<GradientText text="Now with a cool border!" :colors="gradientPreview" :animation-speed="speed"
:show-border="true" class-name="custom-gradient-class" />
<GradientText
text="Now with a cool border!"
:colors="gradientPreview"
:animation-speed="speed"
:show-border="true"
class-name="custom-gradient-class"
/>
</div>
</div>
@@ -24,20 +35,32 @@
<div class="flex flex-col gap-0">
<div class="mb-4">
<label class="block text-sm font-medium mb-2">Colors</label>
<input v-model="colors" type="text" placeholder="Enter colors separated by commas" maxlength="100"
class="w-[300px] px-3 py-2 bg-[#0b0b0b] border border-[#333] rounded-md text-white focus:outline-none focus:border-[#666]" />
<input
v-model="colors"
type="text"
placeholder="Enter colors separated by commas"
maxlength="100"
class="w-[300px] px-3 py-2 bg-[#0b0b0b] border border-[#333] rounded-md text-white focus:outline-none focus:border-[#666]"
/>
</div>
<div class="w-[300px] h-3 rounded-md border border-[#271E37]" :style="{
background: `linear-gradient(to right, ${gradientPreview.join(', ')})`
}" />
<div
class="w-[300px] h-3 rounded-md border border-[#271E37]"
:style="{
background: `linear-gradient(to right, ${gradientPreview.join(', ')})`
}"
/>
</div>
</Customize>
<p class="demo-extra-info mt-4 flex items-center gap-2">
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd"
<path
fill-rule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z"
clip-rule="evenodd" />
clip-rule="evenodd"
/>
</svg>
For a smoother animation, the gradient should start and end with the same color.
</p>
@@ -57,20 +80,20 @@
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import GradientText from '../../content/TextAnimations/GradientText/GradientText.vue'
import { gradientText } from '@/constants/code/TextAnimations/gradientTextCode'
import { ref, computed } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import GradientText from '../../content/TextAnimations/GradientText/GradientText.vue';
import { gradientText } from '@/constants/code/TextAnimations/gradientTextCode';
const colors = ref('#40ffaa, #4079ff, #40ffaa, #4079ff, #40ffaa')
const speed = ref(3)
const colors = ref('#40ffaa, #4079ff, #40ffaa, #4079ff, #40ffaa');
const speed = ref(3);
const gradientPreview = computed(() => colors.value.split(',').map(color => color.trim()))
const gradientPreview = computed(() => colors.value.split(',').map(color => color.trim()));
const propData = [
{
@@ -103,10 +126,14 @@ const propData = [
default: 'false',
description: 'Determines whether a border with the gradient effect is displayed.'
}
]
];
</script>
<style scoped>
.demo-container {
min-height: 200px;
}
.demo-title-extra {
font-size: 1.125rem;
font-weight: 600;

View File

@@ -0,0 +1,166 @@
<template>
<TabbedLayout>
<template #preview>
<div class="relative min-h-[400px] max-h-[400px] overflow-hidden demo-container">
<div
class="flex flex-row justify-center items-center p-12 sm:p-20 md:p-24 w-full h-full overflow-hidden font-light text-[1.5rem] text-white sm:text-[1.875rem] md:text-[3rem] dark:text-muted leading-8 sm:leading-9 md:leading-none"
>
<LayoutGroup>
<motion.p :is="'p'" class="flex items-center gap-[0.2em] font-black" layout>
<motion.span
:is="'span'"
class="pt-0.5 sm:pt-1 md:pt-2"
layout
:transition="{ type: 'spring', damping: 30, stiffness: 400 }"
>
Creative{{ ' ' }}
</motion.span>
<RotatingText
:texts="words"
mainClassName="px-2 py-0.5 bg-[#27FF64] text-[#222] overflow-hidden flex justify-center rounded-lg sm:py-1 md:py-2 md:px-3"
staggerFrom="last"
:initial="{ y: '100%' }"
:animate="{ y: 0 }"
:exit="{ y: '-120%' }"
:staggerDuration="0.025"
splitLevelClassName="overflow-hidden pb-0.5 sm:pb-1"
:transition="{ type: 'spring', damping: 30, stiffness: 400 }"
:rotationInterval="2000"
/>
</motion.p>
</LayoutGroup>
</div>
</div>
<PropTable :data="propData" />
<Dependencies :dependency-list="['motion-v']" />
</template>
<template #code>
<CodeExample :code-object="rotatingText" />
</template>
<template #cli>
<CliInstallation :command="rotatingText.cli" />
</template>
</TabbedLayout>
</template>
<script setup lang="ts">
import { LayoutGroup, motion } from 'motion-v';
import { ref } from 'vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import PropTable from '../../components/common/PropTable.vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import { rotatingText } from '../../constants/code/TextAnimations/rotatingTextCode';
import RotatingText from '../../content/TextAnimations/RotatingText/RotatingText.vue';
const words = ref(['thinking', 'coding', 'components!']);
const propData = [
{
name: 'texts',
type: 'string[]',
default: '[]',
description: 'An array of text strings to be rotated.'
},
{
name: 'rotationInterval',
type: 'number',
default: '2000',
description: 'The interval (in milliseconds) between text rotations.'
},
{
name: 'initial',
type: 'object',
default: '{ y: "100%", opacity: 0 }',
description: 'Initial animation state for each element.'
},
{
name: 'animate',
type: 'object',
default: '{ y: 0, opacity: 1 }',
description: 'Animation state when elements enter.'
},
{
name: 'exit',
type: 'object',
default: '{ y: "-120%", opacity: 0 }',
description: 'Exit animation state for elements.'
},
{
name: 'animatePresenceMode',
type: 'string',
default: '"wait"',
description: "Mode for AnimatePresence; for example, 'wait' to finish exit animations before entering."
},
{
name: 'animatePresenceInitial',
type: 'boolean',
default: 'false',
description: 'Determines whether the AnimatePresence component should run its initial animation.'
},
{
name: 'staggerDuration',
type: 'number',
default: '0',
description: "Delay between each character's animation."
},
{
name: 'staggerFrom',
type: 'string',
default: '"first"',
description: 'Specifies the order from which the stagger starts.'
},
{
name: 'transition',
type: 'object',
default: '',
description: 'Transition settings for the animations.'
},
{
name: 'loop',
type: 'boolean',
default: 'true',
description: 'Determines if the rotation should loop back to the first text after the last one.'
},
{
name: 'auto',
type: 'boolean',
default: 'true',
description: 'If true, the text rotation starts automatically.'
},
{
name: 'splitBy',
type: 'string',
default: '"characters"',
description: 'Determines how the text is split into animatable elements (e.g., by characters, words, or lines).'
},
{
name: 'onNext',
type: 'function',
default: 'undefined',
description: 'Callback function invoked when the text rotates to the next item.'
},
{
name: 'mainClassName',
type: 'string',
default: "''",
description: 'Additional class names for the main container element.'
},
{
name: 'splitLevelClassName',
type: 'string',
default: "''",
description: 'Additional class names for the container wrapping each split group (e.g., a word).'
},
{
name: 'elementLevelClassName',
type: 'string',
default: "''",
description: 'Additional class names for each individual animated element.'
}
];
</script>

View File

@@ -0,0 +1,186 @@
<template>
<TabbedLayout>
<template #preview>
<div ref="containerRef" class="demo-container" @wheel="smoothScroll">
<div class="scroll-instruction">Scroll Down</div>
<div class="scroll-content">
<ScrollFloat
:children="scrollText"
:animation-duration="animationDuration"
:ease="ease"
:scroll-start="scrollStart"
:scroll-end="scrollEnd"
:stagger="stagger"
:container-class-name="containerClassName"
:text-class-name="textClassName"
:scroll-container-ref="{ current: containerRef }"
:key="rerenderKey"
/>
</div>
</div>
<Customize>
<PreviewSlider title="Stagger:" v-model="stagger" :min="0.01" :max="0.1" :step="0.01" value-unit="s" />
<PreviewSlider
title="Animation Duration:"
v-model="animationDuration"
:min="1"
:max="10"
:step="0.1"
value-unit="s"
/>
</Customize>
<PropTable :data="propData" />
</template>
<template #code>
<CodeExample :code-object="scrollFloatCode" />
</template>
<template #cli>
<CliInstallation :command="scrollFloatCode.cli" />
</template>
</TabbedLayout>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { gsap } from 'gsap';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import ScrollFloat from '../../content/TextAnimations/ScrollFloat/ScrollFloat.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import { scrollFloatCode } from '@/constants/code/TextAnimations/scrollFloatCode';
const containerRef = ref<HTMLElement | null>(null);
const scrollText = ref('Vue Bits!');
const animationDuration = ref(1);
const ease = ref('back.inOut(2)');
const scrollStart = ref('center bottom+=50%');
const scrollEnd = ref('bottom bottom-=40%');
const stagger = ref(0.03);
const containerClassName = ref('');
const textClassName = ref('');
const rerenderKey = ref(0);
const smoothScroll = (e: WheelEvent) => {
e.preventDefault();
const container = containerRef.value;
if (!container) return;
const delta = e.deltaY || e.detail;
const scrollAmount = delta * 2;
gsap.to(container, {
scrollTop: container.scrollTop + scrollAmount,
duration: 1,
ease: 'power3.out',
overwrite: 'auto'
});
};
onMounted(() => {
const container = containerRef.value;
if (container) {
container.addEventListener('wheel', smoothScroll, { passive: false });
}
});
onUnmounted(() => {
const container = containerRef.value;
if (container) {
container.removeEventListener('wheel', smoothScroll);
}
});
const propData = [
{
name: 'children',
type: 'string',
default: '""',
description: 'The text content to be animated character by character'
},
{
name: 'scrollContainerRef',
type: 'object',
default: 'undefined',
description: 'Ref to a custom scroll container (defaults to window)'
},
{
name: 'containerClassName',
type: 'string',
default: '""',
description: 'Additional CSS classes for the container element'
},
{
name: 'textClassName',
type: 'string',
default: '""',
description: 'Additional CSS classes for the text element'
},
{
name: 'animationDuration',
type: 'number',
default: '1',
description: 'Duration of the animation in seconds'
},
{
name: 'ease',
type: 'string',
default: '"back.inOut(2)"',
description: 'GSAP easing function for the animation'
},
{
name: 'scrollStart',
type: 'string',
default: '"center bottom+=50%"',
description: 'ScrollTrigger start position'
},
{
name: 'scrollEnd',
type: 'string',
default: '"bottom bottom-=40%"',
description: 'ScrollTrigger end position'
},
{
name: 'stagger',
type: 'number',
default: '0.03',
description: 'Delay between each character animation'
}
];
</script>
<style scoped>
.demo-container {
height: 60vh;
overflow-y: auto;
}
.scroll-content {
padding-top: 150vh !important;
padding-bottom: 50vh;
}
.scroll-instruction {
text-align: center;
color: #222;
font-size: clamp(4rem, 6vw, 4rem);
font-weight: 900;
position: absolute;
top: 50%;
left: 0;
right: 0;
transform: translateY(-50%);
}
.scroll-content {
color: aliceblue;
}
</style>

View File

@@ -0,0 +1,203 @@
<template>
<TabbedLayout>
<template #preview>
<div ref="containerRef" class="demo-container" @wheel="smoothScroll">
<div class="scroll-instruction">Scroll Down</div>
<div class="scroll-content">
<ScrollReveal
:children="scrollText"
:enable-blur="enableBlur"
:base-opacity="baseOpacity"
:base-rotation="baseRotation"
:blur-strength="blurStrength"
:container-class-name="containerClassName"
:text-class-name="textClassName"
:rotation-end="rotationEnd"
:word-animation-end="wordAnimationEnd"
:scroll-container-ref="{ current: containerRef }"
:key="rerenderKey"
/>
</div>
</div>
<Customize>
<PreviewSwitch
title="Enable Hover"
:model-value="enableBlur"
@update:model-value="
(val: boolean) => {
enableBlur = val;
forceRerender();
}
"
/>
<PreviewSlider title="Base Opacity:" v-model="baseOpacity" :min="0" :max="1" :step="0.1" value-unit="" />
<PreviewSlider title="Base Rotation:" v-model="baseRotation" :min="0" :max="10" :step="0.5" value-unit="deg" />
<PreviewSlider title="Blur Strength:" v-model="blurStrength" :min="0" :max="10" :step="0.5" value-unit="px" />
</Customize>
<PropTable :data="propData" />
</template>
<template #code>
<CodeExample :code-object="scrollRevealCode" />
</template>
<template #cli>
<CliInstallation :command="scrollRevealCode.cli" />
</template>
</TabbedLayout>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { gsap } from 'gsap';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import ScrollReveal from '../../content/TextAnimations/ScrollReveal/ScrollReveal.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import { scrollRevealCode } from '@/constants/code/TextAnimations/scrollRevealCode';
const containerRef = ref<HTMLElement | null>(null);
const scrollText = ref(
'When does a man die? When he is hit by a bullet? No! When he suffers a disease? No! When he ate a soup made out of a poisonous mushroom? No! A man dies when he is forgotten!'
);
const enableBlur = ref(true);
const baseOpacity = ref(0.1);
const baseRotation = ref(3);
const blurStrength = ref(4);
const containerClassName = ref('');
const textClassName = ref('');
const rotationEnd = ref('bottom bottom');
const wordAnimationEnd = ref('bottom bottom');
const rerenderKey = ref(0);
const forceRerender = () => {
rerenderKey.value++;
};
const smoothScroll = (e: WheelEvent) => {
e.preventDefault();
const container = containerRef.value;
if (!container) return;
const delta = e.deltaY || e.detail;
const scrollAmount = delta * 2;
gsap.to(container, {
scrollTop: container.scrollTop + scrollAmount,
duration: 2,
ease: 'power3.out',
overwrite: 'auto'
});
};
onMounted(() => {
const container = containerRef.value;
if (container) {
container.addEventListener('wheel', smoothScroll, { passive: false });
}
});
onUnmounted(() => {
const container = containerRef.value;
if (container) {
container.removeEventListener('wheel', smoothScroll);
}
});
const propData = [
{
name: 'children',
type: 'string',
default: '""',
description: 'The text content to be animated word by word'
},
{
name: 'scrollContainerRef',
type: 'object',
default: 'undefined',
description: 'Ref to a custom scroll container (defaults to window)'
},
{
name: 'enableBlur',
type: 'boolean',
default: 'true',
description: 'Whether to enable blur animation'
},
{
name: 'baseOpacity',
type: 'number',
default: '0.1',
description: 'Starting opacity value for words'
},
{
name: 'baseRotation',
type: 'number',
default: '3',
description: 'Starting rotation value in degrees'
},
{
name: 'blurStrength',
type: 'number',
default: '4',
description: 'Blur strength in pixels'
},
{
name: 'containerClassName',
type: 'string',
default: '""',
description: 'Additional CSS classes for the container element'
},
{
name: 'textClassName',
type: 'string',
default: '""',
description: 'Additional CSS classes for the text element'
},
{
name: 'rotationEnd',
type: 'string',
default: '"bottom bottom"',
description: 'ScrollTrigger end position for rotation animation'
},
{
name: 'wordAnimationEnd',
type: 'string',
default: '"bottom bottom"',
description: 'ScrollTrigger end position for word animations'
}
];
</script>
<style scoped>
.demo-container {
height: 60vh;
overflow-y: auto;
}
.scroll-content {
padding-top: 150vh !important;
padding-bottom: 50vh;
}
.scroll-instruction {
text-align: center;
color: #222;
font-size: clamp(4rem, 6vw, 4rem);
font-weight: 900;
position: absolute;
top: 50%;
left: 0;
right: 0;
transform: translateY(-50%);
}
.scroll-content {
color: aliceblue;
}
</style>

View File

@@ -3,21 +3,28 @@
<TabbedLayout>
<template #preview>
<h2 class="demo-title-extra">Basic</h2>
<div class="demo-container relative min-h-[150px] text-2xl flex items-center justify-center">
<div class="demo-container">
<ShinyText text="Just some shiny text!" :disabled="false" :speed="3" class-name="shiny-text-demo" />
</div>
<h2 class="demo-title-extra">Button Text</h2>
<div class="demo-container relative min-h-[150px] text-2xl flex items-center justify-center">
<div class="demo-container">
<div class="shiny-button">
<ShinyText text="Shiny Button" :disabled="false" :speed="3" class-name="shiny-text-demo" />
</div>
</div>
<h2 class="demo-title-extra">Configurable Speed</h2>
<div class="demo-container relative min-h-[150px] text-2xl flex items-center justify-center">
<ShinyText :text="speed < 2.5 ? '🐎 This is fast!' : '🐌 This is slow!'" :disabled="false" :speed="speed"
class-name="shiny-text-demo" />
<ShinyText
:text="speed < 2.5 ? '🐎 This is fast!' : '🐌 This is slow!'"
:disabled="false"
:speed="speed"
class-name="shiny-text-demo"
/>
</div>
<Customize>
@@ -39,17 +46,17 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import ShinyText from '../../content/TextAnimations/ShinyText/ShinyText.vue'
import { shinyText } from '@/constants/code/TextAnimations/shinyTextCode'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import ShinyText from '../../content/TextAnimations/ShinyText/ShinyText.vue';
import { shinyText } from '@/constants/code/TextAnimations/shinyTextCode';
const speed = ref(3)
const speed = ref(3);
const propData = [
{
@@ -76,10 +83,14 @@ const propData = [
default: "''",
description: 'Adds custom classes to the root element.'
}
]
];
</script>
<style scoped>
.demo-container {
min-height: 200px;
}
.shiny-button {
padding: 12px 24px;
border-radius: 50px;

View File

@@ -5,25 +5,56 @@
<div class="demo-container">
<RefreshButton @refresh="forceRerender" />
<SplitText :key="rerenderKey" text="Hello, Vue!" :delay="delay" :duration="duration" :ease="ease"
:split-type="splitType" :threshold="threshold" class="split-text-demo-text"
@animation-complete="() => { showCallback && showToast() }" />
<SplitText
:key="rerenderKey"
text="Hello, Vue!"
:delay="delay"
:duration="duration"
:ease="ease"
:split-type="splitType"
:threshold="threshold"
class="split-text-demo-text"
@animation-complete="
() => {
showCallback && showToast();
}
"
/>
</div>
<Customize>
<PreviewSwitch title="Show Completion Toast" v-model="showCallback" @update:model-value="forceRerender" />
<PreviewSlider title="Stagger Delay (ms)" v-model="delay" :min="10" :max="500" :step="10"
@update:model-value="forceRerender" />
<PreviewSlider
title="Stagger Delay (ms)"
v-model="delay"
:min="10"
:max="500"
:step="10"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Duration (s)" v-model="duration" :min="0.1" :max="2" :step="0.1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Duration (s)"
v-model="duration"
:min="0.1"
:max="2"
:step="0.1"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Threshold" v-model="threshold" :min="0.1" :max="1" :step="0.1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Threshold"
v-model="threshold"
:min="0.1"
:max="1"
:step="0.1"
@update:model-value="forceRerender"
/>
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['gsap']" />
</template>
@@ -39,37 +70,37 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import RefreshButton from '../../components/common/RefreshButton.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import SplitText from '../../content/TextAnimations/SplitText/SplitText.vue'
import { splitText } from '@/constants/code/TextAnimations/splitTextCode'
import { useToast } from 'primevue/usetoast'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import RefreshButton from '../../components/common/RefreshButton.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import SplitText from '../../content/TextAnimations/SplitText/SplitText.vue';
import { splitText } from '@/constants/code/TextAnimations/splitTextCode';
import { useToast } from 'primevue/usetoast';
import { useForceRerender } from '@/composables/useForceRerender';
const delay = ref(10)
const duration = ref(2)
const ease = ref('elastic.out(1, 0.3)')
const splitType = ref<'chars' | 'words' | 'lines' | 'words, chars'>('chars')
const threshold = ref(0.1)
const showCallback = ref(true)
const toast = useToast()
const { rerenderKey, forceRerender } = useForceRerender()
const delay = ref(10);
const duration = ref(2);
const ease = ref('elastic.out(1, 0.3)');
const splitType = ref<'chars' | 'words' | 'lines' | 'words, chars'>('chars');
const threshold = ref(0.1);
const showCallback = ref(true);
const toast = useToast();
const { rerenderKey, forceRerender } = useForceRerender();
const showToast = () => {
toast.add({
severity: 'secondary',
summary: 'Animation Finished!',
life: 3000
})
}
});
};
const propData = [
{ name: 'text', type: 'string', default: '""', description: 'The text content to animate.' },
@@ -77,12 +108,42 @@ const propData = [
{ name: 'delay', type: 'number', default: '100', description: 'Delay between animations for each letter (in ms).' },
{ name: 'duration', type: 'number', default: '0.6', description: 'Duration of each letter animation (in seconds).' },
{ name: 'ease', type: 'string', default: '"power3.out"', description: 'GSAP easing function for the animation.' },
{ name: 'splitType', type: 'string', default: '"chars"', description: 'Split type: "chars", "words", "lines", or "words, chars".' },
{ name: 'from', type: 'object', default: '{ opacity: 0, y: 40 }', description: 'Initial GSAP properties for each letter/word.' },
{ name: 'to', type: 'object', default: '{ opacity: 1, y: 0 }', description: 'Target GSAP properties for each letter/word.' },
{ name: 'threshold', type: 'number', default: '0.1', description: 'Intersection threshold to trigger the animation (0-1).' },
{
name: 'splitType',
type: 'string',
default: '"chars"',
description: 'Split type: "chars", "words", "lines", or "words, chars".'
},
{
name: 'from',
type: 'object',
default: '{ opacity: 0, y: 40 }',
description: 'Initial GSAP properties for each letter/word.'
},
{
name: 'to',
type: 'object',
default: '{ opacity: 1, y: 0 }',
description: 'Target GSAP properties for each letter/word.'
},
{
name: 'threshold',
type: 'number',
default: '0.1',
description: 'Intersection threshold to trigger the animation (0-1).'
},
{ name: 'rootMargin', type: 'string', default: '"-100px"', description: 'Root margin for the ScrollTrigger.' },
{ name: 'textAlign', type: 'string', default: '"center"', description: 'Text alignment: "left", "center", "right", etc.' },
{ name: 'onLetterAnimationComplete', type: 'function', default: 'undefined', description: 'Callback function when all animations complete.' }
]
</script>
{
name: 'textAlign',
type: 'string',
default: '"center"',
description: 'Text alignment: "left", "center", "right", etc.'
},
{
name: 'onLetterAnimationComplete',
type: 'function',
default: 'undefined',
description: 'Callback function when all animations complete.'
}
];
</script>

View File

@@ -3,10 +3,16 @@
<TabbedLayout>
<template #preview>
<div class="demo-container relative h-[500px] overflow-hidden">
<TextCursor :key="key" :text="text" :follow-mouse-direction="followMouseDirection"
:random-float="randomFloat" />
<TextCursor
:key="key"
:text="text"
:follow-mouse-direction="followMouseDirection"
:random-float="randomFloat"
/>
<div
class="absolute inset-0 flex items-center justify-center pointer-events-none text-[4rem] font-[900] text-[#222] select-none">
class="absolute inset-0 flex items-center justify-center pointer-events-none text-[4rem] font-[900] text-[#222] select-none"
>
Hover Around!
</div>
</div>
@@ -14,17 +20,27 @@
<Customize>
<div class="mb-4">
<label class="block text-sm font-medium mb-2">Text</label>
<input v-model="text" type="text" placeholder="Enter text..." maxlength="10"
class="w-[160px] px-3 py-2 bg-[#0b0b0b] border border-[#333] rounded-md text-white focus:outline-none focus:border-[#666]" />
<input
v-model="text"
type="text"
placeholder="Enter text..."
maxlength="10"
class="w-[160px] px-3 py-2 bg-[#0b0b0b] border border-[#333] rounded-md text-white focus:outline-none focus:border-[#666]"
/>
</div>
<PreviewSwitch title="Follow Mouse Direction" v-model="followMouseDirection"
@update:model-value="forceRerender" />
<PreviewSwitch
title="Follow Mouse Direction"
v-model="followMouseDirection"
@update:model-value="forceRerender"
/>
<PreviewSwitch title="Enable Random Floating" v-model="randomFloat" @update:model-value="forceRerender" />
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['motion-v']" />
</template>
@@ -40,23 +56,23 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import TextCursor from '../../content/TextAnimations/TextCursor/TextCursor.vue'
import { textCursor } from '@/constants/code/TextAnimations/textCursorCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import TextCursor from '../../content/TextAnimations/TextCursor/TextCursor.vue';
import { textCursor } from '@/constants/code/TextAnimations/textCursorCode';
import { useForceRerender } from '@/composables/useForceRerender';
const { rerenderKey: key, forceRerender } = useForceRerender()
const { rerenderKey: key, forceRerender } = useForceRerender();
const text = ref('💚')
const followMouseDirection = ref(true)
const randomFloat = ref(true)
const text = ref('💚');
const followMouseDirection = ref(true);
const randomFloat = ref(true);
const propData = [
{
@@ -107,5 +123,5 @@ const propData = [
default: '5',
description: 'The maximum number of trail points to display.'
}
]
</script>
];
</script>

View File

@@ -4,17 +4,33 @@
<template #preview>
<div class="demo-container relative bg-[#060010] min-h-[400px] max-h-[450px] overflow-hidden mb-6">
<div class="w-full h-full">
<TextPressure :key="rerenderKey" :text="text" :flex="flex" :alpha="alpha" :stroke="stroke" :width="width"
:weight="weight" :italic="italic" :text-color="textColor" :stroke-color="strokeColor"
:min-font-size="36" />
<TextPressure
:key="rerenderKey"
:text="text"
:flex="flex"
:alpha="alpha"
:stroke="stroke"
:width="width"
:weight="weight"
:italic="italic"
:text-color="textColor"
:stroke-color="strokeColor"
:min-font-size="36"
/>
</div>
</div>
<Customize>
<div class="mb-4">
<label class="block text-sm font-medium mb-2">Text</label>
<input v-model="text" type="text" placeholder="Your text here..." maxlength="10"
class="w-[200px] px-3 py-2 bg-[#0b0b0b] border border-[#333] rounded-md text-white focus:outline-none focus:border-[#666]" />
<input
v-model="text"
type="text"
placeholder="Your text here..."
maxlength="10"
class="w-[200px] px-3 py-2 bg-[#0b0b0b] border border-[#333] rounded-md text-white focus:outline-none focus:border-[#666]"
/>
</div>
<div class="color-controls">
@@ -24,19 +40,73 @@
</div>
<p class="mt-6 text-[#999] text-sm">Animation Settings</p>
<div class="flex gap-4 flex-wrap">
<PreviewSwitch title="Flex" :model-value="flex"
@update:model-value="(val: boolean) => { flex = val; forceRerender() }" />
<PreviewSwitch title="Alpha" :model-value="alpha"
@update:model-value="(val: boolean) => { alpha = val; forceRerender() }" />
<PreviewSwitch title="Stroke" :model-value="stroke"
@update:model-value="(val: boolean) => { stroke = val; forceRerender() }" />
<PreviewSwitch title="Width" :model-value="width"
@update:model-value="(val: boolean) => { width = val; forceRerender() }" />
<PreviewSwitch title="Weight" :model-value="weight"
@update:model-value="(val: boolean) => { weight = val; forceRerender() }" />
<PreviewSwitch title="Italic" :model-value="italic"
@update:model-value="(val: boolean) => { italic = val; forceRerender() }" />
<PreviewSwitch
title="Flex"
:model-value="flex"
@update:model-value="
(val: boolean) => {
flex = val;
forceRerender();
}
"
/>
<PreviewSwitch
title="Alpha"
:model-value="alpha"
@update:model-value="
(val: boolean) => {
alpha = val;
forceRerender();
}
"
/>
<PreviewSwitch
title="Stroke"
:model-value="stroke"
@update:model-value="
(val: boolean) => {
stroke = val;
forceRerender();
}
"
/>
<PreviewSwitch
title="Width"
:model-value="width"
@update:model-value="
(val: boolean) => {
width = val;
forceRerender();
}
"
/>
<PreviewSwitch
title="Weight"
:model-value="weight"
@update:model-value="
(val: boolean) => {
weight = val;
forceRerender();
}
"
/>
<PreviewSwitch
title="Italic"
:model-value="italic"
@update:model-value="
(val: boolean) => {
italic = val;
forceRerender();
}
"
/>
</div>
</Customize>
@@ -55,29 +125,29 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import PreviewColor from '../../components/common/PreviewColor.vue'
import TextPressure from '../../content/TextAnimations/TextPressure/TextPressure.vue'
import { textPressure } from '@/constants/code/TextAnimations/textPressureCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import PreviewColor from '../../components/common/PreviewColor.vue';
import TextPressure from '../../content/TextAnimations/TextPressure/TextPressure.vue';
import { textPressure } from '@/constants/code/TextAnimations/textPressureCode';
import { useForceRerender } from '@/composables/useForceRerender';
const text = ref('Hello!')
const flex = ref(true)
const alpha = ref(false)
const stroke = ref(false)
const width = ref(true)
const weight = ref(true)
const italic = ref(true)
const textColor = ref('#ffffff')
const strokeColor = ref('#27FF64')
const text = ref('Hello!');
const flex = ref(true);
const alpha = ref(false);
const stroke = ref(false);
const width = ref(true);
const weight = ref(true);
const italic = ref(true);
const textColor = ref('#ffffff');
const strokeColor = ref('#27FF64');
const { rerenderKey, forceRerender } = useForceRerender()
const { rerenderKey, forceRerender } = useForceRerender();
const propData = [
{
@@ -164,7 +234,7 @@ const propData = [
default: '24',
description: 'Sets a minimum font-size to avoid overly tiny text on smaller screens.'
}
]
];
</script>
<style scoped>

View File

@@ -3,28 +3,59 @@
<TabbedLayout>
<template #preview>
<div class="demo-container relative h-[500px] overflow-hidden p-0">
<TextTrail :key="`${key}-${animateColor}`" :noise-factor="noiseFactor" :noise-scale="noiseScale / 10000"
:font-weight="fontWeight" :alpha-persist-factor="alphaPersistFactor" :animate-color="animateColor"
:text-color="animateColor ? undefined : '#ffffff'" />
<TextTrail
:key="`${key}-${animateColor}`"
:noise-factor="noiseFactor"
:noise-scale="noiseScale / 10000"
:font-weight="fontWeight"
:alpha-persist-factor="alphaPersistFactor"
:animate-color="animateColor"
:text-color="animateColor ? undefined : '#ffffff'"
/>
</div>
<Customize>
<PreviewSlider title="Noise Factor" v-model="noiseFactor" :min="1" :max="25" :step="1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Noise Factor"
v-model="noiseFactor"
:min="1"
:max="25"
:step="1"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Noise Scale" v-model="noiseScale" :min="0" :max="100" :step="1"
@update:model-value="forceRerender" />
<PreviewSlider
title="Noise Scale"
v-model="noiseScale"
:min="0"
:max="100"
:step="1"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Font Weight" v-model="fontWeight" :min="100" :max="900" :step="100"
@update:model-value="forceRerender" />
<PreviewSlider
title="Font Weight"
v-model="fontWeight"
:min="100"
:max="900"
:step="100"
@update:model-value="forceRerender"
/>
<PreviewSlider title="Alpha Persist Factor" v-model="alphaPersistFactor" :min="0.5" :max="0.95" :step="0.01"
@update:model-value="forceRerender" />
<PreviewSlider
title="Alpha Persist Factor"
v-model="alphaPersistFactor"
:min="0.5"
:max="0.95"
:step="0.01"
@update:model-value="forceRerender"
/>
<PreviewSwitch title="Animate Color" v-model="animateColor" @update:model-value="forceRerender" />
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['three']" />
</template>
@@ -40,26 +71,26 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TabbedLayout from '../../components/common/TabbedLayout.vue'
import PropTable from '../../components/common/PropTable.vue'
import Dependencies from '../../components/code/Dependencies.vue'
import CliInstallation from '../../components/code/CliInstallation.vue'
import CodeExample from '../../components/code/CodeExample.vue'
import Customize from '../../components/common/Customize.vue'
import PreviewSlider from '../../components/common/PreviewSlider.vue'
import PreviewSwitch from '../../components/common/PreviewSwitch.vue'
import TextTrail from '../../content/TextAnimations/TextTrail/TextTrail.vue'
import { textTrail } from '@/constants/code/TextAnimations/textTrailCode'
import { useForceRerender } from '@/composables/useForceRerender'
import { ref } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import TextTrail from '../../content/TextAnimations/TextTrail/TextTrail.vue';
import { textTrail } from '@/constants/code/TextAnimations/textTrailCode';
import { useForceRerender } from '@/composables/useForceRerender';
const { rerenderKey: key, forceRerender } = useForceRerender()
const { rerenderKey: key, forceRerender } = useForceRerender();
const noiseFactor = ref(1)
const noiseScale = ref(5)
const fontWeight = ref(900)
const alphaPersistFactor = ref(0.95)
const animateColor = ref(false)
const noiseFactor = ref(1);
const noiseScale = ref(5);
const fontWeight = ref(900);
const alphaPersistFactor = ref(0.95);
const animateColor = ref(false);
const propData = [
{
@@ -140,7 +171,7 @@ const propData = [
default: '2',
description: 'Supersampling factor for text quality (higher = better quality)'
}
]
];
</script>
<style scoped>

View File

@@ -0,0 +1,141 @@
<template>
<div class="truefocus-demo">
<TabbedLayout>
<template #preview>
<div class="relative py-6 overflow-hidden demo-container" style="min-height: 200px">
<div :key="key" class="flex flex-col justify-center items-center m-8 pl-6 w-full">
<TrueFocus v-bind="config" />
</div>
</div>
<Customize>
<PreviewColor title="Corners Color" v-model="borderColor" @update:model-value="forceRerender" />
<PreviewSwitch title="Hover Mode" v-model="manualMode" @update:model-value="forceRerender" />
<PreviewSlider
title="Blur Amount"
v-model="blurAmount"
:min="0"
:max="15"
:step="0.5"
value-unit="px"
@update:model-value="forceRerender"
/>
<PreviewSlider
title="Animation Duration"
v-model="animationDuration"
:min="0.1"
:max="3"
:step="0.1"
value-unit="s"
:disabled="!manualMode"
@update:model-value="forceRerender"
/>
<PreviewSlider
title="Pause Between Animations"
v-model="pauseBetweenAnimations"
:min="0"
:max="5"
:step="0.5"
value-unit="s"
:disabled="manualMode"
@update:model-value="forceRerender"
/>
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['motion-v']" />
</template>
<template #code>
<CodeExample :code-object="trueFocus" />
</template>
<template #cli>
<CliInstallation :command="trueFocus.cli" />
</template>
</TabbedLayout>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import Customize from '../../components/common/Customize.vue';
import PreviewColor from '../../components/common/PreviewColor.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
import TrueFocus from '../../content/TextAnimations/TrueFocus/TrueFocus.vue';
import { trueFocus } from '../../constants/code/TextAnimations/trueFocusCode';
import { useForceRerender } from '@/composables/useForceRerender';
const { rerenderKey: key, forceRerender } = useForceRerender();
const manualMode = ref(false);
const blurAmount = ref(5);
const animationDuration = ref(0.5);
const pauseBetweenAnimations = ref(1);
const borderColor = ref('#27FF64');
const config = computed(() => ({
sentence: 'True Focus',
manualMode: manualMode.value,
blurAmount: blurAmount.value,
borderColor: borderColor.value,
animationDuration: animationDuration.value,
pauseBetweenAnimations: pauseBetweenAnimations.value
}));
const propData = [
{
name: 'sentence',
type: 'string',
default: "'True Focus'",
description: 'The text to display with the focus animation.'
},
{
name: 'manualMode',
type: 'boolean',
default: 'false',
description: 'Disables automatic animation when set to true.'
},
{
name: 'blurAmount',
type: 'number',
default: '5',
description: 'The amount of blur applied to non-active words.'
},
{
name: 'borderColor',
type: 'string',
default: "'green'",
description: 'The color of the focus borders.'
},
{
name: 'glowColor',
type: 'string',
default: "'rgba(0, 255, 0, 0.6)'",
description: 'The color of the glowing effect on the borders.'
},
{
name: 'animationDuration',
type: 'number',
default: '0.5',
description: 'The duration of the animation for each word.'
},
{
name: 'pauseBetweenAnimations',
type: 'number',
default: '1',
description: 'Time to pause between focusing on each word (in auto mode).'
}
];
</script>