Tessina UI
Tessina UI
GitHubIntroduction
InstallationUsageTheming
Components
ButtonIconButtonLinkSpinnerBadgeAvatarStatusChipShortcutSkeletonSurfaceProgressMeterRating
LabelFieldFieldsetCheckboxRadioSwitchSliderSelectComboboxSearchTextareaNumberFieldDate PickerTime PickerOTP InputFile UploadCalendar
AlertBannerToastTooltip
TabsAccordionCollapsibleBreadcrumbPaginationStepperSegmentedControlButtonGroupToggleButtonToggleGroupToolbarNavigation MenuMenubarBottom NavSidebar
Split ButtonFABDropdown MenuContextMenuCommandPopoverHoverCard
ContainerStackFlexGridAspectRatioSpacerCardCarouselDividerScroll Area
Table
ChatBubblePromptInputCodeBlock
ModalAlertDialogDrawerAction SheetTop Header MobileTop Header DesktopEmptyStateForm
Contributing
ComponentsFeedback Blocks

Banner

Promotional / informational surface for marketing, onboarding, upsell, and announcements. Three layouts (inline, centered, landscape with edge-to-edge image), four variants, six intents, prefix/suffix slots, primary + secondary actions, inline arrow link, optional footer row, dismissible, LTR/RTL.

Playground

Installation

pnpm add @tessinaui/ui

Usage

import { Banner } from "@tessinaui/ui";
{/* Inline — text + trailing icon tile (Chime+ pattern) */}
<Banner
  intent="success"
  variant="soft"
  rounded="xl"
  dismissible
  inlineLink={{ label: "Unlock Chime+" }}
  title="Accelerate your savings with a 3.50% savings APY with Chime+"
  image={<ChimeLogo />}
/>

{/* Inline — text + inline button (7-Eleven pattern) */}
<Banner
  intent="info"
  variant="soft"
  title="Earn rewards with your 7REWARDS loyalty account"
  action={{ label: "See details", variant: "secondary", intent: "none" }}
  image={<SevenElevenLogo />}
/>

{/* Centered — POF-style stacked promo */}
<Banner
  layout="centered"
  variant="soft"
  icon={<Volleyball />}
  title="Keep the ball rolling"
  description="You probably know at least 1 person that has found someone on POF!"
  action={{ label: "Meet new people", rounded: "full" }}
/>

{/* Solid centered — premium upsell */}
<Banner
  layout="centered"
  intent="primary"
  variant="solid"
  title="Premium"
  description="Up to 2× the matches and more"
  action={{ label: "Upgrade now", variant: "secondary", intent: "none" }}
/>

{/* Landscape with footer (Verify-yourself pattern) */}
<Banner
  layout="landscape"
  variant="soft"
  title="Verify yourself"
  description="Real connections are just a selfie away"
  inlineLink={{ label: "Selfie-verified" }}
  image={<HeroPhoto />}
  footer={
    <>
      <span>+20,000 verified singles</span>
      <button>Get verified</button>
    </>
  }
/>

Showcase

Banner vs Alert

BannerAlert
PurposePromotional / informational — marketing, upsell, onboardingFeedback / status — error, warning, success, info
User contextOpt-in — user wasn't asking for it, but it's relevantReactive — surface in response to a user action or system event
Examples"Unlock Chime+", "Premium upsell", "7-Eleven loyalty""Failed to save", "Payment received", "Update available"
LayoutsInline / centered / landscape — designed for richer contentInline only — designed for a tight message + optional CTA
Image / photoFirst-class — leading icon tile, trailing logo, full-bleed photoDecorative icon only

If the surface is selling, onboarding, or otherwise promotional — use Banner. If it's reporting what just happened — use Alert.

Layouts

LayoutWhen to use
inline (default)Text + small icon / logo on the side. Most marketing slots.
centeredStacked icon, title, description, CTA. Hero promos, opt-in cards.
landscapeImage fills one full edge of the banner. Use when the visual carries the message.

API Reference

Props

PropTypeDefaultDescription
titleReactNode—Headline
descriptionReactNode—Subhead / body copy
layout"inline" | "centered" | "landscape""inline"Visual layout
imagePosition"leading" | "trailing""trailing"Side the image / icon sits on (inline + landscape)
align"start" | "center""center"Text alignment in centered layout
iconReactNode—Small leading icon — renders as a tinted square tile
imageReactNode—Larger graphic / photo — fills its edge in landscape
actionBannerAction | ReactNode—Primary CTA
secondaryActionBannerAction | ReactNode—Quieter secondary CTA next to primary
inlineLinkBannerInlineLink—Inline arrow-style link below the description
footerReactNode—Free-form bottom row (stat + CTA, terms, etc.)
dismissiblebooleanfalseShow × button in the top-end corner
onDismiss() => void—Called when the dismiss button is clicked
dismissLabelstring"Dismiss"aria-label for the × button
intent"none" | "primary" | "error" | "warning" | "success" | "info""none"Color intent — affects bg/border + default action intent
variant"solid" | "soft" | "outline" | "ghost""soft"Visual weight
size"sm" | "md" | "lg""md"Size token — scales padding and font sizes
rounded"none" | "sm" | "md" | "lg" | "xl" | "full""lg"Container border radius
shadowbooleanfalseDrop shadow
dir"ltr" | "rtl"inheritedText direction
roleAriaRole"region"ARIA role — set to "alert" for live announcements

BannerAction

When you pass an object, the banner renders a <Button> for you. When you pass a ReactNode, that node is rendered as-is — useful for SplitButton, IconButton, custom links, etc.

FieldTypeDescription
labelReactNodeButton text
onClick(event) => voidClick handler
hrefstringWhen set, the button renders as <a href> via Button's render prop
variant"primary" | "secondary" | "ghost" | "outline"Button variant
intent"none" | "error" | "warning" | "success" | "info"Button intent
size"xs" | "sm" | "md" | "lg" | "xl"Button size
rounded"none" | "sm" | "md" | "lg" | "full"Button corner radius
loadingbooleanShow spinner
disabledbooleanDisabled state
leadingIcon / trailingIconReactNodeIcons inside the button

BannerInlineLink

Quieter than a button — a small underlined arrow link, typically placed below the description.

FieldTypeDescription
labelReactNodeLink text
hrefstringLink target — when set, renders as <a>
onClick(event) => voidClick handler
trailingIconReactNodeOverride the default → arrow

Notes

  • Action defaults: when you pass a BannerAction object, its variant, intent, size, and rounded default to sensible values for the banner's intent + variant — so the common case (<Banner intent="primary" action={{ label: "Action" }} />) needs no extra tuning.
  • solid actions: when the banner is variant="solid", the default action variant flips to secondary (white pill on color) to read against the saturated background — see the Premium upsell example.
  • Image vs icon: icon becomes a tinted square tile sized to the banner. image is rendered as-is — pass any element. In landscape, image fills the full-edge column.
  • Footer row: rendered with a soft divider on non-solid variants and a translucent overlay on solid. Pass any layout you want — typically a stat on one side and a CTA on the other.
  • Distinct from Alert: Banner is for opt-in promotional content; Alert is for reactive feedback. Same primitives, different role.
  • Accessibility: defaults to role="region". Pass role="alert" for live promotional announcements you want screen readers to interrupt for.

Alert

Contextual feedback messages for user actions or system events. Four visual variants (solid, soft, outline, ghost), five intents, three sizes, six rounded options, optional close button, actions, and RTL support.

Toast

Transient floating notifications for short feedback messages, with optional actions and auto-dismiss.

On this page

PlaygroundInstallationUsageShowcaseBanner vs AlertLayoutsAPI ReferencePropsBannerActionBannerInlineLinkNotes