Merge branch 'main' into feat/bounce-cards

This commit is contained in:
David
2025-07-25 16:39:31 +03:00
committed by GitHub
16 changed files with 2083 additions and 4 deletions
+202
View File
@@ -0,0 +1,202 @@
<template>
<TabbedLayout>
<template #preview>
<div class="relative p-0 h-[600px] overflow-hidden demo-container">
<FaultyTerminal
:key="key"
:scale="scale"
:digit-size="digitSize"
:time-scale="timeScale"
:scanline-intensity="scanlineIntensity"
:curvature="curvature"
:tint="tint"
:mouse-react="mouseReact"
:mouse-strength="mouseStrength"
:page-load-animation="pageLoadAnimation"
:noise-amp="noiseAmp"
:brightness="brightness"
/>
<BackgroundContent pill-text="New Background" headline="It works on my machine, please check again" />
</div>
<Customize>
<PreviewColor title="Tint Color" v-model="tint" />
<PreviewSlider :min="1" :max="3" :step="0.1" v-model="scale" title="Scale" />
<PreviewSlider :min="0.5" :max="3" :step="0.1" v-model="digitSize" title="Digit Size" />
<PreviewSlider :min="0" :max="3" :step="0.1" v-model="timeScale" title="Speed" />
<PreviewSlider :min="0.5" :max="1" :step="0.1" v-model="noiseAmp" title="Noise Amplitude" />
<PreviewSlider :min="0.1" :max="1" :step="0.1" v-model="brightness" title="Brightness" />
<PreviewSlider :min="0" :max="2" :step="0.1" v-model="scanlineIntensity" title="Scanline Intensity" />
<PreviewSlider :min="0" :max="0.5" :step="0.01" v-model="curvature" title="Curvature" />
<PreviewSlider :min="0" :max="2" :step="0.1" v-model="mouseStrength" title="Mouse Strength" />
<PreviewSwitch title="Mouse React" v-model="mouseReact" />
<PreviewSwitch title="Page Load Animation" v-model="pageLoadAnimation" />
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['ogl']" />
</template>
<template #code>
<CodeExample :code-object="faultyTerminal" />
</template>
<template #cli>
<CliInstallation :command="faultyTerminal.cli" />
</template>
</TabbedLayout>
</template>
<script setup lang="ts">
import { useForceRerender } from '@/composables/useForceRerender';
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 BackgroundContent from '../../components/common/BackgroundContent.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 PropTable from '../../components/common/PropTable.vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import { faultyTerminal } from '../../constants/code/Backgrounds/faultyTerminalCode';
import FaultyTerminal from '../../content/Backgrounds/FaultyTerminal/FaultyTerminal.vue';
const { rerenderKey: key } = useForceRerender();
const scale = ref(1.5);
const digitSize = ref(1.2);
const timeScale = ref(0.5);
const scanlineIntensity = ref(0.5);
const curvature = ref(0.1);
const tint = ref('#A7EF9E');
const mouseReact = ref(true);
const mouseStrength = ref(0.5);
const pageLoadAnimation = ref(true);
const noiseAmp = ref(1);
const brightness = ref(0.6);
const propData = [
{
name: 'scale',
type: 'number',
default: '1.5',
description: 'Controls the zoom/scale of the pattern.'
},
{
name: 'gridMul',
type: 'Vec2',
default: '[2, 1]',
description: 'Grid multiplier for glyph density [x, y].'
},
{
name: 'digitSize',
type: 'number',
default: '1.2',
description: 'Size of individual glyphs.'
},
{
name: 'timeScale',
type: 'number',
default: '1',
description: 'Animation speed multiplier.'
},
{
name: 'pause',
type: 'boolean',
default: 'false',
description: 'Pause/resume animation.'
},
{
name: 'scanlineIntensity',
type: 'number',
default: '1',
description: 'Strength of scanline effects.'
},
{
name: 'glitchAmount',
type: 'number',
default: '1',
description: 'Glitch displacement intensity.'
},
{
name: 'flickerAmount',
type: 'number',
default: '1',
description: 'Flicker effect strength.'
},
{
name: 'noiseAmp',
type: 'number',
default: '1',
description: 'Noise pattern amplitude.'
},
{
name: 'chromaticAberration',
type: 'number',
default: '0',
description: 'RGB channel separation in pixels.'
},
{
name: 'dither',
type: 'number | boolean',
default: '0',
description: 'Dithering effect intensity.'
},
{
name: 'curvature',
type: 'number',
default: '0',
description: 'Barrel distortion amount.'
},
{
name: 'tint',
type: 'string',
default: "'#ffffff'",
description: 'Color tint (hex).'
},
{
name: 'mouseReact',
type: 'boolean',
default: 'true',
description: 'Enable/disable mouse interaction.'
},
{
name: 'mouseStrength',
type: 'number',
default: '0.5',
description: 'Mouse interaction intensity.'
},
{
name: 'pageLoadAnimation',
type: 'boolean',
default: 'false',
description: 'Enable fade-in animation on load.'
},
{
name: 'brightness',
type: 'number',
default: '1',
description: 'Overall opacity/brightness control.'
},
{
name: 'className',
type: 'string',
default: "''",
description: 'Additional CSS classes.'
},
{
name: 'style',
type: 'React.CSSProperties',
default: '{}',
description: 'Inline styles.'
}
];
</script>
<style scoped>
.demo-container {
padding: 0;
}
</style>
+177
View File
@@ -0,0 +1,177 @@
<template>
<TabbedLayout>
<template #preview>
<div class="demo-container h-[400px] overflow-hidden relative">
<Counter
:value="value"
:places="[100, 10, 1]"
gradientFrom="#0b0b0b"
:fontSize="fontSize"
:padding="5"
:gap="gap"
:borderRadius="10"
:horizontalPadding="15"
textColor="white"
:fontWeight="900"
/>
<div class="flex gap-4 bottom-4 justify-center mt-4 absolute left-1/2 transform -translate-x-1/2">
<button
class="cursor-pointer bg-[#0b0b0b] rounded-[10px] border border-[#333] hover:bg-[#222] text-white h-10 w-10 transition-colors"
@click="value > 0 && value--"
>
-
</button>
<button
class="cursor-pointer bg-[#0b0b0b] rounded-[10px] border border-[#333] hover:bg-[#222] text-white h-10 w-10 transition-colors"
@click="value < 999 && value++"
>
+
</button>
</div>
</div>
<Customize>
<PreviewSlider title="Value" v-model="value" :min="0" :max="999" :step="1" />
<PreviewSlider title="Gap" v-model="gap" :min="0" :max="50" :step="5" />
<PreviewSlider title="Font Size" v-model="fontSize" :min="40" :max="200" :step="10" />
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['motion-v']" />
</template>
<template #code>
<CodeExample :code-object="counter" />
</template>
<template #cli>
<CliInstallation :command="counter.cli" />
</template>
</TabbedLayout>
</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 PropTable from '../../components/common/PropTable.vue';
import CodeExample from '../../components/code/CodeExample.vue';
import CliInstallation from '../../components/code/CliInstallation.vue';
import Dependencies from '../../components/code/Dependencies.vue';
import Counter from '../../content/Components/Counter/Counter.vue';
import { counter } from '../../constants/code/Components/counterCode';
const value = ref(123);
const fontSize = ref(80);
const gap = ref(10);
const propData = [
{
name: 'value',
type: 'number',
default: 'N/A (required)',
description: 'The numeric value to display in the counter.'
},
{
name: 'fontSize',
type: 'number',
default: '100',
description: 'The base font size used for the counter digits.'
},
{
name: 'padding',
type: 'number',
default: '0',
description: 'Additional padding added to the digit height.'
},
{
name: 'places',
type: 'number[]',
default: '[100, 10, 1]',
description: 'An array of place values to determine which digits to display.'
},
{
name: 'gap',
type: 'number',
default: '8',
description: 'The gap (in pixels) between each digit.'
},
{
name: 'borderRadius',
type: 'number',
default: '4',
description: 'The border radius (in pixels) for the counter container.'
},
{
name: 'horizontalPadding',
type: 'number',
default: '8',
description: 'The horizontal padding (in pixels) for the counter container.'
},
{
name: 'textColor',
type: 'string',
default: "'white'",
description: 'The text color for the counter digits.'
},
{
name: 'fontWeight',
type: 'string | number',
default: "'bold'",
description: 'The font weight of the counter digits.'
},
{
name: 'containerStyle',
type: 'CSSProperties',
default: '{}',
description: 'Custom inline styles for the outer container.'
},
{
name: 'counterStyle',
type: 'CSSProperties',
default: '{}',
description: 'Custom inline styles for the counter element.'
},
{
name: 'digitStyle',
type: 'CSSProperties',
default: '{}',
description: 'Custom inline styles for each digit container.'
},
{
name: 'gradientHeight',
type: 'number',
default: '16',
description: 'The height (in pixels) of the gradient overlays.'
},
{
name: 'gradientFrom',
type: 'string',
default: "'black'",
description: 'The starting color for the gradient overlays.'
},
{
name: 'gradientTo',
type: 'string',
default: "'transparent'",
description: 'The ending color for the gradient overlays.'
},
{
name: 'topGradientStyle',
type: 'CSSProperties',
default: 'undefined',
description: 'Custom inline styles for the top gradient overlay.'
},
{
name: 'bottomGradientStyle',
type: 'CSSProperties',
default: 'undefined',
description: 'Custom inline styles for the bottom gradient overlay.'
}
];
</script>
@@ -0,0 +1,75 @@
<template>
<TabbedLayout>
<template #preview>
<div class="demo-container relative min-h-[500px] overflow-hidden">
<div class="flex h-full max-w-[600px] flex-col items-center justify-center">
<h2
class="absolute top-4 mt-6 whitespace-nowrap text-center font-black text-2xl text-white md:top-4 md:text-5xl"
>
Your trip to Thailand.
</h2>
<RollingGallery
:autoplay="autoplay"
:pause-on-hover="pauseOnHover"
:images="customImages.length > 0 ? customImages : undefined"
/>
</div>
</div>
<Customize>
<PreviewSwitch title="Autoplay" v-model="autoplay" />
<PreviewSwitch title="Pause on Hover" v-model="pauseOnHover" />
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['motion-v']" />
</template>
<template #code>
<CodeExample :code-object="rollingGallery" />
</template>
<template #cli>
<CliInstallation :command="rollingGallery.cli" />
</template>
</TabbedLayout>
</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 RollingGallery from '@/content/Components/RollingGallery/RollingGallery.vue';
import { rollingGallery } from '@/constants/code/Components/rollingGalleryCode';
const autoplay = ref(true);
const pauseOnHover = ref(true);
const customImages = ref<string[]>([]);
const propData = [
{
name: 'autoplay',
type: 'boolean',
default: 'false',
description: 'Controls the autoplay toggle of the carousel. When turned on, it rotates and loops infinitely.'
},
{
name: 'pauseOnHover',
type: 'boolean',
default: 'false',
description: 'Allows the carousel to be paused on hover when autoplay is turned on.'
},
{
name: 'images',
type: 'string[]',
default: '[]',
description: 'Array of image URLs to display in the gallery.'
}
];
</script>
+216
View File
@@ -0,0 +1,216 @@
<template>
<TabbedLayout>
<template #preview>
<div class="relative h-[500px] overflow-hidden demo-container">
<RefreshButton
@refresh="
() => {
isCompleted = false;
forceRerender();
}
"
/>
<p
class="top-[25%] left-[50%] absolute font-black text-[#333] text-[clamp(2rem,4vw,3rem)] text-center transition-all -translate-x-1/2 -translate-y-1/2 duration-300 ease-in-out pointer-events-none transform"
>
{{ isCompleted ? 'Stack Completed!' : 'Scroll Down' }}
</p>
<ScrollStack
:key="rerenderKey"
:item-distance="itemDistance"
className="scroll-stack-demo-container"
:item-stack-distance="itemStackDistance"
:stack-position="stackPosition"
:base-scale="baseScale"
:rotation-amount="rotationAmount"
:blur-amount="blurAmount"
@stackComplete="handleStackComplete"
>
<ScrollStackItem itemClassName="scroll-stack-card-demo ssc-demo-1">
<h3>Text Animations</h3>
<div className="stack-img-container">
<i class="pi-align-left pi" style="font-size: 120px"></i>
</div>
</ScrollStackItem>
<ScrollStackItem itemClassName="scroll-stack-card-demo ssc-demo-2">
<h3>Animations</h3>
<div className="stack-img-container">
<i class="pi pi-play" style="font-size: 120px"></i>
</div>
</ScrollStackItem>
<ScrollStackItem itemClassName="scroll-stack-card-demo ssc-demo-3">
<h3>Components</h3>
<div className="stack-img-container">
<i class="pi pi-sliders-h" style="font-size: 120px"></i>
</div>
</ScrollStackItem>
<ScrollStackItem itemClassName="scroll-stack-card-demo ssc-demo-4">
<h3>Backgrounds</h3>
<div className="stack-img-container">
<i class="pi pi-image" style="font-size: 120px"></i>
</div>
</ScrollStackItem>
<ScrollStackItem itemClassName="scroll-stack-card-demo ssc-demo-5">
<h3>All on Vue Bits!</h3>
</ScrollStackItem>
</ScrollStack>
</div>
<Customize>
<PreviewSlider title="Item Distance" v-model="itemDistance" :min="0" :max="1000" :step="10" value-unit="px" />
<PreviewSlider
title="Stack Distance"
v-model="itemStackDistance"
:min="0"
:max="40"
:step="5"
value-unit="px"
/>
<PreviewSelect title="Stack Position" v-model="stackPosition" :options="stackPositionOptions" />
<PreviewSlider title="Base Scale" v-model="baseScale" :min="0.5" :max="1.0" :step="0.05" />
<PreviewSlider title="Rotation Amount" v-model="rotationAmount" :min="0" :max="1" :step="0.1" value-unit="°" />
<PreviewSlider title="Blur Amount" v-model="blurAmount" :min="0" :max="10" :step="0.5" value-unit="px" />
</Customize>
<PropTable :data="propData" />
<Dependencies :dependency-list="['lenis']" />
</template>
<template #code>
<CodeExample :code-object="scrollStack" />
</template>
<template #cli>
<CliInstallation :command="scrollStack.cli" />
</template>
</TabbedLayout>
</template>
<script setup lang="ts">
import PreviewSelect from '@/components/common/PreviewSelect.vue';
import { useForceRerender } from '@/composables/useForceRerender';
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 Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue';
import PropTable from '../../components/common/PropTable.vue';
import RefreshButton from '../../components/common/RefreshButton.vue';
import TabbedLayout from '../../components/common/TabbedLayout.vue';
import { scrollStack } from '../../constants/code/Components/scrollStackCode';
import ScrollStack, { ScrollStackItem } from '../../content/Components/ScrollStack/ScrollStack.vue';
const { rerenderKey, forceRerender } = useForceRerender();
const isCompleted = ref(false);
const itemDistance = ref(200);
const itemStackDistance = ref(30);
const baseScale = ref(0.85);
const rotationAmount = ref(0);
const blurAmount = ref(0);
const stackPosition = ref('20%');
const handleStackComplete = () => {
isCompleted.value = true;
};
const stackPositionOptions = [
{ value: '10%', label: '10%' },
{ value: '15%', label: '15%' },
{ value: '20%', label: '20%' },
{ value: '25%', label: '25%' },
{ value: '30%', label: '30%' },
{ value: '35%', label: '35%' }
];
const propData = [
{
name: 'children',
type: 'ReactNode',
default: 'required',
description: 'The content to be displayed in the scroll stack. Should contain ScrollStackItem components.'
},
{
name: 'className',
type: 'string',
default: '""',
description: 'Additional CSS classes to apply to the scroll stack container.'
},
{
name: 'itemDistance',
type: 'number',
default: '100',
description: 'Distance between stacked items in pixels.'
},
{
name: 'itemScale',
type: 'number',
default: '0.03',
description: 'Scale increment for each stacked item.'
},
{
name: 'itemStackDistance',
type: 'number',
default: '30',
description: 'Distance between items when they start stacking.'
},
{
name: 'stackPosition',
type: 'string',
default: '"20%"',
description: 'Position where the stacking effect begins as a percentage of viewport height.'
},
{
name: 'scaleEndPosition',
type: 'string',
default: '"10%"',
description: 'Position where the scaling effect ends as a percentage of viewport height.'
},
{
name: 'baseScale',
type: 'number',
default: '0.85',
description: 'Base scale value for the first item in the stack.'
},
{
name: 'scaleDuration',
type: 'number',
default: '0.5',
description: 'Duration of the scaling animation in seconds.'
},
{
name: 'rotationAmount',
type: 'number',
default: '0',
description: 'Rotation amount for each item in degrees.'
},
{
name: 'blurAmount',
type: 'number',
default: '0',
description: 'Blur amount for items that are further back in the stack.'
},
{
name: 'onStackComplete',
type: 'function',
default: 'undefined',
description: 'Callback function called when the stack animation is complete.'
}
];
</script>
<style scoped>
.demo-container {
padding: 0;
}
</style>