Banner
5 blocksBanner 01
Preview
npx nateui@latest add BannerAnnouncementDark
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 BannerPolicyUpdateDark
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 BannerProductAnnouncementDark
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 BannerUpgradePromptDark
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 BannerCollaborationPromptDark
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