Button

The Button component is a versatile UI element used to trigger actions, navigate users, or submit forms. It supports various styles, sizes, loading, and states to fit different use cases. Designed for flexibility, it can be easily customized to match your application's theme.


Buttons preview

Please install everything that's required

Before setup and using this component, please install all the required dependencies from this link (if you have never installed).

1. Quick setup

Create a SpinLoadingIcon.tsx file in folder /components/icons/SpinLoadingIcon.tsx

jsx
import React from "react"; import { cn } from "@/utils/cn"; const sizeMap: { [key: number]: string } = { 4: "w-4 h-4", 5: "w-5 h-5", 6: "w-6 h-6", 7: "w-7 h-7", 8: "w-8 h-8", 10: "w-10 h-10", 12: "w-12 h-12", }; const SpinLoadingIcon = ({ size = 5, className, ...rest }: { size?: number; className?: string; }) => { return ( <svg className={cn( `-ml-1 mr-3 animate-spin`, sizeMap[size], // Fallback to w-5 h-5 if size is not mapped className, )} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" {...rest} > <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" /> <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" /> </svg> ); }; export default SpinLoadingIcon;

Create a Button.tsx file in folder /components/common/Button.tsx

jsx
import React from "react"; import Link from "next/link"; import { cn } from "@/utils/cn"; import SpinLoadingIcon from "./icons/SpinLoadingIcon"; const variantStyles = { primary: `bg-primary font-semibold text-white hover:opacity-80 active:bg-zinc-800 active:text-zinc-100/70`, secondary: `bg-zinc-50 font-medium text-zinc-900 border border-gray-300 hover:opacity-80 active:bg-zinc-100 active:text-zinc-900/60`, }; type ButtonProps = { variant?: keyof typeof variantStyles; isATag?: boolean; isLoading?: boolean; rounded?: boolean; shadow?: boolean; children: any; } & ( | (React.ComponentPropsWithoutRef<"button"> & { href?: undefined }) | React.ComponentPropsWithoutRef<typeof Link> ); const Button = ({ variant = "primary", className, isATag = false, children, isLoading, rounded = true, shadow = false, ...props }: ButtonProps) => { className = cn( `${rounded ? "rounded-full" : "rounded-md"} inline-flex items-center gap-1 justify-center py-2 px-3 text-sm outline-offset-2 transition active:transition-none`, variantStyles[variant], isLoading ? "cursor-not-allowed bg-gray-400 opacity-60" : "cursor-pointer", shadow && "shadow-md hover:shadow-lg", className, ); if (isATag) return ( // @ts-expect-error: Unreachable code error <a className={className} {...props}> {children} </a> ); return typeof props.href === "undefined" ? ( <button className={className} {...props} disabled={isLoading}> {isLoading && ( <SpinLoadingIcon className={`${variant === "secondary" ? "text-primary" : "text-white"} `} /> )} {children} </button> ) : ( <Link className={className} {...props}> {children} </Link> ); }; export default Button;

2. Usages

2.1 Shapes

jsx
<Button>Click here!</Button> <Button rounded={false}>Click here!</Button>

2.2 Primary and secondary buttons

jsx
<Button>Click here!</Button> <Button variant="secondary">Click here!</Button>

2.3 Shadow button

jsx
<Button shadow>Shadow Button</Button>

2.4 Loading button

Sometimes, when you call the API so you want the user see the loading and user can not click on your button, so you need the loading button:

jsx
<Button isLoading>is loading ...</Button>

2.5 Button with icon

If you want to add icon on your button like: download button, back button, forward button, ... just add inside Button component like the children:

Notes: If you want use the icon like me, just refer this link

jsx
import { ArrowDownTrayIcon } from "@heroicons/react/24/solid"; <Button isLoading> Download <ArrowDownTrayIcon aria-hidden="true" className="size-5 font-semibold" /> </Button>

Sometimes, if you want to use the link to navigate but you want the link with UI like button. Just simple add the href in Button. The Button component will use the Link component from NextJs.

jsx
<Button href="/internal-path">Click here!</Button>

2.7 Button as <a> tag

Sometimes, if you want to use the a tag as the button, you can add the href and set isTag=true for Button component. The Button component will use a tag (it works a lit bit with Link com).

jsx
<Button href="/test" isATag={true}>Click here!</Button>
Previous
Avatar
Next
Badge