UI
Button
Well, a Button.
import { Button } from '@/components/Button'; export const ButtonHero = () => ( <div className="flex justify-center"> <Button asChild> <a href="#installation">Continue to installation</a> </Button> </div>);
Installation
npm install @radix-ui/react-slot tailwind-variants @remixicon/react
- Copy and paste the code into your project’s component directory. Do not forget to update the import paths.
// Tremor Button [v0.2.0] import React from "react"import { Slot } from "@radix-ui/react-slot"import { RiLoader2Fill } from "@remixicon/react"import { tv, type VariantProps } from "tailwind-variants" import { cx, focusRing } from "@/lib/utils" const buttonVariants = tv({ base: [ // base "relative inline-flex items-center justify-center whitespace-nowrap rounded-md border px-3 py-2 text-center text-sm font-medium shadow-sm transition-all duration-100 ease-in-out", // disabled "disabled:pointer-events-none disabled:shadow-none", // focus focusRing, ], variants: { variant: { primary: [ // border "border-transparent", // text color "text-white dark:text-white", // background color "bg-blue-500 dark:bg-blue-500", // hover color "hover:bg-blue-600 dark:hover:bg-blue-600", // disabled "disabled:bg-blue-300 disabled:text-white", "disabled:dark:bg-blue-800 disabled:dark:text-blue-400", ], secondary: [ // border "border-gray-300 dark:border-gray-800", // text color "text-gray-900 dark:text-gray-50", // background color "bg-white dark:bg-gray-950", //hover color "hover:bg-gray-50 dark:hover:bg-gray-900/60", // disabled "disabled:text-gray-400", "disabled:dark:text-gray-600", ], light: [ // base "shadow-none", // border "border-transparent", // text color "text-gray-900 dark:text-gray-50", // background color "bg-gray-200 dark:bg-gray-900", // hover color "hover:bg-gray-300/70 dark:hover:bg-gray-800/80", // disabled "disabled:bg-gray-100 disabled:text-gray-400", "disabled:dark:bg-gray-800 disabled:dark:text-gray-600", ], ghost: [ // base "shadow-none", // border "border-transparent", // text color "text-gray-900 dark:text-gray-50", // hover color "bg-transparent hover:bg-gray-100 dark:hover:bg-gray-800/80", // disabled "disabled:text-gray-400", "disabled:dark:text-gray-600", ], destructive: [ // text color "text-white", // border "border-transparent", // background color "bg-red-600 dark:bg-red-700", // hover color "hover:bg-red-700 dark:hover:bg-red-600", // disabled "disabled:bg-red-300 disabled:text-white", "disabled:dark:bg-red-950 disabled:dark:text-red-400", ], }, }, defaultVariants: { variant: "primary", },}) interface ButtonProps extends React.ComponentPropsWithoutRef<"button">, VariantProps<typeof buttonVariants> { asChild?: boolean isLoading?: boolean loadingText?: string} const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( ( { asChild, isLoading = false, loadingText, className, disabled, variant, children, ...props }: ButtonProps, forwardedRef, ) => { const Component = asChild ? Slot : "button" return ( <Component ref={forwardedRef} className={cx(buttonVariants({ variant }), className)} disabled={disabled || isLoading} tremor-id="tremor-raw" {...props} > {isLoading ? ( <span className="pointer-events-none flex shrink-0 items-center justify-center gap-1.5"> <RiLoader2Fill className="size-4 shrink-0 animate-spin" aria-hidden="true" /> <span className="sr-only"> {loadingText ? loadingText : "Loading"} </span> {loadingText ? loadingText : children} </span> ) : ( children )} </Component> ) },) Button.displayName = "Button" export { Button, buttonVariants, type ButtonProps }
Example: Button variants
There are 4 button variants.
import { Button } from '@/components/Button';
export const ButtonVariantExample = () => ( <div className="flex flex-wrap justify-center gap-6"> <Button variant="primary">Primary</Button> <Button variant="secondary">Secondary</Button> <Button variant="light">Light</Button> <Button variant="ghost">Ghost</Button> <Button variant="destructive">Destructive</Button> </div>);
Example: Loading
To set the button in a loading state, use the isLoading prop. You can also set a custom loading text by passing a string to loadingText.
import { Button } from '@/components/Button';
export const ButtonLoadingExample = () => ( <div className="mx-auto flex w-fit gap-6"> <Button isLoading>Primary</Button> <Button isLoading loadingText="Loading text"> Primary </Button> </div>);
Example: Create anchor with asChild pop
Using the asChild asChild prop, we can wrap an anchor tag with the Button and render an anchor (<a/>) tag instead of a button.
import { Button } from '@/components/Button'; export const ButtonAsChildExample = () => ( <div className="flex justify-center"> <Button asChild> <a href="#api-reference-button">API Reference</a> </Button> </div>);
API Reference: Button
This component is based on the button element and supports all of its props.
- variant
- Set a predefined look.
"primary" | "secondary" | "light" | "ghost" | "destructive"
Default: "primary"
- isLoading
- If set to true, an animated spinner is shown and the button is in a disabeld state.
boolean
Default: false
- loadingText
- Alternative text, if loading property is set to true.
string