Banner

A banner is a component that showcases an important message at the uppermost part of the display.

import Banner from "@tailus-ui/Banner";
import { Link, Text } from "@tailus-ui/typography";
import { CircleAlert } from "lucide-react";

export const Overview = () => (
    <div className="space-y-4">
        <Banner.Root intent="danger" className="p-[--toast-padding]">
            <Banner.Content>
                <CircleAlert className="size-5 text-[--body-text-color]"/>
                <div className="space-y-2">
                    <Text size="sm" className="my-0 text-danger-800 dark:text-danger-300">
                        Almost out of storage (95% used). If you run out, you can’t back up photos, or send and receive email in Gmail. {' '}
                        <Link className="text-danger-900 dark:text-danger-200" href="#" intent="danger" size="sm" variant="underlined">Manage Storage</Link>
                    </Text>
                </div>
            </Banner.Content>
        </Banner.Root>

        <Banner.Root intent="info" className="p-[--toast-padding]">
            <Banner.Content>
                <CircleAlert className="size-5 text-[--body-text-color]"/>
                <div className="space-y-2">
                    <Text size="sm" className="my-0 text-info-800 dark:text-info-300">
                        Almost out of storage (95% used). If you run out, you can’t back up photos, or send and receive email in Gmail. {' '}
                        <Link className="text-info-900 dark:text-info-200" href="#" intent="info" size="sm" variant="underlined">Manage Storage</Link>
                    </Text>
                    
                </div>
            </Banner.Content>
        </Banner.Root>

        <Banner.Root intent="success" className="p-[--toast-padding]">
            <Banner.Content>
                <CircleAlert className="size-5 text-[--body-text-color]"/>
                <div className="space-y-2">
                    <Text size="sm" className="my-0 text-success-800 dark:text-success-300">
                        Almost out of storage (95% used). If you run out, you can’t back up photos, or send and receive email in Gmail. {' '}
                        <Link className="text-success-900 dark:text-success-200" href="#" intent="success" size="sm" variant="underlined">Manage Storage</Link>
                    </Text>
                </div>
            </Banner.Content>
        </Banner.Root>

        <Banner.Root intent="warning" className="p-[--toast-padding]">
            <Banner.Content>
                <CircleAlert className="size-5 text-[--body-text-color]"/>
                <div className="space-y-2">
                    <Text size="sm" className="my-0 text-warning-900 dark:text-warning-300">
                        Almost out of storage (95% used). If you run out, you can’t back up photos, or send and receive email in Gmail. {' '}
                        <Link className="text-warning-900 dark:text-warning-200" href="#" intent="warning" size="sm" variant="underlined">Manage Storage</Link>
                    </Text>
                </div>
            </Banner.Content>
        </Banner.Root>

        <Banner.Root intent="gray" className="p-[--toast-padding]">
            <Banner.Content>
                <CircleAlert className="size-5 text-[--body-text-color]"/>
                <div className="space-y-2">
                    <Text size="sm" className="my-0 text-gray-800 dark:text-gray-300">
                        Almost out of storage (95% used). If you run out, you can’t back up photos, or send and receive email in Gmail. {' '}
                        <Link className="text-gray-900 dark:text-gray-200" href="#" intent="gray" size="sm" variant="underlined">Manage Storage</Link>
                    </Text>
                </div>
            </Banner.Content>
        </Banner.Root>
    </div>
)

Installation

Copy-Paste the component code in a .tsx file.

import { banner, type BannerProps } from "@tailus/themer";
import React, { cloneElement } from "react";

export const Root = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement> & BannerProps>(
    ({ className, intent = "info", ...props }, ref) => {
        const { root } = banner();
        return (
            <div
                ref={ref}
                role="banner"
                aria-label={`${intent} banner`}
                className={root({ intent, className})}
                {...props}
            />
        )
    }
);

export const Content = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
    ({ className, ...props }, ref) => {
        const { content } = banner();
        return (
            <div
                ref={ref}
                className={content({ className })}
                {...props}
            />
        )
    }
);

export const Icon = React.forwardRef<HTMLElement, React.HTMLAttributes<HTMLDivElement>>(
    ({ className, children, ...props }, ref) => {
        const { icon } = banner();
        return (
            cloneElement(children as React.ReactElement, {className: icon({ className }), ref:ref, ...props})
        )
    }
);

export default {
    Root,
    Content,
    Icon,
}