# Spec: My Notes WYSIWYG editor via `react-native-enriched`

**Author:** tele (mobile coordinator)
**Date:** 2026-04-19
**Target:** mobile repo, new draft PR
**Branch:** `feat/notes-enriched-editor`
**Supersedes:** `feat/notes-rich-text-editor` (tentap-based, shelved)

---

## Why

The My Notes form sheet needs a WYSIWYG editor that matches the Figma (node `6330-130610`) — 4-pill paragraph-style row (Title / Heading / Subheading / Body) + inline format tiles (Bold, Italic, Underline, Bullet List, Numbered List). The previous tentap-based attempt (`feat/notes-rich-text-editor`) rendered as a white-boxed webview inside the sheet, which could not be visually reconciled with the dark theme design without forking the library. User explicitly rejected custom-maintaining an editor.

**Switching to `software-mansion/react-native-enriched`** — fully native, true WYSIWYG, no webview, maintained by the team behind Reanimated / Gesture Handler / Skia bindings. Matches the Figma intent without us owning CSS shells.

## Scope

### In scope (Phase 1)

1. Add dependency `react-native-enriched` (follow their install guide — pod install for iOS, expo prebuild handling if needed)
2. Replace `NoteFormSheet`'s editor area with `<EnrichedTextInput>` (or whatever the component name is — see library docs)
3. Replace tentap-based toolbar with a native-RN toolbar calling the library's commands:
   - **Paragraph-style pills** (4 options): Title = H1, Heading = H2, Subheading = H3, Body = paragraph
   - **Inline format tiles** (5 options): Bold, Italic, Underline, Bullet list, Numbered list
   - Active state driven by the library's selection API
4. Keep the **markdown-string storage contract** — note.content stays markdown per the prior decision
5. Wire up marked + turndown as the conversion bridge (from earlier work, already in package.json if the tentap branch landed deps — otherwise add)
6. Visual match to Figma node `6330-130610` — apply styling via the library's style prop / theme hooks (native, no CSS)
7. Full-screen / modal open behavior same as current (no layout regressions)

### Out of scope

- Any editor feature beyond the 9 formatting actions listed above (no tables, no inline images, no mentions, no code blocks — library supports these but the design doesn't call for them)
- NoteCard rendering of saved markdown — unchanged (handled elsewhere, outside editor)
- Nested lists — library only supports single-level, and design doesn't show nested lists either
- Any offline sync / collaboration / realtime features
- PostHog instrumentation (separate follow-up, flagged earlier)

### Explicitly drop from the tentap branch

- `@10play/tentap-editor` dependency
- Any tentap-specific WebView components
- All tentap-specific HTML bridge code (marked + turndown utilities **keep**, they're library-agnostic)

## Design details

### Component structure

```
features/stock-detail/presentation/components/notes/
├── NoteFormSheet.tsx          (container — open/close/save orchestration)
├── NoteEditor.tsx             (NEW — wraps EnrichedTextInput + toolbar)
├── NoteEditorToolbar.tsx      (NEW — 4 paragraph-style pills + 5 format tiles)
└── utils/
    ├── htmlToMarkdown.ts      (turndown wrapper)
    └── markdownToHtml.ts      (marked wrapper)
```

### Content flow

```
Load note:  stored.content (markdown) → marked → HTML → enriched editor
Save note:  enriched editor → HTML (library output) → turndown → markdown → stored.content
```

Storage contract unchanged; only the editor surface differs.

### Toolbar state

Listen to the library's selection-change events. Compute "active" state for each button:
- Paragraph pill: which heading level (or paragraph) is the current block?
- Format tile: does the current selection have bold / italic / underline / list?

Library should expose this via a hook or ref — follow whatever pattern the docs recommend.

### Visual styling

Match Figma node `6330-130610`:
- Dark theme background (matches sheet)
- Typography tokens from `src/shared/theme/tokens.ts`
- Toolbar pills: matches existing chip styles (scoped from the earlier 14-finding audit — same targets apply regardless of editor)
- Format tiles: 40×40 or per Figma spec, active state = white bg + dark text

Apply via library's theme/style props — NO CSS, NO webview.

## Acceptance criteria

- [ ] `react-native-enriched` added to deps, iOS pods installed, Android autolinked
- [ ] NoteFormSheet renders the new editor surface (no webview visible on screen)
- [ ] All 9 toolbar actions function: Title/Heading/Subheading/Body + Bold/Italic/Underline/Bullet/Numbered
- [ ] Toolbar active-state reflects current selection
- [ ] Existing markdown notes load correctly (marked bridge)
- [ ] Typing + saving a note produces valid markdown in storage (turndown bridge)
- [ ] Visual match to Figma node 6330-130610 (dark theme, typography, spacing, pill/tile shapes)
- [ ] Sheet open/close animations unchanged (no layout jank from the new native component)
- [ ] `rtk pnpm check` green
- [ ] New tests: editor-content-round-trip (md → editor → md returns equivalent markdown for the supported features)
- [ ] Visual verification on device via EAS preview

## Known risks

1. **Pre-1.0 library (v0.6.1).** Software Mansion ships breaking changes in minor versions. Pin to exact minor version in `package.json`. If they release v0.7 with breaking changes, we budget 1-2h to migrate; our usage surface is small.
2. **Fabric requirement.** Project is on Expo SDK 54 + RN 0.81.5 = Fabric enabled. Confirmed OK; but if any dependency forces legacy arch, we'd have to debug.
3. **Single-level lists only.** Design doesn't show nested lists, so fine. If future design adds nested lists, we'd need a different editor OR contribute nested-list support upstream.
4. **HTML ↔ markdown round-trip fidelity.** Not every HTML feature the editor emits maps cleanly to markdown (e.g., underline has no markdown spec; uses raw `<u>` passthrough). Validate with the round-trip test.

## Branch + PR

- **Branch:** `feat/notes-enriched-editor` off latest `origin/main`
- **PR:** draft on open, **do NOT mark ready** — user flips
- **EAS preview:** auto-posts on push (PostToolUse hook)
- **No CR retrigger commands** — standard CR-review flow

## Agent brief (for the implementing agent)

1. Read this spec fully + look at `feat/notes-rich-text-editor` branch for reusable bits (marked/turndown utils, toolbar visual structure, audit findings from `.agent-status/noteformsheet-figma-delta.md`)
2. Check `react-native-enriched` README for exact install steps + component API
3. Create worktree off latest `origin/main`, new branch `feat/notes-enriched-editor`
4. Phase-by-phase commits (suggested):
   - `chore(deps)`: add react-native-enriched
   - `feat(notes)`: scaffold NoteEditor wrapping EnrichedTextInput (no toolbar yet, just renders)
   - `feat(notes)`: NoteEditorToolbar with 4 paragraph pills + 5 format tiles, wired to editor commands
   - `feat(notes)`: markdown ↔ HTML bridge wiring (marked + turndown utils)
   - `feat(notes)`: visual styling per Figma node 6330-130610
   - `test(notes)`: round-trip + toolbar state tests
5. `rtk pnpm check` before commits
6. Push + draft PR with human-readable description:
   - Why (supersedes tentap, matches user's Figma + native-no-webview intent)
   - What changes
   - What doesn't change (storage contract, NoteCard render path)
   - How to test (both on EAS preview + round-trip test)
   - Known limitations (pre-1.0 lib, single-level lists)
7. Ping coordinator on each commit + final PR URL

## Migration hygiene

Once this PR merges:
- Delete the local `feat/notes-rich-text-editor` branch (`git branch -D feat/notes-rich-text-editor`) — superseded
- Remove `@10play/tentap-editor` from `package.json` if still present (should be cleaned by this PR)
- Keep `marked` + `turndown` (still needed as the markdown bridge)
