Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/JPF3N998/astro-x-aceternityui


https://github.com/JPF3N998/astro-x-aceternityui

Last synced: about 2 months ago
JSON representation

Awesome Lists containing this project

README

        

# Astro X Aceternity UI

[Astro](https://astro.build/) X [Aceternity UI](https://ui.aceternity.com/)

# Demo

![Demo GIF](demo/astro-x-aceternityui.gif)

# Set up

1. Set up basic Astro project

```bash
pnpm create astro@latest
```

2. Add Tailwind CSS

```bash
pnpx astro add tailwind
```

3. Add React

```bash
pnpx astro add react
```

4. Install Aceternity UI additional dependencies

- [Official guide](https://ui.aceternity.com/docs/add-utilities)

```bash
pnpm i framer-motion clsx tailwind-merge
```

5. Set up cn

`utils/cn.ts`
```typescript
import { ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
```

6. Update `tailwind.config.ts`

```diff
+ const {
+ default: flattenColorPalette,
+ } = require("tailwindcss/lib/util/flattenColorPalette");

/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",

// Or if using `src` directory:
"./src/**/*.{js,ts,jsx,tsx,mdx}",
],
+ darkMode: "class",
theme: {
extend: {},
},
+ plugins: [addVariablesForColors],
};

+ // This plugin adds each Tailwind color as a global CSS variable, e.g. var(--gray-200).
+ function addVariablesForColors({ addBase, theme }: any) {
+ let allColors = flattenColorPalette(theme("colors"));
+ let newVars = Object.fromEntries(
+ Object.entries(allColors).map(([key, val]) => [`--${key}`, val])
+ );
+
+ addBase({
+ ":root": newVars,
+ });
}

```

7. Optional: Path aliases

`tsconfig.json`

```diff
{
"extends": "astro/tsconfigs/strict",
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "react",
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["src/*"],
+ "@components/*": ["src/components/*"],
+ "@aceternityui/*": ["src/components/react/aceternityui/*"]
}
}
}
```

# My approach

> We'll use the [Card Stack component](https://ui.aceternity.com/components/card-stack) as an example

1. Component source
2. React implementation
3. Astro component wrapper
4. Use Aceternity UI component

## 1. Component source

`src/components/react/aceternityui/CardStack.tsx`


Card Stack source code

```jsx
// "use client"; <- Can be omitted, this is React not Next.js
import { useEffect, useState } from "react";
import { motion } from "framer-motion";

let interval: any;

type Card = {
id: number;
name: string;
designation: string;
content: React.ReactNode;
};

export const CardStack = ({
items,
offset,
scaleFactor,
}: {
items: Card[];
offset?: number;
scaleFactor?: number;
}) => {
const CARD_OFFSET = offset || 10;
const SCALE_FACTOR = scaleFactor || 0.06;
const [cards, setCards] = useState(items);

useEffect(() => {
startFlipping();
}, []);
const startFlipping = () => {
interval = setInterval(() => {
setCards((prevCards: Card[]) => {
const newArray = [...prevCards]; // create a copy of the array
newArray.unshift(newArray.pop()!); // move the last element to the front
return newArray;
});
}, 5000);

return () => clearInterval(interval);
};

return (


{cards.map((card, index) => {
return (


{card.content}



{card.name}



{card.designation}




);
})}

);
};
```

## 2. React implementation


Card Stack source code in use

```jsx
// "use client"; <- Can be omitted, this is React not Next.js
import { CardStack } from "../ui/card-stack";
import { cn } from "@/utils/cn";
export function CardStackDemo() {
return (




);
}

// Small utility to highlight the content of specific section of a testimonial content
export const Highlight = ({
children,
className,
}: {
children: React.ReactNode;
className?: string;
}) => {
return (

{children}

);
};

const CARDS = [
{
id: 0,
name: "Manu Arora",
designation: "Senior Software Engineer",
content: (


These cards are amazing, I want to use them in my
project. Framer motion is a godsend ngl tbh fam 🙏


),
},
{
id: 1,
name: "Elon Musk",
designation: "Senior Shitposter",
content: (


I dont like this Twitter thing,{" "}
deleting it right away because yolo. Instead, I
would like to call it X.com so that it can easily
be confused with adult sites.


),
},
{
id: 2,
name: "Tyler Durden",
designation: "Manager Project Mayhem",
content: (


The first rule of
Fight Club is that you do not talk about fight
club. The second rule of
Fight club is that you DO NOT TALK about fight
club.


),
},
];
```

## 3. Wrap React component with an Astro component and expose it

```astro
---
import { CardStackDemo } from '@components/react/CardStack'
---

```

## 4. Use "Astro-fied" Aceternity UI component

`src/pages/index.astro`

```astro
---
import CardStack from '@components/CardStack.astro'
---






Astro



```

# Reference

- [Using React components in Astro page/component](https://docs.astro.build/en/guides/framework-components/#using-framework-components)