Skip to content
kerfjsGitHub

Alert

A message that stays in the page until it is dealt with.

SourcePackage @kerf-js/veneerTry it

Preview

tsx
import { Alert, Stack } from '@kerf-js/veneer'export function Tones() {  return (  <Stack gap="related">    <Alert      tone="info"      title="Maintenance on Sunday"    >      Deploys pause for an hour from 02:00 UTC.    </Alert>    <Alert      tone="positive"      title="All regions healthy"    >      Every check passed in the last hour.    </Alert>    <Alert      tone="caution"      title="Close to your limit"    >      You've used 82% of this month's build minutes.    </Alert>    <Alert      tone="critical"      title="Deploy failed"    >      mobile-bff stopped at the health check.    </Alert>  </Stack>  )}

Installation

npm install @kerf-js/veneer

Try it

Change the controls: the preview and its code update together. The address keeps what you set, so you can link to it.

Live preview
Controls
Tone
Codeupdates as you change the controls
import { Alert } from '@kerf-js/veneer'<Alert title="Deploy failed" tone="critical">mobile-bff stopped at the health check.</Alert>

Usage

tsx
import { Alert } from '@kerf-js/veneer'<Alert>mobile-bff stopped at the health check.</Alert>

Title only

An alert needs only a title when nothing more has to be said.

tsx
import { Alert } from '@kerf-js/veneer'export function TitleOnly() {  return (  <Alert    tone="positive"    title="Domain verified"  />  )}

Text only

An alert can carry just text, with no title.

tsx
import { Alert } from '@kerf-js/veneer'export function BodyOnly() {  return (  <Alert tone="info">    Previews are removed 30 days after their branch is    deleted.  </Alert>  )}

With actions

Use actions to add buttons under the message.

tsx
import { Alert, Button } from '@kerf-js/veneer'export function WithActions() {  return (  <Alert    tone="critical"    title="Deploy failed"    actions={      <>        <Button          size="sm"          tone="critical"        >          Retry        </Button>        <Button          size="sm"          emphasis="ghost"          tone="neutral"        >          See logs        </Button>      </>    }  >    mobile-bff stopped at the health check after four    minutes.  </Alert>  )}

Dismissible

onDismiss adds the close button. You remove the alert.

tsx
import { state } from '@kerf-js/core'import {  Alert,  Button,  Row,  Stack} from '@kerf-js/veneer'export function Dismiss() {  const shown = state(true)  return (    <Stack>      {shown.value ? (        <Alert          tone="info"          title="New: preview comments"          onDismiss={() => (shown.value = false)}        >          Your team can now comment on any preview.        </Alert>      ) : (        <Row justify="center">          <Button            emphasis="ghost"            tone="neutral"            onClick={() => (shown.value = true)}          >            Show it again          </Button>        </Row>      )}    </Stack>  )}

A form error

Press Add domain with the box empty. live announces it.

tsx
import { state } from '@kerf-js/core'import {  Alert,  Button,  Input,  Row,  Stack} from '@kerf-js/veneer'export function FormError() {  const domain = state('')  const failed = state(false)  const save = (e: Event) => {    e.preventDefault()    failed.value = !domain.value.includes('.')  }  return (    <Stack      as="form"      gap="group"      onSubmit={save}    >      {failed.value && (        <Alert          live          tone="critical"          title="That domain won't work"        >          Use a full domain, like shop.kerf.dev.        </Alert>      )}      <Input        label="Domain"        placeholder="shop.kerf.dev"        value={domain.value}        onInput={(e: Event) =>          (domain.value = (            e.target as HTMLInputElement          ).value)        }      />      <Row justify="end">        <Button type="submit">Add domain</Button>      </Row>    </Stack>  )}

Close to a limit

An alert with tone set to caution and an actions button warns about a limit and offers a fix.

tsx
import { state } from '@kerf-js/core'import { Alert, Button, Stack } from '@kerf-js/veneer'export function Usage() {  const upgraded = state(false)  return (    <Stack>      {upgraded.value ? (        <Alert          tone="positive"          title="You're on Scale"        >          Your new build minutes are ready.        </Alert>      ) : (        <Alert          tone="caution"          title="82% of build minutes used"          actions={            <Button              size="sm"              onClick={() => (upgraded.value = true)}            >              Upgrade            </Button>          }        >          At this pace you'll run out on the 26th, and          deploys will queue.        </Alert>      )}    </Stack>  )}

When to use

Use it for

  • Something people should know about this part of the page
  • A form error that has just happened

Reach for something else

  • Toaster, when it is a passing confirmation
  • Modal, when people can't go on until they answer

Accessibility

  • live sets role="alert", which interrupts screen readers. Keep it for new errors.
  • An alert on the page at load is not announced.

Theming

Restyle it app-wide from veneer() in your kerf config. Every key takes colour, spacing, size, radius, shadow, type and motion; its own keys are listed. A state nests inside: hover: { bg: 'ink' }. Text on a fill you set is contrast-checked at build. How theming works

KeyOwn keysStates
parts.close—hover, focus, press, active, open, disabled
ts
veneer({  colors: { brand: '#e8590c', ink: '#1b1b1f' },  parts: {    close: { size: 28 },  },})

API Reference

PropTypeDefaultDescription
toneTone'info'What it means. Sets the colour and the icon.
titleunknown—The first line, in bold.
livebooleanfalseRead it out as soon as it appears. Only for new errors.
actionsunknown—Buttons, under the text.
childrenunknown—What it contains.
EventTypeDefaultDescription
onDismiss(() => void)—Adds a close button. Called when it is pressed.

Parts

Every element carries a stable name, so you can style it from your own CSS: [data-scope="alert"] [data-part="icon"]

icontitledescriptionactionsclose

RelatedToasterModal