Compare commits
2 Commits
e525a67376
...
dfa315a7c3
Author | SHA1 | Date |
---|---|---|
|
dfa315a7c3 | 6 months ago |
|
4a491d5de9 | 6 months ago |
@ -0,0 +1,3 @@ |
||||
{ |
||||
"extends": ["next/core-web-vitals", "next/typescript"] |
||||
} |
@ -0,0 +1,36 @@ |
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. |
||||
|
||||
# dependencies |
||||
/node_modules |
||||
/.pnp |
||||
.pnp.js |
||||
.yarn/install-state.gz |
||||
|
||||
# testing |
||||
/coverage |
||||
|
||||
# next.js |
||||
/.next/ |
||||
/out/ |
||||
|
||||
# production |
||||
/build |
||||
|
||||
# misc |
||||
.DS_Store |
||||
*.pem |
||||
|
||||
# debug |
||||
npm-debug.log* |
||||
yarn-debug.log* |
||||
yarn-error.log* |
||||
|
||||
# local env files |
||||
.env*.local |
||||
|
||||
# vercel |
||||
.vercel |
||||
|
||||
# typescript |
||||
*.tsbuildinfo |
||||
next-env.d.ts |
@ -0,0 +1,36 @@ |
||||
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). |
||||
|
||||
## Getting Started |
||||
|
||||
First, run the development server: |
||||
|
||||
```bash |
||||
npm run dev |
||||
# or |
||||
yarn dev |
||||
# or |
||||
pnpm dev |
||||
# or |
||||
bun dev |
||||
``` |
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. |
||||
|
||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. |
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. |
||||
|
||||
## Learn More |
||||
|
||||
To learn more about Next.js, take a look at the following resources: |
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. |
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. |
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! |
||||
|
||||
## Deploy on Vercel |
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. |
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. |
@ -0,0 +1,21 @@ |
||||
{ |
||||
"$schema": "https://ui.shadcn.com/schema.json", |
||||
"style": "new-york", |
||||
"rsc": true, |
||||
"tsx": true, |
||||
"tailwind": { |
||||
"config": "tailwind.config.ts", |
||||
"css": "src/app/globals.css", |
||||
"baseColor": "gray", |
||||
"cssVariables": true, |
||||
"prefix": "" |
||||
}, |
||||
"aliases": { |
||||
"components": "@/components", |
||||
"utils": "@/lib/utils", |
||||
"ui": "@/components/ui", |
||||
"lib": "@/lib", |
||||
"hooks": "@/hooks" |
||||
}, |
||||
"iconLibrary": "lucide" |
||||
} |
@ -0,0 +1,4 @@ |
||||
/** @type {import('next').NextConfig} */ |
||||
const nextConfig = {}; |
||||
|
||||
export default nextConfig; |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,33 @@ |
||||
{ |
||||
"name": "edu-connect", |
||||
"version": "0.1.0", |
||||
"private": true, |
||||
"scripts": { |
||||
"dev": "next dev", |
||||
"build": "next build", |
||||
"start": "next start", |
||||
"lint": "next lint" |
||||
}, |
||||
"dependencies": { |
||||
"@radix-ui/react-navigation-menu": "^1.2.3", |
||||
"@radix-ui/react-slot": "^1.1.1", |
||||
"class-variance-authority": "^0.7.1", |
||||
"clsx": "^2.1.1", |
||||
"lucide-react": "^0.471.0", |
||||
"next": "14.2.23", |
||||
"react": "^18", |
||||
"react-dom": "^18", |
||||
"tailwind-merge": "^2.6.0", |
||||
"tailwindcss-animate": "^1.0.7" |
||||
}, |
||||
"devDependencies": { |
||||
"@types/node": "^20", |
||||
"@types/react": "^18", |
||||
"@types/react-dom": "^18", |
||||
"eslint": "^8", |
||||
"eslint-config-next": "14.2.23", |
||||
"postcss": "^8", |
||||
"tailwindcss": "^3.4.1", |
||||
"typescript": "^5" |
||||
} |
||||
} |
@ -0,0 +1,8 @@ |
||||
/** @type {import('postcss-load-config').Config} */ |
||||
const config = { |
||||
plugins: { |
||||
tailwindcss: {}, |
||||
}, |
||||
}; |
||||
|
||||
export default config; |
After Width: | Height: | Size: 25 KiB |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,78 @@ |
||||
@tailwind base; |
||||
@tailwind components; |
||||
@tailwind utilities; |
||||
|
||||
body { |
||||
font-family: Arial, Helvetica, sans-serif; |
||||
} |
||||
|
||||
@layer utilities { |
||||
.text-balance { |
||||
text-wrap: balance; |
||||
} |
||||
} |
||||
|
||||
@layer base { |
||||
:root { |
||||
--background: 0 0% 100%; |
||||
--foreground: 224 71.4% 4.1%; |
||||
--card: 0 0% 100%; |
||||
--card-foreground: 224 71.4% 4.1%; |
||||
--popover: 0 0% 100%; |
||||
--popover-foreground: 224 71.4% 4.1%; |
||||
--primary: 220.9 39.3% 11%; |
||||
--primary-foreground: 210 20% 98%; |
||||
--secondary: 220 14.3% 95.9%; |
||||
--secondary-foreground: 220.9 39.3% 11%; |
||||
--muted: 220 14.3% 95.9%; |
||||
--muted-foreground: 220 8.9% 46.1%; |
||||
--accent: 220 14.3% 95.9%; |
||||
--accent-foreground: 220.9 39.3% 11%; |
||||
--destructive: 0 84.2% 60.2%; |
||||
--destructive-foreground: 210 20% 98%; |
||||
--border: 220 13% 91%; |
||||
--input: 220 13% 91%; |
||||
--ring: 224 71.4% 4.1%; |
||||
--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: 224 71.4% 4.1%; |
||||
--foreground: 210 20% 98%; |
||||
--card: 224 71.4% 4.1%; |
||||
--card-foreground: 210 20% 98%; |
||||
--popover: 224 71.4% 4.1%; |
||||
--popover-foreground: 210 20% 98%; |
||||
--primary: 210 20% 98%; |
||||
--primary-foreground: 220.9 39.3% 11%; |
||||
--secondary: 215 27.9% 16.9%; |
||||
--secondary-foreground: 210 20% 98%; |
||||
--muted: 215 27.9% 16.9%; |
||||
--muted-foreground: 217.9 10.6% 64.9%; |
||||
--accent: 215 27.9% 16.9%; |
||||
--accent-foreground: 210 20% 98%; |
||||
--destructive: 0 62.8% 30.6%; |
||||
--destructive-foreground: 210 20% 98%; |
||||
--border: 215 27.9% 16.9%; |
||||
--input: 215 27.9% 16.9%; |
||||
--ring: 216 12.2% 83.9%; |
||||
--chart-1: 220 70% 50%; |
||||
--chart-2: 160 60% 45%; |
||||
--chart-3: 30 80% 55%; |
||||
--chart-4: 280 65% 60%; |
||||
--chart-5: 340 75% 55%; |
||||
} |
||||
} |
||||
|
||||
@layer base { |
||||
* { |
||||
@apply border-border; |
||||
} |
||||
body { |
||||
@apply bg-background text-foreground; |
||||
} |
||||
} |
@ -0,0 +1,39 @@ |
||||
import type { Metadata } from "next"; |
||||
import localFont from "next/font/local"; |
||||
import "./globals.css"; |
||||
import { NavigationMenuWithIcons } from "@/components/common/Navbar/navMenu"; |
||||
import Footer from "@/components/common/Footer/footer"; |
||||
|
||||
const geistSans = localFont({ |
||||
src: "./fonts/GeistVF.woff", |
||||
variable: "--font-geist-sans", |
||||
weight: "100 900", |
||||
}); |
||||
const geistMono = localFont({ |
||||
src: "./fonts/GeistMonoVF.woff", |
||||
variable: "--font-geist-mono", |
||||
weight: "100 900", |
||||
}); |
||||
|
||||
export const metadata: Metadata = { |
||||
title: "Create Next App", |
||||
description: "Generated by create next app", |
||||
}; |
||||
|
||||
export default function RootLayout({ |
||||
children, |
||||
}: Readonly<{ |
||||
children: React.ReactNode; |
||||
}>) { |
||||
return ( |
||||
<html lang="en"> |
||||
<body |
||||
className={`${geistSans.variable} ${geistMono.variable} antialiased`} |
||||
> |
||||
<NavigationMenuWithIcons /> |
||||
{children} |
||||
<Footer /> |
||||
</body> |
||||
</html> |
||||
); |
||||
} |
@ -0,0 +1,101 @@ |
||||
import Image from "next/image"; |
||||
|
||||
export default function Home() { |
||||
return ( |
||||
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]"> |
||||
<main className="flex flex-col gap-8 row-start-2 items-center sm:items-start"> |
||||
<Image |
||||
className="dark:invert" |
||||
src="https://nextjs.org/icons/next.svg" |
||||
alt="Next.js logo" |
||||
width={180} |
||||
height={38} |
||||
priority |
||||
/> |
||||
<ol className="list-inside list-decimal text-sm text-center sm:text-left font-[family-name:var(--font-geist-mono)]"> |
||||
<li className="mb-2"> |
||||
Get started by editing{" "} |
||||
<code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-semibold"> |
||||
src/app/page.tsx |
||||
</code> |
||||
. |
||||
</li> |
||||
<li>Save and see your changes instantly.</li> |
||||
</ol> |
||||
|
||||
<div className="flex gap-4 items-center flex-col sm:flex-row"> |
||||
<a |
||||
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5" |
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" |
||||
target="_blank" |
||||
rel="noopener noreferrer" |
||||
> |
||||
<Image |
||||
className="dark:invert" |
||||
src="https://nextjs.org/icons/vercel.svg" |
||||
alt="Vercel logomark" |
||||
width={20} |
||||
height={20} |
||||
/> |
||||
Deploy now |
||||
</a> |
||||
<a |
||||
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:min-w-44" |
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" |
||||
target="_blank" |
||||
rel="noopener noreferrer" |
||||
> |
||||
Read our docs |
||||
</a> |
||||
</div> |
||||
</main> |
||||
<footer className="row-start-3 flex gap-6 flex-wrap items-center justify-center"> |
||||
<a |
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4" |
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" |
||||
target="_blank" |
||||
rel="noopener noreferrer" |
||||
> |
||||
<Image |
||||
aria-hidden |
||||
src="https://nextjs.org/icons/file.svg" |
||||
alt="File icon" |
||||
width={16} |
||||
height={16} |
||||
/> |
||||
Learn |
||||
</a> |
||||
<a |
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4" |
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" |
||||
target="_blank" |
||||
rel="noopener noreferrer" |
||||
> |
||||
<Image |
||||
aria-hidden |
||||
src="https://nextjs.org/icons/window.svg" |
||||
alt="Window icon" |
||||
width={16} |
||||
height={16} |
||||
/> |
||||
Examples |
||||
</a> |
||||
<a |
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4" |
||||
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" |
||||
target="_blank" |
||||
rel="noopener noreferrer" |
||||
> |
||||
<Image |
||||
aria-hidden |
||||
src="https://nextjs.org/icons/globe.svg" |
||||
alt="Globe icon" |
||||
width={16} |
||||
height={16} |
||||
/> |
||||
Go to nextjs.org → |
||||
</a> |
||||
</footer> |
||||
</div> |
||||
); |
||||
} |
@ -0,0 +1,64 @@ |
||||
|
||||
import { Input } from "@/components/ui/input" |
||||
import { Button } from "@/components/ui/button" |
||||
import Link from "next/link" |
||||
import { Facebook, Instagram, Linkedin, Twitter } from "lucide-react" |
||||
|
||||
|
||||
export default function Footer() { |
||||
return ( |
||||
<section className="w-full py-12 md:py-24 lg:py-32 bg-zinc-900 dark:bg-zinc-100"> |
||||
<div className="container px-4 md:px-6 flex flex-col items-center text-center"> |
||||
<h2 className="text-2xl font-bold tracking-tighter sm:text-3xl md:text-4xl lg:text-5xl/none text-white"> |
||||
Stay Connected |
||||
</h2> |
||||
<p className="mx-auto max-w-[700px] text-zinc-100 md:text-lg dark:text-zinc-800"> |
||||
Subscribe to our newsletter and follow us on our social media. |
||||
</p> |
||||
<div className="w-full max-w-md space-y-2 my-4"> |
||||
<form className="flex space-x-2"> |
||||
<Input type="email" placeholder="Enter your email" className="max-w-lg flex-1 text-zinc-900 bg-white" /> |
||||
<Button type="submit" variant="outline" className="text-white border-white"> |
||||
Subscribe |
||||
</Button> |
||||
</form> |
||||
</div> |
||||
<div className="flex justify-center space-x-4"> |
||||
<Link href="#" aria-label="Facebook page" className="text-white" prefetch={false}> |
||||
<Facebook className="h-6 w-6" /> |
||||
</Link> |
||||
<Link href="#" aria-label="Twitter profile" className="text-white" prefetch={false}> |
||||
<Twitter className="h-6 w-6" /> |
||||
</Link> |
||||
<Link href="#" aria-label="Instagram profile" className="text-white" prefetch={false}> |
||||
<Instagram className="h-6 w-6" /> |
||||
</Link> |
||||
<Link href="#" aria-label="LinkedIn profile" className="text-white" prefetch={false}> |
||||
<Linkedin className="h-6 w-6" /> |
||||
</Link> |
||||
</div> |
||||
</div> |
||||
</section> |
||||
) |
||||
} |
||||
|
||||
// function FacebookIcon(props) {
|
||||
// return (
|
||||
// <svg
|
||||
// {...props}
|
||||
// xmlns="http://www.w3.org/2000/svg"
|
||||
// width="24"
|
||||
// height="24"
|
||||
// viewBox="0 0 24 24"
|
||||
// fill="none"
|
||||
// stroke="currentColor"
|
||||
// strokeWidth="2"
|
||||
// strokeLinecap="round"
|
||||
// strokeLinejoin="round"
|
||||
// >
|
||||
// <path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z" />
|
||||
// </svg>
|
||||
// )
|
||||
// }
|
||||
|
||||
|
@ -0,0 +1,129 @@ |
||||
import * as React from "react" |
||||
import Link from "next/link" |
||||
import { Home, Settings, Book, FileText, Bell, User } from "lucide-react" |
||||
|
||||
import { |
||||
NavigationMenu, |
||||
NavigationMenuContent, |
||||
NavigationMenuItem, |
||||
NavigationMenuLink, |
||||
NavigationMenuList, |
||||
NavigationMenuTrigger, |
||||
navigationMenuTriggerStyle, |
||||
} from "@/components/ui/navigation-menu" |
||||
import { cn } from "@/lib/utils" |
||||
|
||||
const components = [ |
||||
{ |
||||
title: "Dashboard", |
||||
href: "/dashboard", |
||||
description: "Overview of your account and key metrics", |
||||
icon: Home |
||||
}, |
||||
{ |
||||
title: "Settings", |
||||
href: "/settings", |
||||
description: "Manage your account preferences and configuration", |
||||
icon: Settings |
||||
}, |
||||
{ |
||||
title: "Documentation", |
||||
href: "/docs", |
||||
description: "Detailed guides and API references", |
||||
icon: Book |
||||
}, |
||||
{ |
||||
title: "Reports", |
||||
href: "/reports", |
||||
description: "View and generate activity reports", |
||||
icon: FileText |
||||
}, |
||||
{ |
||||
title: "Notifications", |
||||
href: "/notifications", |
||||
description: "Manage your alerts and notifications", |
||||
icon: Bell |
||||
}, |
||||
{ |
||||
title: "Profile", |
||||
href: "/profile", |
||||
description: "View and edit your profile information", |
||||
icon: User |
||||
}, |
||||
] |
||||
|
||||
export function NavigationMenuWithIcons() { |
||||
return ( |
||||
<NavigationMenu> |
||||
<NavigationMenuList> |
||||
<NavigationMenuItem> |
||||
<NavigationMenuTrigger> |
||||
<Home className="mr-2 h-4 w-4" /> |
||||
Menu |
||||
</NavigationMenuTrigger> |
||||
<NavigationMenuContent> |
||||
<ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px]"> |
||||
{components.map((component) => ( |
||||
<ListItem |
||||
key={component.title} |
||||
title={component.title} |
||||
href={component.href} |
||||
icon={component.icon} |
||||
> |
||||
{component.description} |
||||
</ListItem> |
||||
))} |
||||
</ul> |
||||
</NavigationMenuContent> |
||||
</NavigationMenuItem> |
||||
|
||||
<NavigationMenuItem> |
||||
<Link href="/docs" legacyBehavior passHref> |
||||
<NavigationMenuLink className={navigationMenuTriggerStyle()}> |
||||
<Book className="mr-2 h-4 w-4" /> |
||||
Documentation |
||||
</NavigationMenuLink> |
||||
</Link> |
||||
</NavigationMenuItem> |
||||
|
||||
<NavigationMenuItem> |
||||
<Link href="/profile" legacyBehavior passHref> |
||||
<NavigationMenuLink className={navigationMenuTriggerStyle()}> |
||||
<User className="mr-2 h-4 w-4" /> |
||||
Profile |
||||
</NavigationMenuLink> |
||||
</Link> |
||||
</NavigationMenuItem> |
||||
</NavigationMenuList> |
||||
</NavigationMenu> |
||||
) |
||||
} |
||||
|
||||
const ListItem = React.forwardRef< |
||||
React.ElementRef<"a">, |
||||
React.ComponentPropsWithoutRef<"a"> & { icon?: React.ElementType } |
||||
>(({ className, title, children, icon: Icon, ...props }, ref) => { |
||||
return ( |
||||
<li> |
||||
<NavigationMenuLink asChild> |
||||
<a |
||||
ref={ref} |
||||
className={cn( |
||||
"block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground", |
||||
className |
||||
)} |
||||
{...props} |
||||
> |
||||
<div className="flex items-center text-sm font-medium leading-none"> |
||||
{Icon && <Icon className="mr-2 h-4 w-4" />} |
||||
{title} |
||||
</div> |
||||
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground mt-2"> |
||||
{children} |
||||
</p> |
||||
</a> |
||||
</NavigationMenuLink> |
||||
</li> |
||||
) |
||||
}) |
||||
ListItem.displayName = "ListItem" |
@ -0,0 +1,57 @@ |
||||
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 gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", |
||||
{ |
||||
variants: { |
||||
variant: { |
||||
default: |
||||
"bg-primary text-primary-foreground shadow hover:bg-primary/90", |
||||
destructive: |
||||
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", |
||||
outline: |
||||
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", |
||||
secondary: |
||||
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", |
||||
ghost: "hover:bg-accent hover:text-accent-foreground", |
||||
link: "text-primary underline-offset-4 hover:underline", |
||||
}, |
||||
size: { |
||||
default: "h-9 px-4 py-2", |
||||
sm: "h-8 rounded-md px-3 text-xs", |
||||
lg: "h-10 rounded-md px-8", |
||||
icon: "h-9 w-9", |
||||
}, |
||||
}, |
||||
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 } |
@ -0,0 +1,22 @@ |
||||
import * as React from "react" |
||||
|
||||
import { cn } from "@/lib/utils" |
||||
|
||||
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>( |
||||
({ className, type, ...props }, ref) => { |
||||
return ( |
||||
<input |
||||
type={type} |
||||
className={cn( |
||||
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", |
||||
className |
||||
)} |
||||
ref={ref} |
||||
{...props} |
||||
/> |
||||
) |
||||
} |
||||
) |
||||
Input.displayName = "Input" |
||||
|
||||
export { Input } |
@ -0,0 +1,128 @@ |
||||
import * as React from "react" |
||||
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu" |
||||
import { cva } from "class-variance-authority" |
||||
import { ChevronDown } from "lucide-react" |
||||
|
||||
import { cn } from "@/lib/utils" |
||||
|
||||
const NavigationMenu = React.forwardRef< |
||||
React.ElementRef<typeof NavigationMenuPrimitive.Root>, |
||||
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root> |
||||
>(({ className, children, ...props }, ref) => ( |
||||
<NavigationMenuPrimitive.Root |
||||
ref={ref} |
||||
className={cn( |
||||
"relative z-10 flex max-w-max flex-1 items-center justify-center", |
||||
className |
||||
)} |
||||
{...props} |
||||
> |
||||
{children} |
||||
<NavigationMenuViewport /> |
||||
</NavigationMenuPrimitive.Root> |
||||
)) |
||||
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName |
||||
|
||||
const NavigationMenuList = React.forwardRef< |
||||
React.ElementRef<typeof NavigationMenuPrimitive.List>, |
||||
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List> |
||||
>(({ className, ...props }, ref) => ( |
||||
<NavigationMenuPrimitive.List |
||||
ref={ref} |
||||
className={cn( |
||||
"group flex flex-1 list-none items-center justify-center space-x-1", |
||||
className |
||||
)} |
||||
{...props} |
||||
/> |
||||
)) |
||||
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName |
||||
|
||||
const NavigationMenuItem = NavigationMenuPrimitive.Item |
||||
|
||||
const navigationMenuTriggerStyle = cva( |
||||
"group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50" |
||||
) |
||||
|
||||
const NavigationMenuTrigger = React.forwardRef< |
||||
React.ElementRef<typeof NavigationMenuPrimitive.Trigger>, |
||||
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger> |
||||
>(({ className, children, ...props }, ref) => ( |
||||
<NavigationMenuPrimitive.Trigger |
||||
ref={ref} |
||||
className={cn(navigationMenuTriggerStyle(), "group", className)} |
||||
{...props} |
||||
> |
||||
{children}{" "} |
||||
<ChevronDown |
||||
className="relative top-[1px] ml-1 h-3 w-3 transition duration-300 group-data-[state=open]:rotate-180" |
||||
aria-hidden="true" |
||||
/> |
||||
</NavigationMenuPrimitive.Trigger> |
||||
)) |
||||
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName |
||||
|
||||
const NavigationMenuContent = React.forwardRef< |
||||
React.ElementRef<typeof NavigationMenuPrimitive.Content>, |
||||
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content> |
||||
>(({ className, ...props }, ref) => ( |
||||
<NavigationMenuPrimitive.Content |
||||
ref={ref} |
||||
className={cn( |
||||
"left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto ", |
||||
className |
||||
)} |
||||
{...props} |
||||
/> |
||||
)) |
||||
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName |
||||
|
||||
const NavigationMenuLink = NavigationMenuPrimitive.Link |
||||
|
||||
const NavigationMenuViewport = React.forwardRef< |
||||
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>, |
||||
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport> |
||||
>(({ className, ...props }, ref) => ( |
||||
<div className={cn("absolute left-0 top-full flex justify-center")}> |
||||
<NavigationMenuPrimitive.Viewport |
||||
className={cn( |
||||
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]", |
||||
className |
||||
)} |
||||
ref={ref} |
||||
{...props} |
||||
/> |
||||
</div> |
||||
)) |
||||
NavigationMenuViewport.displayName = |
||||
NavigationMenuPrimitive.Viewport.displayName |
||||
|
||||
const NavigationMenuIndicator = React.forwardRef< |
||||
React.ElementRef<typeof NavigationMenuPrimitive.Indicator>, |
||||
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator> |
||||
>(({ className, ...props }, ref) => ( |
||||
<NavigationMenuPrimitive.Indicator |
||||
ref={ref} |
||||
className={cn( |
||||
"top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in", |
||||
className |
||||
)} |
||||
{...props} |
||||
> |
||||
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" /> |
||||
</NavigationMenuPrimitive.Indicator> |
||||
)) |
||||
NavigationMenuIndicator.displayName = |
||||
NavigationMenuPrimitive.Indicator.displayName |
||||
|
||||
export { |
||||
navigationMenuTriggerStyle, |
||||
NavigationMenu, |
||||
NavigationMenuList, |
||||
NavigationMenuItem, |
||||
NavigationMenuContent, |
||||
NavigationMenuTrigger, |
||||
NavigationMenuLink, |
||||
NavigationMenuIndicator, |
||||
NavigationMenuViewport, |
||||
} |
@ -0,0 +1,6 @@ |
||||
import { clsx, type ClassValue } from "clsx" |
||||
import { twMerge } from "tailwind-merge" |
||||
|
||||
export function cn(...inputs: ClassValue[]) { |
||||
return twMerge(clsx(inputs)) |
||||
} |
@ -0,0 +1,63 @@ |
||||
import type { Config } from "tailwindcss"; |
||||
|
||||
const config: Config = { |
||||
darkMode: ["class"], |
||||
content: [ |
||||
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}", |
||||
"./src/components/**/*.{js,ts,jsx,tsx,mdx}", |
||||
"./src/app/**/*.{js,ts,jsx,tsx,mdx}", |
||||
], |
||||
theme: { |
||||
extend: { |
||||
colors: { |
||||
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))' |
||||
}, |
||||
secondary: { |
||||
DEFAULT: 'hsl(var(--secondary))', |
||||
foreground: 'hsl(var(--secondary-foreground))' |
||||
}, |
||||
muted: { |
||||
DEFAULT: 'hsl(var(--muted))', |
||||
foreground: 'hsl(var(--muted-foreground))' |
||||
}, |
||||
accent: { |
||||
DEFAULT: 'hsl(var(--accent))', |
||||
foreground: 'hsl(var(--accent-foreground))' |
||||
}, |
||||
destructive: { |
||||
DEFAULT: 'hsl(var(--destructive))', |
||||
foreground: 'hsl(var(--destructive-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))' |
||||
} |
||||
}, |
||||
borderRadius: { |
||||
lg: 'var(--radius)', |
||||
md: 'calc(var(--radius) - 2px)', |
||||
sm: 'calc(var(--radius) - 4px)' |
||||
} |
||||
} |
||||
}, |
||||
plugins: [require("tailwindcss-animate")], |
||||
}; |
||||
export default config; |
@ -0,0 +1,26 @@ |
||||
{ |
||||
"compilerOptions": { |
||||
"lib": ["dom", "dom.iterable", "esnext"], |
||||
"allowJs": true, |
||||
"skipLibCheck": true, |
||||
"strict": true, |
||||
"noEmit": true, |
||||
"esModuleInterop": true, |
||||
"module": "esnext", |
||||
"moduleResolution": "bundler", |
||||
"resolveJsonModule": true, |
||||
"isolatedModules": true, |
||||
"jsx": "preserve", |
||||
"incremental": true, |
||||
"plugins": [ |
||||
{ |
||||
"name": "next" |
||||
} |
||||
], |
||||
"paths": { |
||||
"@/*": ["./src/*"] |
||||
} |
||||
}, |
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], |
||||
"exclude": ["node_modules"] |
||||
} |
Loading…
Reference in new issue