React-Likert
React components for rendering Likert-like visualizations within a table.
View the demo for a few examples.
Why?
While various chart options exist for this kind of survey question, none of them can easily integrate into a true table while offering key features like diverging bars and good defaults. Typically, our survey results will be presented most cleanly in a table format within which the Likert visualization is only one part alongside various other statistics. This tool makes that possible without compromising or splitting between a table and chart.
What?
I've taken a somewhat unorthodox approach to rendering: using the included <TableWrapper/>
, you replace the cells in the desired column with the <CellRenderer/>
it provides. This renderer creates normal table cells (with aria attributes to indicate the value of the cell for accessiblity), then draws a single svg over that entire table region and animates it with D3. This offers the benefits of a single chart alongside the stability and accessibility of a true table.
How?
A simple syntax example:
const scale = 'Strongly Disagree' 'Disagree' 'Undecided' 'Agree' 'Strongly Agree' const data = prompt: 'Likerts are useful' responded: 35 'Strongly Disagree': 03 'Disagree': 025 'Undecided': 0 'Agree': 022 'Strongly Agree': 023 prompt: 'D3 is still a viable choice in React projects' responded: 38 'Strongly Disagree': 01 'Disagree': 022 'Undecided': 005 'Agree': 045 'Strongly Agree': 018 // etc const DivergingLikertExample = <div> <TableWrapper scale=scale> <table style= width: '100%' > <thead> <tr> <th style=textAlign: 'left'>prompt </th> <th style=textAlign: 'left' width: '3em'>n </th> <td style=width: '50%'> </td> </tr> </thead> <tbody> data </tbody> </table> </TableWrapper> </div>
Components
<TableWrapper>
Required as parent of the <table>
you will draw; requires a scale
prop at minium (with a flat list of Likert choices in the order you wish them displayed), but will also accept options
object (see section below). Provides a CellRenderer
to its child (in the render-prop or function-as-child pattern), which will be bound to this table context so that rendering of each Likert can be coordinated as a single visualization.
<TableWrapper = => <table> ... // see below for usage of CellRenderer </table> </TableWrapper>
Note that the scale
is assumed to be a symmetrical Likert (unless using continuous: true
option; see below), so that the positive / negative values divide either evenly or with a "neutral" middle term when the count is odd.
Example scales:
[ 'Strongly Disagree', 'Disagree', 'Undecided', 'Agree', 'Strongly Agree' ]
[ 'Very Unlikely', 'Unlikely', 'Likely', 'Very Likely' ]
<CellRenderer>
This component is not a direct export of the library, and is provided only by the TableWrapper
invoked as shown above. Use it to render the entire table cell where you want the Likert, passing a value
object with keys matching the scale you passed to the TableWrapper
, as floats adding up to 1.
<table> <thead> <tr> <th>prompt </th> <th>result </th> </tr> </thead> <tbody> <tr> <td>Is this library useful?</td> <CellRenderer = /> </tr> <tr> <td>Would you recommend it?</td> <CellRenderer = /> </tr> </tbody> </table>}
<LikertLegend>
Draws a simple legend for your Likert, for use outside of the table. Requires the scale
, optionally accepts inline
(Boolean; if true, renders as spans inline), a size
in pixels for the squares, and any additional styles to apply.
<LikertLegend = = = =/>
Options
The options
object should be passed as a prop to the <TableWrapper>
, and offers a number of customizations (see examples and their source code for context).
Key | Type | Description |
---|---|---|
diverging |
Boolean |
Whether to draw as diverging bars; if false , renders as normal stacked. |
usePatterns |
Boolean |
By default, patterns are applied to the segments; pass false to disable. |
continuous |
Boolean |
If set to true , a continuous scale will be drawn (no pos/neg polarity). |
colors |
Array |
Custom colors; the order depends on the type of chart, see below. |
The colors
take one of two forms. For the default diverging type of chart, you must pass three items with two nested arrays:
[ neutral, [left-main, left-highlight], [right-main, right-highlight]]
e.g.
['#888', ['#800e84', '#ad72b5'], ['#006f30','#48bf6f']]
For a "continuous" chart, where the scale does not have a left / right polarity and simply increases, you only pass two values:
[ left, right ]
e.g.
['#eeeeee', '#995555']
Once again, check the examples for usage in context.