Feedback Widget
The @inputbuffer/feedback package is a lightweight widget you can drop into any web page — documentation sites, dashboards, API references, or your own app. It sends feedback directly to InputBuffer without any server-side code.
By the end of this guide, you'll have a feedback widget on your page that collects thumbs-up/down votes and optional written comments. Each submission appears automatically in your InputBuffer inbox. No backend required.
Before you start
You need a widget-scoped API token. Widget tokens are safe to embed in client-side code — they can only create inputs, not read or modify your organization's data.
To create one:
- Go to Settings → API Tokens in your organization
- Click Create token and select the Widget scope
- Copy the token — it's shown once
Do not use a full-access API token in the widget. Full-access tokens are rejected by the widget API when sent from a browser. Use a widget-scoped token only.
Feedback submitted through the widget is sent to third-party AI services for classification and search. InputBuffer does not yet scrub content before processing — avoid placing the widget where users are likely to submit personal information, credentials, or production secrets.
Quick start
Add an inline thumbs bar
The simplest way to add feedback. Paste this into your page where you want the bar to appear:
<script src="https://cdn.jsdelivr.net/npm/@inputbuffer/feedback/dist/bar.js"></script>
<inputbuffer-feedback
api-key="YOUR_WIDGET_TOKEN"
label="Was this helpful?">
</inputbuffer-feedback>What you should see: A thumbs up/down bar appears inline where you placed the element. After a user clicks a thumb, a short follow-up form appears so they can add context. Once they submit, the feedback appears in your InputBuffer inbox under Inputs.
If the bar does not appear, check your browser console for errors. A 401 error means your token is missing or is a full-access token instead of a widget-scoped one.
More ways to embed
Once the inline bar is working, two other patterns are available:
Floating bar — pins to the bottom of the viewport, useful for documentation pages:
<script src="https://cdn.jsdelivr.net/npm/@inputbuffer/feedback/dist/bar.js"></script>
<inputbuffer-feedback
api-key="YOUR_WIDGET_TOKEN"
label="Was this helpful?"
placement="fixed">
</inputbuffer-feedback>Modal triggered by a button — attaches to an existing button, no JavaScript required:
<button id="feedback-btn">Send feedback</button>
<script
src="https://cdn.jsdelivr.net/npm/@inputbuffer/feedback/dist/modal.js"
data-api-key="YOUR_WIDGET_TOKEN"
data-attach-to="#feedback-btn">
</script>The modal opens when the button is clicked. The feedback appears in your InputBuffer inbox once submitted.
Bundles
Three bundles are available. The quick start examples use bar.js or modal.js — pick the smallest bundle that covers your use case:
| Bundle | Size | What it includes |
|---|---|---|
bar.js | 18 KB | Thumbs up/down bar with optional follow-up form |
modal.js | 19 KB | Full-text feedback modal |
widget.js | 36 KB | Both bar and modal |
All bundles are available via CDN:
https://cdn.jsdelivr.net/npm/@inputbuffer/feedback/dist/bar.js
https://cdn.jsdelivr.net/npm/@inputbuffer/feedback/dist/modal.js
https://cdn.jsdelivr.net/npm/@inputbuffer/feedback/dist/widget.jsOr install from npm: npm install @inputbuffer/feedback
Web component reference
Use <inputbuffer-feedback> with bar.js or widget.js.
| Attribute | Default | Description |
|---|---|---|
api-key | required | Your widget-scoped token |
api-url | — | Override the API endpoint |
label | — | Text shown next to the thumbs (e.g. "Was this helpful?") |
show-label | true | Set to false to hide the text label |
placement | inline | inline renders in place; fixed pins to bottom of viewport |
modal-title | — | Heading for the follow-up form |
modal-placeholder | — | Textarea placeholder text in the follow-up form |
show-title-field | false | Show optional title field in the follow-up form |
show-email-field | true | Show optional email field in the follow-up form |
source | — | Tag submissions with a source string for filtering |
user-id | — | Attach a user identifier to reaction submissions |
theme-primary | — | Primary color (buttons, focus rings) |
theme-background | — | Bar background color |
theme-text | — | Text color |
theme-selected | — | Selected thumb button background |
theme-selected-color | — | Selected thumb icon color |
inject-styles | true | Set to false to disable automatic CSS injection |
Script tag auto-init (data-* attributes)
Add data-api-key to any script tag pointing at modal.js or widget.js and the modal initializes automatically:
| Attribute | Description |
|---|---|
data-api-key | Triggers auto-init on page load |
data-attach-to | CSS selector for the element that opens the modal on click |
data-api-url | Override the API endpoint |
data-color-scheme | light, dark, or auto (default: auto) |
data-inject-styles | Set to false to disable automatic CSS injection |
data-theme-primary | Primary color |
data-theme-background | Modal background color |
data-theme-text | Text color |
data-theme-selected | Selected sentiment thumb background |
data-theme-selected-color | Selected sentiment thumb icon color |
Programmatic API
For full control, use the JavaScript API directly.
createBar(config)
Clicking a thumb immediately records a reaction via the reactions API (fire-and-forget). The selected vote is persisted to localStorage for 24 hours and restored on revisit — so users see their previous choice when they return to the page.
import { createBar } from '@inputbuffer/feedback';
// or: const { createBar } = window.InputBufferIO;
const bar = createBar({
apiKey: 'YOUR_WIDGET_TOKEN',
label: 'Was this helpful?',
placement: 'inline', // or 'fixed'
colorScheme: 'auto', // 'light' | 'dark' | 'auto'
showEmailField: true,
modalTitle: 'Share your feedback',
modalPlaceholder: "What's on your mind?",
});
document.getElementById('feedback-slot').appendChild(bar.element);createBar config options:
| Option | Default | Description |
|---|---|---|
apiKey | required | Your widget-scoped token |
apiUrl | — | Override the API endpoint |
label | — | Text shown next to the thumbs |
placement | 'inline' | 'inline' renders in place; 'fixed' pins to bottom of viewport |
colorScheme | 'auto' | 'light', 'dark', or 'auto' |
showEmailField | true | Show optional email field in the follow-up form |
modalTitle | 'Share your feedback' | Heading for the follow-up form |
modalPlaceholder | "What's on your mind?" | Textarea placeholder text in the follow-up form |
source | — | Tag submissions with a source string for filtering |
userId | — | Attach a user identifier to reaction submissions |
injectStyles | true | Set to false to disable automatic CSS injection |
theme | — | Theme object — see Theming |
Bar instance methods:
| Method | Description |
|---|---|
bar.on('vote', ({ sentiment }) => {}) | User clicked a thumb |
bar.on('open', ({ sentiment }) => {}) | Follow-up form opened |
bar.on('submit', ({ id }) => {}) | Feedback submitted — id is the InputBuffer input ID |
bar.on('close', () => {}) | Follow-up form closed |
bar.on('error', (err) => {}) | Submission failed |
bar.destroy() | Remove the bar and clean up listeners |
createModal(config)
import { createModal } from '@inputbuffer/feedback';
// or: const { createModal } = window.InputBufferIO;
const modal = createModal({
apiKey: 'YOUR_WIDGET_TOKEN',
title: 'Share your feedback',
placeholder: "What's on your mind?",
showEmailField: true,
showSentiment: false,
colorScheme: 'auto',
});
document.getElementById('my-button').addEventListener('click', () => modal.open());createModal config options:
| Option | Default | Description |
|---|---|---|
apiKey | required | Your widget-scoped token |
apiUrl | — | Override the API endpoint |
attachTo | — | CSS selector for an element that opens the modal on click |
title | 'Share your feedback' | Modal heading |
placeholder | "What's on your mind?" | Textarea placeholder text |
showEmailField | true | Show optional email field |
showSentiment | false | Show thumbs up/down sentiment selector |
colorScheme | 'auto' | 'light', 'dark', or 'auto' |
injectStyles | true | Set to false to disable automatic CSS injection |
theme | — | Theme object — see Theming |
Modal instance methods:
| Method | Description |
|---|---|
modal.open(options?) | Open the modal, optionally with context — see below |
modal.close() | Close the modal programmatically |
modal.destroy() | Clean up and remove all listeners |
modal.on('submit', ({ id }) => {}) | Feedback submitted — id is the InputBuffer input ID |
modal.on('close', () => {}) | Modal closed |
modal.on('error', (err) => {}) | Submission failed |
The id returned by the submit event is the InputBuffer input ID for the submitted feedback. You can use it to correlate widget submissions with entries in your inbox or via the REST API.
modal.open(options)
Pass options to pre-populate the modal or attach feedback to a specific target:
modal.open({
title: 'Feedback on this page', // Override modal heading
sentiment: 'negative', // Pre-select a thumb ('positive' | 'negative')
prefill: {
email: '[email protected]', // Pre-fill email
description: 'This section was...', // Pre-fill textarea
},
target: {
type: 'documentation',
metadata: {
page_url: window.location.href,
section_heading: 'Submit your first input', // optional
},
},
});Targeting
Targets attach feedback to a specific resource in your product — a documentation page, REST endpoint, or CLI command. This lets you see which specific pages or endpoints have the most issues.
Targets are optional. Without a target, feedback goes into your general inbox. With a target, you can filter and track feedback per resource.
Documentation page
modal.open({
target: {
type: 'documentation',
metadata: {
page_url: 'https://docs.example.com/getting-started',
section_heading: 'Authentication', // optional
doc_version: 'v2', // optional
},
},
});REST API endpoint
modal.open({
target: {
type: 'rest_endpoint',
metadata: {
method: 'POST',
path: '/v1/users',
host: 'api.example.com', // optional
api_version: 'v1', // optional
},
},
});CLI command
modal.open({
target: {
type: 'cli_command',
metadata: {
command: 'deploy',
subcommand: 'production', // optional
cli_version: '2.4.0', // optional
args: ['--env', 'prod'], // optional
},
},
});Theming
Color scheme
createModal({ apiKey: '...', colorScheme: 'dark' });
// or 'light' | 'auto' (default: 'auto' follows system preference)Theme object
Override individual colors via the theme config option:
createModal({
apiKey: '...',
theme: {
primary: '#6366f1', // Button and focus ring color
background: '#1e1e2e', // Modal background
surface: '#2a2a3e', // Modal header background
text: '#cdd6f4', // Body text
selected: '#6366f1', // Selected thumb background
selectedColor: '#ffffff', // Selected thumb icon color
},
});The same theme option is available on createBar(). For the web component, use theme-* attributes:
<inputbuffer-feedback
api-key="..."
theme-primary="#6366f1"
theme-background="#1e1e2e"
theme-text="#cdd6f4">
</inputbuffer-feedback>CSS custom properties
When injectStyles is true (default), the widget injects its own stylesheet and exposes CSS custom properties you can override:
/* Modal: set on #ib-modal */
#ib-modal {
--ib-primary: #6366f1;
--ib-primary-hover: #4338ca;
--ib-background: #1e1e2e;
--ib-surface: #2a2a3e;
--ib-text: #cdd6f4;
--ib-muted: #9399b2;
--ib-border: #45475a;
--ib-selected: #6366f1;
--ib-selected-color: #ffffff;
--ib-radius: 8px;
--ib-radius-input: 4px;
}
/* Bar: set on .ib-bar-wrapper */
.ib-bar-wrapper {
--ib-primary: #6366f1;
}CSS customization
When injectStyles: false, you can style everything from scratch using stable selectors.
Modal selectors
| Selector | Element |
|---|---|
#ib-overlay | Full-screen backdrop |
#ib-modal | Modal container (CSS variable scope) |
#ib-modal-header | Header bar |
#ib-modal-body | Body content area |
#ib-title | Modal heading |
#ib-textarea | Feedback textarea |
#ib-email | Email input |
#ib-submit | Submit button |
#ib-close | Close button |
#ib-success | Success message |
#ib-error | Error message |
Bar selectors
| Selector | Element |
|---|---|
.ib-bar-wrapper | Outer wrapper (CSS variable scope) |
.ib-bar | Visible bar strip |
.ib-bar-label | Label text |
.ib-bar-btn | Thumb buttons |
.ib-popover | Follow-up popover |
.ib-popover-header | Popover header |
.ib-popover-title | Popover heading |
.ib-popover-textarea | Feedback textarea |
.ib-popover-email | Email input |
.ib-popover-submit | Submit button |
.ib-popover-success | Success message |
.ib-popover-error | Error message |
Next steps
- REST API reference — submit feedback server-side, query inputs, or integrate with your backend