Skip to content
Get started

Components

FeedbackBar

Unstable: "Was this helpful?" under an AI answer, a thumbs up and a thumbs down that toggle, and optional reasons after a thumbs down. Import it from @nizivo/react/unstable/feedback-bar.

Tier: clientUnstable

Examples

Basic

Three states: not voted, a thumbs up, and a thumbs down with its reasons.

Was this helpful?
Thanks — glad it helped.
Thanks. What went wrong?
import type { JSX } from 'react';
import { FeedbackBar } from '@nizivo/react/unstable/feedback-bar';

const REASONS = ['Not accurate', 'Not helpful', 'Too long', 'Something else'];

export function FeedbackBarExample(): JSX.Element {
  return (
    <div style={{ display: 'grid', gap: 16 }}>
      <FeedbackBar reasons={REASONS} />
      <FeedbackBar defaultValue="up" reasons={REASONS} />
      <FeedbackBar defaultValue="down" reasons={REASONS} />
    </div>
  );
}

Import

import { FeedbackBar } from '@nizivo/react/unstable/feedback-bar';

// Once per app (Getting started), after
// @nizivo/tokens/tokens.css and @nizivo/react/css/base.css and @nizivo/react/css/chip-group.css and @nizivo/react/css/icon-button.css
import '@nizivo/react/css/feedback-bar.css';

Static or interactive

Client. The votes are IconButtons with aria-pressed, and the reasons a ChipGroup. How to choose.

Votes

value, defaultValue and onValueChange hold the vote: 'up', 'down' or null. Pressing the pressed vote clears it. The buttons keep their names ("Good answer", "Bad answer"); the prompt changes to a thanks, and a screen reader hears it. A vote never opens a dialog or moves focus.

Reasons

Pass reasons to offer them after a thumbs down, one to pick; reason, defaultReason and onReasonChange hold it. Keep them few and short: "Not accurate", "Too long".

Props

Client component Renders data-slot="feedback-bar" with the class nz-feedback-bar. Props: FeedbackBarProps. Source: src/unstable/feedback-bar/feedback-bar.client.tsx.

NameTypeDefaultDescription
defaultReasonstring–

The reason at first (uncontrolled).

defaultValueFeedbackValue
"up""down"null
null

The vote at first (uncontrolled).

labelsPartial<FeedbackBarLabels>–
onReasonChange(reason: string) => void–
onValueChange(value: FeedbackValue, details: ChangeDetails<"press">) => void–
promptReactNode–

Replaces the prompt; still replaced by the thanks after a vote.

reasonstring | null–

The picked reason (controlled).

reasonsreadonly string[]–

Shown after a thumbs down, one to pick: "Not accurate", "Too long".

renderRenderProp<FeedbackBarState>–

Must render a <div>.

valueFeedbackValue
"up""down"null
–

The vote (controlled).

  • Also takes every attribute of <div> except children, defaultValue, onChange. (Omit<ComponentPropsWithRef<"div">, "defaultValue" | "onChange" | "children">)

render takes an element, or, in client code, a function of the props and this state (FeedbackBarState):

NameTypeDefaultDescription
valuerequiredFeedbackValue
"up""down"null
–

Other exports

FeedbackBarLabels type

import type { FeedbackBarLabels } from '@nizivo/react/unstable/feedback-bar'

FeedbackBar's own strings (§16.4): serialisable, English defaults.

NameTypeDefaultDescription
downrequiredstring'Bad answer'

The thumbs down's name.

promptrequiredstring'Was this helpful?'
reasonsrequiredstring'What went wrong'

The reasons' group name.

thanksDownrequiredstring'Thanks. What went wrong?'

After a thumbs down.

thanksUprequiredstring'Thanks — glad it helped.'

After a thumbs up.

uprequiredstring'Good answer'

The thumbs up's name.

FeedbackBarProps type

import type { FeedbackBarProps } from '@nizivo/react/unstable/feedback-bar'

The props of FeedbackBar, listed above.

FeedbackBarState type

import type { FeedbackBarState } from '@nizivo/react/unstable/feedback-bar'

The render state of FeedbackBar, listed above.

FeedbackValue type

import type { FeedbackValue } from '@nizivo/react/unstable/feedback-bar'

A vote, or none.

type FeedbackValue = "up" | "down" | null

Data attributes and slots

Style parts by class (.nz-<slot>) and state by data attribute. Attribute meanings come from contracts/vocabulary.json.

SlotRendered byData attributes
feedback-bar
.nz-feedback-bar
FeedbackBar
root (takes render)
none
feedback-bar-prompt
.nz-feedback-bar-prompt
FeedbackBar
inner element (CSS only)
none
feedback-bar-reason
.nz-feedback-bar-reason
FeedbackBar
inner element (CSS only); interactive, focus: nested-input
none
feedback-bar-vote
.nz-feedback-bar-vote
FeedbackBar
inner element (CSS only); interactive, focus: self
none

CSS hooks

Set a hook on the component's class or any ancestor to restyle it without specificity games; leave it unset for the default shown.

This stylesheet reads no public hook.

Layers: nz.components. Classes: .nz-feedback-bar, .nz-feedback-bar-prompt, .nz-feedback-bar-reason, .nz-feedback-bar-row, .nz-feedback-bar-vote, .nz-feedback-bar-votes.

Tokens this stylesheet reads (8)

--nz-font-body-s, --nz-radius-full, --nz-space-0-5, --nz-space-1, --nz-space-2, --nz-space-3, --nz-space-8, --nz-text-secondary

Accessibility

These parts are interactive. Each gets the focus outline and touch-action rule from @nizivo/react/css/base.css (the nz.base layer), so the floor survives a restyle:

  • feedback-bar-reason: draws the outline when the hidden input inside it has keyboard focus.
  • feedback-bar-vote: draws the focus outline itself on keyboard focus.

Keyboard

To be written.

On this page