Universal Feedback Widget

Collect user feedback and automatically create GitHub discussions or issues

Zero Dependencies Any Framework GitHub Integration Custom Theming

Getting Started

Add feedback collection to any website with just two lines of code. Choose between GitHub discussions (recommended) or issues:

Quick Setup - GitHub Discussions (Recommended)

<!-- Include the widget --> <script src="https://cdn.jsdelivr.net/npm/@samletnorge/feedback-widget@latest/dist/feedback-widget.min.js"></script> <!-- Add to your page --> <feedback-widget data-repo="your-username/your-repo" data-token="your-github-pat-token" data-type="discussion" data-category="feedback" ></feedback-widget>

Alternative - GitHub Issues

<feedback-widget data-repo="your-username/your-repo" data-token="your-github-pat-token" data-type="issue" data-labels="feedback,website" ></feedback-widget>

Try the Demo

Click any button above to see different widget configurations in action! Also notice the vertical "Feedback" tab on the right side of your screen.

Key Features

GitHub Integration

  • Creates GitHub discussions
  • Creates GitHub issues
  • Automatic categorization
  • Custom labeling support

Flexible Theming

  • Inherit page styles
  • Tailwind CSS support
  • Custom color schemes
  • Dark/light themes

Custom Triggers

  • Vertical tab design
  • Custom trigger elements
  • Programmatic API
  • Event-based triggering

Universal Support

  • React, Vue, Svelte, Angular
  • Plain HTML
  • Mobile responsive
  • Accessibility ready

Discussions vs Issues

Choose the right GitHub feature for your feedback collection:

Feature GitHub Discussions GitHub Issues
Best for General feedback, questions, community input Bug reports, feature requests, actionable items
Structure Threaded conversations, organized by category Linear comments, organized by labels
Workflow Community-driven discussions Project management, assignees, milestones
Configuration data-type="discussion"
data-category="feedback"
data-type="issue"
data-labels="feedback,bug"

Theming & Customization

1. Inherit Page Styles (Recommended)

Let the widget inherit your site's existing CSS for perfect integration. This requires adding CSS classes to style the widget components:

Step 1: Enable inherit styling

<feedback-widget data-repo="myuser/myrepo" data-token="token" data-inherit-styling="true" ></feedback-widget>

Step 2: Add CSS styles for widget components

<!-- Regular CSS --> <style> .feedback-widget-modal { background: white; border: 1px solid #e5e7eb; border-radius: 0.5rem; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); padding: 1.5rem; } .feedback-widget-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; } .feedback-widget-title { font-size: 1.25rem; font-weight: 600; color: #111827; margin: 0; } .feedback-widget-input, .feedback-widget-textarea { width: 100%; padding: 0.75rem; border: 1px solid #d1d5db; border-radius: 0.375rem; background: white; } .feedback-widget-btn-primary { background: #3b82f6; color: white; border: none; padding: 0.5rem 1rem; border-radius: 0.375rem; cursor: pointer; } </style>

Step 3: Tailwind CSS Version

<!-- Tailwind CSS classes --> <style> :global(.feedback-widget-modal) { @apply bg-white border border-gray-200 rounded-lg shadow-lg p-6; } :global(.feedback-widget-header) { @apply flex justify-between items-center mb-6; } :global(.feedback-widget-title) { @apply text-xl font-semibold text-gray-900 m-0; } :global(.feedback-widget-close-btn) { @apply text-2xl bg-transparent border-0 cursor-pointer text-gray-400 hover:text-gray-600; } :global(.feedback-widget-field) { @apply mb-4; } :global(.feedback-widget-label) { @apply block mb-2 font-medium text-gray-700; } :global(.feedback-widget-input), :global(.feedback-widget-textarea) { @apply w-full p-3 border border-gray-300 rounded-md bg-white text-gray-900 placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500; } :global(.feedback-widget-textarea) { @apply resize-y; } :global(.feedback-widget-actions) { @apply flex gap-3 justify-end; } :global(.feedback-widget-btn) { @apply px-4 py-2 rounded-md font-medium cursor-pointer transition-colors; } :global(.feedback-widget-btn-primary) { @apply bg-blue-600 text-white hover:bg-blue-700; } :global(.feedback-widget-btn-secondary) { @apply bg-gray-100 text-gray-700 hover:bg-gray-200; } </style>

Available CSS Classes for Styling

CSS Class Element Description
.feedback-widget-modal Modal container Main modal wrapper
.feedback-widget-header Header section Contains title and close button
.feedback-widget-title Modal title H2 heading element
.feedback-widget-close-btn Close button X button in header
.feedback-widget-form Form element Main form container
.feedback-widget-field Field wrapper Contains label + input
.feedback-widget-label Form labels Label elements
.feedback-widget-input Text inputs Subject and email inputs
.feedback-widget-textarea Textarea Feedback message field
.feedback-widget-actions Button container Cancel and submit buttons
.feedback-widget-btn Base button Base class for all buttons
.feedback-widget-btn-primary Submit button Primary action button
.feedback-widget-btn-secondary Cancel button Secondary action button

2. Tailwind CSS Classes (Quick Setup)

Use Tailwind CSS classes for quick theming without inherit styling:

<feedback-widget data-primary-color-class="bg-blue-600" data-background-color-class="bg-white dark:bg-gray-900" data-text-color-class="text-gray-900 dark:text-white" data-border-color-class="border-gray-200 dark:border-gray-700" ></feedback-widget>

3. Custom Colors & Button Positions

Direct color customization and button positioning:

<feedback-widget data-primary-color="#8B5CF6" data-background-color="#F8FAFC" data-text-color="#1E293B" data-border-radius="12px" data-position="left" data-theme="dark" ></feedback-widget>

Position options: right (default), left, bottom-right, bottom-left

Custom Triggers & Forms

Custom Trigger Button

Use your own styled button instead of the default vertical tab:

<button id="my-feedback-btn">Give Feedback</button> <feedback-widget data-repo="myuser/myrepo" data-token="token" data-custom-trigger="#my-feedback-btn" ></feedback-widget>

Programmatic API

Trigger the feedback modal programmatically:

// Simple helper function window.openFeedbackWidget(); // Or dispatch custom event document.dispatchEvent( new Event('feedback-widget-open') );

Custom Form

Provide your own completely custom form:

<div id="custom-form" style="display: none;"> <form> <input name="subject" placeholder="What's this about?"> <textarea name="feedback" placeholder="Tell us more..."></textarea> <button type="submit">Send</button> </form> </div> <feedback-widget data-custom-form="#custom-form" data-repo="myuser/myrepo" data-token="token" ></feedback-widget>

Framework Examples

React/Next.js

import { useEffect } from 'react'; function App() { useEffect(() => { const script = document.createElement('script'); script.src = 'https://cdn.jsdelivr.net/npm/@samletnorge/feedback-widget@latest/dist/feedback-widget.min.js'; document.head.appendChild(script); }, []); return ( <div> <feedback-widget data-repo="myuser/myrepo" data-token={process.env.REACT_APP_GITHUB_TOKEN} data-type="discussion" data-inherit-styling="true" /> </div> ); }

Svelte/SvelteKit

<script> import { onMount } from 'svelte'; onMount(() => { const script = document.createElement('script'); script.src = 'https://cdn.jsdelivr.net/npm/@samletnorge/feedback-widget@latest/dist/feedback-widget.min.js'; document.head.appendChild(script); }); </script> <!-- CSS for custom styling --> <style> :global(.feedback-widget-modal) { @apply bg-background border border-border rounded-lg; } </style> <feedback-widget data-repo="myuser/myrepo" data-token="token" data-primary-color-class="bg-primary" data-background-color-class="bg-background" data-inherit-styling="true" />

Vue.js

<template> <feedback-widget :data-repo="repo" :data-token="token" data-type="discussion" data-category="general" data-position="left" /> </template> <script> export default { data() { return { repo: 'myuser/myrepo', token: process.env.VUE_APP_GITHUB_TOKEN } }, mounted() { const script = document.createElement('script'); script.src = 'https://cdn.jsdelivr.net/npm/@samletnorge/feedback-widget@latest/dist/feedback-widget.min.js'; document.head.appendChild(script); } } </script>

Angular

// app.component.ts import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-root', template: ` <feedback-widget [attr.data-repo]="repo" [attr.data-token]="token" data-type="discussion" data-inherit-styling="true"> </feedback-widget> ` }) export class AppComponent implements OnInit { repo = 'myuser/myrepo'; token = environment.githubToken; ngOnInit() { const script = document.createElement('script'); script.src = 'https://cdn.jsdelivr.net/npm/@samletnorge/feedback-widget@latest/dist/feedback-widget.min.js'; document.head.appendChild(script); } }

Complete Configuration Reference

All available configuration options:

Attribute Type Default Description
data-repo String Required GitHub repository (owner/repo)
data-token String Required GitHub Personal Access Token
data-type String "discussion" "discussion" or "issue"
data-category String "feedback" Discussion category name
data-labels String "feedback" Comma-separated issue labels
data-title String "Feedback" Modal title
data-position String "right" "right", "left", "bottom-right", "bottom-left"
data-inherit-styling Boolean false Use page CSS instead of inline styles
data-custom-trigger String null CSS selector for custom trigger button
data-custom-form String null CSS selector for custom form
data-theme String "light" "light" or "dark"
data-primary-color String "#007bff" Primary color (hex/rgb)
data-primary-color-class String null CSS class for primary color

GitHub Token Setup

Create a GitHub Personal Access Token with the right permissions:

For GitHub Discussions

Required scopes: • public_repo (for public repositories) • repo (for private repositories) • write:discussion

For GitHub Issues

Required scopes: • public_repo (for public repositories) • repo (for private repositories)

Steps to Create Token

  1. Go to GitHub Settings → Developer settings → Personal access tokens
  2. Click "Generate new token (classic)"
  3. Select required scopes based on your needs
  4. Set appropriate expiration date
  5. Copy the token and store it securely

Ready to collect feedback?

Get started in under 2 minutes with our universal feedback widget

View on GitHub NPM Package Direct CDN Link

Custom Styled Feedback