Settings — Two-Pane Admin Pattern

/settings is a Shopify-admin-style two-pane settings shell, aligned to Shopify's App Home / admin settings guidelines: a left category nav + a right content pane per category, each category page owning its own grouped cards, dirty-tracking Save Bar, and confirmation modals.

Structure

The dirty-tracking contract (repeated per page)

Every settings page follows the same shape (see SettingsGeneral as the canonical example):

private readonly baseline = signal<Values>(INITIAL);      // last-saved snapshot
private readonly currentValues = computed<Values>(() => ({ /* live field signals */ }));
readonly dirty = computed(() => JSON.stringify(this.currentValues()) !== JSON.stringify(this.baseline()));

onSave(): void { this.baseline.set(this.currentValues()); this.toast.show('Settings saved', { tone: 'success' }); }
onDiscard(): void { this.applyValues(this.baseline()); }

tip-save-bar [visible]="dirty()" is the first element inside the page's scrollable container (so its sticky; top: 0 pins correctly — see save-bar.md). Destructive actions (Reset, in General) route through a tip-modal confirmation before mutating baseline, and a tip-button variant="critical" inside [primary-action].

Shopify alignment

The category-nav + grouped-cards + inline row (label/sublabel + chevron or control) shape, the sticky contextual save bar, and confirmation modals for destructive settings mirror Shopify's admin settings template directly — this is a deliberate reference, not an accidental convergence; consult the linked Shopify doc before deviating from the category/card grouping when adding a new settings section.

Composing a new settings page

  1. Add a SettingsCategory entry to CATEGORIES in settings-layout.ts (id, label, icon, path) and a matching child route under /settings in app.routes.ts.
  2. Create pages/<name>.ts + .html + .css, following the dirty-tracking contract above if the page has editable fields.
  3. Group related fields into tip-cards with a .stg-card-head (title + subtitle) — reuse settings-shared.css classes (stg-page, stg-card-head, stg-row, stg-field-grid, …) rather than inventing new layout classes per page.