0
# Visualization Components
1
2
Specialized components for displaying progress, rankings, distributions, and status beyond traditional charts.
3
4
## Visualization Selection
5
6
| Component | Use Case | Key Props |
7
|-----------|----------|-----------|
8
| BarList | Rankings, top N comparisons | `data`, `sortOrder`, `valueFormatter`, `showAnimation` |
9
| ProgressBar | Linear progress (0-100) | `value`, `color`, `showAnimation`, `label` |
10
| ProgressCircle | Circular progress | `value`, `size`, `children` (center content), `color` |
11
| CategoryBar | 100% stacked distribution | `values`, `colors`, `markerValue`, `showLabels` |
12
| DeltaBar | Change from baseline | `value`, `isIncreasePositive` |
13
| MarkerBar | Progress vs target | `value`, `minValue`, `maxValue` |
14
| Tracker | Timeline status blocks | `data: {color, tooltip}[]` |
15
16
## BarList
17
18
Horizontal bars for rankings and comparisons. Auto-sorts by default.
19
20
```typescript { .api }
21
interface BarListProps<T = any> {
22
data: Array<T & {
23
value: number; // Required
24
name: React.ReactNode; // Required
25
key?: string;
26
icon?: React.JSXElementConstructor<any>;
27
href?: string;
28
target?: string;
29
color?: Color; // Per-item color override
30
}>;
31
valueFormatter?: (value: number) => string;
32
color?: Color; // Default color for all items
33
showAnimation?: boolean;
34
onValueChange?: (payload: any) => void;
35
sortOrder?: "ascending" | "descending" | "none"; // default: "descending"
36
}
37
```
38
39
**Examples:**
40
41
```typescript
42
import { BarList, Card, Title } from '@tremor/react';
43
44
const data = [
45
{ name: 'New York', value: 2890 },
46
{ name: 'London', value: 2756 },
47
{ name: 'Tokyo', value: 1322 },
48
];
49
50
<Card>
51
<Title>Sales by City</Title>
52
<BarList
53
data={data}
54
valueFormatter={(v) => `$${v.toLocaleString()}`}
55
className="mt-4"
56
/>
57
</Card>
58
59
// Custom colors per item
60
const coloredData = [
61
{ name: 'Excellent', value: 45, color: 'emerald' },
62
{ name: 'Good', value: 30, color: 'blue' },
63
{ name: 'Fair', value: 15, color: 'amber' },
64
];
65
<BarList data={coloredData} sortOrder="none" showAnimation={true} />
66
```
67
68
## ProgressBar
69
70
Linear progress indicator (0-100).
71
72
```typescript { .api }
73
interface ProgressBarProps {
74
value: number; // 0-100 (required)
75
label?: string;
76
tooltip?: string;
77
showAnimation?: boolean;
78
color?: Color;
79
}
80
```
81
82
**Examples:**
83
84
```typescript
85
import { ProgressBar, Card, Text, Flex } from '@tremor/react';
86
87
<ProgressBar value={75} color="blue" />
88
89
// With label
90
<div>
91
<Flex justifyContent="between" className="mb-2">
92
<Text>Project Completion</Text>
93
<Text>75%</Text>
94
</Flex>
95
<ProgressBar value={75} color="blue" />
96
</div>
97
98
// Multiple progress indicators
99
<Card className="space-y-4">
100
<div><Text>Development</Text><ProgressBar value={80} color="blue" /></div>
101
<div><Text>Testing</Text><ProgressBar value={60} color="violet" /></div>
102
<div><Text>Documentation</Text><ProgressBar value={40} color="amber" /></div>
103
</Card>
104
```
105
106
## ProgressCircle
107
108
Circular progress with optional center content.
109
110
```typescript { .api }
111
interface ProgressCircleProps {
112
value?: number; // 0-100
113
size?: Size; // "xs" | "sm" | "md" | "lg" | "xl"
114
color?: Color;
115
showAnimation?: boolean;
116
tooltip?: string;
117
radius?: number; // Custom radius (overrides size)
118
strokeWidth?: number; // Custom stroke width (overrides size)
119
children?: React.ReactNode; // Center content
120
}
121
```
122
123
**Examples:**
124
125
```typescript
126
import { ProgressCircle, Card, Text, Grid } from '@tremor/react';
127
128
<ProgressCircle value={75} />
129
130
// With center content
131
<ProgressCircle value={65} color="blue">
132
<span className="text-2xl font-bold">65%</span>
133
</ProgressCircle>
134
135
// Different sizes
136
<Grid numItems={3}>
137
<ProgressCircle value={85} color="emerald" size="lg">
138
<span className="text-xl font-bold">85%</span>
139
</ProgressCircle>
140
<Text className="mt-2">Complete</Text>
141
</Grid>
142
```
143
144
## CategoryBar
145
146
Segmented bar showing 100% stacked distribution.
147
148
```typescript { .api }
149
interface CategoryBarProps {
150
values: number[]; // Must sum to 100
151
colors?: Color[];
152
markerValue?: number; // Optional marker position (0-100)
153
showLabels?: boolean;
154
tooltip?: string;
155
showAnimation?: boolean;
156
}
157
```
158
159
**Examples:**
160
161
```typescript
162
import { CategoryBar, Card, Title, Text, Flex } from '@tremor/react';
163
164
<Card>
165
<Title>Browser Usage</Title>
166
<CategoryBar values={[45, 30, 15, 10]} colors={['blue', 'cyan', 'orange', 'violet']} />
167
<Flex justifyContent="between" className="mt-2">
168
<Text>Chrome: 45%</Text>
169
<Text>Safari: 30%</Text>
170
<Text>Firefox: 15%</Text>
171
<Text>Other: 10%</Text>
172
</Flex>
173
</Card>
174
175
// With marker (target line)
176
<CategoryBar
177
values={[65, 20, 15]}
178
colors={['blue', 'violet', 'gray']}
179
markerValue={70}
180
/>
181
```
182
183
## DeltaBar
184
185
Visualize positive/negative change from baseline.
186
187
```typescript { .api }
188
interface DeltaBarProps {
189
value: number; // -100 to 100
190
isIncreasePositive?: boolean; // default: true
191
tooltip?: string;
192
showAnimation?: boolean;
193
}
194
```
195
196
**Examples:**
197
198
```typescript
199
import { DeltaBar, Card, Text, Flex } from '@tremor/react';
200
201
// Positive change
202
<div>
203
<Flex justifyContent="between">
204
<Text>Revenue vs. Target</Text>
205
<Text>+15%</Text>
206
</Flex>
207
<DeltaBar value={15} />
208
</div>
209
210
// Negative change (decrease is good, e.g., costs)
211
<DeltaBar value={-12} isIncreasePositive={false} />
212
```
213
214
## MarkerBar
215
216
Bar with marker for targets/thresholds.
217
218
```typescript { .api }
219
interface MarkerBarProps {
220
value: number;
221
minValue?: number; // default: 0
222
maxValue?: number; // default: 100
223
markerTooltip?: string;
224
rangeTooltip?: string;
225
showAnimation?: boolean;
226
color?: Color;
227
}
228
```
229
230
**Examples:**
231
232
```typescript
233
import { MarkerBar, Card, Text, Flex } from '@tremor/react';
234
235
<Card>
236
<Flex justifyContent="between">
237
<Text>Revenue Progress</Text>
238
<Text>$75K / $100K</Text>
239
</Flex>
240
<MarkerBar
241
value={75}
242
markerTooltip="Target: $100K"
243
rangeTooltip="Current: $75K"
244
color="blue"
245
/>
246
</Card>
247
```
248
249
## Tracker
250
251
Timeline visualization with colored status blocks.
252
253
```typescript { .api }
254
interface TrackerProps {
255
data: Array<{
256
key?: string | number;
257
color?: Color | string;
258
tooltip?: string;
259
}>;
260
}
261
```
262
263
**Examples:**
264
265
```typescript
266
import { Tracker, Card, Title } from '@tremor/react';
267
268
// Deployment status
269
const deploymentData = [
270
{ color: 'emerald', tooltip: 'Jan: Successful' },
271
{ color: 'emerald', tooltip: 'Feb: Successful' },
272
{ color: 'red', tooltip: 'Mar: Failed' },
273
{ color: 'emerald', tooltip: 'Apr: Successful' },
274
];
275
276
<Card>
277
<Title>Deployment History</Title>
278
<Tracker data={deploymentData} className="mt-4" />
279
</Card>
280
281
// 30-day uptime
282
const uptimeData = Array.from({ length: 30 }, (_, i) => ({
283
color: Math.random() > 0.1 ? 'emerald' : 'red',
284
tooltip: `Day ${i + 1}: ${Math.random() > 0.1 ? 'Online' : 'Offline'}`,
285
}));
286
287
<Card>
288
<Title>30-Day Uptime</Title>
289
<Tracker data={uptimeData} className="mt-4" />
290
</Card>
291
```
292
293
## Visualization Dashboard Pattern
294
295
```typescript
296
import {
297
Grid,
298
Card,
299
Title,
300
Text,
301
Flex,
302
BarList,
303
ProgressBar,
304
CategoryBar,
305
Tracker,
306
} from '@tremor/react';
307
308
function VisualizationDashboard() {
309
return (
310
<Grid numItems={1} numItemsLg={2} className="gap-6">
311
{/* Rankings */}
312
<Card>
313
<Title>Quarterly Sales</Title>
314
<BarList
315
data={[
316
{ name: 'Q1', value: 8500 },
317
{ name: 'Q2', value: 9200 },
318
{ name: 'Q3', value: 10100 },
319
]}
320
valueFormatter={(v) => `$${(v / 1000).toFixed(1)}K`}
321
/>
322
</Card>
323
324
{/* Progress */}
325
<Card>
326
<Title>Goal Progress</Title>
327
<div className="space-y-4">
328
<div>
329
<Flex justifyContent="between">
330
<Text>Annual Target</Text>
331
<Text>87%</Text>
332
</Flex>
333
<ProgressBar value={87} color="blue" />
334
</div>
335
</div>
336
</Card>
337
338
{/* Distribution */}
339
<Card>
340
<Title>Revenue by Category</Title>
341
<CategoryBar
342
values={[40, 30, 20, 10]}
343
colors={['blue', 'violet', 'cyan', 'gray']}
344
/>
345
</Card>
346
347
{/* Status */}
348
<Card>
349
<Title>30-Day Uptime</Title>
350
<Tracker data={statusData} />
351
</Card>
352
</Grid>
353
);
354
}
355
```
356
357
## Common Mistakes
358
359
- ❌ Using ProgressBar/ProgressCircle with values outside 0-100 range
360
- ❌ CategoryBar values not summing to 100
361
- ❌ Not providing `name` and `value` for BarList items
362
- ❌ Forgetting `tooltip` for Tracker blocks (improves UX)
363
- ❌ Not using `valueFormatter` for BarList (inconsistent formatting)
364
365
## See Also
366
367
- [Types Reference](./types.md) for Color, Size, ValueFormatter types
368
- [Common Props](./common-props.md) for ValueFormatter examples
369