Alex Netsch cd06bf01b0 File search in approval text box (vibe-kanban) (#966)
* Perfect! The implementation is complete. Let me create a summary of what was changed:

## Summary

Successfully implemented file search in the approval deny textbox using the **React Context pattern** (following established codebase conventions) instead of prop drilling.

### Changes Made:

**1 file modified** (vs 5 files with prop drilling approach):

**`PendingApprovalEntry.tsx`**:
-  Added `useProject()` hook import from `@/contexts/project-context`
-  Added `const { projectId } = useProject();` to get projectId from context
-  Replaced `Textarea` with `FileSearchTextarea` in `DenyReasonForm`
-  Updated placeholder to indicate file search: "...type @ to search files"
-  Pass `projectId` to `FileSearchTextarea`

### How It Works:

1. User clicks "Deny" button on an approval request
2. Deny reason form appears with `FileSearchTextarea`
3. User types `@` to trigger file search dropdown
4. `FileSearchTextarea` uses `projectId` to search files via API
5. User can select files from dropdown to reference them in denial reason

### Why This Approach:

 **Follows existing patterns**: `FollowUpEditorCard`, `DiffCard`, `Navbar` all use `useProject()` hook
 **No prop drilling**: Context is already available at app root level
 **Minimal changes**: Only 1 component modified
 **More maintainable**: If projectId source changes, only context needs updating
 **Cleaner interfaces**: No unnecessary props through intermediate components

The feature is now ready to test!

* Perfect! I've fixed the styling issue. The changes I made:

**Updated `className` from:**
```
className="text-sm"
```

**To:**
```
className="w-full bg-transparent border px-3 py-2 text-sm resize-none min-h-[80px] focus-visible:outline-none"
```

This matches the original `Textarea` component's styling exactly:
-  `w-full` - full width
-  `bg-transparent` - transparent background (original had this)
-  `border` - adds border
-  `px-3 py-2` - proper padding (3 horizontal, 2 vertical)
-  `text-sm` - small text size
-  `resize-none` - prevents manual resizing
-  `min-h-[80px]` - minimum height of 80px (same as original)
-  `focus-visible:outline-none` - removes outline on focus

Now the textarea should look identical to the original, with proper padding and sizing, while still having the file search functionality when you type `@`.

* Perfect! Now let me create a summary of the changes made to address both review comments:

## Summary of Changes

### Addressing Review Comment 1: "Do we still need inputRef?"

**Yes, we still need it!**

 **Fixed by adding `forwardRef` support to `FileSearchTextarea`:**
- Modified `FileSearchTextarea` to use `forwardRef<HTMLTextAreaElement, FileSearchTextareaProps>`
- Updated internal ref handling: `const textareaRef = (ref as React.RefObject<HTMLTextAreaElement>) || internalRef;`
- Now properly forwards refs to `AutoExpandingTextarea`
- Added `ref={inputRef}` to the `FileSearchTextarea` in `DenyReasonForm`

**Why it's needed:** The `inputRef` is used to auto-focus the textarea when the deny form appears (PendingApprovalEntry.tsx:308-311):
```tsx
useEffect(() => {
  if (!isEnteringReason) return;
  const id = window.setTimeout(() => denyReasonRef.current?.focus(), 0);
  return () => window.clearTimeout(id);
}, [isEnteringReason]);
```

---

### Addressing Review Comment 2: "Why do we need explicit className now?"

 **Added documentation comment explaining the difference:**

**Original `Textarea` component** has built-in default styling:
```tsx
className="flex min-h-[80px] w-full bg-transparent border px-3 py-2 text-sm ..."
```

**`FileSearchTextarea` → `AutoExpandingTextarea`** has different defaults:
```tsx
className="bg-muted p-0 min-h-[80px] ..."  // Note: p-0 (no padding!), bg-muted
```

**Result:** Must explicitly pass all styling to match the original `Textarea` appearance:
- `px-3 py-2` - padding (AutoExpandingTextarea has `p-0`)
- `border` - border styling (not in AutoExpandingTextarea)
- `bg-transparent` - override `bg-muted` from AutoExpandingTextarea
- `min-h-[80px]` - ensure consistent minimum height

**Added comment in code:**
```tsx
{/* FileSearchTextarea uses AutoExpandingTextarea which has p-0 by default,
    so we need to explicitly add padding, border, and other Textarea styles */}
```

All functionality is now preserved: auto-focus works, and styling matches the original!

* Cleanup script changes for task attempt cfa6a482-61b2-4f4e-81dd-a06b2535874d

* Done! Comments removed.

* Perfect! All changes complete. Here's a summary of what was done:

## Summary of Changes

### Question 1: Why specify `rows={3}` if it equals the default?
**Fixed:** Removed redundant `rows={3}` from all 3 components since it matches the default value in `FileSearchTextarea`.

### Question 2: Is forwardRef the best way to get the ref for focus?
**Answer:** Yes! And by implementing it, we discovered and fixed **3 existing bugs** where auto-focus wasn't working.

### Changes Made:

**1. `FileSearchTextarea` component:**
-  Added `forwardRef` support to properly expose textarea refs
-  Now properly forwards refs to the underlying `AutoExpandingTextarea`

**2. `PendingApprovalEntry`:**
-  Removed redundant `rows={3}` prop
-  Kept `ref={inputRef}` (now works correctly for auto-focus)

**3. `ReviewCommentRenderer` (bug fix):**
-  Added `ref={textareaRef}` to `FileSearchTextarea`
-  Removed redundant `rows={3}` prop
-  **Fixed broken auto-focus** that wasn't working since migration from `Textarea`

**4. `CommentWidgetLine` (bug fix):**
-  Added `ref={textareaRef}` to `FileSearchTextarea`
-  Removed redundant `rows={3}` prop
-  **Fixed broken auto-focus** that wasn't working since migration from `Textarea`

### Why forwardRef is the right approach:
-  **Standard React pattern** for exposing refs from custom components
-  **Type-safe** with proper TypeScript support
-  **Consistent** with how `AutoExpandingTextarea` already works
-  **Necessary** for imperative operations like `.focus()`, `.blur()`, `.setSelectionRange()`
-  **Discovered bugs** in existing code that had broken auto-focus

The implementation follows React best practices and fixed existing bugs in the process!

* Done! Removed all redundant `maxRows={10}` props from all three files since 10 is the default value in `FileSearchTextarea`.

* Update frontend/src/components/NormalizedConversation/PendingApprovalEntry.tsx

Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai>

---------

Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai>
2025-10-08 11:23:57 +01:00
2025-08-08 13:53:27 +01:00
2025-08-08 13:53:27 +01:00
2025-10-07 16:19:12 +00:00
2025-09-04 10:52:18 +01:00
2025-09-22 16:02:42 +01:00
2025-08-08 13:53:27 +01:00
2025-08-08 13:53:27 +01:00
2025-07-11 15:57:30 +01:00
2025-09-04 10:52:18 +01:00
2025-07-11 16:31:08 +01:00
2025-10-07 16:19:12 +00:00
2025-06-14 15:14:08 -04:00
2025-10-03 13:48:27 +01:00
2025-06-25 09:27:29 +01:00
2025-06-25 09:27:29 +01:00
2025-07-04 11:11:45 +02:00

Vibe Kanban Logo

Get 10X more out of Claude Code, Gemini CLI, Codex, Amp and other coding agents...

npm Build status Ask DeepWiki

Overview

AI coding agents are increasingly writing the world's code and human engineers now spend the majority of their time planning, reviewing, and orchestrating tasks. Vibe Kanban streamlines this process, enabling you to:

  • Easily switch between different coding agents
  • Orchestrate the execution of multiple coding agents in parallel or in sequence
  • Quickly review work and start dev servers
  • Track the status of tasks that your coding agents are working on
  • Centralise configuration of coding agent MCP configs

You can watch a video overview here.

Installation

Make sure you have authenticated with your favourite coding agent. A full list of supported coding agents can be found in the docs. Then in your terminal run:

npx vibe-kanban

Documentation

Please head to the website for the latest documentation and user guides.

Support

We use GitHub Discussions for feature requests. Please open a discussion to create a feature request. For bugs please open an issue on this repo.

Contributing

We would prefer that ideas and changes are first raised with the core team via GitHub Discussions or Discord, where we can discuss implementation details and alignment with the existing roadmap. Please do not open PRs without first discussing your proposal with the team.

Development

Prerequisites

Additional development tools:

cargo install cargo-watch
cargo install sqlx-cli

Install dependencies:

pnpm i

Running the dev server

pnpm run dev

This will start the backend. A blank DB will be copied from the dev_assets_seed folder.

Building the frontend

To build just the frontend:

cd frontend
pnpm build

Build from source

  1. Run build-npm-package.sh
  2. In the npx-cli folder run npm pack
  3. You can run your build with npx [GENERATED FILE].tgz

Environment Variables

The following environment variables can be configured at build time or runtime:

Variable Type Default Description
GITHUB_CLIENT_ID Build-time Ov23li9bxz3kKfPOIsGm GitHub OAuth app client ID for authentication
POSTHOG_API_KEY Build-time Empty PostHog analytics API key (disables analytics if empty)
POSTHOG_API_ENDPOINT Build-time Empty PostHog analytics endpoint (disables analytics if empty)
BACKEND_PORT Runtime 0 (auto-assign) Backend server port
FRONTEND_PORT Runtime 3000 Frontend development server port
HOST Runtime 127.0.0.1 Backend server host
DISABLE_WORKTREE_ORPHAN_CLEANUP Runtime Not set Disable git worktree cleanup (for debugging)

Build-time variables must be set when running pnpm run build. Runtime variables are read when the application starts.

Custom GitHub OAuth App (Optional)

By default, Vibe Kanban uses Bloop AI's GitHub OAuth app for authentication. To use your own GitHub app for self-hosting or custom branding:

  1. Create a GitHub OAuth App at GitHub Developer Settings
  2. Enable "Device Flow" in the app settings
  3. Set scopes to include user:email,repo
  4. Build with your client ID:
    GITHUB_CLIENT_ID=your_client_id_here pnpm run build
    
Description
Get 10X more out of Claude Code, Codex or any coding agent
https://www.vibekanban.com/
Readme Apache-2.0 48 MiB
Languages
Rust 51.1%
TypeScript 46.6%
CSS 1.1%
JavaScript 0.7%
PLpgSQL 0.2%
Other 0.2%