Custom Modal Content: Tailor the Feedback Form
Customize the feedback modal's title, placeholder text, submit button, and add custom fields.
The thumbs tell you the direction. The modal is where you find out why, and what you write in it decides whether anybody bothers.
What is in the modal
A title acknowledging the vote, a subtitle asking for more, a textarea with placeholder text, a submit button, and a skip button that sends the vote without a message. Click through it:
Default Modal
Click a button to see the standard modal
Eight strings in the text object
Every word in that modal is a default you can replace:
| Property | Default | Description |
|---|---|---|
modalTitle | "Thank you for your feedback!" | The main heading in the modal |
modalSubtitle | "Would you like to add a message..." | Explanatory text below the title |
placeholder | "Optional: Tell us more..." | Placeholder text in the textarea |
submitButton | "Submit" | Text on the primary action button |
skipButton | "Skip" | Text on the secondary action button |
confirmationTitle | "Thank you!" | Heading on the success screen |
confirmationMessage | "Your feedback has been received." | Body copy on the success screen |
confirmationClose | "Close" | Text on the success screen's dismiss button |
For a product team
Product Feedback
Customized for product teams
new QaidFeedback({
endpoint: '/api/feedback',
text: {
modalTitle: "We appreciate your input!",
modalSubtitle: "Help our product team understand what you experienced.",
placeholder: "Describe what happened, what you expected, or what could be improved...",
submitButton: "Send Feedback",
skipButton: "Not now"
}
});
For bug reports
Bug Report Style
Optimized for collecting bug reports
new QaidFeedback({
endpoint: '/api/feedback',
text: {
modalTitle: "Thanks for reporting this issue",
modalSubtitle: "The more detail you provide, the faster we can fix it.",
placeholder: "Steps to reproduce: 1) ... 2) ... 3) ...",
submitButton: "Report Bug",
skipButton: "Skip details"
}
});
Stripped back
Minimal Style
Short and to the point
new QaidFeedback({
endpoint: '/api/feedback',
text: {
modalTitle: "Got it!",
modalSubtitle: "Anything else?",
placeholder: "Type here...",
submitButton: "Done",
skipButton: "Nope"
}
});
Where the modal appears
With targeting on, the modal anchors to whatever element the reader picked. With skipTargeting: true it anchors near the buttons instead.
The order it tries
Below the target first. Above it if there is no room below. Then clamped so no edge leaves the viewport, with an arrow pointing back at where the click landed.
It keeps 8px off the target and 16px off the viewport edges.
Making it wider
modalWidth takes a number of pixels:
new QaidFeedback({
endpoint: '/api/feedback',
modalWidth: 500 // Default is 400
});
Worth it if your placeholder runs to two lines. Not worth it otherwise, since a wide box on a phone just becomes a tall one.
Restyling it with CSS
The structure is fixed, the appearance is not. Pass a stylesheet through css and target these:
/* The card itself */
.qaid-modal-box {
background: #fff;
border-radius: 12px;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
}
.qaid-modal-title {
color: #1a1a1a;
font-size: 1.125rem;
font-weight: 600;
}
.qaid-modal-subtitle {
color: #666;
font-size: 0.875rem;
}
.qaid-textarea {
border: 1px solid #e0e0e0;
border-radius: 8px;
resize: vertical;
}
/* Both actions share this class; colour comes from colors.marker */
button.qaid-btn-submit {
border-radius: 8px;
}
Set the backdrop through backdropOpacity rather than restyling .qaid-backdrop, and the button colour through colors.marker rather than CSS. Styling the modal has the full selector list, including the mobile bottom sheet, which uses different outer classes.
What config does without CSS
Three of the common changes are settings:
new QaidFeedback({
endpoint: '/api/feedback',
// Modal width in pixels
modalWidth: 400,
// Backdrop opacity (0-1)
backdropOpacity: 0.3,
// Font for all text
fontFamily: 'Inter, system-ui, sans-serif',
// Base font size
fontSize: 16,
// Colors affect modal buttons
colors: {
positive: '#22c55e', // Submit button color for positive feedback
negative: '#ef4444' // Submit button color for negative feedback
}
});
Custom Styled
Modified with configuration options
The message is always optional
Skip sends the vote with no text. That is deliberate: a required message turns a one-click rating into a writing task, and most people close the tab instead.
You cannot make it mandatory, but you can lean either way with the copy.
Asking harder
Name what you want and the skip button gets pressed less:
new QaidFeedback({
endpoint: '/api/feedback',
text: {
modalSubtitle: "Please tell us more so we can take action.",
placeholder: "We need details to investigate this...",
skipButton: "Submit without details"
}
});
Getting out of the way
Or say plainly that one word is fine:
new QaidFeedback({
endpoint: '/api/feedback',
text: {
modalSubtitle: "Optionally add context (or just skip ahead).",
placeholder: "No pressure - only if you have time!",
skipButton: "Skip"
}
});
The success screen
A sent message gets a checkmark and a line of acknowledgement instead of the modal just vanishing. That matters most for embeds mounted in the page, where nothing overlays anything, so a silent close looks exactly like a failure.
On by default since v1.7.0. All three strings are yours:
new QaidFeedback({
endpoint: '/api/feedback',
text: {
confirmationTitle: "Message received",
confirmationMessage: "Thanks — we read every one of these.",
confirmationClose: "Done"
}
});
Turning it off
hideConfirmation: true restores the pre-1.7.0 behaviour and closes straight away:
new QaidFeedback({
endpoint: '/api/feedback',
hideConfirmation: true
});
Or as a data attribute:
<script
src="https://unpkg.com/@qaiddev/thumbs-embed"
data-endpoint="/api/feedback"
data-hide-confirmation="true"
></script>
It only shows on a delivered message. A failed request closes the modal the old way, because thanking somebody for feedback you never received is worse than saying nothing.
Modal copy alongside other features
When screenshots are on
The modal is where you tell people an image is attached:
new QaidFeedback({
endpoint: '/api/feedback',
captureScreenshot: true,
text: {
modalTitle: "Screenshot captured!",
modalSubtitle: "Add notes to explain what you see in the screenshot.",
placeholder: "Point out what's wrong or what you'd like to change..."
}
});
Alongside a theme
Strings and styling set together:
Branded Experience
Text + visual customization
new QaidFeedback({
endpoint: '/api/feedback',
colors: {
positive: "#a78bfa",
negative: "#f472b6"
},
text: {
modalTitle: "You're awesome!",
modalSubtitle: "Help us make this even better.",
placeholder: "Your ideas matter to us...",
submitButton: "Send love",
skipButton: "Skip for now"
}
});
As data attributes
Every string works on a script tag too:
<script
src="https://unpkg.com/@qaiddev/thumbs-embed/dist/embed.js"
data-endpoint="/api/feedback"
data-modal-title="We value your feedback!"
data-modal-subtitle="Tell us what you think."
data-placeholder="Share your experience..."
data-submit-button="Send"
data-skip-button="Skip"
data-modal-width="450"
data-backdrop-opacity="0.4"
></script>
Writing the copy
Six words in the title, because it gets scanned rather than read. Ask for one specific thing in the subtitle, since "tell us more" gets you "it's broken" and "which page was this on?" gets you an answer. Start the buttons with verbs.
Then spend a minute on the skip button, which is the string nobody edits. "Skip", "Not now" and "No thanks" send quite different signals about whether you wanted the message in the first place.