Aksara UI

Banner

Banners are persistent inline messages with an optional icon, action, close button and details panel.

import { Banner } from '@aksornproject/aksara-ui'

Variants

Banner is a namespace. Banner.Base is the root, and Banner.Icon, Banner.Content, Banner.Title, Banner.Description, Banner.Action and Banner.Panel fill it.

variant sets the fill, the icon colour and the default role. Use information, success, warning and error for a status. default is a neutral grey and brand uses the accent colour, for messages that carry no status.

The Banner never picks a glyph. Pass one to Banner.Icon through icon or children, and it renders in a 24px slot in the status colour.

Check your classes before Monday.
Parents can see them from tomorrow.
The site is read-only from 22:00 to 23:00.
Browse 300 ready-made lesson plans.
<div className="flex w-full flex-col gap-spacing-12">
  {messages.map(({ variant, icon, title, description }) => (
    <Banner.Base key={variant} variant={variant} showCloseButton={false}>
      <Banner.Icon icon={icon} />
      <Banner.Content>
        <Banner.Title>{title}</Banner.Title>
        <Banner.Description>{description}</Banner.Description>
      </Banner.Content>
    </Banner.Base>
  ))}
</div>

Container

container="card", the default, has a 12px radius. section has square corners, for a full-width message at the top of a page. Both fill their parent.

Changes here do not affect this term.
<Banner.Base
  variant="information"
  container="section"
  showCloseButton={false}
>
  <Banner.Icon
    icon={<IconInterfaceEssentialInfoInformationCircle aria-hidden />}
  />
  <Banner.Content>
    <Banner.Title>You are viewing last year's class</Banner.Title>
    <Banner.Description>
      Changes here do not affect this term.
    </Banner.Description>
  </Banner.Content>
</Banner.Base>

Action

Banner.Action holds your controls beside the text. It wraps below the text when less than 240px remains. It does not restyle its children, so pass a Secondary XSmall Button in the status colour.

<Banner.Base variant="error" showCloseButton={false}>
  <Banner.Icon
    icon={<IconInterfaceEssentialDeleteDisabled aria-hidden />}
  />
  <Banner.Content>
    <Banner.Title>Sync failed</Banner.Title>
    <Banner.Description>
      Attendance from 9 May did not upload.
    </Banner.Description>
  </Banner.Content>
  <Banner.Action>
    <Button type="button" color="destructive" variant="secondary" size="xs">
      Retry
    </Button>
  </Banner.Action>
</Banner.Base>

Close

The close button shows by default. A click calls onClose with no arguments. The Banner keeps no visibility state, so the app unmounts it. showCloseButton={false} removes the button.

closeButtonLabel renames it, "Close alert" by default. customCloseIcon replaces the X glyph and closeButtonClassName merges last into the button.

Parents can see them from tomorrow.
<div className="flex w-full flex-col items-center gap-spacing-12">
  {visible ? (
    <Banner.Base variant="success" onClose={() => setVisible(false)}>
      <Banner.Icon icon={<IconInterfaceEssentialDoneCheck aria-hidden />} />
      <Banner.Content>
        <Banner.Title>Grades submitted</Banner.Title>
        <Banner.Description>
          Parents can see them from tomorrow.
        </Banner.Description>
      </Banner.Content>
    </Banner.Base>
  ) : (
    <Button variant="secondary-accent" onClick={() => setVisible(true)}>
      Show the banner again
    </Button>
  )}
</div>

Disabled and loading

disabled greys the title and the description and disables the close and expand buttons. Controls in Banner.Action keep their own disabled state, so disable them yourself.

loading replaces every child and both buttons with an aria-hidden skeleton and sets aria-busy.

It opens again on 1 June.
<div className="flex w-full flex-col gap-spacing-12">
  <Banner.Base variant="information" disabled>
    <Banner.Icon
      icon={<IconInterfaceEssentialInfoInformationCircle aria-hidden />}
    />
    <Banner.Content>
      <Banner.Title>Enrolment is closed</Banner.Title>
      <Banner.Description>It opens again on 1 June.</Banner.Description>
    </Banner.Content>
  </Banner.Base>
  <Banner.Base variant="information" loading>
    <Banner.Icon
      icon={<IconInterfaceEssentialInfoInformationCircle aria-hidden />}
    />
    <Banner.Content>
      <Banner.Title>Enrolment is closed</Banner.Title>
      <Banner.Description>It opens again on 1 June.</Banner.Description>
    </Banner.Content>
  </Banner.Base>
</div>

Details panel

A Banner.Panel adds an expand button to the header and opens below it at the full width. The panel is unstyled, so the app sets its padding, fill and border.

expandButtonLabel names the expand button, "Details" by default. expanded, defaultExpanded and onExpandedChange control it. Use one Panel per Banner.

Reload when you are ready.
<Banner.Base
  variant="information"
  showCloseButton={false}
  expandButtonLabel="Release notes"
>
  <Banner.Icon
    icon={<IconInterfaceEssentialInfoInformationCircle aria-hidden />}
  />
  <Banner.Content>
    <Banner.Title>Update available</Banner.Title>
    <Banner.Description>Reload when you are ready.</Banner.Description>
  </Banner.Content>
  <Banner.Panel
    className={`flex flex-col gap-spacing-8 border-t-(length:--border-border-1) border-color-border bg-color-background-surface px-spacing-16 py-spacing-12 ${typography('body-regular')} text-color-text-primary`}
  >
    Lesson plans now sort by unit. Attendance exports include late arrivals.
  </Banner.Panel>
</Banner.Base>

Accessibility

  • error and warning default to role="alert". The other variants use role="status". A role prop overrides the default.
  • The close and expand buttons are type="button", so a Banner inside a form never submits it.
  • The expand button carries aria-expanded.
  • Give a custom icon accessible text when it adds information. Otherwise mark it aria-hidden.
  • Banner.Icon and Banner.Panel must be direct children of Banner.Base or sit inside fragments. Content and Action can be wrapped in your own components.
  • A render target must keep the root role and the disclosure attributes.

API

Banner.Base

Prop

Type

Banner.Icon

Prop

Type

Banner.Content, Banner.Title, Banner.Description, Banner.Action

Prop

Type

Banner.Panel

Prop

Type

Edit on GitHub

On this page