Desishub Lessons
Next JS and TypeScript
Re-Useable Components

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