-
Notifications
You must be signed in to change notification settings - Fork 97
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: add Tiltable component with examples and documentation * docs: add usage examples to illustrate the Tilt component's features * feat: add isRevese prop to Tilt component for reverse rotation * docs: add isRevese prop description to Tilt component documentation * feat: update tilt API * feat: add tilt-spotlight * feat: tilt UI examples update * fix: build --------- Co-authored-by: afpedreros <[email protected]>
- Loading branch information
1 parent
5f72b88
commit fa4d98d
Showing
5 changed files
with
218 additions
and
0 deletions.
There are no files selected for viewing
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
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,52 @@ | ||
export const metadata = { | ||
title: 'Tilt - Motion-Primitives', | ||
description: | ||
'3D tilt effect that responds to mouse movement, enhancing UI elements with a dynamic depth effect, customizable rotation factors and spring options.', | ||
}; | ||
|
||
import { TiltCard1 } from './tilt-card-1'; | ||
import { TiltSpotlight } from './tilt-spotlight'; | ||
import ComponentCodePreview from '@/components/website/component-code-preview'; | ||
import CodeBlock from '@/components/website/code-block'; | ||
|
||
# Tilt | ||
|
||
3D tilt effect that responds to mouse movement, enhancing UI elements with a dynamic depth effect, customizable rotation factors and spring options. | ||
|
||
## Examples | ||
|
||
### Basic Tilt Card | ||
|
||
<ComponentCodePreview | ||
component={<TiltCard1 />} | ||
filePath='app/docs/tilt/tilt-card-1.tsx' | ||
/> | ||
|
||
### Tilt with Spotlight | ||
|
||
Example of the [Spotlight component](/docs/spotlight) used with the Tilt component. | ||
|
||
<ComponentCodePreview | ||
component={<TiltSpotlight />} | ||
filePath='app/docs/tilt/tilt-spotlight.tsx' | ||
/> | ||
|
||
## Code | ||
|
||
<CodeBlock filePath='components/core/tilt.tsx' /> | ||
|
||
## Component API | ||
|
||
### Border Trail | ||
|
||
| Prop | Type | Default | Description | | ||
| :------------- | :------------ | :------ | :---------------------------------------------- | | ||
| className | string | | Additional CSS classes for styling the tilt. | | ||
| style | MotionStyle | | Additional CSS classes for styling the tilt. | | ||
| rotationFactor | number | 15 | Controls the maximum rotation angle in degrees. | | ||
| isRevese | boolean | false | Reverses the tilt effect's rotation direction. | | ||
| springOptions | SpringOptions | | Spring options for the tilt effect. | | ||
|
||
## Credits | ||
|
||
Initiated by [@AFPedreros](https://github.com/AFPedreros) |
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,26 @@ | ||
import { Tilt } from '@/components/core/tilt'; | ||
|
||
export function TiltCard1() { | ||
return ( | ||
<Tilt rotationFactor={8} isRevese> | ||
<div | ||
style={{ | ||
borderRadius: '12px', | ||
}} | ||
className='flex max-w-[270px] flex-col overflow-hidden border border-zinc-950/10 bg-white dark:border-zinc-50/10 dark:bg-zinc-900' | ||
> | ||
<img | ||
src='https://images.beta.cosmos.so/f7fcb95d-981b-4cb3-897f-e35f6c20e830?format=jpeg' | ||
alt='Ghost in the shell - Kôkaku kidôtai' | ||
className='h-48 w-full object-cover' | ||
/> | ||
<div className='p-2'> | ||
<h1 className='font-mono leading-snug text-zinc-950 dark:text-zinc-50'> | ||
Ghost in the Shell | ||
</h1> | ||
<p className='text-zinc-700 dark:text-zinc-400'>Kôkaku kidôtai</p> | ||
</div> | ||
</div> | ||
</Tilt> | ||
); | ||
} |
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,43 @@ | ||
import { Spotlight } from '@/components/core/spotlight'; | ||
import { Tilt } from '@/components/core/tilt'; | ||
|
||
export function TiltSpotlight() { | ||
return ( | ||
<div className='max-w-sm'> | ||
<Tilt | ||
rotationFactor={6} | ||
isRevese | ||
style={{ | ||
transformOrigin: 'center center', | ||
}} | ||
springOptions={{ | ||
stiffness: 26.7, | ||
damping: 4.1, | ||
mass: 0.2, | ||
}} | ||
className='group relative rounded-lg' | ||
> | ||
<Spotlight | ||
className='z-10 from-white/50 via-white/20 to-white/10 blur-2xl' | ||
size={248} | ||
springOptions={{ | ||
stiffness: 26.7, | ||
damping: 4.1, | ||
mass: 0.2, | ||
}} | ||
/> | ||
<img | ||
src='https://images.beta.cosmos.so/f7fcb95d-981b-4cb3-897f-e35f6c20e830?format=jpeg' | ||
alt='Ghost in the shell - Kôkaku kidôtai' | ||
className='h-32 w-full rounded-lg object-cover grayscale duration-700 group-hover:grayscale-0' | ||
/> | ||
</Tilt> | ||
<div className='flex flex-col space-y-0.5 pb-0 pt-3'> | ||
<h3 className='font-mono text-sm font-medium text-zinc-500 dark:text-zinc-400'> | ||
Ghost in the Shell | ||
</h3> | ||
<p className='text-sm text-black dark:text-white'>Kôkaku kidôtai</p> | ||
</div> | ||
</div> | ||
); | ||
} |
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,92 @@ | ||
'use client'; | ||
|
||
import React, { useRef } from 'react'; | ||
import { | ||
motion, | ||
useMotionTemplate, | ||
useMotionValue, | ||
useSpring, | ||
useTransform, | ||
MotionStyle, | ||
SpringOptions, | ||
} from 'framer-motion'; | ||
|
||
type TiltProps = { | ||
children: React.ReactNode; | ||
className?: string; | ||
style?: MotionStyle; | ||
rotationFactor?: number; | ||
isRevese?: boolean; | ||
springOptions?: SpringOptions; | ||
}; | ||
|
||
export function Tilt({ | ||
children, | ||
className, | ||
style, | ||
rotationFactor = 15, | ||
isRevese = false, | ||
springOptions, | ||
}: TiltProps) { | ||
const ref = useRef<HTMLDivElement>(null); | ||
|
||
const x = useMotionValue(0); | ||
const y = useMotionValue(0); | ||
|
||
const xSpring = useSpring(x, springOptions); | ||
const ySpring = useSpring(y, springOptions); | ||
|
||
const rotateX = useTransform( | ||
ySpring, | ||
[-0.5, 0.5], | ||
isRevese | ||
? [rotationFactor, -rotationFactor] | ||
: [-rotationFactor, rotationFactor] | ||
); | ||
const rotateY = useTransform( | ||
xSpring, | ||
[-0.5, 0.5], | ||
isRevese | ||
? [-rotationFactor, rotationFactor] | ||
: [rotationFactor, -rotationFactor] | ||
); | ||
|
||
const transform = useMotionTemplate`perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`; | ||
|
||
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => { | ||
if (!ref.current) return; | ||
|
||
const rect = ref.current.getBoundingClientRect(); | ||
const width = rect.width; | ||
const height = rect.height; | ||
const mouseX = e.clientX - rect.left; | ||
const mouseY = e.clientY - rect.top; | ||
|
||
const xPos = mouseX / width - 0.5; | ||
const yPos = mouseY / height - 0.5; | ||
|
||
x.set(xPos); | ||
y.set(yPos); | ||
}; | ||
|
||
const handleMouseLeave = () => { | ||
x.set(0); | ||
y.set(0); | ||
}; | ||
|
||
return ( | ||
<motion.div | ||
ref={ref} | ||
className={className} | ||
style={{ | ||
transformStyle: 'preserve-3d', | ||
...style, | ||
transform, | ||
}} | ||
onMouseMove={handleMouseMove} | ||
onMouseLeave={handleMouseLeave} | ||
> | ||
{children} | ||
</motion.div> | ||
); | ||
} |