-
-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Warp Background Component, forked from Magic UI.
- Loading branch information
1 parent
f468f2a
commit 49d8e38
Showing
4 changed files
with
216 additions
and
0 deletions.
There are no files selected for viewing
19 changes: 19 additions & 0 deletions
19
components/content/inspira/examples/warp-background/WarpBackgroundDemo.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<template> | ||
<div class="w-full"> | ||
<WarpBackground> | ||
<UiCard class="mx-auto w-72"> | ||
<UiCardContent class="flex flex-col gap-2 p-4"> | ||
<UiCardTitle>Congratulations on Your Promotion!</UiCardTitle> | ||
<UiCardDescription> | ||
Your hard work and dedication have paid off. We're thrilled to see you take this | ||
next step in your career. Keep up the fantastic work! | ||
</UiCardDescription> | ||
</UiCardContent> | ||
</UiCard> | ||
</WarpBackground> | ||
</div> | ||
</template> | ||
|
||
<script lang="ts" setup></script> | ||
|
||
<style></style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<template> | ||
<div | ||
v-motion | ||
:style="{ | ||
'--x': `${props.x}`, | ||
'--width': `${props.width}`, | ||
'--aspect-ratio': `${ar}`, | ||
'--background': `linear-gradient(hsl(${hue} 80% 60%), transparent)`, | ||
}" | ||
class="absolute left-[var(--x)] top-0 translate-y-[100cqmax] [aspect-ratio:1/var(--aspect-ratio)] [background:var(--background)] [width:var(--width)]" | ||
:initial="{ | ||
x: -50, | ||
y: 200, | ||
}" | ||
:enter="{ | ||
x: -50, | ||
y: -100, | ||
transition: { | ||
duration: props.duration, | ||
delay: props.delay, | ||
repeat: Infinity, | ||
ease: 'linear', | ||
}, | ||
}" | ||
></div> | ||
</template> | ||
|
||
<script lang="ts" setup> | ||
interface Props { | ||
width: string | number; | ||
x: string | number; | ||
delay: number; | ||
duration: number; | ||
} | ||
const props = defineProps<Props>(); | ||
const hue = computed(() => Math.floor(Math.random() * 360)); | ||
const ar = computed(() => Math.floor(Math.random() * 10) + 1); | ||
</script> | ||
|
||
<style></style> |
117 changes: 117 additions & 0 deletions
117
components/content/inspira/ui/warp-background/WarpBackground.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
<template> | ||
<div :class="cn('relative rounded border p-2 md:p-20', props.class)"> | ||
<div | ||
:style="{ | ||
'--perspective': `${props.perspective}px`, | ||
'--grid-color': props.gridColor, | ||
'--beam-size': `${props.beamSize}%`, | ||
}" | ||
class="pointer-events-none absolute left-0 top-0 size-full overflow-hidden [clip-path:inset(0)] [container-type:size] [perspective:var(--perspective)] [transform-style:preserve-3d]" | ||
> | ||
<!-- TOP --> | ||
<div | ||
class="absolute [background-size:var(--beam-size)_var(--beam-size)] [background:linear-gradient(var(--grid-color)_0_1px,_transparent_1px_var(--beam-size))_50%_-0.5px_/var(--beam-size)_var(--beam-size),linear-gradient(90deg,_var(--grid-color)_0_1px,_transparent_1px_var(--beam-size))_50%_50%_/var(--beam-size)_var(--beam-size)] [container-type:inline-size] [height:100cqmax] [transform-origin:50%_0%] [transform-style:preserve-3d] [transform:rotateX(-90deg)] [width:100cqi]" | ||
> | ||
<Beam | ||
v-for="(beam, index) in topBeams" | ||
:key="`top-${index}`" | ||
:width="`${props.beamSize}%`" | ||
:x="`${beam.x * props.beamSize}%`" | ||
:delay="beam.delay" | ||
:duration="beamDuration" | ||
/> | ||
</div> | ||
<!-- BOTTOM --> | ||
<div | ||
class="absolute top-full [background-size:var(--beam-size)_var(--beam-size)] [background:linear-gradient(var(--grid-color)_0_1px,_transparent_1px_var(--beam-size))_50%_-0.5px_/var(--beam-size)_var(--beam-size),linear-gradient(90deg,_var(--grid-color)_0_1px,_transparent_1px_var(--beam-size))_50%_50%_/var(--beam-size)_var(--beam-size)] [container-type:inline-size] [height:100cqmax] [transform-origin:50%_0%] [transform-style:preserve-3d] [transform:rotateX(-90deg)] [width:100cqi]" | ||
> | ||
<Beam | ||
v-for="(beam, index) in bottomBeams" | ||
:key="`bottom-${index}`" | ||
:width="`${props.beamSize}%`" | ||
:x="`${beam.x * props.beamSize}%`" | ||
:delay="beam.delay" | ||
:duration="beamDuration" | ||
/> | ||
</div> | ||
<!-- LEFT --> | ||
<div | ||
class="absolute left-0 top-0 [background-size:var(--beam-size)_var(--beam-size)] [background:linear-gradient(var(--grid-color)_0_1px,_transparent_1px_var(--beam-size))_50%_-0.5px_/var(--beam-size)_var(--beam-size),linear-gradient(90deg,_var(--grid-color)_0_1px,_transparent_1px_var(--beam-size))_50%_50%_/var(--beam-size)_var(--beam-size)] [container-type:inline-size] [height:100cqmax] [transform-origin:0%_0%] [transform-style:preserve-3d] [transform:rotate(90deg)_rotateX(-90deg)] [width:100cqh]" | ||
> | ||
<Beam | ||
v-for="(beam, index) in leftBeams" | ||
:key="`left-${index}`" | ||
:width="`${props.beamSize}%`" | ||
:x="`${beam.x * props.beamSize}%`" | ||
:delay="beam.delay" | ||
:duration="beamDuration" | ||
/> | ||
</div> | ||
<!-- RIGHT --> | ||
<div | ||
class="absolute right-0 top-0 [background-size:var(--beam-size)_var(--beam-size)] [background:linear-gradient(var(--grid-color)_0_1px,_transparent_1px_var(--beam-size))_50%_-0.5px_/var(--beam-size)_var(--beam-size),linear-gradient(90deg,_var(--grid-color)_0_1px,_transparent_1px_var(--beam-size))_50%_50%_/var(--beam-size)_var(--beam-size)] [container-type:inline-size] [height:100cqmax] [transform-origin:100%_0%] [transform-style:preserve-3d] [transform:rotate(-90deg)_rotateX(-90deg)] [width:100cqh]" | ||
> | ||
<Beam | ||
v-for="(beam, index) in rightBeams" | ||
:key="`right-${index}`" | ||
:width="`${props.beamSize}%`" | ||
:x="`${beam.x * props.beamSize}%`" | ||
:delay="beam.delay" | ||
:duration="beamDuration" | ||
/> | ||
</div> | ||
</div> | ||
|
||
<div class="relative"> | ||
<slot /> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script lang="ts" setup> | ||
import { cn } from "@/lib/utils"; | ||
import Beam from "./Beam.vue"; | ||
interface Props { | ||
perspective?: number; | ||
beamsPerSide?: number; | ||
beamSize?: number; | ||
beamDelayMax?: number; | ||
beamDelayMin?: number; | ||
beamDuration?: number; | ||
gridColor?: string; | ||
class?: string; | ||
} | ||
const props = withDefaults(defineProps<Props>(), { | ||
perspective: 100, | ||
beamsPerSide: 3, | ||
beamSize: 5, | ||
beamDelayMax: 3, | ||
beamDelayMin: 0, | ||
beamDuration: 3, | ||
gridColor: "hsl(var(--border))", | ||
}); | ||
const beamDuration = computed(() => props.beamDuration * 1000); | ||
const beamDelayMax = computed(() => props.beamDelayMax * 1000); | ||
const beamDelayMin = computed(() => props.beamDelayMin * 1000); | ||
function generateBeams() { | ||
const beams = []; | ||
for (let i = 0; i < props.beamsPerSide; i++) { | ||
const x = Math.floor((i * Math.floor(100 / props.beamSize)) / props.beamsPerSide); | ||
const delay = Math.random() * beamDelayMax.value - beamDelayMin.value + beamDelayMin.value; | ||
beams.push({ x, delay }); | ||
} | ||
return beams; | ||
} | ||
// generateBeams | ||
const topBeams = generateBeams(); | ||
const bottomBeams = generateBeams(); | ||
const leftBeams = generateBeams(); | ||
const rightBeams = generateBeams(); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
--- | ||
title: Warp Background | ||
description: A container component that applies a warp animation effect to its children | ||
navBadges: | ||
- value: New | ||
type: lime | ||
--- | ||
|
||
::ComponentLoader{label="Preview" componentName="WarpBackgroundDemo" type="examples" id="warp-background"} | ||
:: | ||
|
||
## API | ||
|
||
| Prop Name | Type | Default | Description | | ||
| -------------- | -------- | ---------------------- | ------------------------------------- | | ||
| `perspective` | `number` | `100` | The perspective of the warp animation | | ||
| `beamsPerSide` | `number` | `3` | The number of beams per side | | ||
| `beamSize` | `number` | `5` | The size of the beams | | ||
| `beamDelayMax` | `number` | `3` | The maximum delay of the beams | | ||
| `beamDelayMin` | `number` | `0` | The minimum delay of the beams | | ||
| `beamDuration` | `number` | `3` | The duration of the beams | | ||
| `gridColor` | `string` | `"hsl(var(--border))"` | The color of the grid lines | | ||
|
||
## Component Code | ||
|
||
You can copy and paste the following code to create these components: | ||
|
||
::CodeGroup | ||
::CodeViewer{filename="WarpBackground.vue" language="vue" componentName="WarpBackground" type="ui" id="warp-background"} | ||
:: | ||
|
||
::CodeViewer{filename="Beam.vue" language="vue" componentName="Beam" type="ui" id="warp-background"} | ||
:: | ||
:: | ||
|
||
## Credits | ||
|
||
- Credits to [Whbbit1999](https://github.com/Whbbit1999) for this component. | ||
- Inspired and ported from [Magic UI WarpBackground](https://magicui.design/docs/components/warp-background). |