import { LikertChart } from "semiotic"
Visualize Likert scale survey data as diverging bar charts (horizontal) or stacked 100% bar charts (vertical). Supports raw integer scores, pre-aggregated counts, and any scale size (3-point to 7-point and beyond).
Quick Start — Diverging (Horizontal)
The default horizontal orientation creates a diverging bar chart. "Strongly Disagree" and "Disagree" extend left, "Agree" and "Strongly Agree" extend right, and "Neutral" is centered on the axis — split equally across both sides. Data is raw integer scores (1–5) that the chart aggregates automatically.
JSX
import { LikertChart } from "semiotic" const levels = [ "Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree" ] // Raw responses — each row is one respondent's score (1–5) const data = [ { question: "Product quality", score: 5 }, { question: "Product quality", score: 4 }, { question: "Customer support", score: 2 }, // ... ] // Diverging palette: red → neutral → blue const divergingColors = ["#da1e28", "#ff8389", "#a8a8a8", "#4589ff", "#0043ce"] <LikertChart data={data} categoryAccessor="question" valueAccessor="score" // Integer score → mapped to levels by index levels={levels} orientation="horizontal" // Diverging bar chart (default) colorScheme={divergingColors} title="Customer Satisfaction Survey" showLegend legendPosition="bottom" tooltip />
Stacked 100% (Vertical)
Set orientation="vertical" for a normalized stacked bar chart where each bar totals 100%. Useful when comparing the proportion of each level across questions without directional emphasis.
JSX
<LikertChart data={data} categoryAccessor="question" valueAccessor="score" levels={levels} orientation="vertical" // Stacked 100% bar chart colorScheme={divergingColors} title="Customer Satisfaction (Stacked)" showLegend legendPosition="bottom" />
Scale Variants
Convention: The levels array defines the semantic order from most negative to most positive. The diverging layout assigns polarity by position — the first half is "negative" (extends left), the second half is "positive" (extends right), and the center entry (if odd) is "neutral" (centered on the axis). If your data doesn't follow this low-to-high ordering convention, the chart will misrepresent which responses are positive vs. negative.
Raw responses (integer scores)
Each row is one respondent's answer. Set valueAccessorto the score field. Scores are 1-based — score 1 maps tolevels[0], score 2 to levels[1], etc. The chart aggregates counts per question per level automatically.
JSX
// Raw responses — the chart aggregates internally const data = [ { question: "Q1", score: 4 }, // score 4 → levels[3] = "Agree" { question: "Q1", score: 5 }, // score 5 → levels[4] = "Strongly Agree" { question: "Q2", score: 2 }, // score 2 → levels[1] = "Disagree" ] <LikertChart data={data} categoryAccessor="question" valueAccessor="score" levels={["Str. Disagree", "Disagree", "Neutral", "Agree", "Str. Agree"]} />
Pre-aggregated (question + level + count)
Each row is a (question, level, count) triple. SetlevelAccessor and countAccessor. Eachlevel value must match an entry in thelevels array.
JSX
const data = [ { question: "Q1", level: "Strongly Agree", count: 45 }, { question: "Q1", level: "Agree", count: 30 }, { question: "Q1", level: "Neutral", count: 10 }, { question: "Q1", level: "Disagree", count: 12 }, { question: "Q1", level: "Strongly Disagree", count: 3 }, ] <LikertChart data={data} categoryAccessor="question" levelAccessor="level" countAccessor="count" levels={["Str. Disagree", "Disagree", "Neutral", "Agree", "Str. Agree"]} />
Props
| Prop | Type | Required | Default | Description |
|---|
data | object[] | — | — | Array of raw response or pre-aggregated data objects. Omit when using push API for streaming. |
categoryAccessor | string | function | — | "question" | Question/item field. The ordinal axis. |
valueAccessor | string | function | — | "score" | Integer score field (raw response mode). Scores are 1-based: 1 → levels[0], 2 → levels[1], etc. |
levelAccessor | string | function | — | — | Level name field (pre-aggregated mode). Each value must match an entry in levels. |
countAccessor | string | function | — | "count" | Count/frequency field (pre-aggregated mode). |
levels | string[] | — | ["Very Low", "Low", "Neutral", "High", "Very High"] | Ordered response labels, most negative to most positive. Odd count → center is neutral. Even → clean negative/positive split. |
orientation | "horizontal" | "vertical" | — | "horizontal" | Horizontal: diverging bar chart centered at 0%. Vertical: stacked 100% bar chart. |
colorScheme | string[] | — | auto diverging | One color per level. Should match levels.length. Defaults to a Carbon-inspired red → gray → blue diverging palette. |
barPadding | number | — | 20 | Padding between category bars in pixels. |
Plus all common HOC props:title, width, height,margin, enableHover, tooltip,showLegend, legendPosition,legendInteraction, showGrid,annotations, frameProps,selection, linkedHover,onObservation, responsiveWidth.