npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@treditpackage/feedback

v1.0.0

Published

A lightweight, customizable React feedback widget for collecting user feedback with built-in image upload support.

Readme

@treditpackage/feedback

A lightweight, customizable React feedback widget for collecting user feedback with built-in image upload support.

npm version License: MIT

✨ Features

  • 🎯 Customizable feedback types: Provide your own dropdown options
  • 📸 Image upload with drag-and-drop and clipboard paste (Ctrl+V)
  • Form validation with inline error messages
  • 🛡️ Honeypot spam protection built-in
  • 🎨 Fully customizable via CSS variables
  • 📱 Responsive design - works on mobile and desktop
  • Lightweight - minimal dependencies
  • 🔧 Flexible positioning - fixed side button or inline top bar
  • 🎭 Custom button variants - 8 pre-built styles
  • 🚫 No notification system dependency - handle success/error your way
  • 🔌 Custom submit handler - full control over form submission with onSubmit callback

📦 Installation

npm install @treditpackage/feedback antd

Peer Dependencies

  • react >= 17
  • react-dom >= 17

🚀 Quick Start

import { FeedbackWidget } from "@treditpackage/feedback";

function App() {
  return (
    <div>
      <YourAppContent />

      {/* Fixed feedback button on right side */}
      <FeedbackWidget triggerPosition="right-side" simulationMode="random" />
    </div>
  );
}

Styles are automatically included — no need for separate CSS imports!

📖 API Reference

FeedbackWidget Props

| Prop | Type | Default | Description | | ----------------- | --------------------------------------------------------- | ----------------------- | ------------------------------------------------ | | triggerPosition | "right-side" \| "top-bar" | "right-side" | Position of the trigger button | | simulationMode | "success" \| "error" \| "random" | "random" | Mock submission behavior for testing | | triggerVariant | ButtonVariant | "primary" | Style variant for trigger button | | submitVariant | ButtonVariant | "primary" | Style variant for submit button | | feedbackOptions | Array<{value: string, label: string}> | [{Bug}, {Suggestion}] | Custom options for feedback type dropdown | | onSubmit | (data: FeedbackSubmissionData) => void \| Promise<void> | undefined | Callback fired on form submission with form data |

Button Variants

Available variants: primary, secondary, danger, success, warning, info, ghost, outline

Example with Custom Variants

<FeedbackWidget
  triggerPosition="right-side"
  triggerVariant="info"
  submitVariant="success"
  simulationMode="success"
/>

Custom Feedback Options

Customize the feedback type dropdown with your own options:

const customOptions = [
  { value: "Bug", label: "🐛 Bug Report" },
  { value: "Feature", label: "✨ Feature Request" },
  { value: "Question", label: "❓ Question" },
  { value: "Praise", label: "👏 Praise" },
];

<FeedbackWidget feedbackOptions={customOptions} triggerPosition="right-side" />;

Handle Form Submission

Use the onSubmit callback to receive form data and integrate with your backend:

import { FeedbackWidget } from "@treditpackage/feedback";
import type { FeedbackSubmissionData } from "@treditpackage/feedback";

function App() {
  const handleFeedbackSubmit = async (data: FeedbackSubmissionData) => {
    // Access all form data
    console.log(data.feedbackType); // e.g., "Bug"
    console.log(data.message); // User's message
    console.log(data.imageFile); // File object or undefined
    console.log(data.sourcePath); // Current page path

    // Send to your API
    const formData = new FormData();
    formData.append("type", data.feedbackType);
    formData.append("message", data.message);
    if (data.imageFile) {
      formData.append("image", data.imageFile);
    }

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

    if (response.ok) {
      // Show success notification
      alert("Thank you for your feedback!");
    } else {
      throw new Error("Submission failed");
    }
  };

  return (
    <div>
      <YourContent />
      <FeedbackWidget
        onSubmit={handleFeedbackSubmit}
        triggerPosition="right-side"
      />
    </div>
  );
}

🎨 Customization

CSS Variables

Override these CSS variables to match your brand:

:root {
  /* Background & borders */
  --feedback-bg: rgba(8, 28, 53, 0.96);
  --feedback-border: rgba(148, 163, 184, 0.6);

  /* Text colors */
  --feedback-text: #e7f1ff;
  --feedback-muted: #94a3b8;

  /* Accent color */
  --feedback-accent: #bc88ff;
  --feedback-accent-text: #020b18;

  /* Button styles */
  --feedback-button-bg: #bc88ff;
  --feedback-button-text: #020b18;
  --feedback-button-hover-bg: #a66ff7;
}

Dark/Light Theme Example

/* Light theme */
.light-theme {
  --feedback-bg: rgba(255, 255, 255, 0.98);
  --feedback-text: #1a202c;
  --feedback-border: rgba(0, 0, 0, 0.1);
  --feedback-accent: #4f46e5;
}

/* Dark theme */
.dark-theme {
  --feedback-bg: rgba(17, 24, 39, 0.98);
  --feedback-text: #f9fafb;
  --feedback-border: rgba(255, 255, 255, 0.1);
  --feedback-accent: #818cf8;
}

💡 Usage Examples

Fixed Side Button

<FeedbackWidget triggerPosition="right-side" triggerVariant="primary" />

Creates a fixed button on the right edge of the screen.

Top Bar Inline Button

<nav>
  <Logo />
  <NavLinks />
  <FeedbackWidget triggerPosition="top-bar" triggerVariant="ghost" />
</nav>

Renders an inline button suitable for navigation bars.

Testing Different Scenarios

// Always succeed
<FeedbackWidget simulationMode="success" />

// Always fail (for error handling testing)
<FeedbackWidget simulationMode="error" />

// Random (75% success, 25% error)
<FeedbackWidget simulationMode="random" />

🔧 Advanced Usage

Backend Integration

Use the onSubmit callback to send feedback to your backend API:

import { FeedbackWidget } from "@treditpackage/feedback";
import type { FeedbackSubmissionData } from "@treditpackage/feedback";

function App() {
  const handleSubmit = async (data: FeedbackSubmissionData) => {
    const formData = new FormData();
    formData.append("type", data.feedbackType);
    formData.append("message", data.message);
    formData.append("path", data.sourcePath || "");

    if (data.imageFile) {
      formData.append("screenshot", data.imageFile);
    }

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

    if (!response.ok) {
      throw new Error("Failed to submit feedback");
    }

    // Optionally return data from your API
    const result = await response.json();
    console.log("Feedback ID:", result.id);
  };

  return <FeedbackWidget onSubmit={handleSubmit} />;
}

With Notification System Integration

import { FeedbackWidget } from "@treditpackage/feedback";
import type { FeedbackSubmissionData } from "@treditpackage/feedback";
import { toast } from "your-toast-library";

function App() {
  const handleSubmit = async (data: FeedbackSubmissionData) => {
    try {
      await fetch("/api/feedback", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(data),
      });

      toast.success("Thank you for your feedback!");
    } catch (error) {
      toast.error("Failed to submit feedback. Please try again.");
      throw error; // Re-throw to prevent form reset
    }
  };

  return <FeedbackWidget onSubmit={handleSubmit} />;
}

Handling Success/Error

The widget automatically handles form submission and resets on success. When you provide the onSubmit callback, you have full control over the submission process:

const handleSubmit = async (data: FeedbackSubmissionData) => {
  try {
    await sendToBackend(data);
    // Show success message with your notification system
    showNotification("Feedback submitted!", "success");
  } catch (error) {
    // Handle errors your way
    showNotification("Failed to submit feedback", "error");
    throw error; // Re-throw to prevent form reset
  }
};

<FeedbackWidget onSubmit={handleSubmit} />;

Note: If onSubmit is not provided, the widget uses its default mock submission service with simulationMode for testing purposes.

📝 TypeScript Support

Full TypeScript support with exported types:

import type {
  FeedbackType,
  FeedbackSubmission,
  FeedbackSubmissionData, // New! Data passed to onSubmit callback
  ButtonVariant,
} from "@treditpackage/feedback";

FeedbackSubmissionData Interface

interface FeedbackSubmissionData {
  feedbackType: string; // Selected feedback type
  message: string; // User's message
  imageFile?: File; // Uploaded image (if any)
  sourcePath?: string; // Current page path
}

🎯 Features Detail

Image Upload

  • Drag & drop files onto the dropzone
  • Click to browse file selection
  • Clipboard paste (Ctrl+V / Cmd+V)
  • Image preview with remove option
  • Accepts: PNG, JPG, JPEG, GIF, WebP (max 5MB)

Form Validation

  • Required field validation
  • Character limits (10-500 chars for message)
  • Image size validation
  • Real-time error messages

Spam Protection

Includes invisible honeypot field that bots typically fill out, helping filter spam submissions.

🎨 CSS & Styling

Automatic CSS Bundling

All styles are automatically bundled into the main package output. When you import the component, CSS is applied automatically — no additional imports required.

import { FeedbackWidget } from "@treditpackage/feedback";
// ✅ Styles are already included!

Manual CSS Imports (Optional)

If you prefer to manage CSS imports explicitly, you can import the CSS files directly:

import { FeedbackWidget } from "@treditpackage/feedback";
import "@treditpackage/feedback/feedback.css";
import "@treditpackage/feedback/select.css";

This approach is useful if you want to:

  • Control the order of CSS imports in your application
  • Dynamically load styles conditionally
  • Use CSS preprocessors or CSS-in-JS solutions

CSS Files Included

The package includes the following CSS files:

  • feedback.css - Widget layout, colors, spacing, and animations
  • select.css - Select dropdown component styles

Both files are automatically bundled into index.js, but are also available for separate import.

Override Styles with CSS Variables

To customize the appearance, override CSS variables in your global styles or component:

:root {
  --feedback-bg: rgba(8, 28, 53, 0.96);
  --feedback-text: #e7f1ff;
  --feedback-accent: #bc88ff;
  /* ... other variables */
}

See the Customization section for all available CSS variables.

📦 Package Structure

dist/
├── index.js          # Main component exports (includes bundled CSS)
└── index.d.ts        # TypeScript definitions

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

MIT © [Tredit]

🐛 Issues

Found a bug? Please open an issue with:

  • Steps to reproduce
  • Expected behavior
  • Actual behavior
  • Screenshots (if applicable)

🚀 Roadmap

  • [ ] Email field option
  • [ ] Custom field support
  • [ ] Analytics integration
  • [ ] File attachment support (non-image files)
  • [ ] Multi-language support
  • [ ] Accessibility improvements (WCAG 2.1 AA)

Made with ❤️ by Tredit