Skip to content
weftGitHub

SaveBar

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

SourcePackage @weft-js/warp

Preview

tsx
import { state } from '@weft-js/core'import { Input, SaveBar, Stack, Toaster } from '@weft-js/warp'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 @weft-js/warp

Usage

tsx
import { SaveBar } from '@weft-js/warp'

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