mirror of
https://github.com/fergalmoran/opengifame.git
synced 2025-12-22 09:38:44 +00:00
MagicUI added (undecided for now)
This commit is contained in:
@@ -14,7 +14,6 @@
|
|||||||
"components": "@/components",
|
"components": "@/components",
|
||||||
"utils": "@/lib/utils",
|
"utils": "@/lib/utils",
|
||||||
"ui": "@/components/ui",
|
"ui": "@/components/ui",
|
||||||
"lib": "@/lib",
|
"magicui": "@/components/magicui"
|
||||||
"hooks": "@/hooks"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
"db:migrate": "drizzle-kit migrate",
|
"db:migrate": "drizzle-kit migrate",
|
||||||
"db:push": "drizzle-kit push",
|
"db:push": "drizzle-kit push",
|
||||||
"db:studio": "drizzle-kit studio",
|
"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": "NODE_ENV=development next dev -p 3002 & local-ssl-proxy --config ./ssl-proxy.json",
|
||||||
"dev:plain": "next dev",
|
"dev:plain": "next dev",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
@@ -65,6 +66,7 @@
|
|||||||
"date-fns": "^4.0.0",
|
"date-fns": "^4.0.0",
|
||||||
"drizzle-orm": "^0.33.0",
|
"drizzle-orm": "^0.33.0",
|
||||||
"embla-carousel-react": "^8.3.0",
|
"embla-carousel-react": "^8.3.0",
|
||||||
|
"framer-motion": "^11.5.4",
|
||||||
"geist": "^1.3.1",
|
"geist": "^1.3.1",
|
||||||
"http-status-codes": "^2.3.0",
|
"http-status-codes": "^2.3.0",
|
||||||
"input-otp": "^1.2.4",
|
"input-otp": "^1.2.4",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
"use client";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { SessionProvider } from "next-auth/react";
|
import { SessionProvider } from "next-auth/react";
|
||||||
|
|
||||||
|
|||||||
79
src/components/magicui/bento-grid.tsx
Normal file
79
src/components/magicui/bento-grid.tsx
Normal 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 };
|
||||||
39
src/components/magicui/blur-in.tsx
Normal file
39
src/components/magicui/blur-in.tsx
Normal 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;
|
||||||
@@ -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";
|
const createGridCard = (
|
||||||
import Image from "next/image";
|
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() {
|
return <BentoCard key={key} {...value} />;
|
||||||
const [latestImages] = api.image.getTrending.useSuspenseQuery();
|
};
|
||||||
|
|
||||||
|
export async function TrendingImages() {
|
||||||
|
const latestImages = await api.image.getTrending();
|
||||||
return (
|
return (
|
||||||
<div className="w-full max-w-xs">
|
<BentoGrid className="lg:grid-rows-3">
|
||||||
{latestImages ? (
|
{latestImages.map((image) =>
|
||||||
latestImages.map((image) => (
|
createGridCard(
|
||||||
<Image
|
image.id,
|
||||||
key={image.id}
|
image.url,
|
||||||
src={image.url}
|
image.title ?? "",
|
||||||
alt={image.title ?? "An image"}
|
image.description ?? "",
|
||||||
width={320}
|
image.tags ?? [],
|
||||||
height={320}
|
),
|
||||||
/>
|
|
||||||
// <img src={image.url} key={image.id} />
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<p>No images yet.</p>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</BentoGrid>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { clsx, type ClassValue } from "clsx"
|
import { type ClassValue, clsx } from "clsx"
|
||||||
import { twMerge } from "tailwind-merge"
|
import { twMerge } from "tailwind-merge"
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--background: 0 0% 100%;
|
--background: 0 0% 100%;
|
||||||
@@ -22,13 +23,14 @@
|
|||||||
--border: 240 5.9% 90%;
|
--border: 240 5.9% 90%;
|
||||||
--input: 240 5.9% 90%;
|
--input: 240 5.9% 90%;
|
||||||
--ring: 240 10% 3.9%;
|
--ring: 240 10% 3.9%;
|
||||||
|
--radius: 0.5rem;
|
||||||
--chart-1: 12 76% 61%;
|
--chart-1: 12 76% 61%;
|
||||||
--chart-2: 173 58% 39%;
|
--chart-2: 173 58% 39%;
|
||||||
--chart-3: 197 37% 24%;
|
--chart-3: 197 37% 24%;
|
||||||
--chart-4: 43 74% 66%;
|
--chart-4: 43 74% 66%;
|
||||||
--chart-5: 27 87% 67%;
|
--chart-5: 27 87% 67%;
|
||||||
--radius: 0.5rem
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--background: 240 10% 3.9%;
|
--background: 240 10% 3.9%;
|
||||||
--foreground: 0 0% 98%;
|
--foreground: 0 0% 98%;
|
||||||
@@ -53,9 +55,10 @@
|
|||||||
--chart-2: 160 60% 45%;
|
--chart-2: 160 60% 45%;
|
||||||
--chart-3: 30 80% 55%;
|
--chart-3: 30 80% 55%;
|
||||||
--chart-4: 280 65% 60%;
|
--chart-4: 280 65% 60%;
|
||||||
--chart-5: 340 75% 55%
|
--chart-5: 340 75% 55%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
* {
|
* {
|
||||||
@apply border-border;
|
@apply border-border;
|
||||||
|
|||||||
@@ -1,26 +1,29 @@
|
|||||||
import { type Config } from "tailwindcss";
|
import type { Config } from "tailwindcss"
|
||||||
|
|
||||||
export default {
|
const config = {
|
||||||
darkMode: ["class"],
|
darkMode: ["class"],
|
||||||
content: ["./src/**/*.tsx"],
|
content: [
|
||||||
|
'./pages/**/*.{ts,tsx}',
|
||||||
|
'./components/**/*.{ts,tsx}',
|
||||||
|
'./app/**/*.{ts,tsx}',
|
||||||
|
'./src/**/*.{ts,tsx}',
|
||||||
|
],
|
||||||
|
prefix: "",
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
container: {
|
||||||
borderRadius: {
|
center: true,
|
||||||
lg: "var(--radius)",
|
padding: "2rem",
|
||||||
md: "calc(var(--radius) - 2px)",
|
screens: {
|
||||||
sm: "calc(var(--radius) - 4px)",
|
"2xl": "1400px",
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
extend: {
|
||||||
colors: {
|
colors: {
|
||||||
|
border: "hsl(var(--border))",
|
||||||
|
input: "hsl(var(--input))",
|
||||||
|
ring: "hsl(var(--ring))",
|
||||||
background: "hsl(var(--background))",
|
background: "hsl(var(--background))",
|
||||||
foreground: "hsl(var(--foreground))",
|
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: {
|
primary: {
|
||||||
DEFAULT: "hsl(var(--primary))",
|
DEFAULT: "hsl(var(--primary))",
|
||||||
foreground: "hsl(var(--primary-foreground))",
|
foreground: "hsl(var(--primary-foreground))",
|
||||||
@@ -29,6 +32,10 @@ export default {
|
|||||||
DEFAULT: "hsl(var(--secondary))",
|
DEFAULT: "hsl(var(--secondary))",
|
||||||
foreground: "hsl(var(--secondary-foreground))",
|
foreground: "hsl(var(--secondary-foreground))",
|
||||||
},
|
},
|
||||||
|
destructive: {
|
||||||
|
DEFAULT: "hsl(var(--destructive))",
|
||||||
|
foreground: "hsl(var(--destructive-foreground))",
|
||||||
|
},
|
||||||
muted: {
|
muted: {
|
||||||
DEFAULT: "hsl(var(--muted))",
|
DEFAULT: "hsl(var(--muted))",
|
||||||
foreground: "hsl(var(--muted-foreground))",
|
foreground: "hsl(var(--muted-foreground))",
|
||||||
@@ -37,37 +44,28 @@ export default {
|
|||||||
DEFAULT: "hsl(var(--accent))",
|
DEFAULT: "hsl(var(--accent))",
|
||||||
foreground: "hsl(var(--accent-foreground))",
|
foreground: "hsl(var(--accent-foreground))",
|
||||||
},
|
},
|
||||||
destructive: {
|
popover: {
|
||||||
DEFAULT: "hsl(var(--destructive))",
|
DEFAULT: "hsl(var(--popover))",
|
||||||
foreground: "hsl(var(--destructive-foreground))",
|
foreground: "hsl(var(--popover-foreground))",
|
||||||
},
|
},
|
||||||
border: "hsl(var(--border))",
|
card: {
|
||||||
input: "hsl(var(--input))",
|
DEFAULT: "hsl(var(--card))",
|
||||||
ring: "hsl(var(--ring))",
|
foreground: "hsl(var(--card-foreground))",
|
||||||
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))",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
borderRadius: {
|
||||||
|
lg: "var(--radius)",
|
||||||
|
md: "calc(var(--radius) - 2px)",
|
||||||
|
sm: "calc(var(--radius) - 4px)",
|
||||||
|
},
|
||||||
keyframes: {
|
keyframes: {
|
||||||
"accordion-down": {
|
"accordion-down": {
|
||||||
from: {
|
from: { height: "0" },
|
||||||
height: "0",
|
to: { height: "var(--radix-accordion-content-height)" },
|
||||||
},
|
|
||||||
to: {
|
|
||||||
height: "var(--radix-accordion-content-height)",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
"accordion-up": {
|
"accordion-up": {
|
||||||
from: {
|
from: { height: "var(--radix-accordion-content-height)" },
|
||||||
height: "var(--radix-accordion-content-height)",
|
to: { height: "0" },
|
||||||
},
|
|
||||||
to: {
|
|
||||||
height: "0",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
animation: {
|
animation: {
|
||||||
@@ -77,4 +75,6 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [require("tailwindcss-animate")],
|
plugins: [require("tailwindcss-animate")],
|
||||||
} satisfies Config;
|
} satisfies Config
|
||||||
|
|
||||||
|
export default config
|
||||||
Reference in New Issue
Block a user