npm package: @loudevuno/feedback-widget
Description: Reusable feedback widget component with Linear integration
Author: loudoguno
Latest version: 1.1.0


# Smart Feedback Widget

A reusable, dark-themed feedback component for React applications. Modeled after the Linear/Raycast command palette aesthetic, it allows users to submit bug reports, feature requests, and general feedback with file attachments.

## Package Update Workflow

This package is published to npm as `@loudevuno/feedback-widget`. When updates are made to this repository, here's how they propagate to downstream applications:

### 1. Development & Build
```bash
# Make changes to the widget in this repository
npm run build              # Build the package for distribution
```

### 2. Publish to npm
```bash
# Update version in package.json (following semver)
npm version patch          # or minor/major depending on changes
npm publish                # Publishes to npm registry
```

### 3. Update Downstream Apps
In each application that uses this widget:

```bash
# Update to latest version
npm install @loudevuno/feedback-widget@latest

# Or update package.json manually and run
npm install
```

### 4. Deploy Apps
After updating the dependency, redeploy your applications to production. **No code changes are required** in the consuming apps - they automatically receive the updated widget UI and functionality.

### Quick Reference
- **This repo**: Source code and development of the widget package
- **Downstream apps**: Applications that import and use `@loudevuno/feedback-widget`
- **Update flow**: Code changes → Build → Publish to npm → Apps update dependency → Apps redeploy

## Features

*   **Linear/Raycast Aesthetic**: Clean, dark-mode UI with blur effects.
*   **Zero External CSS**: Uses Tailwind CSS classes.
*   **Accessibility**: Keyboard friendly (Esc to close), proper focus management.
*   **File Uploads**: Drag and drop support for images, logs, and videos.
*   **Lightweight**: Only depends on `framer-motion` for animations and standard React hooks.

## Installation

### 1. Dependencies

Ensure you have the following packages installed:

```bash
npm install framer-motion lucide-react
# If you aren't using Tailwind, you'll need to set it up or adapt the classes.
```
*Note: The icons in the provided code use a local `Icons.tsx` file to avoid heavy icon library dependencies, but you can swap them for `lucide-react` or `heroicons` easily.*

### 2. Copy Components

Copy the following files into your project structure:

*   `components/FeedbackWidget.tsx`
*   `components/ui/Icons.tsx` (or use your own icon library)
*   `types.ts`
*   `services/submissionService.ts`

### 3. Usage

Import and render the component at the root of your application (or anywhere global).

```tsx
import { FeedbackWidget } from './components/FeedbackWidget';

function App() {
  return (
    <>
      <YourMainAppContent />
      <FeedbackWidget />
    </>
  );
}
```

## Backend Integration

The widget uses `services/submissionService.ts` to handle data transmission. You must implement the API call in this file to connect to your backend.

### The Payload

The widget sends data in the following format:

```typescript
interface FeedbackData {
  type: 'issue' | 'idea' | 'other';
  description: string;
  contact?: string; // Optional email/name
  files?: File[];
  metadata?: Record<string, any>; // url, userAgent
}
```

### Example: Connect to Next.js API Route

**1. Update `services/submissionService.ts`:**

```typescript
export const submitFeedback = async (data: FeedbackData) => {
  const formData = new FormData();
  formData.append('type', data.type);
  formData.append('description', data.description);
  if (data.contact) formData.append('contact', data.contact);
  
  // Attach files
  if (data.files) {
    data.files.forEach((file) => formData.append('files', file));
  }

  const response = await fetch('/api/feedback', {
    method: 'POST',
    body: formData,
  });

  if (!response.ok) throw new Error('Failed to submit');
  return await response.json();
};
```

**2. Create API Route (e.g. `app/api/feedback/route.ts`):**

You can then forward this data to GitHub Issues or Linear.

**GitHub Example:**

```typescript
import { Octokit } from "octokit";

const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });

export async function POST(req: Request) {
  const formData = await req.formData();
  const description = formData.get('description') as string;
  const type = formData.get('type') as string;
  const contact = formData.get('contact') as string;
  
  const title = `[${type.toUpperCase()}] New Feedback`;
  const body = `${description}\n\n**Contact:** ${contact || 'N/A'}`;

  await octokit.rest.issues.create({
    owner: "your-org",
    repo: "your-repo",
    title: title,
    body: body,
    labels: [type === 'issue' ? 'bug' : 'enhancement']
  });

  return Response.json({ success: true });
}
```