PhiaUi.Components.FeedbackWidget (phia_ui v0.1.17)

Copy Markdown View Source

Micro-feedback collection components for gathering quick user feedback without interrupting the user's workflow.

Inspired by Notion's page reactions, GitHub's "Was this helpful?" pattern, Intercom's CSAT survey, and Linear's NPS widget.

Pure HEEx — no JavaScript hooks required. All state managed server-side via LiveView assigns and phx-click events.

Sub-components

ComponentPurpose
feedback_thumb/1Single thumbs-up "Was this helpful?" button
feedback_reaction/1Emoji/icon reaction bar (👍 ❤️ 😂 😮 😢 😡)
feedback_nps/1Net Promoter Score 0–10 scale widget
feedback_survey_card/1"Was this helpful?" card with Yes/No and optional comment

Thumbs up (docs helpful)

<.feedback_thumb
  helpful={@page_helpful}
  count={@helpful_count}
  phx-click="toggle_helpful"
/>

Emoji reactions

<.feedback_reaction
  reactions={@reactions}
  current_reaction={@my_reaction}
  phx-value-reaction="..."
  phx-click="react"
/>

NPS score

<.feedback_nps
  selected={@nps_score}
  phx-click="submit_nps"
  phx-value-score="..."
/>

Survey card

<.feedback_survey_card
  :if={!@feedback_submitted}
  title="Was this article helpful?"
  phx-click-yes="feedback_yes"
  phx-click-no="feedback_no"
/>

Summary

Functions

Renders a Net Promoter Score (NPS) 0–10 rating widget.

Renders an emoji reaction bar.

Renders a compact "Was this helpful?" survey card.

Renders a single "thumbs up / helpful" feedback button.

Functions

feedback_nps(assigns)

Renders a Net Promoter Score (NPS) 0–10 rating widget.

Wire phx-click and phx-value-score at the wrapper level or on each button. Scores 0–6 are Detractors (red), 7–8 Passives (amber), 9–10 Promoters (green).

Example

<.feedback_nps
  question="How likely are you to recommend PhiaUI?"
  selected={@nps_score}
  phx-click="submit_nps"
/>

# LiveView handler
def handle_event("submit_nps", %{"score" => score}, socket) do
  {:noreply, assign(socket, nps_score: String.to_integer(score))}
end

Attributes

  • selected (:any) - Currently selected score (0–10), or nil if not yet answered. Defaults to nil.
  • question (:string) - The NPS question displayed above the scale. Defaults to "How likely are you to recommend us to a friend?".
  • class (:string) - Additional CSS classes. Defaults to nil.
  • Global attributes are accepted. HTML attrs forwarded to the wrapper. Add phx-click here.

feedback_reaction(assigns)

Renders an emoji reaction bar.

Each reaction button shows the emoji + count. The active reaction (matching :current_reaction) is highlighted. Wire phx-click and phx-value-reaction at the wrapper level for event delegation.

Example

<.feedback_reaction
  reactions={[
    %{emoji: "👍", count: 14, value: "like"},
    %{emoji: "❤️", count: 7, value: "love"},
    %{emoji: "😂", count: 3, value: "laugh"},
    %{emoji: "😮", count: 2, value: "wow"}
  ]}
  current_reaction={@my_reaction}
  phx-click="react"
/>

Attributes

  • reactions (:list) - List of reaction maps. Each map:

    • :emoji (string) — the emoji character or label
    • :count (integer) — current count
    • :value (string) — value sent as phx-value-reaction

    Example: [%{emoji: "👍", count: 12, value: "like"}]

    Defaults to [].

  • current_reaction (:string) - The :value of the reaction the current user has selected (if any). Defaults to nil.

  • class (:string) - Additional CSS classes. Defaults to nil.

  • Global attributes are accepted. HTML attrs forwarded to the wrapper <div>. Add phx-click here.

feedback_survey_card(assigns)

Renders a compact "Was this helpful?" survey card.

Provides Yes/No buttons with phx-click-yes and phx-click-no support. Combine with a LiveView assign to swap the card content after answering.

Example

<.feedback_survey_card
  :if={!@feedback_submitted}
  title="Was this article helpful?"
  phx-click-yes="feedback_yes"
  phx-click-no="feedback_no"
/>
<div :if={@feedback_submitted} class="text-sm text-muted-foreground text-center py-4">
  Thank you for your feedback!
</div>

Attributes

  • title (:string) - Survey question displayed as the card title. Defaults to "Was this helpful?".
  • description (:string) - Optional sub-text below the title. Defaults to nil.
  • yes_label (:string) - Label for the positive response. Defaults to "Yes".
  • no_label (:string) - Label for the negative response. Defaults to "No".
  • class (:string) - Additional CSS classes. Defaults to nil.
  • Global attributes are accepted. HTML attrs forwarded to the card <div>.

Slots

  • after_answer - Content to render after the user answers (e.g. thank-you message). Wire using :if.

feedback_thumb(assigns)

Renders a single "thumbs up / helpful" feedback button.

Commonly used at the bottom of documentation pages, support articles, and knowledge base entries. State is toggled server-side via phx-click.

Example

<.feedback_thumb helpful={@helpful} count={@count} phx-click="toggle_helpful" />

Attributes

  • helpful (:boolean) - Whether the current user has marked as helpful. Defaults to false.
  • count (:integer) - Optional count of people who found it helpful. Defaults to nil.
  • label (:string) - Button label text. Defaults to "Helpful".
  • class (:string) - Additional CSS classes. Defaults to nil.
  • Global attributes are accepted. HTML attrs forwarded to the <button>.