---
name: Approval UI Workflow
slug: approval-ui-workflow
category: Frontend
description: Approval UI Workflow keeps approval prompts and presenters visually consistent while preserving keyboard flow and safe preview rendering. Use it when adding or changing Approval prompt UI or diff previews.
github: "https://github.com/yusifeng/formax/tree/main/.codex/skills/formax-approval-ui-workflow"
language: TypeScript
stars: 192
forks: 7
install: "npx degit https://github.com/yusifeng/formax/tree/main/.codex/skills/formax-approval-ui-workflow ~/.claude/skills/formax-approval-ui-workflow"
installs_to: ~/.claude/skills/formax-approval-ui-workflow
source_path: .codex/skills/formax-approval-ui-workflow/SKILL.md
collection_size: 22
category_size: 670
collection_url: "https://dirskills.com/collections/yusifeng/formax"
added: 2026-09-06T05:19:17.467Z
last_synced: 2026-09-06T05:19:17.467Z
canonical_url: "https://dirskills.com/skills/approval-ui-workflow"
---

# Approval UI Workflow

Approval UI Workflow keeps approval prompts and presenters visually consistent while preserving keyboard flow and safe preview rendering. Use it when adding or changing Approval prompt UI or diff previews.

**Install:**

```bash
npx degit https://github.com/yusifeng/formax/tree/main/.codex/skills/formax-approval-ui-workflow ~/.claude/skills/formax-approval-ui-workflow
```

## README

# formax-approval-ui-workflow

## Goal

- Keep **Approval prompts** visually consistent + Claude Code-aligned (only when explicitly requested).
- Preserve existing **behavior + keyboard flow** (Enter/Esc/Shift+Tab), avoid UI regressions.
- Keep preview rendering **fast and safe** (no sync IO in render; guard against quadratic diffs).
## Where to change what

- Shared approval “chrome”
  - `packages/core/src/components/ui/ApprovalHeader.tsx` (top divider + title color)
  - `packages/core/src/components/ui/ConfirmMenu.tsx` (numbered options + selection color)
- Preview (optional section under header)
  - `packages/core/src/components/tool/ApprovalPreview.tsx` (simple file preview)
  - `packages/core/src/components/tool/PatchApprovalPreview.tsx` (edit-file wrapper: header + file + preview)
  - `packages/core/src/components/tool/PatchPreview.tsx` (diff rendering + performance guards)
- Per-tool approval prompts (labels, options, allow/ask/deny / remember write paths)
  - `packages/core/src/components/tool/bashApprovalPrompt.tsx`
  - `packages/core/src/components/tool/fsReadApprovalPrompt.tsx`
  - `packages/core/src/components/tool/fsWriteApprovalPrompt.tsx`
  - `packages/core/src/components/tool/skillApprovalPrompt.tsx`
  - (if present) `packages/core/src/components/tool/editApprovalPrompt.tsx` (legacy)
- Tool presenters that mount approval prompts
  - `packages/core/src/tools/modules/bash/presenter.tsx`
  - `packages/core/src/tools/modules/read/presenter.tsx`
  - `packages/core/src/tools/modules/write/presenter.tsx`
  - `packages/core/src/tools/modules/edit/presenter.tsx`
  - `packages/core/src/tools/modules/skill/presenter.tsx`
- Colors / theme
  - `packages/core/src/tui/theme.ts` (`theme.permission`, `theme.text`, `theme.diff.*`)
## Patterns

- Layout skeleton (keep consistent)
  - `[Top divider line]`
  - `Title` (color = `theme.permission`)
  - Optional `Preview` box
  - Question line (e.g. “Do you want to … <file>?”)
  - Options list (numbered)
  - Bottom hint (e.g. “Esc to cancel”)

- Options rendering (text + emphasis)
  - If an option needs mixed styling (e.g. make `capture-terminal/` bold/white): make `ConfirmMenu` accept `ReactNode` labels.
  - Ensure **selection color wins** over nested `Text color={...}` when highlighted:
    - Prefer passing “unstyled” children and let row wrapper decide color, or
    - In nested text, only set `bold`, avoid hardcoding `color` unless required.

- Preview performance (must not block UI)
  - No `fs.readFileSync`/`fs.statSync`/blocking IO inside render path (`useMemo` included).
  - If file context is needed (e.g. line numbers), compute via async `fs/promises` + `useEffect`.

- Diff safety (avoid OOM / hangs)
  - Any token/word diff based on DP/LCS must have a **hard cap** (max cells).
  - If cap exceeded: fall back to truncated / line-only / “too large to diff” preview.
## Tests to update

- Unit/component tests (minimum regression set):
  - `packages/core/src/components/ui/ConfirmMenu.test.tsx` (ReactNode label + selection color)
  - `packages/core/src/components/tool/bashApprovalPrompt.test.tsx` (if exists)
  - `packages/core/src/components/tool/fsReadApprovalPrompt.test.tsx` (if exists)
  - `packages/core/src/components/tool/fsWriteApprovalPrompt.test.tsx` (if exists)
  - `packages/core/src/components/tool/skillApprovalPrompt.test.tsx` (if exists)
  - `packages/core/src/tools/modules/edit/presenter.test.tsx` (preview/diff layout + performance guard)

- Manual spot-check (fast)
  - Trigger one approval for each kind: `Bash`, `Read(outside workspace)`, `Write`, `Edit`.
  - Verify: top divider, title color, option numbering, selection color, Esc behavior.
## Guardrails

- Do **not** change UI copy/spacing/colors unless explicitly requested for Claude Code parity.
- Treat **UI output vs model context injection** as orthogonal; don’t change injection behavior as a side-effect of approval UI work.
- Do **not** add a syntax highlighting library (keep preview rendering lightweight).
- Do **not** broaden scope (“refactor approval system”); only touch what the prompt requires.
- Keep rendering responsive:
  - no sync IO in render
  - hard caps for quadratic diff algorithms
- Loop discipline:
  - run targeted tests first, then `bun run test` if needed
  - run review before committing using `AGENTS.md` -> `Review Profile (Single Source of Truth)`; fix all high/medium findings
