Skip to content

Commit

Permalink
feat: add music stack interaction widget (#314)
Browse files Browse the repository at this point in the history
  • Loading branch information
mohitahlawat2001 authored Oct 17, 2024
1 parent 20b049d commit f74de40
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 4 deletions.
10 changes: 6 additions & 4 deletions .github/ISSUE_TEMPLATE/new-component-ticket.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,28 @@ name: New Component Ticket [HACKTOBERFEST]
about: Create a new animated component task for Hacktoberfest
title: Component Name
labels: hacktoberfest
assignees: ''

assignees: ""
---

### Description

Create the component as shown in the video attached below.

### Animation Preview

- Screenshot/Video:

[Upload file here]


> [!NOTE]
> Please refer to the **Animata contributing guidelines** available [here](https://www.animata.design/docs/contributing) for rules on how to contribute to the project. Let us know in the comments if you’re working on this issue, and feel free to ask any questions!
### Requirements

1. Create a new animated component that matches the provided design.
2. Add example usage of the component in the documentation or storybook.
3. **Add credits** for any resources, references, or assets used, as specified in the **Additional Resources** section.


<details>
<summary>
<h3> Guidelines & Best Practices</h3>
Expand All @@ -38,12 +38,14 @@ Create the component as shown in the video attached below.

> [!IMPORTANT]
> To ensure more contributors have the opportunity to participate, we kindly request that:
>
> - Each contributor submits only **one pull request** related to this issue.
> - If you're interested in working on this issue, please comment below. We will assign the issue on a **first-come, first-served basis**.
---

### Additional Resources

<!-- Add references and credits here -->

---
Expand Down
53 changes: 53 additions & 0 deletions animata/widget/music-stack-interaction.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import MusicStackInteraction from "@/animata/widget/music-stack-interaction";
import { Meta, StoryObj } from "@storybook/react";

const meta = {
title: "Widget/Music Stack Interaction",
component: MusicStackInteraction,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
argTypes: {},
} satisfies Meta<typeof MusicStackInteraction>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Primary: Story = {
args: {
albums: [
{
id: 1,
title: "The Dark Side of the Moon",
artist: "Pink Floyd",
cover: "https://images.unsplash.com/photo-1569424758782-cba94e6165fd",
},
{
id: 2,
title: "Abbey Road",
artist: "The Beatles",
cover: "https://images.unsplash.com/photo-1516410529446-2c777cb7366d",
},
{
id: 3,
title: "Thriller",
artist: "Michael Jackson",
cover: "https://images.unsplash.com/photo-1559406041-c7d2b2e98690",
},
{
id: 4,
title: "The Wall",
artist: "Pink Floyd",
cover: "https://images.unsplash.com/photo-1528822234686-beae35cab346",
},
],
},
render: (args) => {
return (
<div className="flex w-auto items-center justify-center rounded-xl border bg-gray-900 p-4 text-white shadow-2xl">
<MusicStackInteraction {...args} />
</div>
);
},
};
126 changes: 126 additions & 0 deletions animata/widget/music-stack-interaction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import React, { useState } from "react";
import { motion } from "framer-motion";
import { Layers, LayoutGrid } from "lucide-react";

import { cn } from "@/lib/utils";

const carouselStyles = {
perspective: "1000px",
overflow: "hidden",
};

const carouselInnerStyles: React.CSSProperties = {
display: "flex",
transformStyle: "preserve-3d",
transition: "transform 2s",
justifyContent: "center",
alignItems: "center",
height: "100%",
};

const carouselItemStyles: React.CSSProperties = {
minWidth: "200px",
marginLeft: "-180px",
transform: "rotateY(15deg) translateZ(300px) translateX(-50px)",
backfaceVisibility: "hidden",
boxShadow: "0 4px 8px rgba(0, 0, 0, 0.2)",
transition: "transform 2s, box-shadow 2s",
};

const carouselItemFirstChildStyles: React.CSSProperties = {
minWidth: "200px",
marginLeft: "20px",
transform: "rotateY(5deg) translateZ(300px) translateX(0)",
backfaceVisibility: "hidden",
boxShadow: "0 4px 8px rgba(0, 0, 0, 0.2)",
transition: "transform 2s, box-shadow 2s",
};

interface albumsProps {
/*
* Array of album objects
*/
albums: {
id: number;
title: string;
artist: string;
cover: string;
}[];
}

export default function MusicStackInteraction({ albums }: albumsProps) {
const [isGridView, setIsGridView] = useState(true);

const handleToggleView = () => {
setIsGridView(!isGridView);
};

return (
<div className="relative mx-auto h-[33rem] w-80 rounded bg-gray-900 p-2 text-white">
<motion.div
className={cn("h-96 w-full", { "mt-24": !isGridView })}
style={isGridView ? undefined : carouselStyles}
layout
>
<motion.div
className={cn("", { "mb-4 grid grid-cols-2 gap-6": isGridView })}
style={isGridView ? undefined : carouselInnerStyles}
layout
>
{albums.map((album, index) => (
<div
key={album.id}
className={cn("relative w-full shadow-lg")}
style={
isGridView
? undefined
: index === 0
? carouselItemFirstChildStyles
: carouselItemStyles
}
>
<motion.img
layout
src={album.cover + "?w=200&h=200"}
alt={album.title}
className="h-auto rounded-xl shadow-md"
/>
<motion.div
layout
className="absolute bottom-0 left-0 w-full bg-opacity-50 bg-gradient-to-b from-transparent to-gray-800 px-4 py-2 text-white"
>
<motion.h3 layout className="font-semibold leading-tight">
{album.title}
</motion.h3>
<motion.p layout className="text-sm leading-snug">
{album.artist}
</motion.p>
</motion.div>
</div>
))}
</motion.div>
</motion.div>

<motion.div className="duration-2000 absolute bottom-4 left-0 right-0 -mb-4 flex w-auto items-center justify-center rounded-xl bg-gray-800 p-4 text-white shadow-2xl transition-all">
<div className="flex w-32 items-center space-x-2 rounded-full bg-gray-900 p-2">
<div
className={cn("flex h-8 w-16 cursor-pointer items-center justify-center rounded-full", {
"bg-gray-700": isGridView,
})}
onClick={handleToggleView}
>
<LayoutGrid />
</div>
<div
className={cn("flex h-8 w-16 cursor-pointer items-center justify-center rounded-full", {
"bg-gray-700": !isGridView,
})}
onClick={handleToggleView}
>
<Layers />
</div>
</div>
</motion.div>
</div>
);
}
38 changes: 38 additions & 0 deletions content/docs/widget/music-stack-interaction.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Music Stack Interaction
description: widget for Music stack and unstacking
author: Mahlawat2001
---

<ComponentPreview name="widget-music-stack-interaction--docs" />

## Installation

<Steps>
<Step>Install dependencies</Step>

```bash
npm install lucide-react framer-motion
```

<Step>Run the following command</Step>

It will create a new file `music-stack-interaction.tsx` inside the `components/animata/widget` directory.

```bash
mkdir -p components/animata/widget && touch components/animata/widget/music-stack-interaction.tsx
```

<Step>Paste the code</Step>{" "}

Open the newly created file and paste the following code:

```jsx file=<rootDir>/animata/widget/music-stack-interaction.tsx

```

</Steps>

## Credits

Built by [Mohit Ahlawat](https://github.com/mohitahlawat2001)

0 comments on commit f74de40

Please sign in to comment.