Banner

5 blocks

Banner 01

Preview
npx nateui@latest add BannerAnnouncement
Dark
import { useState } from 'react'
import IconFrame from '@/components/composites/IconFrame'
import Button from '@/components/ui/Button'
import Card from '@/components/ui/Card'
import CloseButton from '@/components/ui/CloseButton'
import { PiSparkle } from 'react-icons/pi'
import type { ReactNode } from 'react'

export type BannerAnnouncementProps = {
    title?: ReactNode
    description?: ReactNode
    actionLabel?: ReactNode
    actionHref?: string
    onDismiss?: () => void
}

const BannerAnnouncement = ({
    title = 'Your weekly report is ready.',
    description = 'Review progress, decisions, and what is moving next.',
    actionLabel = 'View report',
    actionHref = '#weekly-report',
    onDismiss,
}: BannerAnnouncementProps) => {
    const [isVisible, setIsVisible] = useState(true)

    if (!isVisible) {
        return null
    }

    const handleDismiss = () => {
        setIsVisible(false)
        onDismiss?.()
    }

    return (
        <Card className="mx-4 card-shadow bg-background" bodyClass="px-4 py-3">
            <div className="flex flex-col gap-4 sm:flex-row sm:items-center">
                <div className="flex min-w-0 flex-1 items-start gap-3 sm:items-center">
                    <IconFrame size={40} className="shrink-0">
                        <PiSparkle aria-hidden="true" className="text-xl" />
                    </IconFrame>
                    <p className="min-w-0 text-sm text-foreground">
                        <span className="font-semibold">{title}</span>{' '}
                        <span className="text-muted-foreground">{description}</span>
                    </p>
                </div>
                <div className="flex shrink-0 items-center gap-2 self-end sm:self-auto">
                    <Button asElement="a" href={actionHref} variant="default">
                        {actionLabel}
                    </Button>
                    <CloseButton aria-label="Dismiss announcement" onClick={handleDismiss} />
                </div>
            </div>
        </Card>
    )
}

export default BannerAnnouncement

Banner 02

Preview
npx nateui@latest add BannerPolicyUpdate
Dark
import CloseButton from '@/components/ui/CloseButton'
import Card from '@/components/ui/Card'
import { PiArrowRight, PiShieldCheck } from 'react-icons/pi'
import { useState } from 'react'

const BannerPolicyUpdate = () => {
    const [isVisible, setIsVisible] = useState(true)

    if (!isVisible) {
        return null
    }

    return (
        <Card className="mx-4" bodyClass="flex items-start gap-4 p-4">
            <div className="flex min-w-0 flex-1 items-start gap-3">
                <PiShieldCheck
                    aria-hidden="true"
                    className="mt-0.5 shrink-0 text-2xl"
                />
                <div className="min-w-0 space-y-2">
                    <div className="space-y-1">
                        <h6 className="text-base font-semibold text-foreground">
                            Data controls updated
                        </h6>
                        <p className="text-muted-foreground">
                            Review the latest changes affecting your workspace.
                        </p>
                    </div>
                    <a
                        href="#data-controls"
                        className="inline-flex items-center gap-1 text-sm font-medium text-primary hover:text-primary-hover"
                    >
                        Review update
                        <PiArrowRight aria-hidden="true" />
                    </a>
                </div>
            </div>
            <CloseButton
                aria-label="Dismiss data controls update"
                className="shrink-0"
                onClick={() => setIsVisible(false)}
            />
        </Card>
    )
}

export default BannerPolicyUpdate

Banner 03

Preview
npx nateui@latest add BannerProductAnnouncement
Dark
import { useState } from 'react'
import Button from '@/components/ui/Button'
import Tag from '@/components/ui/Tag'
import Card from '@/components/ui/Card'
import CloseButton from '@/components/ui/CloseButton'

const BannerProductAnnouncement = () => {
    const [isVisible, setIsVisible] = useState(true)

    if (!isVisible) {
        return null
    }

    return (
        <section aria-label="Automation setup prompt" className="mx-4">
            <Card
                className="border0 bg-palette-purple-soft"
                bodyClass="flex flex-col gap-4 p-4 lg:flex-row lg:items-center lg:justify-between"
            >
                <div className="min-w-0 space-y-1.5">
                    <div className="flex flex-wrap items-center gap-2">
                        <Tag className="bg-palette-purple text-white boder-0">
                            New
                        </Tag>
                        <h6 className="text-base font-semibold text-palette-purple-soft-foreground">
                            Turn each sign-up into a clear next step
                        </h6>
                    </div>
                    <p className="max-w-2xl text-palette-purple-soft-foreground">
                        Capture key context at sign-up and send every follow-up
                        to the teammate who can act first.
                    </p>
                </div>
                <div className="flex shrink-0 items-center gap-2 self-start lg:self-auto">
                    <Button>
                        Create automation
                    </Button>
                    <CloseButton
                        aria-label="Dismiss automation setup prompt"
                        onClick={() => setIsVisible(false)}
                    />
                </div>
            </Card>
        </section>
    )
}

export default BannerProductAnnouncement

Banner 04

Preview
npx nateui@latest add BannerUpgradePrompt
Dark
import Button from '@/components/ui/Button'
import Card from '@/components/ui/Card'
import { PiArrowRight } from 'react-icons/pi'

const assetBase = 'https://statics.nateui.com/img'

const BannerUpgradePrompt = () => {
    return (
        <Card
            className="mx-4 border-0 bg-gradient-to-r from-palette-cyan-soft/50 via-card to-palette-rose-soft/50"
            bodyClass="flex flex-col gap-4 p-4 sm:p-8 lg:flex-row lg:items-center lg:justify-between"
        >
            <div className="max-w-2xl space-y-4">
                <div className="space-y-2">
                    <h2 className="text-3xl font-semibold tracking-tight text-foreground">
                        Your team is at capacity
                    </h2>
                    <p className="text-base text-muted-foreground">
                        Choose a plan that makes room for the people building this project.
                    </p>
                </div>
                <Button
                    asElement="a"
                    href="#plans"
                    variant="solid"
                    className="inline-flex"
                    icon={<PiArrowRight aria-hidden="true" />}
                    iconAlignment="end"
                >
                    Compare plans
                </Button>
            </div>
            <img
                src={`${assetBase}/thumbs/misc/img-11.png`}
                alt="Four of four team seats assigned"
                className="w-full max-w-sm shrink-0"
            />
        </Card>
    )
}

export default BannerUpgradePrompt

Banner 05

Preview
npx nateui@latest add BannerCollaborationPrompt
Dark
import Card from '@/components/ui/Card'
import Link from '@/components/ui/Link'
import { PiArrowRight } from 'react-icons/pi'

const assetBase = 'https://statics.nateui.com/img'

const orbitLogoSizeClass = {
    small: 'h-9 w-9 lg:h-10 lg:w-10',
    medium: 'h-10 w-10 lg:h-12 lg:w-12',
    large: 'h-12 w-12 lg:h-14 lg:w-14',
}

const orbitIntegrations = [
    {
        name: 'Slack',
        file: 'slack.png',
        size: 'medium',
        positionClass: 'left-1/2 top-8 -translate-x-1/2 lg:top-10',
    },
    {
        name: 'Facebook',
        file: 'facebook.png',
        size: 'medium',
        positionClass: 'right-10 top-14 lg:right-12 lg:top-16',
    },
    {
        name: 'Figma',
        file: 'figma.png',
        size: 'medium',
        positionClass: 'right-0 top-1/2 -translate-y-1/2',
    },
    {
        name: 'Dropbox',
        file: 'dropbox.png',
        size: 'medium',
        positionClass: 'bottom-14 right-10 lg:bottom-16 lg:right-12',
    },
    {
        name: 'Instagram',
        file: 'instagram.png',
        size: 'large',
        positionClass: 'bottom-8 left-1/2 -translate-x-1/2 lg:bottom-10',
    },
    {
        name: 'Shopify',
        file: 'shopify.png',
        size: 'medium',
        positionClass: 'bottom-14 left-10 lg:bottom-16 lg:left-12',
    },
    {
        name: 'GitHub',
        file: 'github.png',
        size: 'medium',
        positionClass: 'left-0 top-1/2 -translate-y-1/2',
    },
    {
        name: 'Mailchimp',
        file: 'mailchimp.png',
        size: 'medium',
        positionClass: 'left-10 top-14 lg:left-12 lg:top-16',
    }
] as const

const BannerCollaborationPrompt = () => {
    return (
        <Card
            bordered={false}
            className="mx-4 overflow-hidden border-0 bg-palette-emerald-soft shadow-none"
            bodyClass="grid gap-10 p-8 sm:p-10 md:grid-cols-[minmax(0,1fr)_320px] md:items-center md:gap-12 lg:grid-cols-[minmax(0,1fr)_360px]"
        >
            <section className="min-w-0 max-w-xl space-y-5">
                <div className="space-y-3">
                    <h2 className="h2 max-w-md">
                        Connect the apps your team already relies on
                    </h2>
                    <p className="max-w-lg text-base leading-relaxed text-muted-foreground">
                        Bring conversations, content, automations, and reporting
                        into one coordinated workflow.
                    </p>
                </div>
                <Link
                    href="#integrations"
                    className="inline-flex items-center gap-2 rounded-control bg-card px-4 py-2 text-sm font-medium text-foreground shadow-card hover:text-foreground hover:no-underline"
                >
                    Browse integrations
                    <PiArrowRight aria-hidden="true" className="text-lg" />
                </Link>
            </section>

            <div
                aria-hidden="true"
                className="relative h-64 w-full justify-self-center md:h-48 md:translate-x-6 md:justify-self-end lg:translate-x-12"
            >
                <div className="absolute left-1/2 top-1/2 h-72 w-72 -translate-x-1/2 -translate-y-1/2 sm:h-80 sm:w-80 lg:h-96 lg:w-96">
                    <span className="absolute inset-6 rounded-full border border-foreground/10 lg:inset-8" />
                    <span className="absolute inset-16 rounded-full border border-foreground/10 lg:inset-20" />
                    <span className="absolute inset-28 rounded-full border border-foreground/10 lg:inset-32" />

                    {orbitIntegrations.map((integration) => (
                        <span
                            key={integration.name}
                            className={`absolute z-10 flex items-center justify-center rounded-control-sm bg-white p-1.5 shadow-card ${
                                orbitLogoSizeClass[integration.size]
                            } ${integration.positionClass}`}
                        >
                            <img
                                alt=""
                                src={`${assetBase}/thumbs/brands/${integration.file}`}
                                className="block h-full w-full object-contain"
                                loading="lazy"
                            />
                        </span>
                    ))}

                    <div
                        className="absolute left-1/2 top-1/2 z-20 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center size-16"
                    >
                        <img
                            alt=""
                            src={`${assetBase}/logos/logo-collapsed.svg`}
                            className="block h-full w-full dark:hidden"
                        />
                        <img
                            alt=""
                            src={`${assetBase}/logos/logo-white-collapsed.svg`}
                            className="hidden h-full w-full dark:block"
                        />
                    </div>
                </div>
            </div>
        </Card>
    )
}

export default BannerCollaborationPrompt