---
name: durable-ui
description: >
Durable UI patterns for modern web development — persisting client-side state across page loads, browser sessions,
and shareable URLs. Use this skill when implementing localStorage persistence, URL query parameter state, form draft
auto-save, multi-step wizard persistence, click-outside dismissal, modal/dialog backdrop patterns, or any client-side
state and interaction pattern that should be resilient and well-behaved. Works with React, Vue, and Svelte.
metadata:
author: sailscastshq
version: '1.1.0'
tags: durable-ui, localStorage, url-state, query-params, form-persistence, multi-step-forms, click-outside, modal, dialog, backdrop, dropdown, state-management, web-dev
---
# Durable UI
Durable UI is the practice of making client-side state and interactions resilient. State should survive page reloads, browser sessions, and — where appropriate — be shareable via URL. Interactive elements like dropdowns and modals should be dismissable in the ways users expect (click outside, Escape, backdrop click). Multi-step flows should never lose progress. Durable UI fills the gap for **UI preferences**, **navigation context**, and **interaction patterns** that belong on the client.
## When to Use
Use this skill when:
- Persisting UI preferences in localStorage (sidebar collapsed, dark mode, dismissed banners)
- Syncing filters, tabs, or pagination state to URL query parameters
- Auto-saving form drafts to localStorage with restore-on-return
- Building multi-step wizard forms that preserve progress across reloads and navigation
- Making dropdowns, context menus, and popovers close on outside click or Escape
- Closing modals, dialogs, and confirms via backdrop click or Escape
- Deciding where state should live (client localStorage vs URL vs server session vs database)
- Building `useLocalStorage`, `useQueryState`, `useDurableUrl`, `useDurableStorage`, `useFormDraft`, `useWizardDraft`, or `useClickOutside` hooks/composables/stores
- Handling cross-tab synchronization of localStorage values
- Implementing unsaved-changes warnings with Inertia.js navigation guards
- Managing focus return after modal close, focus trapping, and focus after list item deletion
- Building optimistic UI updates with rollback on error (toggles, list mutations, Inertia integration)
- Restoring scroll position after navigation, back/forward, and within scrollable containers
- Implementing toast notification queues with auto-dismiss, pause-on-hover, and aria-live
- Building debounced search with AbortController cancellation for client-side and server-side filtering
## Rules
Read individual rule files for detailed explanations and code examples:
- [rules/principles.md](rules/principles.md) - Decision framework: when to use localStorage vs URL params vs session vs database
- [rules/local-storage.md](rules/local-storage.md) - localStorage patterns with examples for React, Vue, and Svelte
- [rules/url-state.md](rules/url-state.md) - URL query parameter sync with pushState/replaceState patterns
- [rules/form-persistence.md](rules/form-persistence.md) - Auto-save form drafts with restore, expiry, and unsaved-changes warnings
- [rules/multi-step-forms.md](rules/multi-step-forms.md) - Multi-step wizard persistence with per-step drafts and aggregate submission
- [rules/click-outside.md](rules/click-outside.md) - Close dropdowns, context menus, modals, and dialogs on outside click, backdrop click, or Escape
- [rules/focus-management.md](rules/focus-management.md) - Focus return after modal close, focus trapping, and focus after list item deletion
- [rules/optimistic-ui.md](rules/optimistic-ui.md) - Optimistic updates with rollback on error for toggles, list mutations, and Inertia actions
- [rules/scroll-restoration.md](rules/scroll-restoration.md) - Scroll position restoration after navigation, back/forward, and within scrollable containers
- [rules/toast-notifications.md](rules/toast-notifications.md) - Toast notification queues with auto-dismiss, pause-on-hover, and Inertia flash integration
- [rules/debounced-search.md](rules/debounced-search.md) - Debounced search with AbortController cancellation for client-side and server-side filtering
- [rules/react.md](rules/react.md) - Complete React hook implementations (useLocalStorage, useQueryState, useFormDraft)
- [rules/vue.md](rules/vue.md) - Complete Vue composable implementations (useLocalStorage, useQueryState, useDurableUrl, useDurableStorage, useFormDraft)
- [rules/svelte.md](rules/svelte.md) - Complete Svelte store implementations (localStorageStore, queryStateStore, formDraftStore)