mirror of
https://github.com/FranP-code/spooky-spotify-showcase.git
synced 2025-10-13 00:02:36 +00:00
Tilt effect
This commit is contained in:
@@ -26,6 +26,7 @@
|
|||||||
"next": "^14.2.4",
|
"next": "^14.2.4",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
"react-parallax-tilt": "^1.7.246",
|
||||||
"server-only": "^0.0.1",
|
"server-only": "^0.0.1",
|
||||||
"spotify-web-api-node": "^5.0.2",
|
"spotify-web-api-node": "^5.0.2",
|
||||||
"superjson": "^2.2.1",
|
"superjson": "^2.2.1",
|
||||||
|
|||||||
32
pnpm-lock.yaml
generated
32
pnpm-lock.yaml
generated
@@ -41,6 +41,9 @@ importers:
|
|||||||
react-dom:
|
react-dom:
|
||||||
specifier: ^18.3.1
|
specifier: ^18.3.1
|
||||||
version: 18.3.1(react@18.3.1)
|
version: 18.3.1(react@18.3.1)
|
||||||
|
react-parallax-tilt:
|
||||||
|
specifier: ^1.7.246
|
||||||
|
version: 1.7.246(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
server-only:
|
server-only:
|
||||||
specifier: ^0.0.1
|
specifier: ^0.0.1
|
||||||
version: 0.0.1
|
version: 0.0.1
|
||||||
@@ -1518,6 +1521,12 @@ packages:
|
|||||||
react-is@16.13.1:
|
react-is@16.13.1:
|
||||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||||
|
|
||||||
|
react-parallax-tilt@1.7.246:
|
||||||
|
resolution: {integrity: sha512-2NFfrQKlmB+zkDSKT4jaJg88elk0IvMeM/R8A/Scir7B1tKUdSqcio0Gp2aLEdVghO57M0fPMa6FYN7yjKrSYQ==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||||
|
react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||||
|
|
||||||
react@18.3.1:
|
react@18.3.1:
|
||||||
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
|
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -2550,8 +2559,8 @@ snapshots:
|
|||||||
'@typescript-eslint/parser': 8.8.1(eslint@8.57.1)(typescript@5.6.3)
|
'@typescript-eslint/parser': 8.8.1(eslint@8.57.1)(typescript@5.6.3)
|
||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1)
|
eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1)
|
||||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
|
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
|
||||||
eslint-plugin-jsx-a11y: 6.10.0(eslint@8.57.1)
|
eslint-plugin-jsx-a11y: 6.10.0(eslint@8.57.1)
|
||||||
eslint-plugin-react: 7.37.1(eslint@8.57.1)
|
eslint-plugin-react: 7.37.1(eslint@8.57.1)
|
||||||
eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1)
|
eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1)
|
||||||
@@ -2570,37 +2579,37 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1):
|
eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nolyfill/is-core-module': 1.0.39
|
'@nolyfill/is-core-module': 1.0.39
|
||||||
debug: 4.3.7
|
debug: 4.3.7
|
||||||
enhanced-resolve: 5.17.1
|
enhanced-resolve: 5.17.1
|
||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
|
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
|
||||||
fast-glob: 3.3.2
|
fast-glob: 3.3.2
|
||||||
get-tsconfig: 4.8.1
|
get-tsconfig: 4.8.1
|
||||||
is-bun-module: 1.2.1
|
is-bun-module: 1.2.1
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
|
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@typescript-eslint/parser'
|
- '@typescript-eslint/parser'
|
||||||
- eslint-import-resolver-node
|
- eslint-import-resolver-node
|
||||||
- eslint-import-resolver-webpack
|
- eslint-import-resolver-webpack
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1):
|
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 3.2.7
|
debug: 3.2.7
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@typescript-eslint/parser': 8.8.1(eslint@8.57.1)(typescript@5.6.3)
|
'@typescript-eslint/parser': 8.8.1(eslint@8.57.1)(typescript@5.6.3)
|
||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1)
|
eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1):
|
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rtsao/scc': 1.1.0
|
'@rtsao/scc': 1.1.0
|
||||||
array-includes: 3.1.8
|
array-includes: 3.1.8
|
||||||
@@ -2611,7 +2620,7 @@ snapshots:
|
|||||||
doctrine: 2.1.0
|
doctrine: 2.1.0
|
||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
|
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
|
||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
is-core-module: 2.15.1
|
is-core-module: 2.15.1
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
@@ -3369,6 +3378,11 @@ snapshots:
|
|||||||
|
|
||||||
react-is@16.13.1: {}
|
react-is@16.13.1: {}
|
||||||
|
|
||||||
|
react-parallax-tilt@1.7.246(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||||
|
dependencies:
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
|
||||||
react@18.3.1:
|
react@18.3.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify: 1.4.0
|
loose-envify: 1.4.0
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import Tilt from "react-parallax-tilt";
|
||||||
import { TrackByAlbum } from "./spotify-data";
|
import { TrackByAlbum } from "./spotify-data";
|
||||||
import { api } from "@/trpc/react";
|
import { api } from "@/trpc/react";
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ export default function AlbumShowcase({
|
|||||||
? album.images[0].url
|
? album.images[0].url
|
||||||
: "https://via.placeholder.com/150";
|
: "https://via.placeholder.com/150";
|
||||||
|
|
||||||
|
const [showSpookyImage, setShowSpookyImage] = useState(false);
|
||||||
const [spookyImageLoaded, setSpookyImageLoaded] = useState(false);
|
const [spookyImageLoaded, setSpookyImageLoaded] = useState(false);
|
||||||
|
|
||||||
const entry = api.entry.get.useQuery({
|
const entry = api.entry.get.useQuery({
|
||||||
@@ -72,19 +74,33 @@ export default function AlbumShowcase({
|
|||||||
className="flex w-full flex-wrap gap-3 rounded-xl bg-white bg-opacity-10 p-5 backdrop-blur-lg backdrop-filter"
|
className="flex w-full flex-wrap gap-3 rounded-xl bg-white bg-opacity-10 p-5 backdrop-blur-lg backdrop-filter"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<img className="h-36 w-36 rounded" src={imageSource} alt={album.name} />
|
<Tilt tiltMaxAngleX={10} tiltMaxAngleY={10} transitionSpeed={200}>
|
||||||
{!!spookyImageSource && (
|
|
||||||
<img
|
<img
|
||||||
className="h-36 w-36 rounded"
|
onClick={() => setShowSpookyImage(!showSpookyImage)}
|
||||||
src={spookyImageSource}
|
className="h-36 w-36 cursor-pointer rounded"
|
||||||
alt={album.name}
|
style={{
|
||||||
onLoad={() => {
|
display: showSpookyImage ? "none" : "block",
|
||||||
if (!spookyImageLoaded && generateSpookyImage.data) {
|
|
||||||
setSpookyImageLoaded(true);
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
|
src={imageSource}
|
||||||
|
alt={album.name}
|
||||||
/>
|
/>
|
||||||
)}
|
{!!spookyImageSource && (
|
||||||
|
<img
|
||||||
|
onClick={() => setShowSpookyImage(!showSpookyImage)}
|
||||||
|
className="h-36 w-36 cursor-pointer rounded"
|
||||||
|
style={{
|
||||||
|
display: showSpookyImage ? "block" : "none",
|
||||||
|
}}
|
||||||
|
src={spookyImageSource}
|
||||||
|
alt={album.name}
|
||||||
|
onLoad={() => {
|
||||||
|
if (!spookyImageLoaded && generateSpookyImage.data) {
|
||||||
|
setSpookyImageLoaded(true);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Tilt>
|
||||||
</div>
|
</div>
|
||||||
<section className="flex h-36 flex-grow flex-col">
|
<section className="flex h-36 flex-grow flex-col">
|
||||||
<h4 className="mb-2 text-lg font-semibold leading-none">
|
<h4 className="mb-2 text-lg font-semibold leading-none">
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
"use client";
|
||||||
|
import Tilt from "react-parallax-tilt";
|
||||||
|
|
||||||
export default function ArtistShowcase({
|
export default function ArtistShowcase({
|
||||||
images,
|
images,
|
||||||
name,
|
name,
|
||||||
@@ -12,14 +15,16 @@ export default function ArtistShowcase({
|
|||||||
: "https://via.placeholder.com/150";
|
: "https://via.placeholder.com/150";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-2 w-56 overflow-hidden rounded-md border-2 border-slate-700">
|
<Tilt tiltMaxAngleX={10} tiltMaxAngleY={10} transitionSpeed={200}>
|
||||||
<img className="h-56 w-56 object-fill" src={imageSource} alt={name} />
|
<div className="mb-2 w-56 cursor-pointer overflow-hidden rounded-md border-2 border-slate-700">
|
||||||
<p
|
<img className="h-56 w-56 object-fill" src={imageSource} alt={name} />
|
||||||
className="w-full truncate break-all border-t-2 border-slate-300 bg-slate-200 p-2 text-center text-sm font-medium text-slate-700"
|
<p
|
||||||
title={name}
|
className="w-full truncate break-all border-t-2 border-slate-300 bg-slate-200 p-2 text-center text-sm font-medium text-slate-700"
|
||||||
>
|
title={name}
|
||||||
{name}
|
>
|
||||||
</p>
|
{name}
|
||||||
</div>
|
</p>
|
||||||
|
</div>
|
||||||
|
</Tilt>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user