Skip to content

FRD: Settings Page Recipe

FieldValue
IDFRD-043
OwnerDavid Holmes
StatusDraft
PriorityP1 — Recipes
SizeM (Recipe)
Target Releasev2.0.0
Last Updated2026-05-26
RelatedADR-027 (Default Tech Stack)

Document Summary

Create an MDX recipe in Storybook that teaches developers how to compose a Settings page using design system components. The recipe covers tabbed/sectioned layouts, form state management with dirty detection, save/cancel button states, field-level and form-level validation, and toast feedback on save. It provides copy-pasteable code for a realistic “Account Settings” page with profile, notification, and security sections.


Introduction

Overview

Settings pages are the second most common page pattern in B2B SaaS after resource list pages. They combine multiple form sections (often in tabs), persistent form state, dirty tracking, validation, and save/cancel workflows. Without a canonical recipe, developers reinvent this pattern with inconsistent approaches to dirty detection, button states, and error handling.

Goals

  • Provide a single MDX recipe showing the complete Settings page composition pattern.
  • Demonstrate tabbed section organization using the Tabs component.
  • Show dirty detection that enables/disables the Save button and warns on unsaved navigation.
  • Show field-level validation (inline errors) and form-level validation (toast on submit failure).
  • Include save/cancel states: disabled save when clean, loading spinner during save, success/error toast.
  • Use realistic sections: Profile, Notifications, Security.

Non-Goals

  • Building new form components or validation libraries.
  • Server-side settings persistence or API design.
  • Implementing a settings framework or state management library.
  • Nested settings pages (e.g., team settings with sub-pages).

Scope

In Scope

ItemDescription
MDX recipe pagesrc/docs/recipes/settings-page.mdx with Storybook sidebar entry
Tab layoutTabs component organizing Profile, Notifications, Security sections
Form compositionTextField, Select, Switch, Checkbox for various setting types
Dirty detectionPattern for tracking whether any field has changed from its initial value
Save/Cancel statesDisabled save when clean, loading during save, cancel resets to initial values
ValidationField-level inline errors, form-level validation summary
Toast feedbackSuccess toast on save, error toast on failure
Overview page updateAdd Settings recipe entry to src/docs/recipes/00-overview.mdx

Out of Scope

ItemReason
Settings data fetchingBackend-specific; recipe covers the form composition
Role-based settings visibilityAuthorization logic varies by application
Multi-tenant settingsComplex pattern that warrants a separate recipe
File upload in settings (avatar)File upload patterns are a separate recipe

Users and Pain Points

UserPain Point
Application developerNo reference for how to wire dirty detection with save/cancel button states
Application developerUnclear whether to use field-level or form-level validation (answer: both)
Application developerTab navigation with unsaved changes causes silent data loss
Application developerSave button is always enabled even when no changes are made — wasted API calls
New team memberNo canonical “this is how we build a settings page” guide

Definitions

TermDefinition
Dirty detectionComparing current form values against initial values to determine if any changes have been made
Field-level validationValidation errors shown inline next to the field that failed
Form-level validationValidation that applies to the form as a whole (e.g., “At least one notification channel must be enabled”)
Unsaved changes guardA warning dialog that appears when the user tries to navigate away with unsaved changes

Current State

  • The src/docs/recipes/00-overview.mdx page lists “Settings Page” as a planned recipe.
  • All required components exist: tabs.tsx, text-field.tsx, select.tsx, checkbox.tsx, toast.tsx, button.tsx, dialog.tsx.
  • Switch/toggle functionality exists in the component library.
  • No recipe MDX file exists yet.
  • No code examples exist for the settings page composition pattern.

Proposed Solution

Create src/docs/recipes/settings-page.mdx with the following structure:

  1. Introduction — What this recipe builds, when to use it, when not to use it.
  2. Component inventory — Table listing every component used with links.
  3. Tab layout — Tabs configuration for section organization.
  4. Profile section — TextField for name/email, Select for timezone, avatar placeholder.
  5. Notifications section — Switch toggles for email/SMS/push, frequency Select.
  6. Security section — Password change fields, two-factor authentication toggle.
  7. Dirty detection — Custom hook pattern comparing current vs. initial form state.
  8. Save/Cancel workflow — Button states (disabled, loading, enabled), cancel reset, success/error toast.
  9. Validation — Field-level inline errors and form-level toast.
  10. Unsaved changes guard — Dialog warning on tab switch or page navigation with dirty state.
  11. Full composition — Complete code block.

Requirements

IDRequirementPriority
REQ-01Recipe is a single MDX file in src/docs/recipes/Must
REQ-02Recipe uses Tabs for section organizationMust
REQ-03Recipe demonstrates dirty detection with save/cancel button statesMust
REQ-04Recipe shows field-level validation with inline errorsMust
REQ-05Recipe shows save success and error feedback via ToastMust
REQ-06All code blocks are copy-pasteable and self-containedMust
REQ-07Recipe shows unsaved changes guard on navigationShould
REQ-08Recipe uses at least 3 different form control types (TextField, Select, Switch)Must

Functional Requirements

IDDescriptionAcceptance
FR-01MDX file renders in Storybook without errorspnpm build-storybook succeeds
FR-02All code blocks compile when extractedManual verification
FR-03Recipe overview page lists Settings recipe as “Available”Status updated
FR-04Save button is disabled when form is cleanShown in code example
FR-05Cancel button resets form to initial valuesShown in code example

Non-Functional Requirements

IDDescriptionTarget
NFR-01Recipe page load timeUnder 2 seconds
NFR-02Individual code block line countUnder 60 lines per block
NFR-03Full composition line countUnder 200 lines

API/Interface Requirements

InterfaceRequirement
MDX fileMust use “
Code blocksMust use fenced tsx code blocks with imports
Dirty detection hookMust be a self-contained useDirtyForm or equivalent pattern

Accessibility Requirements

IDRequirement
A11Y-01Tab sections must use proper role="tabpanel" (handled by Tabs component)
A11Y-02Form fields must have visible labels and associated error messages via aria-describedby
A11Y-03Save/Cancel buttons must have descriptive text (not just icons)
A11Y-04Unsaved changes dialog must trap focus and be dismissible with Escape

Content and Documentation Requirements

IDRequirement
DOC-01Update src/docs/recipes/00-overview.mdx to mark Settings recipe as available
DOC-02Each section must have a 1-2 sentence explanation
DOC-03Include “When to use” and “When not to use” callouts

Dependencies

DependencyTypeRisk
Tabs componentInternalMust support controlled tab index for unsaved changes guard
TextField componentInternalMust support error and helperText props for validation
Toast componentInternalMust support success and error variants
Dialog componentInternalUsed for unsaved changes guard

Risks and Tradeoffs

RiskImpactMitigation
Dirty detection pattern may not cover all form librariesLimited applicabilityShow a vanilla React pattern; note that form libraries (React Hook Form, TanStack Form) have built-in dirty tracking
Settings page structure varies widely across appsRecipe may not fit all casesFocus on the most common pattern (tabbed sections); note alternatives
Unsaved changes guard requires router integrationFramework-specificShow the dialog logic; note that router integration varies

Open Questions

#QuestionStatus
1Should the recipe use TanStack Form for validation or plain React state?Open
2Should the unsaved changes guard use beforeunload for browser navigation?Open
3Should we show a “Settings saved” banner in addition to a toast?Open

Acceptance Criteria

  • src/docs/recipes/settings-page.mdx exists and renders in Storybook.
  • Recipe appears in sidebar under “Docs/Best Practices/Recipes/Settings Page”.
  • Recipe demonstrates Tabs-based section layout.
  • Recipe shows dirty detection enabling/disabling Save button.
  • Recipe shows Cancel resetting form to initial values.
  • Recipe shows field-level validation with inline errors.
  • Recipe shows success and error Toast on save.
  • All code blocks compile when extracted.
  • pnpm build-storybook succeeds.

LLM Handoff Instructions

When an LLM agent picks up this FRD:

  1. Read src/docs/recipes/00-overview.mdx for recipe conventions.
  2. Read component source for: tabs.tsx, text-field.tsx, select.tsx, checkbox.tsx, toast.tsx, button.tsx, dialog.tsx.
  3. Read each component’s stories to understand established usage patterns.
  4. Create src/docs/recipes/settings-page.mdx with the section structure from the Proposed Solution.
  5. Sample data: “Account Settings” with Profile (name, email, timezone), Notifications (email/SMS/push toggles, digest frequency), Security (password change, 2FA toggle).
  6. Dirty detection: show a useDirtyForm(initialValues, currentValues) hook pattern that returns { isDirty, changedFields, reset }.
  7. All code blocks must use public package import paths.
  8. After creating, run pnpm build-storybook to verify.
  9. Update src/docs/recipes/00-overview.mdx.

Decision Log

DateDecisionRationale
2026-05-26Use Tabs for section organization rather than accordion or vertical navTabs are the most common settings page pattern and the design system Tabs component is well-tested
2026-05-26Show vanilla React state for dirty detectionFramework-agnostic; form library users can adapt the pattern

Document History

DateVersionAuthorChanges
2026-05-260.1David HolmesInitial draft