Sentiment Analysis Widget
Pro5 variants: summary (semicircle gauge + breakdown + KPIs), topics (stacked sentiment bars), timeline (SVG area + volume), feed (filter pills + source badges + score bars) and aspects (sentiment per subject — what is loved and what is hated).
import { SvSentimentAnalysisWidgetComponent } from '@styloviz-pro/sentiment-analysis-widget';Demo & usage
Basic usage
ProUsage example — open the gallery for the full interactive demo.
An interactive demo for this component lives in the gallery.
Open live demoMore examples
Topics & timeline
ProWhen to use
- Visualizing sentiment from reviews, support tickets, social or survey text.
- You want summary gauges, per-topic breakdowns, trends and a source feed.
- For raw numeric metrics, the Charts components are more general.
Async states
- loading
- error
- retry
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| loading | boolean | false | True while the data is being fetched. |
| error | SvDataError | string | null | null | Load failure. Use `toSvDataError()` from `@styloviz/core` to normalize an `HttpErrorResponse`. |
| variant | SentimentVariant | 'summary' | View: summary, topics, timeline, source feed or aspects. |
| overallScore | SentimentScore | null | null | Headline score and its breakdown. |
| topics | readonly TopicSentiment[] | [] | Per-topic sentiment. |
| feedItems | readonly FeedItem[] | [] | Individual pieces of feedback. |
| aspectMentions | readonly SvAspectMention[] | [] | The (aspect, opinion) pairs the `aspects` variant groups. One entry per opinion, not per document: a review saying "delivery was quick but the app crashed" is two mentions sharing an `itemId`, and keeping them separate is the whole point of the variant. |
| timeline | readonly TimelinePoint[] | null | null | The series behind the timeline. Shown exactly as given — the range picker reports the user's choice through `timeRangeChange` for you to refetch. `null` renders the empty state; it does not substitute sample data. |
| busy | boolean | false | Analysis is in flight. |
| classifier | SvSentimentClassifier | null | null | What produced these scores. A SENTIMENT NUMBER WITHOUT A CLASSIFIER IDENTITY CANNOT BE DEFENDED. "−0.42, declining" goes into a review and the first question is which model produced it and when; without an answer the figure is an opinion with a decimal point. Two figures from either side of a model swap are not comparable at all — the change measures the classifier, not the customers. |
Outputs
| Event | Payload type | Description |
|---|---|---|
| retry | void | The host should re-run the failed load. |
| timeRangeChange | TimeRange | Emitted when the user changes the analysis time range. |
| feedFilterChange | SentimentLabel | 'all' | Emitted with the sentiment filter the user picks in the feed. |
| feedSourceChange | FeedSource | 'all' | Emitted with the source filter the user picks in the feed. |
Wire it to your API
This component is headless about transport: it renders what you give it and reports what the user asks for. Nothing below requires @styloviz/data — drive it from whatever you already use.
Template
ProBound to the names this component actually exposes.
Host class
ProDrive the three async inputs from your own fetch.
- This component does not emit a query, so it renders what you give it. Fetch on your own trigger and bind `topics`, `loading` and `error`.
- Normalize failures with `toSvDataError()` from `@styloviz/core`. It derives `retryable` from the status, so a 404 does not get a "Try again" button that can only fail again.
Full walkthrough: Connecting to a backend.
Customization & theming
- Every content set is an input defaulting to the bundled sample — `overallScore`, `topics`, `feedItems` and `timeline` — so the widget demonstrates itself out of the box and takes your analysis when you have it.
- Leave `timeline` null and the bundled series follow the range picker; supply one and it is shown as given, with `timeRangeChange` reporting the choice for you to refetch.
- Summary, topics, timeline and feed views.
- Configurable sentiment thresholds.
- Source badges and score bars.
- Emits `timeRangeChange` when the analysis range changes.
- `[classifier]` — model, version, languages, when it was last calibrated and its agreement with human labels — renders above every variant. A sentiment number without a classifier identity cannot be defended when somebody disputes it, and two figures from either side of a model swap are **not comparable at all**: the change measures the classifier, not the customers. With no classifier the widget says so — in every variant that has figures on screen, not only the summary — rather than rendering figures that cannot answer for themselves. Undeclared fields are named as gaps (‘Not recorded: Version, Calibrated’), and a dev build warns once when scores render without a model and its languages.
- Calibration is not training. A model can be years old and calibrated last week, or new and never checked against this dataset — and the second is the one that quietly reports everything as mildly positive. An out-of-range `agreement` is **dropped rather than clamped**: 85 is a host that meant 0.85, and rendering '8500%' as if it were meant is worse than saying nothing.
- `languages` is the field every dashboard omits, and its absence is a silent failure that looks like data: an English-only classifier scores German reviews as **neutral** because it cannot read them, and neutral is indistinguishable from 'no strong feelings' on every chart here. `svClassifierReads()` matches on the primary subtag, so `de` covers `de-AT`, and an undeclared list means unknown rather than none. Set `FeedItem.language` and the feed marks each item the classifier cannot read as unclassified, not neutral.
Best practices
- Do: Render scores and breakdowns as text, not color alone, for accessibility.
- Do: Use the timeline variant to show how sentiment shifts after a change.
- Tip: Let users filter the feed by sentiment/source to investigate drivers.
Accessibility
- Scores and breakdowns rendered as text.
- Time-range and sentiment filters report aria-pressed; show-more toggles expose aria-expanded.
- Filters are labelled, keyboard-operable controls.
Feedback on Sentiment Analysis Widget
Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.