---
phase: quick-260610-jlp
plan: 01
subsystem: pwa/notifications
tags: [bug-fix, refactor, uat, push-notifications]
dependency_graph:
  requires: []
  provides: [InstructionSheet shared component, SettingsSheet how-to-enable wired]
  affects: [PermissionDeniedBanner, SettingsSheet]
tech_stack:
  added: []
  patterns: [shared component extraction, local state for sheet overlay]
key_files:
  created:
    - apps/pwa/src/components/InstructionSheet.tsx
    - apps/pwa/src/components/InstructionSheet.test.tsx
  modified:
    - apps/pwa/src/components/PermissionDeniedBanner.tsx
    - apps/pwa/src/components/SettingsSheet.tsx
decisions:
  - 'Extracted InstructionSheet verbatim from PermissionDeniedBanner; zero markup/copy/style changes (behaviour-preserving extraction)'
  - 'SettingsSheet uses local instructionsOpen state to gate rendering InstructionSheet, not onClose'
metrics:
  duration: ~8 minutes
  completed: '2026-06-10'
requirements: [UAT-05-T4]
---

# Phase quick-260610-jlp Plan 01: Fix Broken "How to Enable" Link in SettingsSheet

**One-liner:** Extracted shared InstructionSheet bottom-sheet from PermissionDeniedBanner and wired SettingsSheet's "How to enable" button to open it via local state (was: `onClick={onClose}` — dead link).

## Tasks Completed

| Task | Name                                                                           | Commit           | Files                                                  |
| ---- | ------------------------------------------------------------------------------ | ---------------- | ------------------------------------------------------ |
| 1    | Extract InstructionSheet into shared component + rewire PermissionDeniedBanner | 74b5d44          | InstructionSheet.tsx (new), PermissionDeniedBanner.tsx |
| 2    | Wire SettingsSheet "How to enable" + write test                                | 874c030          | SettingsSheet.tsx, InstructionSheet.test.tsx (new)     |
| 3    | Full typecheck + build + test gate                                             | (no code change) | —                                                      |

## Quality Gate Results

- `pnpm --filter @familysync/pwa typecheck`: exit 0 (no output)
- `pnpm --filter @familysync/pwa build`: SUCCESS — 1851 modules transformed, dist/assets/index-CaPAI7hF.js 655.55 kB gzip 191.46 kB, dist/sw.js 17.09 kB
- `pnpm --filter @familysync/pwa test`: **15 test files passed, 187 tests passed (0 failed)**

## Deviations from Plan

None — plan executed exactly as written.

## Known Stubs

None — all wiring is functional; InstructionSheet renders real steps.

## Threat Flags

None — no new network endpoints, auth paths, or trust boundary changes. The InstructionSheet is a local display component.

## Self-Check: PASSED

- `apps/pwa/src/components/InstructionSheet.tsx` — exists, named export confirmed
- `apps/pwa/src/components/InstructionSheet.test.tsx` — exists, 2 new tests pass
- `apps/pwa/src/components/PermissionDeniedBanner.tsx` — imports from InstructionSheet.js, no local definition
- `apps/pwa/src/components/SettingsSheet.tsx` — `setInstructionsOpen(true)` on "How to enable", `instructionsOpen &&` render
- Commits 74b5d44 and 874c030 both exist in git log
