Begin working on front end

This commit is contained in:
Gabriel Brown 2024-06-13 15:40:35 -05:00
parent 4794541436
commit 258dccd4f2
15 changed files with 493 additions and 66 deletions

17
components.json Normal file
View File

@ -0,0 +1,17 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/styles/globals.css",
"baseColor": "slate",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "~/components",
"utils": "~/lib/utils"
}
}

View File

@ -5,6 +5,15 @@
await import("./src/env.js"); await import("./src/env.js");
/** @type {import("next").NextConfig} */ /** @type {import("next").NextConfig} */
const config = {}; const config = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: "avatars.githubusercontent.com",
},
],
},
};
export default config; export default config;

View File

@ -15,14 +15,21 @@
}, },
"dependencies": { "dependencies": {
"@auth/drizzle-adapter": "^1.1.0", "@auth/drizzle-adapter": "^1.1.0",
"@radix-ui/react-slot": "^1.0.2",
"@t3-oss/env-nextjs": "^0.10.1", "@t3-oss/env-nextjs": "^0.10.1",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"drizzle-orm": "^0.30.10", "drizzle-orm": "^0.30.10",
"geist": "^1.3.0", "geist": "^1.3.0",
"lucide-react": "^0.394.0",
"next": "^14.2.1", "next": "^14.2.1",
"next-auth": "5.0.0-beta.19", "next-auth": "5.0.0-beta.19",
"postgres": "^3.4.4", "postgres": "^3.4.4",
"react": "^18.3.0", "react": "^18.3.0",
"react-dom": "^18.3.0", "react-dom": "^18.3.0",
"react-icons": "^5.2.1",
"tailwind-merge": "^2.3.0",
"tailwindcss-animate": "^1.0.7",
"zod": "^3.23.3" "zod": "^3.23.3"
}, },
"devDependencies": { "devDependencies": {

107
pnpm-lock.yaml generated
View File

@ -11,15 +11,27 @@ importers:
'@auth/drizzle-adapter': '@auth/drizzle-adapter':
specifier: ^1.1.0 specifier: ^1.1.0
version: 1.2.0 version: 1.2.0
'@radix-ui/react-slot':
specifier: ^1.0.2
version: 1.0.2(@types/react@18.3.3)(react@18.3.1)
'@t3-oss/env-nextjs': '@t3-oss/env-nextjs':
specifier: ^0.10.1 specifier: ^0.10.1
version: 0.10.1(typescript@5.4.5)(zod@3.23.8) version: 0.10.1(typescript@5.4.5)(zod@3.23.8)
class-variance-authority:
specifier: ^0.7.0
version: 0.7.0
clsx:
specifier: ^2.1.1
version: 2.1.1
drizzle-orm: drizzle-orm:
specifier: ^0.30.10 specifier: ^0.30.10
version: 0.30.10(@types/react@18.3.3)(postgres@3.4.4)(react@18.3.1) version: 0.30.10(@types/react@18.3.3)(postgres@3.4.4)(react@18.3.1)
geist: geist:
specifier: ^1.3.0 specifier: ^1.3.0
version: 1.3.0(next@14.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) version: 1.3.0(next@14.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
lucide-react:
specifier: ^0.394.0
version: 0.394.0(react@18.3.1)
next: next:
specifier: ^14.2.1 specifier: ^14.2.1
version: 14.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) version: 14.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -35,6 +47,15 @@ importers:
react-dom: react-dom:
specifier: ^18.3.0 specifier: ^18.3.0
version: 18.3.1(react@18.3.1) version: 18.3.1(react@18.3.1)
react-icons:
specifier: ^5.2.1
version: 5.2.1(react@18.3.1)
tailwind-merge:
specifier: ^2.3.0
version: 2.3.0
tailwindcss-animate:
specifier: ^1.0.7
version: 1.0.7(tailwindcss@3.4.3)
zod: zod:
specifier: ^3.23.3 specifier: ^3.23.3
version: 3.23.8 version: 3.23.8
@ -518,6 +539,24 @@ packages:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'} engines: {node: '>=14'}
'@radix-ui/react-compose-refs@1.0.1':
resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/react-slot@1.0.2':
resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@rushstack/eslint-patch@1.10.3': '@rushstack/eslint-patch@1.10.3':
resolution: {integrity: sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==} resolution: {integrity: sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==}
@ -809,6 +848,9 @@ packages:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
engines: {node: '>= 8.10.0'} engines: {node: '>= 8.10.0'}
class-variance-authority@0.7.0:
resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==}
cli-color@2.0.4: cli-color@2.0.4:
resolution: {integrity: sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==} resolution: {integrity: sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==}
engines: {node: '>=0.10'} engines: {node: '>=0.10'}
@ -816,6 +858,14 @@ packages:
client-only@0.0.1: client-only@0.0.1:
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
clsx@2.0.0:
resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==}
engines: {node: '>=6'}
clsx@2.1.1:
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
engines: {node: '>=6'}
color-convert@2.0.1: color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'} engines: {node: '>=7.0.0'}
@ -1595,6 +1645,11 @@ packages:
lru-queue@0.1.0: lru-queue@0.1.0:
resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==}
lucide-react@0.394.0:
resolution: {integrity: sha512-PzTbJ0bsyXRhH59k5qe7MpTd5MxlpYZUcM9kGSwvPGAfnn0J6FElDwu2EX6Vuh//F7y60rcVJiFQ7EK9DCMgfw==}
peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0
memoizee@0.4.17: memoizee@0.4.17:
resolution: {integrity: sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==} resolution: {integrity: sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==}
engines: {node: '>=0.12'} engines: {node: '>=0.12'}
@ -1926,6 +1981,11 @@ packages:
peerDependencies: peerDependencies:
react: ^18.3.1 react: ^18.3.1
react-icons@5.2.1:
resolution: {integrity: sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==}
peerDependencies:
react: '*'
react-is@16.13.1: react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
@ -2109,6 +2169,14 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
tailwind-merge@2.3.0:
resolution: {integrity: sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA==}
tailwindcss-animate@1.0.7:
resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==}
peerDependencies:
tailwindcss: '>=3.0.0 || insiders'
tailwindcss@3.4.3: tailwindcss@3.4.3:
resolution: {integrity: sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==} resolution: {integrity: sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==}
engines: {node: '>=14.0.0'} engines: {node: '>=14.0.0'}
@ -2527,6 +2595,21 @@ snapshots:
'@pkgjs/parseargs@0.11.0': '@pkgjs/parseargs@0.11.0':
optional: true optional: true
'@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.3)(react@18.3.1)':
dependencies:
'@babel/runtime': 7.24.6
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.3
'@radix-ui/react-slot@1.0.2(@types/react@18.3.3)(react@18.3.1)':
dependencies:
'@babel/runtime': 7.24.6
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.3.1)
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.3
'@rushstack/eslint-patch@1.10.3': {} '@rushstack/eslint-patch@1.10.3': {}
'@swc/counter@0.1.3': {} '@swc/counter@0.1.3': {}
@ -2878,6 +2961,10 @@ snapshots:
optionalDependencies: optionalDependencies:
fsevents: 2.3.3 fsevents: 2.3.3
class-variance-authority@0.7.0:
dependencies:
clsx: 2.0.0
cli-color@2.0.4: cli-color@2.0.4:
dependencies: dependencies:
d: 1.0.2 d: 1.0.2
@ -2888,6 +2975,10 @@ snapshots:
client-only@0.0.1: {} client-only@0.0.1: {}
clsx@2.0.0: {}
clsx@2.1.1: {}
color-convert@2.0.1: color-convert@2.0.1:
dependencies: dependencies:
color-name: 1.1.4 color-name: 1.1.4
@ -3818,6 +3909,10 @@ snapshots:
dependencies: dependencies:
es5-ext: 0.10.64 es5-ext: 0.10.64
lucide-react@0.394.0(react@18.3.1):
dependencies:
react: 18.3.1
memoizee@0.4.17: memoizee@0.4.17:
dependencies: dependencies:
d: 1.0.2 d: 1.0.2
@ -4081,6 +4176,10 @@ snapshots:
react: 18.3.1 react: 18.3.1
scheduler: 0.23.2 scheduler: 0.23.2
react-icons@5.2.1(react@18.3.1):
dependencies:
react: 18.3.1
react-is@16.13.1: {} react-is@16.13.1: {}
react@18.3.1: react@18.3.1:
@ -4286,6 +4385,14 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {} supports-preserve-symlinks-flag@1.0.0: {}
tailwind-merge@2.3.0:
dependencies:
'@babel/runtime': 7.24.6
tailwindcss-animate@1.0.7(tailwindcss@3.4.3):
dependencies:
tailwindcss: 3.4.3
tailwindcss@3.4.3: tailwindcss@3.4.3:
dependencies: dependencies:
'@alloc/quick-lru': 5.2.0 '@alloc/quick-lru': 5.2.0

View File

@ -0,0 +1 @@
<svg width="98" height="96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 960 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 KiB

View File

@ -1,13 +1,49 @@
import { signIn } from "~/auth" import { signIn, signOut, auth } from "~/auth"
import Image from "next/image";
export async function SignInGH() { export async function SignInGH() {
const session = await auth();
if (session) {
return ( return (
<form className="w-full" <div className="">
<form className=""
action={async () => {
"use server";
await signOut();
}}>
<button className="" type="submit">
<div className="flex flex-col items-center">
<Image
className="rounded-full"
src={session.user?.image ? session.user.image : ""}
alt="Profile Picture"
width={50} height={50}
/>
<div>Sign Out</div>
</div>
</button>
</form>
</div>
);
} else {
return (
<form className=""
action={async () => { action={async () => {
"use server"; "use server";
await signIn("github"); await signIn("github");
}}> }}>
<button className="w-full" type="submit">Sign In With GitHub</button> <button className="" type="submit">
<div className="flex flex-col items-center">
<Image
className="rounded-full"
src="/images/github-mark-white.svg"
alt="GitHub"
width={50} height={50}
/>
<div>Sign In</div>
</div>
</button>
</form> </form>
); );
} }
}

View File

@ -0,0 +1,6 @@
export function Dock() {
return (
<div className="fixed dock w-1/2 rounded-full bg-slate-500 h-20 bottom-2 left-1/4">
</div>
);
};

View File

@ -1,8 +1,31 @@
import { SignInGH } from "~/app/_components/auth/sign_in_gh";
import { GoDotFill } from "react-icons/go";
import { CiPower } from "react-icons/ci";
import { AiFillSound } from "react-icons/ai";
import { FaNetworkWired } from "react-icons/fa";
import { Button } from "~/components/ui/button";
export function Top_Bar() { export function Top_Bar() {
return ( return (
<div className="top-bar w-full h-16 bg-black text-white"> <div className="top-bar w-full h-10 flex flex-row bg-black text-white rounded-full m">
<div className="Workspaces flex w-1/3 justify-start pl-4 my-auto">
<Button className="bg-black text-white hover:bg-slate-900 rounded-full">
<GoDotFill />
<GoDotFill />
</Button>
</div>
<div className="Notifications flex w-1/3 justify-center my-auto">
<Button className="bg-black text-white hover:bg-slate-900 rounded-full">
{new Date().toLocaleTimeString()}
</Button>
</div>
<div className="Quick_Settings flex w-1/3 justify-end my-auto px-4">
<Button className="bg-black text-white hover:bg-slate-900 rounded-full">
<FaNetworkWired className="w-5 h-5 mx-2" />
< AiFillSound className="w-5 h-5 mx-2" />
< CiPower className="w-5 h-5 ml-1" />
</Button>
</div>
</div> </div>
); );
}; };

View File

@ -1,8 +1,10 @@
import "~/styles/globals.css"; import "~/styles/globals.css";
import { GeistSans } from "geist/font/sans"; import { GeistSans } from "geist/font/sans";
import type { Metadata } from "next"; import type { Metadata } from "next";
import { Top_Bar } from "~/app/_components/ui/top_bar";
import { SessionProvider } from "next-auth/react"; import { SessionProvider } from "next-auth/react";
import { auth } from "~/auth";
import { Top_Bar } from "~/app/_components/ui/top_bar";
import { Dock } from "~/app/_components/ui/dock";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Create T3 App", title: "Create T3 App",
@ -10,19 +12,33 @@ export const metadata: Metadata = {
icons: [{ rel: "icon", url: "/favicon.ico" }], icons: [{ rel: "icon", url: "/favicon.ico" }],
}; };
export default function RootLayout({ export default async function RootLayout({
children, children,
}: { }: {
children: React.ReactNode; children: React.ReactNode;
}) { }) {
const session = await auth();
if (!session) {
return ( return (
<html lang="en" className={`${GeistSans.variable}`}> <html lang="en" className={`${GeistSans.variable}`}>
<body> <body className="backgrd">
<SessionProvider> <SessionProvider>
<Top_Bar />
{children} {children}
</SessionProvider> </SessionProvider>
</body> </body>
</html> </html>
); );
} else {
return (
<html lang="en" className={`${GeistSans.variable}`}>
<body className="backgrd">
<SessionProvider>
<Top_Bar />
{children}
< Dock />
</SessionProvider>
</body>
</html>
);
}
} }

View File

@ -1,37 +1,27 @@
import Link from "next/link"; import Link from "next/link";
import { auth } from "~/auth";
import { SignInGH } from "~/app/_components/auth/sign_in_gh";
export default function HomePage() { export default async function HomePage() {
const session = await auth();
if (!session) {
return ( return (
<main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white"> <main className="flex min-h-screen flex-col items-center justify-center bg-none text-white">
<div className="container flex flex-col items-center justify-center gap-12 px-4 py-16 "> <h1 className="flex flex-col text-white text-5xl pb-10 text-center">
<h1 className="text-5xl font-extrabold tracking-tight text-white sm:text-[5rem]"> <div className="py-4">
Create <span className="text-[hsl(280,100%,70%)]">T3</span> App {new Date().toDateString()}
</div>
<div className="py-4">
{new Date().toLocaleTimeString()}
</div>
</h1> </h1>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:gap-8"> < SignInGH />
<Link </main>
className="flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 text-white hover:bg-white/20" );
href="https://create.t3.gg/en/usage/first-steps" } else {
target="_blank" return (
> <main className="flex min-h-screen flex-col items-center justify-center bg-none text-white">
<h3 className="text-2xl font-bold">First Steps </h3>
<div className="text-lg">
Just the basics - Everything you need to know to set up your
database and authentication.
</div>
</Link>
<Link
className="flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 text-white hover:bg-white/20"
href="https://create.t3.gg/en/introduction"
target="_blank"
>
<h3 className="text-2xl font-bold">Documentation </h3>
<div className="text-lg">
Learn more about Create T3 App, the libraries it uses, and how to
deploy it.
</div>
</Link>
</div>
</div>
</main> </main>
); );
} }
}

View File

@ -0,0 +1,56 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "~/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
Button.displayName = "Button"
export { Button, buttonVariants }

6
src/lib/utils.ts Normal file
View File

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

View File

@ -1,3 +1,90 @@
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
@layer base {
:root {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
}
.dark {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;
--radius: 0.5rem;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
.backgrd {
background-image: url("/images/wallpapers/faroe_islands.jpg");
background-size: cover;
background-position: center;
display: flex;
height: 100%;
}

View File

@ -1,14 +1,80 @@
import { type Config } from "tailwindcss"; import type { Config } from "tailwindcss"
import { fontFamily } from "tailwindcss/defaultTheme";
export default { const config = {
content: ["./src/**/*.tsx"], darkMode: ["class"],
content: [
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./src/**/*.{ts,tsx}',
],
prefix: "",
theme: { theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: { extend: {
fontFamily: { colors: {
sans: ["var(--font-geist-sans)", ...fontFamily.sans], border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
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))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
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)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
}, },
}, },
}, },
plugins: [], plugins: [require("tailwindcss-animate")],
} satisfies Config; } satisfies Config
export default config