MagicUI added (undecided for now)

This commit is contained in:
Fergal Moran
2024-09-18 15:27:18 +01:00
parent a06ac8cbf1
commit 8da0abe325
10 changed files with 202 additions and 69 deletions

BIN
bun.lockb

Binary file not shown.

View File

@@ -14,7 +14,6 @@
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
"magicui": "@/components/magicui"
}
}

View File

@@ -9,6 +9,7 @@
"db:migrate": "drizzle-kit migrate",
"db:push": "drizzle-kit push",
"db:studio": "drizzle-kit studio",
"dev:turbo": "NODE_ENV=development next dev -p 3002 --turbo & local-ssl-proxy --config ./ssl-proxy.json",
"dev": "NODE_ENV=development next dev -p 3002 & local-ssl-proxy --config ./ssl-proxy.json",
"dev:plain": "next dev",
"lint": "next lint",
@@ -65,6 +66,7 @@
"date-fns": "^4.0.0",
"drizzle-orm": "^0.33.0",
"embla-carousel-react": "^8.3.0",
"framer-motion": "^11.5.4",
"geist": "^1.3.1",
"http-status-codes": "^2.3.0",
"input-otp": "^1.2.4",

View File

@@ -1,4 +1,3 @@
"use client";
import React from "react";
import { SessionProvider } from "next-auth/react";

View File

@@ -0,0 +1,79 @@
import { ReactNode } from "react";
import { ArrowRightIcon } from "@radix-ui/react-icons";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
const BentoGrid = ({
children,
className,
}: {
children: ReactNode;
className?: string;
}) => {
return (
<div
className={cn(
"grid w-full auto-rows-[22rem] grid-cols-3 gap-4",
className,
)}
>
{children}
</div>
);
};
const BentoCard = ({
name,
className,
background,
Icon,
description,
href,
cta,
}: {
name: string;
className: string;
background: ReactNode;
Icon: any;
description: string;
href: string;
cta: string;
}) => (
<div
key={name}
className={cn(
"group relative col-span-3 flex flex-col justify-between overflow-hidden rounded-xl",
// light styles
"bg-white [box-shadow:0_0_0_1px_rgba(0,0,0,.03),0_2px_4px_rgba(0,0,0,.05),0_12px_24px_rgba(0,0,0,.05)]",
// dark styles
"transform-gpu dark:bg-black dark:[border:1px_solid_rgba(255,255,255,.1)] dark:[box-shadow:0_-20px_80px_-20px_#ffffff1f_inset]",
className,
)}
>
<div>{background}</div>
<div className="pointer-events-none z-10 flex transform-gpu flex-col gap-1 p-6 transition-all duration-300 group-hover:-translate-y-10">
<Icon className="h-12 w-12 origin-left transform-gpu text-neutral-700 transition-all duration-300 ease-in-out group-hover:scale-75" />
<h3 className="text-xl font-semibold text-neutral-700 dark:text-neutral-300">
{name}
</h3>
<p className="max-w-lg text-neutral-400">{description}</p>
</div>
<div
className={cn(
"pointer-events-none absolute bottom-0 flex w-full translate-y-10 transform-gpu flex-row items-center p-4 opacity-0 transition-all duration-300 group-hover:translate-y-0 group-hover:opacity-100",
)}
>
<Button variant="ghost" asChild size="sm" className="pointer-events-auto">
<a href={href}>
{cta}
<ArrowRightIcon className="ml-2 h-4 w-4" />
</a>
</Button>
</div>
<div className="pointer-events-none absolute inset-0 transform-gpu transition-all duration-300 group-hover:bg-black/[.03] group-hover:dark:bg-neutral-800/10" />
</div>
);
export { BentoCard, BentoGrid };

View File

@@ -0,0 +1,39 @@
"use client";
import { motion } from "framer-motion";
import { cn } from "@/lib/utils";
interface BlurIntProps {
word: string;
className?: string;
variant?: {
hidden: { filter: string; opacity: number };
visible: { filter: string; opacity: number };
};
duration?: number;
}
const BlurIn = ({ word, className, variant, duration = 1 }: BlurIntProps) => {
const defaultVariants = {
hidden: { filter: "blur(10px)", opacity: 0 },
visible: { filter: "blur(0px)", opacity: 1 },
};
const combinedVariants = variant || defaultVariants;
return (
<motion.h1
initial="hidden"
animate="visible"
transition={{ duration }}
variants={combinedVariants}
className={cn(
"font-display text-center text-4xl font-bold tracking-[-0.02em] drop-shadow-sm md:text-7xl md:leading-[5rem]",
className,
)}
>
{word}
</motion.h1>
);
};
export default BlurIn;

View File

@@ -1,29 +1,41 @@
"use client";
import { BellIcon } from "@radix-ui/react-icons";
import { useState } from "react";
import { BentoCard, BentoGrid } from "@/components/magicui/bento-grid";
import { api } from "@/trpc/server";
import { api } from "@/trpc/react";
import Image from "next/image";
const createGridCard = (
key: string,
url: string,
title: string,
description: string,
tags: string[],
) => {
const value = {
Icon: BellIcon,
name: title,
description: description,
href: "/",
cta: "Learn more",
background: <img className="h-128 absolute w-full" src={url} />,
className: "col-span-1 row-start-1 row-end-4",
};
export function TrendingImages() {
const [latestImages] = api.image.getTrending.useSuspenseQuery();
return <BentoCard key={key} {...value} />;
};
export async function TrendingImages() {
const latestImages = await api.image.getTrending();
return (
<div className="w-full max-w-xs">
{latestImages ? (
latestImages.map((image) => (
<Image
key={image.id}
src={image.url}
alt={image.title ?? "An image"}
width={320}
height={320}
/>
// <img src={image.url} key={image.id} />
))
) : (
<p>No images yet.</p>
<BentoGrid className="lg:grid-rows-3">
{latestImages.map((image) =>
createGridCard(
image.id,
image.url,
image.title ?? "",
image.description ?? "",
image.tags ?? [],
),
)}
</div>
</BentoGrid>
);
}

View File

@@ -1,4 +1,4 @@
import { clsx, type ClassValue } from "clsx"
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {

View File

@@ -1,6 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
@@ -22,13 +23,14 @@
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 10% 3.9%;
--radius: 0.5rem;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--radius: 0.5rem
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
@@ -53,9 +55,10 @@
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%
--chart-5: 340 75% 55%;
}
}
@layer base {
* {
@apply border-border;
@@ -63,4 +66,4 @@
body {
@apply bg-background text-foreground;
}
}
}

View File

@@ -1,26 +1,29 @@
import { type Config } from "tailwindcss";
import type { Config } from "tailwindcss"
export default {
const config = {
darkMode: ["class"],
content: ["./src/**/*.tsx"],
content: [
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./src/**/*.{ts,tsx}',
],
prefix: "",
theme: {
extend: {
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
@@ -29,6 +32,10 @@ export default {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
@@ -37,37 +44,28 @@ export default {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
chart: {
"1": "hsl(var(--chart-1))",
"2": "hsl(var(--chart-2))",
"3": "hsl(var(--chart-3))",
"4": "hsl(var(--chart-4))",
"5": "hsl(var(--chart-5))",
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
keyframes: {
"accordion-down": {
from: {
height: "0",
},
to: {
height: "var(--radix-accordion-content-height)",
},
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: {
height: "var(--radix-accordion-content-height)",
},
to: {
height: "0",
},
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" },
},
},
animation: {
@@ -77,4 +75,6 @@ export default {
},
},
plugins: [require("tailwindcss-animate")],
} satisfies Config;
} satisfies Config
export default config