6.4 KiB
AI Capture Ratio Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Change the non-mobile AI capture composer to a 70 / 30 text-to-attachments split, stack attachment previews one per row, and render example prompts as a masonry-style cluster.
Architecture: Keep the page-level AI capture placement unchanged and make the entire change inside AIToolbar. Lock the new layout with source-based tests in tests/ai-toolbar.test.ts, then make the smallest JSX/class updates needed in src/components/ai-toolbar.tsx to satisfy them.
Tech Stack: Bun test runner, Next.js, React, TypeScript, Tailwind utility classes, Biome, useIsMobile
Task 1: Lock the 70 / 30 Desktop Composer Contract
Files:
-
Modify:
tests/ai-toolbar.test.ts -
Test:
tests/ai-toolbar.test.ts -
Step 1: Write the failing test
Replace the current non-mobile composer assertion so it expects a 70 / 30 split instead of equal-width columns.
test("desktop composer uses a 70 / 30 row when the page gives it full-width space", () => {
const source = readToolbarSource();
expect(source).toContain("isMobile");
expect(source).toContain('? "grid gap-3"');
expect(source).toContain(
': "grid gap-3 grid-cols-[minmax(0,0.7fr)_minmax(0,0.3fr)]"',
);
});
- Step 2: Run test to verify it fails
Run: bun test tests/ai-toolbar.test.ts
Expected: FAIL because src/components/ai-toolbar.tsx still contains the equal-width non-mobile grid.
- Step 3: Write minimal implementation
Update the non-mobile composer grid in src/components/ai-toolbar.tsx.
Change this branch:
: "grid gap-3 grid-cols-[minmax(0,1fr)_minmax(0,1fr)]"
To:
: "grid gap-3 grid-cols-[minmax(0,0.7fr)_minmax(0,0.3fr)]"
- Step 4: Run test to verify it passes
Run: bun test tests/ai-toolbar.test.ts
Expected: PASS for the updated desktop composer test.
- Step 5: Commit
git add tests/ai-toolbar.test.ts src/components/ai-toolbar.tsx
git commit -m "refactor(ai-toolbar): use 70-30 desktop composer split"
Task 2: Lock One-Preview-Per-Row Attachments
Files:
-
Modify:
tests/ai-toolbar.test.ts -
Modify:
src/components/ai-toolbar.tsx -
Test:
tests/ai-toolbar.test.ts -
Step 1: Write the failing test
Add a test that rejects the old desktop grid-cols-2 preview layout and expects a row-stacked preview container.
test("attachment previews stack one per row instead of using a two-column desktop grid", () => {
const source = readToolbarSource();
expect(source).not.toContain('"mt-3 grid gap-2 grid-cols-2"');
expect(source).toContain('"mt-3 grid gap-2"');
});
- Step 2: Run test to verify it fails
Run: bun test tests/ai-toolbar.test.ts
Expected: FAIL because the preview container still uses the desktop grid-cols-2 branch.
- Step 3: Write minimal implementation
Simplify the preview container in src/components/ai-toolbar.tsx so it uses one shared stacked grid for all widths.
Replace:
className={
isMobile ? "mt-3 grid gap-2" : "mt-3 grid gap-2 grid-cols-2"
}
With:
className="mt-3 grid gap-2"
Keep each preview card as-is so the image and remove button behavior do not change.
- Step 4: Run test to verify it passes
Run: bun test tests/ai-toolbar.test.ts
Expected: PASS for the stacked-preview contract.
- Step 5: Commit
git add tests/ai-toolbar.test.ts src/components/ai-toolbar.tsx
git commit -m "refactor(ai-toolbar): stack attachment previews by row"
Task 3: Lock Masonry-Style Example Prompts
Files:
-
Modify:
tests/ai-toolbar.test.ts -
Modify:
src/components/ai-toolbar.tsx -
Test:
tests/ai-toolbar.test.ts -
Step 1: Write the failing test
Add a test that locks the example prompt area to a clustered layout instead of a flat single-row strip.
test("example prompts use a masonry-style cluster inside the composer footer", () => {
const source = readToolbarSource();
expect(source).toContain("Try:");
expect(source).toContain("columns-2");
expect(source).toContain("break-inside-avoid");
expect(source).toContain("w-full text-left");
});
- Step 2: Run test to verify it fails
Run: bun test tests/ai-toolbar.test.ts
Expected: FAIL because the current prompt chips still live in a flat wrapped flex row.
- Step 3: Write minimal implementation
Refactor only the example prompt block in src/components/ai-toolbar.tsx.
Use this structure:
<div className="columns-2 gap-2">
{examplePrompts.map((prompt) => (
<Button
key={prompt}
type="button"
variant="secondary"
size="sm"
className="mb-2 h-auto w-full break-inside-avoid whitespace-normal rounded-2xl px-3 py-2 text-left text-[11px]"
onClick={() => onAiTemplateSelect(prompt)}
disabled={aiLoading || !canUseAi}
>
{prompt}
</Button>
))}
</div>
Keep the surrounding footer copy and disabled behavior intact. Do not add new helper components.
- Step 4: Run test to verify it passes
Run: bun test tests/ai-toolbar.test.ts
Expected: PASS for the prompt-cluster contract.
- Step 5: Commit
git add tests/ai-toolbar.test.ts src/components/ai-toolbar.tsx
git commit -m "refactor(ai-toolbar): cluster example prompts in masonry layout"
Task 4: Full Verification
Files:
-
Test:
tests/ai-toolbar.test.ts -
Test:
tests/home-page-layout.test.ts -
Verify:
src/components/ai-toolbar.tsx -
Step 1: Run targeted layout tests
Run: bun test tests/ai-toolbar.test.ts tests/home-page-layout.test.ts
Expected: PASS with the AI toolbar and page layout contracts still green.
- Step 2: Run the full test suite
Run: bun test
Expected: PASS with no new failures.
- Step 3: Run typecheck
Run: bun run type:check
Expected: PASS.
- Step 4: Run lint
Run: bun run lint
Expected: PASS, with only the pre-existing src/lib/compose-refs.ts warning if it still appears.
- Step 5: Commit
If Task 4 introduced no code changes, skip a commit here. If a tiny verification-driven tweak was required, commit only that tweak:
git add src/components/ai-toolbar.tsx tests/ai-toolbar.test.ts
git commit -m "test(ai-toolbar): verify desktop composer layout contracts"