Skip to content
kerfjsGitHub

SaveBar

A bar that rises when a form has unsaved changes, with Save and Discard.

SourcePackage @kerf-js/veneer

Preview

tsx
import { state } from '@kerf-js/core'import {  Input,  SaveBar,  Stack,  Toaster} from '@kerf-js/veneer'export function Project() {  const values = state({    name: 'storefront',    branch: 'main',  })  const errors = state<Record<string, string>>({})  const set = (key: 'name' | 'branch', value: string) =>    (values.value = { ...values.value, [key]: value })  return (    <Stack      as="form"      gap="group"    >      <Input        label="Project name"        value={values.value.name}        error={errors.value.name ?? ''}        onInput={(e) =>          set('name', e.currentTarget.value)        }      />      <Input        label="Production branch"        value={values.value.branch}        hint="Change a field and the bar rises."        error={errors.value.branch ?? ''}        onInput={(e) =>          set('branch', e.currentTarget.value)        }      />      <SaveBar        values={values}        errors={errors}        validate={(v) =>          v.name.trim()            ? {}            : { name: 'A project needs a name.' }        }        onSave={() => wait(800)}      />      <Toaster />    </Stack>  )}const wait = (ms: number) =>  new Promise<void>((done) => {    setTimeout(done, ms)  })

Installation

npm install @kerf-js/veneer

Usage

tsx
import { SaveBar } from '@kerf-js/veneer'

When to use

Use it for

  • A long form that saves as a whole

Reach for something else

  • Switch, when each setting saves itself the moment it changes

Accessibility

Enter
Saves, from any field in the form

API Reference

PropTypeDefaultDescription
valuesState<T>—The form's live values, as a state. The bar compares them to a snapshot.
errorsState<FieldErrors>—Where field errors are written, for your fields to read.
validate((values: T) => FieldErrors)—Client checks; anything returned stops the save.
EventTypeDefaultDescription
onSave(values: T) => void | FieldErrors | Promise<void | FieldErrors>—Resolve with field errors to keep the bar; throw on a transport failure.
onDiscard(() => void)—Called after Discard has put the snapshot back.
onLeave((href: string) => void)—Where a confirmed leave goes. Default: the browser navigates.

Parts

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

msgactions

RelatedSettings layoutInput