Re-Usable Componensts
These are some of my re-usable components
General Installation
Install shadcn and Darkmode
npx shadcn-ui@latest init
npm i lucide-react
Install Dark Mode here : Shadcn Guide (opens in a new tab)
Website Header,Layout, Footer and Hero Sections
site-header.tsx
"use client";
import React from "react";
import { useState } from "react";
import { Dialog, DialogPanel } from "@headlessui/react";
import { Bars3Icon, XMarkIcon } from "@heroicons/react/24/outline";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import Link from "next/link";
import { Button } from "./ui/button";
import { ModeToggle } from "./mode-toggle";
import { Session } from "next-auth";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { getInitials } from "@/lib/generateInitials";
// import { useRouter } from "next/navigation";
import { signOut } from "next-auth/react";
import { useRouter } from "next/navigation";
import Logo from "./global/Logo";
import AuthenticatedAvatar from "./AuthenticatedAvatar";
export default function SiteHeader({ session }: { session: Session | null }) {
const navigation = [
{ name: "Become a Vendor", href: "/vendor" },
{ name: "How it Works", href: "#howItWorks" },
{ name: "About", href: "/about" },
{ name: "Register", href: "/register" },
{ name: "Help", href: "/help" },
];
const router = useRouter();
async function handleLogout() {
try {
await signOut();
router.push("/login");
} catch (error) {
console.log(error);
}
}
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
return (
<header className="absolute inset-x-0 top-0 z-50">
<nav
aria-label="Global"
className="flex items-center justify-between p-6 lg:px-8"
>
<div className="flex lg:flex-1">
<Logo href="/" labelShown={false} />
{/* <a href="#" className="-m-1.5 p-1.5">
<span className="sr-only">Car Care Gate</span>
<img
alt=""
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"
className="h-8 w-auto"
/>
</a> */}
</div>
<div className="flex lg:hidden">
<button
type="button"
onClick={() => setMobileMenuOpen(true)}
className="-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-gray-700"
>
<span className="sr-only">Open main menu</span>
<Bars3Icon aria-hidden="true" className="h-6 w-6" />
</button>
</div>
<div className="hidden lg:flex lg:gap-x-12">
{navigation.map((item) => (
<Link
key={item.name}
href={item.href}
className="text-sm font-semibold leading-6 text-gray-900"
>
{item.name}
</Link>
))}
</div>
<div className="hidden lg:flex lg:flex-1 lg:justify-end space-x-2">
<ModeToggle />
{session ? (
<AuthenticatedAvatar session={session} />
) : (
<Button asChild variant={"outline"}>
<Link href="/login">Log in</Link>
</Button>
)}
</div>
</nav>
<Dialog
open={mobileMenuOpen}
onClose={setMobileMenuOpen}
className="lg:hidden"
>
<div className="fixed inset-0 z-50" />
<DialogPanel className="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto bg-white px-6 py-6 sm:max-w-sm sm:ring-1 sm:ring-gray-900/10">
<div className="flex items-center justify-between">
<Logo href="/" labelShown={false} />
<button
type="button"
onClick={() => setMobileMenuOpen(false)}
className="-m-2.5 rounded-md p-2.5 text-gray-700"
>
<span className="sr-only">Close menu</span>
<XMarkIcon aria-hidden="true" className="h-6 w-6" />
</button>
</div>
<div className="mt-6 flow-root">
<div className="-my-6 divide-y divide-gray-500/10">
<div className="space-y-2 py-6">
{navigation.map((item) => (
<Link
key={item.name}
href={item.href}
className="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50"
>
{item.name}
</Link>
))}
</div>
<div className="py-6">
{session ? (
<Button asChild variant={"ghost"}>
<Link href="/dashboard">
<Avatar>
<AvatarImage
src={session?.user?.image}
alt={session?.user?.name}
/>
<AvatarFallback>
{getInitials(session?.user?.name)}
</AvatarFallback>
</Avatar>
<span className="ml-3">Dashboard</span>
</Link>
</Button>
) : (
<Button asChild variant={"outline"}>
<Link href="/login">Log in</Link>
</Button>
)}
</div>
</div>
</div>
</DialogPanel>
</Dialog>
</header>
);
}
React Quill Editor
npm i react-quill
Form Select Input
npm i react-tailwindcss-select
Modify your Tailwind config
// in your tailwind.config.js
module.exports = {
// ...
content: [
"./src/**/*.{js,jsx,ts,tsx}",
"./node_modules/react-tailwindcss-select/dist/index.esm.js"
]
// ...
};
Single Image Input
Follow steps in the docs of [Uploathing] (https://docs.uploadthing.com/getting-started/appdir (opens in a new tab))
npm install uploadthing @uploadthing/react
Multiple Image Upload
Follow steps in the docs of [Uploathing] (https://docs.uploadthing.com/getting-started/appdir (opens in a new tab))
npm install uploadthing @uploadthing/react
Text Input
See how to use React hook form under forms, Include tailwind form plugin in the tailwind config
npm i react-hook-form
npm install -D @tailwindcss/forms
Tailwind config
// tailwind.config.js
module.exports = {
theme: {
// ...
},
plugins: [
require("@tailwindcss/forms"),
// ...
],
};
Textarea
Install Tailwind forms Plugin
Radio Input
Install tailwind forms plugin
Password Input
Install tailwind forms plugin
Submit Button and Close Button
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { Loader, Plus } from "lucide-react";
import React from "react";
type SubmitButtonProps = {
title: string;
loadingTitle?: string;
className?: string;
loaderIcon?: any;
buttonIcon?: any;
loading: boolean;
showIcon?: boolean;
size?: "default" | "sm" | "lg" | "icon" | null | undefined;
};
export default function SubmitButton({
title,
loadingTitle = "Saving Please wait...",
loading,
className,
loaderIcon = Loader,
buttonIcon = Plus,
showIcon = true,
}: SubmitButtonProps) {
const LoaderIcon = loaderIcon;
const ButtonIcon = buttonIcon;
return (
<>
{loading ? (
<button
type="button"
disabled
className={cn(
"items-center flex justify-center rounded-md bg-indigo-600/55 px-3 py-2 text-sm font-semibold leading-6 text-white shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 cursor-not-allowed",
className
)}
>
<LoaderIcon className="w-4 h-4 animate-spin mr-2" />
{loadingTitle}
</button>
) : (
<button
type="submit"
className={cn(
"flex items-center justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",
className
)}
>
{showIcon && <ButtonIcon className="w-4 h-4 mr-2" />}
{title}
</button>
)}
</>
);
}
Forms, Form Header and Form Footer
"use client";
import SubmitButton from "@/components/global/FormInputs/SubmitButton";
import { Button } from "@/components/ui/button";
import { ChevronLeft } from "lucide-react";
import { useRouter } from "next/navigation";
import React from "react";
import CloseButton from "../CloseButton";
type FormHeaderProps = {
title: string;
editingId: string | undefined;
loading: boolean;
href: string;
parent?: string;
};
export default function FormHeader({
title,
editingId,
loading,
href,
parent,
}: FormHeaderProps) {
const router = useRouter();
function goBack() {
router.back();
}
return (
{" "}
<div className="flex items-center justify-between">
<div className="flex items-center gap-4">
<Button
onClick={goBack}
variant="outline"
size="icon"
className="h-7 w-7"
type="button"
>
<ChevronLeft className="h-4 w-4" />
<span className="sr-only">Back</span>
</Button>
<h1 className="flex-1 shrink-0 whitespace-nowrap text-xl font-semibold tracking-tight sm:grow-0">
{editingId ? "Update" : "Create"} {title}
</h1>
</div>
<div className="flex items-center justify-center gap-2">
<CloseButton href={href} parent={parent} />
<SubmitButton
size={"sm"}
title={editingId ? `Update ${title}` : `Save ${title}`}
loading={loading}
/>
</div>
</div>
); }
Multiple File Upload (Both Images and PDFS, All files)
Follow steps in the docs of [Uploathing] (https://docs.uploadthing.com/getting-started/appdir (opens in a new tab))
npm install uploadthing @uploadthing/react
Custome Code Snippet Component
** Install React Code block Package **
npm i react-code-blocks