Hacktron Design System

Banner

A full-width strip at the top of the app for a notice that applies everywhere.

<template>  <Banner color="warning" dismissible dismiss-label="Dismiss" @dismiss="onDismiss">    Your trial ends in 3 days.  </Banner></template>

Props

Name Type Default
color'warning' | 'error'warning
iconstringi-lucide-alert-triangle
dismissiblebooleanfalse
dismissLabelstring"Dismiss"

Slots

Name Description
defaultThe banner's message, plus optionally one inline `TextLink` (it rests in the banner's own color; don't add a color or hover class). There's no separate `actions` prop.

Guidelines

Do

  • Use Banner for a platform-wide notice - one that follows the user across every page for as long as the underlying state holds (a trial ending, a payment overdue, a license expiring) - not something scoped to a single page.
  • Pass dismissible + dismissLabel + @dismiss together, backed by your own org-scoped useDismissible - see apps/frontend's trial-banner.vue for the pattern. Banner has no built-in dismiss persistence of its own.
  • Keep the slot content to a single line: a short message plus, optionally, one TextLink (navigation, with to) or one small Button (an action, like opening a confirm modal). Banner makes a TextLink keep the banner's own warning/error color instead of link blue, so don't add a color or hover class to it.
  • Gate visibility with the caller's own v-if (subscription status, license state, etc.) rather than expecting the banner to decide on its own whether to render.

Don't

  • Don't use Banner for something page-wide - scoped to a single page's content rather than the whole platform - use Alert instead.
  • Don't stack more than one Banner at a time - if a page can hit two triggers at once, pick the one that matters most and drop the rest, same rule as Alert.
  • Don't reach for Banner's underlying id/localStorage persistence - it's deliberately unused so dismissal always stays owned by useDismissible's org scoping.

Examples

warning

A state the user should know about but isn't blocked by.

<template>  <Banner color="warning">    Your trial ends in 3 days.  </Banner></template>

error

A state the user needs to act on.

<template>  <Banner color="error">    Your payment is overdue. Scans are paused.  </Banner></template>

Dismissible

A banner the user can close once they've read it.

<template>  <Banner color="warning" dismissible dismiss-label="Dismiss" @dismiss="onDismiss">    Your trial ends in 3 days.  </Banner></template>

With inline action

A call to action placed inline within the message.

<template>  <Banner color="error">    Your payment is overdue. Scans are paused.    <TextLink to="/billing">Update payment</TextLink>  </Banner></template>