Documentation

Customize and extend Wafir to match your needs

Documentation

Customize and extend Wafir to match your needs.

Quick Start

Widget Attributes

<wafir-widget
  config-url="/wafir.yaml"
  bridge-url="https://your-bridge.example.com"
>
</wafir-widget>

Or configure inline without a config file:

<wafir-widget
  target-type="github/issues"
  target="owner/repo"
  auth-ref="YOUR_INSTALLATION_ID"
>
</wafir-widget>

Custom Triggers

Replace the default floating button with your own custom trigger element using the trigger slot:

<wafir-widget config-url="/wafir.yaml">
  <button slot="trigger" class="my-custom-button">Report an Issue</button>
</wafir-widget>

Tip: Your custom trigger element should handle its own styling. The widget will automatically open/close the modal when clicked.


Configuration File

Configure the feedback widget by placing a wafir.yaml file in your app’s public folder (e.g. public/wafir.yaml). Make sure it is publicly accessible.

Basic Structure

title: "Contact Us"

targets:
  - id: default
    type: github/issues
    target: your-username/your-repo
    authRef: "YOUR_INSTALLATION_ID"

forms:
  - id: bug
    label: Report Bug
    icon: bug
    targets: [default]
    body:
      - id: title
        type: input
        attributes:
          label: "Issue Title"
        validations:
          required: true

Targets

The targets key defines where feedback submissions are routed. Each target specifies a destination type and authentication.

Target Properties

PropertyTypeDescription
idstringUnique identifier referenced by forms
typestringgithub/issues or github/project
targetstringowner/repo for issues, owner/project-number for projects
authRefstringGitHub App installation ID

Example

targets:
  - id: default
    type: github/issues
    target: your-username/your-repo
    authRef: "YOUR_INSTALLATION_ID"
  - id: project
    type: github/project
    target: your-username/9
    authRef: "YOUR_INSTALLATION_ID"

Forms

Forms define the structure of your feedback widget. Each form represents a distinct feedback type with its own fields and routing, displayed as tabs in the widget UI.

Form Properties

PropertyTypeDescription
idstringUnique identifier. Also used as GitHub issue type when creating issues.
labelstringDisplay label shown in the form tab
iconstring?Icon name: bug, lightbulb, or thumbsup
labelsstring[]?GitHub labels to auto-apply to issues
templateUrlstring?URL to a GitHub issue form template YAML
targetsarray?Array of target IDs to route submissions to. Set to a non-existent ID (e.g., [none]) to disable the submit button for informational forms.
bodyarrayArray of field definitions

Example

forms:
  - id: Bug
    label: Report Bug
    icon: bug
    labels:
      - bug
    targets: [default]
    body:
      - id: title
        type: input
        attributes:
          label: "Issue Title"
        validations:
          required: true
      - id: description
        type: textarea
        attributes:
          label: "Description"
        validations:
          required: true

  - id: feedback
    label: Feedback
    icon: thumbsup
    targets: [project]
    body:
      - id: rating
        type: rating
        attributes:
          label: "How satisfied are you?"
          options:
            - "Very Unsatisfied"
            - "Unsatisfied"
            - "Neutral"
            - "Satisfied"
            - "Excellent"
        validations:
          required: true

Using GitHub Issue Templates

Reference an existing GitHub issue form template by providing a templateUrl. The fields will be fetched from the template:

forms:
  - id: Bug
    label: Report Bug
    icon: bug
    templateUrl: https://raw.githubusercontent.com/owner/repo/main/.github/ISSUE_TEMPLATE/bug_report.yml
    targets: [default]

Single Form Mode

If you only need one type of feedback, define a single form. The tab selector will be hidden automatically:

forms:
  - id: issue
    label: Report Issue
    icon: bug
    body:
      - id: title
        type: input
        attributes:
          label: "Issue Title"
        validations:
          required: true

Fields

Each field is defined using id, type, attributes, and validations subkeys. The schema is inspired by GitHub Issue Forms, extended with additional field types.

Field Types

TypeDescriptionKey Attributes
inputSingle-line text inputlabel, description?, placeholder?, value?
emailEmail inputlabel, description?, placeholder?, value?
textareaMulti-line text arealabel, description?, placeholder?, value?, render?
dropdownDropdown selectionlabel, options, description?, multiple?
checkboxesMultiple checkbox optionslabel, options (array of objects with label, required?)
markdownRead-only Markdown displayvalue (required)
ratingIcon-based rating selectorlabel, options, description?, icon?
dateDate picker inputlabel, description?, value?

Field Properties

PropertyLocationTypeDescription
idfield (root)stringUnique identifier for the field
typefield (root)stringField input type (see above)
displayfield (root)string?Field visibility: visible (default) or none (hidden)
attributesfield (root)objectDisplay and options attributes
validationsfield (root)objectValidation rules (e.g., required: true/false)
labelattributesstringDisplay label
descriptionattributesstring?Helper/description text
placeholderattributesstring?Placeholder text
valueattributesstring?Default value or Markdown content
renderattributesstring?Syntax highlighting for textarea (e.g. shell)
optionsattributesarrayOptions for dropdowns, checkboxes, or rating fields
multipleattributesboolean?Allow multiple selections (dropdown only)
iconattributesstring?Unicode character/emoji for rating icon (default: ⭐)
autofillattributesstring?Auto-fill with telemetry data (see Opt-In Telemetry)
requiredvalidationsbooleanIf the field is required

Basic Field Example

body:
  - id: priority
    type: dropdown
    attributes:
      label: "Priority"
      options:
        - "Low"
        - "Medium"
        - "High"
        - "Critical"
    validations:
      required: true

Markdown Field

Markdown fields display formatted content and are never included in submission data:

- id: instructions
  type: markdown
  attributes:
    value: |
      ## Feedback Form
      Please fill out all required fields. Your responses help us improve!

Date Field

Date fields render a native date picker with support for dynamic date tokens:

- id: target-date
  type: date
  attributes:
    label: "Target Completion Date"
    value: "today+30"
  validations:
    required: false

Date Value Tokens

TokenExampleDescription
todayvalue: "today"Current date
today+Nvalue: "today+7"N days in the future
today-Nvalue: "today-30"N days in the past
YYYY-MM-DDvalue: "2026-03-01"Static ISO date

Note: Date values are stored and submitted in ISO 8601 format (YYYY-MM-DD). When submitting to a GitHub Project, date fields automatically map to project Date fields with matching names.

Rating Field

Rating fields display a row of clickable icons for user satisfaction ratings. The number of icons matches the number of options provided:

- id: satisfaction
  type: rating
  attributes:
    label: "How satisfied are you?"
    icon: "⭐"  # Optional, defaults to ⭐
    options:
      - "Very Unsatisfied"
      - "Unsatisfied"
      - "Neutral"
      - "Satisfied"
      - "Excellent"
  validations:
    required: true

Rating Properties

PropertyTypeDefaultDescription
optionsstring[]5 itemsLabels for each rating level (determines count)
iconstringUnicode character/emoji displayed for each level

Tip: Use any unicode character as the icon: ❤️ for hearts, 👍 for thumbs up, for circles, etc. The selected rating value (1 to N) is stored and displayed with the corresponding option label on hover.


Opt-In Telemetry

Wafir supports opt-in telemetry through autofill fields. These give users explicit control over what data they share by presenting a checkbox they must enable.

Available Autofill Types

ValueData CollectedUser Control
screenshotDOM-to-canvas screenshot with optional element highlightingCheckbox + capture
browserInfoURL, user agent, viewport size, languageCheckbox to include
consoleLogRecent console messages (errors, warnings)Checkbox to include

How It Works

  1. Add a textarea field with the autofill attribute
  2. The widget displays an “Include [Label]” checkbox
  3. When checked, the field auto-populates with telemetry data
  4. Users see exactly what data will be shared before submitting
  5. If unchecked, no telemetry data is included

Example

forms:
  - id: bug
    label: Report Bug
    icon: bug
    body:
      - id: title
        type: input
        attributes:
          label: "Issue Title"
        validations:
          required: true
      - id: description
        type: textarea
        attributes:
          label: "Describe the issue"
        validations:
          required: true
      # Opt-in telemetry fields
      - id: browser-info
        type: textarea
        attributes:
          label: "Browser Info"
          autofill: browserInfo
        validations:
          required: false
      - id: screenshot
        type: textarea
        attributes:
          label: "Screenshot"
          autofill: screenshot
        validations:
          required: false
      - id: console-logs
        type: textarea
        attributes:
          label: "Console Logs"
          autofill: consoleLog
        validations:
          required: false

JavaScript API

Wafir provides a JavaScript API for programmatically opening the widget, switching tabs, or prefilling fields.

NPM/Module Usage

import { wafirWidget } from "wafir";

// Open the widget (default tab)
wafirWidget.open();

// Open a specific tab
wafirWidget.open({ tab: "suggestion" });

// Open with prefilled fields
wafirWidget.open({
  tab: "issue",
  prefill: {
    title: "Crash on upload",
    description: "I experienced a crash when uploading a large file.",
  },
});

Script Tag/CDN Usage

When loaded from a <script> tag, the API is available on window:

window.wafirWidget.open({
  tab: "feedback",
  prefill: {
    rating: 5,
    description: "Great experience!",
  },
});

API Reference

interface wafirWidget {
  open(options?: {
    tab?: string;                    // Form ID from your config
    prefill?: Record<string, any>;   // Field ID/value pairs
  }): void;
}

Notes

  • Queued execution: You can call open() before the widget loads; requests are queued until ready.
  • Tab IDs: Must match a form id in your config. Invalid IDs fall back to the default tab with a warning.
  • Field IDs: Prefill keys must match field ids. Invalid keys are ignored with a warning.
  • Read-only fields: Prefill does not affect markdown fields.

Example: Custom Button

<button onclick="window.wafirWidget.open({tab: 'suggestion'})">
  Suggest a Feature
</button>

Connect Personal Projects

GitHub personal projects require additional authorization beyond the GitHub App installation.

Why is this needed?

The Wafir GitHub App only has access to organization repositories and projects. Personal projects require separate OAuth authorization.

How to Connect

  1. Find your Installation ID from your GitHub App installation URL:

    github.com/settings/installations/12345678

    The number at the end is your Installation ID.

  2. Visit the Connect Page on the Wafir website or your self-hosted instance.

  3. Enter your Installation ID and click “Authorize with GitHub”.

  4. Grant the requested permissions:

    • read:user — Read your GitHub profile
    • project — Access your GitHub projects
  5. Complete authorization and you’ll be redirected back with a success message.

Security & Privacy

  • Your access token is stored securely and only used to add issues to your personal projects
  • You can revoke access at any time from your GitHub settings
  • Wafir never stores or accesses any data beyond what’s needed to create project items

Using Personal Projects

targets:
  - id: personal-project
    type: github/project
    target: your-username/project-number
    authRef: "YOUR_INSTALLATION_ID"

Configuration Examples

We provide ready-to-use configuration templates in the /examples folder:

  • Basic — Standard bug reporting setup
  • Minimal — Simplest possible config
  • Full Featured — All options demonstrated
  • Privacy Focused — No automatic data collection
  • Feature Requests — Optimized for ideas
  • Feedback Focused — Star rating and satisfaction surveys

CSS Customization

Wafir uses Shadow DOM for isolation, but exposes CSS custom properties and ::part() selectors for customization.

CSS Custom Properties

Override these variables on the wafir-widget element:

Widget Variables

VariableDefaultDescription
--wafir-font-familySystem fontsFont stack for all text
--wafir-font-size14pxBase font size
--wafir-text-color#111827Primary text color
--wafir-text-secondary#6b7280Secondary/muted text color
--wafir-primary-color#2563ebPrimary brand color
--wafir-primary-hover#1d4ed8Primary color on hover
--wafir-border-color#e5e7ebBorder color
--wafir-button-size48pxTrigger button size
--wafir-button-border-radius50%Trigger button border radius
--wafir-button-offset20pxDistance from screen edge
--wafir-button-icon-size24pxIcon size inside button
--wafir-button-shadow0 4px 12px rgba(0,0,0,0.15)Button shadow
--wafir-button-shadow-hover0 6px 16px rgba(0,0,0,0.2)Button shadow on hover
--wafir-tooltip-bg#1f2937Tooltip background color
--wafir-backdrop-colorrgba(0,0,0,0.5)Modal backdrop color
--wafir-modal-bgwhiteModal background color
--wafir-modal-border-radius12pxModal border radius
--wafir-modal-max-width800pxModal maximum width
--wafir-modal-padding20pxModal header/content padding
--wafir-modal-shadow0 20px 60px rgba(0,0,0,0.3)Modal shadow
--wafir-modal-title-font-size18pxModal title size
--wafir-modal-title-font-weight600Modal title weight
--wafir-modal-title-color--wafir-text-colorModal title color

Form Variables

VariableDefaultDescription
--wafir-form-text-color#374151Form text color
--wafir-form-bgtransparentForm background
--wafir-form-padding20pxForm padding
--wafir-form-border-color#d1d5dbInput border color
--wafir-form-border-radius6pxInput border radius
--wafir-form-input-padding10px 12pxInput padding
--wafir-form-input-color#111827Input text color
--wafir-form-input-bg#ffffffInput background
--wafir-form-primary-color#2563ebSubmit button color
--wafir-form-primary-hover#1d4ed8Submit button hover
--wafir-form-disabled-color#9ca3afDisabled state color
--wafir-form-bg-secondary#f3f4f6Secondary background
--wafir-form-bg-tertiary#f9fafbTertiary background
--wafir-form-text-secondary#6b7280Secondary text color
--wafir-form-telemetry-bg#f9fafbTelemetry section background
--wafir-form-telemetry-border#e5e7ebTelemetry section border
--wafir-form-logs-bg#111827Console logs background
--wafir-form-logs-text#f3f4f6Console logs text color
--wafir-form-log-warn#fde047Warning log color
--wafir-form-log-error#f87171Error log color

Rating Variables

VariableDefaultDescription
--wafir-rating-icon-size28pxRating icon size

Highlighter Variables

VariableDefaultDescription
--wafir-highlighter-overlay-bgrgba(0,0,0,0.1)Overlay background
--wafir-highlighter-primary-color#2563ebHighlight border color
--wafir-highlighter-highlight-bgrgba(37,99,235,0.1)Highlight fill color

Example

wafir-widget {
  --wafir-primary-color: #6366f1;
  --wafir-primary-hover: #818cf8;
  --wafir-modal-bg: #ffffff;
  --wafir-text-color: #1f2937;
  --wafir-border-color: #e5e7eb;
  --wafir-form-border-radius: 8px;
  --wafir-font-family: "Inter", sans-serif;
}

Part Selectors

Use ::part() to style specific elements:

wafir-widget::part(button) {
  background: #10b981;
  box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
}

wafir-widget::part(button):hover {
  background: #059669;
}

Available Parts

Part NameDescription
buttonThe floating trigger button
modalThe feedback modal container
formThe form element
inputText input fields
textareaTextarea fields
selectSelect dropdowns
submitThe submit button