Welcome to Vanilla Breeze
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
Automatically save form drafts to localStorage as the user types. Restores on page reload with a toast notification. Clears on submit or reset.
The data-autosave attribute automatically persists form data to localStorage as the user types. If the page is accidentally closed or refreshed, the draft is restored on the next visit with a toast notification. The draft is cleared when the form is submitted or reset.
<form data-autosave="contact-form"> <input name="name" placeholder="Name"> <textarea name="message" placeholder="Message"></textarea> <button type="submit">Send</button></form>
Add data-autosave to any <form> element with a unique key as the value. The init script:
input and change event listeners on the formlocalStorage with the key vb-autosave:{key} and a timestampinput events so other enhancements updatetoast-msg if availabledata-autosave-init to prevent double-bindingPassword fields (type="password") and file inputs (type="file") are always skipped — sensitive data and file references are never stored.
| Attribute | Value | Description |
|---|---|---|
data-autosave |
string (required) | A unique storage key for this form. Used as part of the localStorage key: vb-autosave:{key}. |
data-autosave-init |
boolean | Set automatically to prevent double-binding. Do not set manually. |
The draft is stored as a JSON object in localStorage. Each named field in the form becomes a key-value pair. A _ts timestamp is included for expiry checking.
<thead> <tr> <th>Detail</th> <th>Value</th> </tr> </thead> <tbody> <tr> <td>Key format</td> <td><code>vb-autosave:{<em>key</em>}</code></td> </tr> <tr> <td>Debounce</td> <td>500ms after last input</td> </tr> <tr> <td>Expiry</td> <td>24 hours from last save</td> </tr> <tr> <td>Skipped types</td> <td><code>password</code>, <code>file</code></td> </tr> </tbody> </table> </section> <section> <h2>Multiple Forms</h2> <p>Each form on a page must have a unique <code>data-autosave</code> key. The key is used directly in the <code>localStorage</code> key, so collisions between forms on different pages are avoided by using descriptive names.</p> <code-block language="html" show-lines label="Multiple forms with unique keys" data-escape><!-- Each form needs a unique key --><form data-autosave="signup-form"> <input name="email" type="email" placeholder="Email"> <input name="username" placeholder="Username"> <button type="submit">Sign Up</button></form> <form data-autosave="feedback-form"> <textarea name="feedback" placeholder="Your feedback"></textarea> <button type="submit">Submit</button></form>
Checkbox and radio inputs are handled correctly during both save and restore:
"on" when checked, "" when unchecked. On restore, the checked property is set accordingly.<form data-autosave="preferences"> <fieldset> <legend>Notifications</legend> <label> <input type="checkbox" name="email-notify" value="yes"> Email notifications </label> <label> <input type="checkbox" name="sms-notify" value="yes"> SMS notifications </label> </fieldset> <fieldset> <legend>Theme</legend> <label> <input type="radio" name="theme" value="light"> Light </label> <label> <input type="radio" name="theme" value="dark"> Dark </label> </fieldset> <button type="submit">Save</button></form>
When a draft is restored, input events are fired on each restored field. This ensures other Vanilla Breeze enhancements that listen for input events — such as data-count, data-grow, and data-show-when — update correctly.
<form data-autosave="registration" class="stacked"> <form-field> <label for="reg-email">Email</label> <input type="email" id="reg-email" name="email" required> </form-field> <form-field> <label for="reg-name">Full Name</label> <input type="text" id="reg-name" name="fullname" required> <small slot="help">As it appears on your ID.</small> </form-field> <form-field> <label for="reg-bio">Bio</label> <textarea id="reg-bio" name="bio" data-count="200" data-grow></textarea> </form-field> <button type="submit">Register</button></form>
When a draft is restored, a toast notification is displayed if toast-msg is available on the page. The toast uses the following configuration:
infoIf toast-msg is not present, the draft is still restored silently without a notification.
The autosave draft is automatically cleared in two scenarios:
localStorage when the form is submittedform.reset()The autosave attribute itself has no visual output. The only visible indicator is the toast notification on restore, which inherits styles from toast-msg.
/* The toast notification uses toast-msg if available *//* Customize the restore notification via toast-msg styles */toast-msg::part(toast) { --toast-bg: var(--color-surface-raised); --toast-color: var(--color-text);}
All behavior is gated on data-autosave-init. Without JavaScript, the form works normally — data simply is not persisted to localStorage.
toast-msg's accessible live regioninput events on restore ensures dependent enhancements (character counts, conditional fields) are in the correct state for assistive technology