@cfasim-ui/charts 0.7.8 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/BarChart/BarChart.d.ts +9 -26
  2. package/dist/ChartMenu/ChartMenu.d.ts +3 -2
  3. package/dist/ChartTooltip/ChartTooltip.d.ts +9 -12
  4. package/dist/ChoroplethMap/ChoroplethMap.d.ts +42 -190
  5. package/dist/ChoroplethMap/ChoroplethTooltip.d.ts +20 -27
  6. package/dist/ChoroplethMap/canvasLayer.d.ts +23 -6
  7. package/dist/ChoroplethMap/cityLayout.d.ts +3 -2
  8. package/dist/ChoroplethMap/mixedGeo.d.ts +74 -0
  9. package/dist/ChoroplethMap/mixedGeo.test.d.ts +1 -0
  10. package/dist/DataTable/DataTable.d.ts +3 -2
  11. package/dist/LineChart/LineChart.d.ts +9 -26
  12. package/dist/_shared/ChartAnnotations.d.ts +3 -2
  13. package/dist/_shared/ChartZoomControls.d.ts +3 -2
  14. package/dist/_shared/index.d.ts +2 -1
  15. package/dist/_shared/mapTheme.d.ts +159 -0
  16. package/dist/_shared/mapTheme.test.d.ts +1 -0
  17. package/dist/index.css +1 -1
  18. package/dist/index.d.ts +1 -0
  19. package/dist/index.js +1821 -1462
  20. package/docs/BarChart.md +776 -0
  21. package/docs/ChoroplethMap.md +1394 -0
  22. package/docs/DataTable.md +386 -0
  23. package/docs/LineChart.md +1267 -0
  24. package/docs/index.json +56 -0
  25. package/package.json +25 -21
  26. package/src/BarChart/BarChart.md +743 -0
  27. package/src/BarChart/BarChart.vue +1901 -0
  28. package/src/ChartMenu/ChartMenu.vue +220 -0
  29. package/src/ChartMenu/download.ts +120 -0
  30. package/src/ChartTooltip/ChartTooltip.vue +97 -0
  31. package/src/ChoroplethMap/ChoroplethMap.md +1354 -0
  32. package/src/ChoroplethMap/ChoroplethMap.vue +3778 -0
  33. package/src/ChoroplethMap/ChoroplethTooltip.vue +103 -0
  34. package/src/ChoroplethMap/canvasLayer.ts +373 -0
  35. package/src/ChoroplethMap/cityLayout.ts +262 -0
  36. package/src/ChoroplethMap/hsaMapping.ts +4116 -0
  37. package/src/ChoroplethMap/mixedGeo.ts +201 -0
  38. package/src/DataTable/DataTable.md +372 -0
  39. package/src/DataTable/DataTable.vue +406 -0
  40. package/src/LineChart/LineChart.md +1225 -0
  41. package/src/LineChart/LineChart.vue +1555 -0
  42. package/src/_shared/ChartAnnotations.vue +420 -0
  43. package/src/_shared/ChartZoomControls.vue +138 -0
  44. package/src/_shared/annotations.ts +106 -0
  45. package/src/_shared/axes.ts +69 -0
  46. package/src/_shared/chartProps.ts +201 -0
  47. package/src/_shared/computeTicks.ts +42 -0
  48. package/src/_shared/contrast.ts +100 -0
  49. package/src/_shared/dateAxis.ts +501 -0
  50. package/src/_shared/index.ts +78 -0
  51. package/src/_shared/mapTheme.ts +551 -0
  52. package/src/_shared/scale.ts +86 -0
  53. package/src/_shared/seriesCsv.ts +68 -0
  54. package/src/_shared/touch.ts +8 -0
  55. package/src/_shared/useChartFoundation.ts +175 -0
  56. package/src/_shared/useChartFullscreen.ts +254 -0
  57. package/src/_shared/useChartMenu.ts +111 -0
  58. package/src/_shared/useChartPadding.ts +235 -0
  59. package/src/_shared/useChartSize.ts +58 -0
  60. package/src/_shared/useChartTooltip.ts +205 -0
  61. package/src/env.d.ts +4 -0
  62. package/src/hsa-mapping.ts +1 -0
  63. package/src/index.ts +41 -0
  64. package/src/tooltip-position.ts +55 -0
  65. package/src/us-cities/data.ts +1371 -0
  66. package/src/us-cities/index.ts +122 -0
  67. package/src/us-cities.ts +7 -0
@@ -0,0 +1,1225 @@
1
+ ---
2
+ keywords: [line, chart, time-series, series, axis, area, confidence band, svg]
3
+ ---
4
+
5
+ # LineChart
6
+
7
+ A responsive SVG line chart with support for multiple series, axis labels, and custom styling.
8
+
9
+ ## Examples
10
+
11
+ ### Single series
12
+
13
+ <ComponentDemo>
14
+ <LineChart :data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]" :height="200" x-label="Days" y-label="Cases" tooltip-trigger="hover" />
15
+
16
+ <template #code>
17
+
18
+ ```vue
19
+ <LineChart
20
+ :data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
21
+ :height="200"
22
+ x-label="Days"
23
+ y-label="Cases"
24
+ tooltip-trigger="hover"
25
+ />
26
+ ```
27
+
28
+ </template>
29
+ </ComponentDemo>
30
+
31
+ ### x/y
32
+
33
+ Pass paired `x` and `y` arrays to plot points at specific x positions.
34
+ `y` is equivalent to `data` (both names are accepted), and they both
35
+ take typed arrays. For multi-series
36
+ charts, set `x` and `y` (or `data`) on each `Series`.
37
+
38
+ <ComponentDemo>
39
+ <LineChart
40
+ :x="[0, 1, 2, 5, 10, 20, 50]"
41
+ :y="[0, 2, 5, 12, 22, 30, 38]"
42
+ :height="200"
43
+ x-label="Days (log-ish)"
44
+ y-label="Cases"
45
+ tooltip-trigger="hover"
46
+ />
47
+
48
+ <template #code>
49
+
50
+ ```vue
51
+ <LineChart
52
+ :x="[0, 1, 2, 5, 10, 20, 50]"
53
+ :y="[0, 2, 5, 12, 22, 30, 38]"
54
+ :height="200"
55
+ x-label="Days"
56
+ y-label="Cases"
57
+ tooltip-trigger="hover"
58
+ />
59
+ ```
60
+
61
+ </template>
62
+ </ComponentDemo>
63
+
64
+ When `x` is omitted, `y`/`data` values are plotted at indices 0, 1, 2, etc.
65
+
66
+ ### Dates
67
+
68
+ Pass ISO date strings (`YYYY-MM-DD`) or `Date` objects as `x` and the
69
+ chart auto-detects a date axis: ticks anchor to year / month / week /
70
+ day / hour boundaries depending on the visible range, and labels
71
+ format themselves accordingly. Numeric `x` arrays keep their existing
72
+ behavior — auto-detection is content-driven and never promotes plain
73
+ numbers.
74
+
75
+ <ComponentDemo>
76
+ <LineChart
77
+ :x="['2026-01-05', '2026-01-12', '2026-01-19', '2026-01-26', '2026-02-02', '2026-02-09', '2026-02-16', '2026-02-23', '2026-03-02', '2026-03-09']"
78
+ :y="[4, 9, 18, 32, 41, 38, 27, 18, 11, 6]"
79
+ :height="220"
80
+ y-label="% ED visits"
81
+ />
82
+
83
+ <template #code>
84
+
85
+ ```vue
86
+ <LineChart
87
+ :x="[
88
+ '2026-01-05',
89
+ '2026-01-12',
90
+ '2026-01-19',
91
+ '2026-01-26',
92
+ '2026-02-02',
93
+ '2026-02-09',
94
+ '2026-02-16',
95
+ '2026-02-23',
96
+ '2026-03-02',
97
+ '2026-03-09',
98
+ ]"
99
+ :y="[4, 9, 18, 32, 41, 38, 27, 18, 11, 6]"
100
+ :height="220"
101
+ y-label="% ED visits"
102
+ />
103
+ ```
104
+
105
+ </template>
106
+ </ComponentDemo>
107
+
108
+ Override the format via `x-tick-format`. Presets: `"iso"`,
109
+ `"iso-datetime"`, `"year"`, `"month-year"`, `"month-day"`, `"day"`,
110
+ `"time"`, `"datetime"`, `"medium"`. You can also pass an
111
+ `Intl.DateTimeFormatOptions` literal, or a function `(ms, unit?) =>
112
+ string` for full control.
113
+
114
+ <ComponentDemo>
115
+ <LineChart
116
+ :x="['2026-01-05', '2026-01-12', '2026-01-19', '2026-01-26', '2026-02-02']"
117
+ :y="[4, 9, 18, 32, 41]"
118
+ x-tick-format="iso"
119
+ :height="220"
120
+ y-label="% ED visits"
121
+ />
122
+
123
+ <template #code>
124
+
125
+ ```vue
126
+ <LineChart
127
+ :x="['2026-01-05', '2026-01-12', '2026-01-19', '2026-01-26', '2026-02-02']"
128
+ :y="[4, 9, 18, 32, 41]"
129
+ x-tick-format="iso"
130
+ :height="220"
131
+ y-label="% ED visits"
132
+ />
133
+ ```
134
+
135
+ </template>
136
+ </ComponentDemo>
137
+
138
+ By default the chart parses bare `YYYY-MM-DD` (and offset-less
139
+ `YYYY-MM-DDTHH:mm:ss`) as UTC and renders tick labels in UTC. Set
140
+ `timezone="local"` to interpret offset-less strings in the browser's
141
+ timezone instead. Strings that include an explicit offset (`Z` or
142
+ `+05:00`) are always parsed exactly as written.
143
+
144
+ > **Annotations on a date axis.** `ChartAnnotation.x` is always in the
145
+ > chart's resolved coordinate space — that's **epoch-ms** when the axis
146
+ > is in date mode. Pass `Date.UTC(2026, 0, 15)`, `new Date("2026-01-15").getTime()`,
147
+ > or `Date.parse("2026-01-15T00:00:00Z")`. Passing a small integer like
148
+ > `0` will place the annotation at 1970-01-01 (off-screen).
149
+ >
150
+ > **`xLabels` on a date axis.** When both `x: [...date strings]` and
151
+ > `xLabels` are supplied, the date axis wins — `xLabels` is ignored.
152
+ > Date strings carry their own labeling.
153
+
154
+ ### Title
155
+
156
+ The `title` prop accepts `\n` to break across lines. Use `titleStyle`
157
+ to override `fontSize`, `lineHeight`, `color`, `fontWeight`, and
158
+ `align` (`"left" | "center" | "right"`, default `"left"`). Top padding
159
+ grows automatically for additional lines.
160
+
161
+ <ComponentDemo>
162
+ <LineChart
163
+ :data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
164
+ :height="220"
165
+ :title="'Daily ED visits\nInfluenza-like illness, last 11 days'"
166
+ :title-style="{ fontSize: 16, lineHeight: 20, color: '#0057b7' }"
167
+ x-label="Days"
168
+ y-label="Cases"
169
+ />
170
+
171
+ <template #code>
172
+
173
+ ```vue
174
+ <LineChart
175
+ :data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
176
+ :height="220"
177
+ :title="'Daily ED visits\nInfluenza-like illness, last 11 days'"
178
+ :title-style="{ fontSize: 16, lineHeight: 20, color: '#0057b7' }"
179
+ x-label="Days"
180
+ y-label="Cases"
181
+ />
182
+ ```
183
+
184
+ </template>
185
+ </ComponentDemo>
186
+
187
+ ### Font sizes
188
+
189
+ Every text element on the chart has its own style prop and default size (in px). The text-styling props (`axisLabelStyle`, `tickLabelStyle`, `legendStyle`) take a `LabelStyle` — `{ fontSize?, color?, fontWeight? }` — and `titleStyle` adds `lineHeight` and `align`. Unset fields fall back to the defaults below.
190
+
191
+ | Chart part | Prop / field | Type | Default size |
192
+ | ------------------------------------------- | ------------------------------------ | ------------ | -----------: |
193
+ | Title | `titleStyle` | `TitleStyle` | 14 |
194
+ | Axis labels (`xLabel` / `yLabel`) | `axisLabelStyle` | `LabelStyle` | 13 |
195
+ | Axis tick labels (the numbers on each axis) | `tickLabelStyle` | `LabelStyle` | 10 |
196
+ | Inline legend | `legendStyle` | `LabelStyle` | 11 |
197
+ | Area section label | `areaSection.inlineLabelStyle` | `LabelStyle` | 11 |
198
+ | Area section description | `areaSection.inlineDescriptionStyle` | `LabelStyle` | 11 |
199
+ | Annotation text | `annotation.fontSize` | `number` | 13 |
200
+
201
+ These are single styles applied to both axes — there's no separate x vs y font size. The same props (except the LineChart-only area-section fields) exist on `BarChart`, since both compose `ChartCommonProps`.
202
+
203
+ <ComponentDemo>
204
+ <LineChart
205
+ :series="[
206
+ { data: [0, 12, 28, 45, 60, 55, 40, 25, 12], color: '#0057b7', legend: 'No interventions' },
207
+ { data: [0, 8, 18, 30, 40, 35, 25, 14, 6], color: '#ef4444', legend: 'Masking + distancing' },
208
+ ]"
209
+ :height="240"
210
+ title="Daily ED visits"
211
+ x-label="Days"
212
+ y-label="Cases"
213
+ :title-style="{ fontSize: 18 }"
214
+ :axis-label-style="{ fontSize: 15, fontWeight: 700 }"
215
+ :tick-label-style="{ fontSize: 13 }"
216
+ :legend-style="{ fontSize: 14 }"
217
+ />
218
+
219
+ <template #code>
220
+
221
+ ```vue
222
+ <LineChart
223
+ :series="[
224
+ {
225
+ data: [0, 12, 28, 45, 60, 55, 40, 25, 12],
226
+ color: '#0057b7',
227
+ legend: 'No interventions',
228
+ },
229
+ {
230
+ data: [0, 8, 18, 30, 40, 35, 25, 14, 6],
231
+ color: '#ef4444',
232
+ legend: 'Masking + distancing',
233
+ },
234
+ ]"
235
+ :height="240"
236
+ title="Daily ED visits"
237
+ x-label="Days"
238
+ y-label="Cases"
239
+ :title-style="{ fontSize: 18 }"
240
+ :axis-label-style="{ fontSize: 15, fontWeight: 700 }"
241
+ :tick-label-style="{ fontSize: 13 }"
242
+ :legend-style="{ fontSize: 14 }"
243
+ />
244
+ ```
245
+
246
+ </template>
247
+ </ComponentDemo>
248
+
249
+ ### Multiple series
250
+
251
+ <ComponentDemo>
252
+ <LineChart
253
+ :series="[
254
+ { data: [0, 10, 25, 45, 60, 55, 40, 20, 8], color: '#fb7e38', strokeWidth: 3 },
255
+ { x: [0, 1, 3, 4, 6, 7, 8], y: [0, 5, 20, 28, 18, 10, 4], color: '#0057b7', strokeWidth: 3 },
256
+ ]"
257
+ :height="200"
258
+ x-label="Weeks"
259
+ y-label="Incidence"
260
+ />
261
+
262
+ <template #code>
263
+
264
+ ```vue
265
+ <LineChart
266
+ :series="[
267
+ {
268
+ data: [0, 10, 25, 45, 60, 55, 40, 20, 8],
269
+ color: '#fb7e38',
270
+ strokeWidth: 3,
271
+ },
272
+ {
273
+ x: [0, 1, 3, 4, 6, 7, 8],
274
+ y: [0, 5, 20, 28, 18, 10, 4],
275
+ color: '#0057b7',
276
+ strokeWidth: 3,
277
+ },
278
+ ]"
279
+ :height="200"
280
+ x-label="Weeks"
281
+ y-label="Incidence"
282
+ />
283
+ ```
284
+
285
+ </template>
286
+ </ComponentDemo>
287
+
288
+ ### Legend
289
+
290
+ Set `legend` on a series to add an entry to the inline legend strip above the plot. When the items don't all fit on one row at the chart's current width, the legend wraps to additional rows and the plot area shrinks to keep the legend clear of the data. Use `showInLegend: false` to keep a series off the legend (e.g. when its `legend` string is reused as a CSV column header) and `showInTooltip: false` to omit it from the hover tooltip.
291
+
292
+ <ComponentDemo>
293
+ <LineChart
294
+ :series="[
295
+ { data: [0, 12, 28, 45, 60, 55, 40, 25, 12], color: '#0057b7', legend: 'No interventions' },
296
+ { data: [0, 10, 22, 38, 50, 45, 32, 18, 8], color: '#fb7e38', legend: 'School closures' },
297
+ { data: [0, 8, 18, 30, 40, 35, 25, 14, 6], color: '#ef4444', legend: 'Masking + distancing' },
298
+ { data: [0, 6, 14, 24, 32, 28, 20, 10, 4], color: '#10b981', legend: 'Vaccination only' },
299
+ { data: [0, 4, 10, 16, 22, 19, 13, 7, 3], color: '#6366f1', legend: 'Vaccination + masking' },
300
+ { data: [0, 3, 7, 11, 15, 13, 9, 5, 2], color: '#a855f7', legend: 'All interventions combined' },
301
+ ]"
302
+ :height="240"
303
+ x-label="Weeks"
304
+ y-label="Incidence"
305
+ />
306
+
307
+ <template #code>
308
+
309
+ ```vue
310
+ <LineChart
311
+ :series="[
312
+ { data: scenarioA, color: '#0057b7', legend: 'No interventions' },
313
+ { data: scenarioB, color: '#fb7e38', legend: 'School closures' },
314
+ { data: scenarioC, color: '#ef4444', legend: 'Masking + distancing' },
315
+ { data: scenarioD, color: '#10b981', legend: 'Vaccination only' },
316
+ { data: scenarioE, color: '#6366f1', legend: 'Vaccination + masking' },
317
+ { data: scenarioF, color: '#a855f7', legend: 'All interventions combined' },
318
+ ]"
319
+ :height="240"
320
+ x-label="Weeks"
321
+ y-label="Incidence"
322
+ />
323
+ ```
324
+
325
+ </template>
326
+ </ComponentDemo>
327
+
328
+ ### Tooltip
329
+
330
+ Hover over the chart to see a tooltip with values at each data point. Set `tooltip-trigger="hover"` to enable the built-in tooltip with crosshair and highlight dots. Use the `#tooltip` slot for custom content. Pass `tooltip-value-format` to control how numeric values render (e.g. percentages, currency); it falls back to `y-tick-format` when omitted.
331
+
332
+ On touch devices, drag **horizontally** across the chart to scrub the tooltip between points; a **vertical** swipe scrolls the page instead of getting captured by the chart.
333
+
334
+ <ComponentDemo>
335
+ <LineChart
336
+ :series="[
337
+ { data: [0, 10, 25, 45, 60, 55, 40, 20, 8], color: '#fb7e38', strokeWidth: 3 },
338
+ { data: [0, 5, 12, 20, 28, 25, 18, 10, 4], color: '#0057b7', strokeWidth: 3 },
339
+ ]"
340
+ :x-tick-format="(_, i) => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep'][i]"
341
+ :height="200"
342
+ x-label="Month"
343
+ y-label="Incidence"
344
+ tooltip-trigger="hover"
345
+ />
346
+
347
+ <template #code>
348
+
349
+ ```vue
350
+ <LineChart
351
+ :series="[
352
+ {
353
+ data: [0, 10, 25, 45, 60, 55, 40, 20, 8],
354
+ color: '#fb7e38',
355
+ strokeWidth: 3,
356
+ },
357
+ {
358
+ data: [0, 5, 12, 20, 28, 25, 18, 10, 4],
359
+ color: '#0057b7',
360
+ strokeWidth: 3,
361
+ },
362
+ ]"
363
+ :x-tick-format="(_, i) => months[i]"
364
+ :height="200"
365
+ x-label="Month"
366
+ y-label="Incidence"
367
+ tooltip-trigger="hover"
368
+ />
369
+ ```
370
+
371
+ </template>
372
+ </ComponentDemo>
373
+
374
+ ### Custom axis ticks
375
+
376
+ Control tick placement with `x-ticks` and `y-ticks`. Pass a **number** for a fixed interval (in data units, respecting `xMin`) or an **array** of explicit values. Use `x-tick-format` / `y-tick-format` to customize labels.
377
+
378
+ <ComponentDemo>
379
+ <LineChart
380
+ :data="[0, 0.12, 0.28, 0.45, 0.61, 0.74, 0.83, 0.89, 0.93, 0.96, 0.97, 0.98, 0.99, 0.99, 1.0]"
381
+ :x-ticks="7"
382
+ :y-ticks="[0, 0.5, 1]"
383
+ :y-tick-format="(v) => `${(v * 100).toFixed(0)}%`"
384
+ :x-tick-format="(v) => `day ${v}`"
385
+ :height="220"
386
+ x-label="Time"
387
+ y-label="Coverage"
388
+ x-grid
389
+ y-grid
390
+ />
391
+
392
+ <template #code>
393
+
394
+ ```vue
395
+ <LineChart
396
+ :data="coverage"
397
+ :x-ticks="7"
398
+ :y-ticks="[0, 0.5, 1]"
399
+ :y-tick-format="(v) => `${(v * 100).toFixed(0)}%`"
400
+ :x-tick-format="(v) => `day ${v}`"
401
+ :height="220"
402
+ x-label="Time"
403
+ y-label="Coverage"
404
+ x-grid
405
+ y-grid
406
+ />
407
+ ```
408
+
409
+ </template>
410
+ </ComponentDemo>
411
+
412
+ ### Logarithmic y-axis
413
+
414
+ Set `y-scale-type="log"` to switch the y axis to base-10 log scaling. Useful
415
+ when data spans several orders of magnitude (e.g. epidemic case counts in
416
+ early exponential growth). Non-positive values collapse to the axis
417
+ floor, and `yMin <= 0` is ignored.
418
+
419
+ <ComponentDemo>
420
+ <LineChart
421
+ :data="[1, 3, 8, 22, 60, 165, 450, 1230, 3350]"
422
+ y-scale-type="log"
423
+ :height="220"
424
+ x-label="Day"
425
+ y-label="Cases"
426
+ y-grid
427
+ />
428
+
429
+ <template #code>
430
+
431
+ ```vue
432
+ <LineChart
433
+ :data="[1, 3, 8, 22, 60, 165, 450, 1230, 3350]"
434
+ y-scale-type="log"
435
+ :height="220"
436
+ x-label="Day"
437
+ y-label="Cases"
438
+ y-grid
439
+ />
440
+ ```
441
+
442
+ </template>
443
+ </ComponentDemo>
444
+
445
+ ### Dashed baseline
446
+
447
+ <ComponentDemo>
448
+ <LineChart
449
+ :series="[
450
+ { data: [0, 10, 25, 45, 60, 55, 40, 20, 8], color: '#999', dashed: true, strokeWidth: 2 },
451
+ { data: [0, 5, 12, 20, 28, 25, 18, 10, 4], color: '#2563eb', strokeWidth: 2 },
452
+ ]"
453
+ :height="200"
454
+ />
455
+
456
+ <template #code>
457
+
458
+ ```vue
459
+ <LineChart
460
+ :series="[
461
+ {
462
+ data: [0, 10, 25, 45, 60, 55, 40, 20, 8],
463
+ color: '#999',
464
+ dashed: true,
465
+ strokeWidth: 2,
466
+ },
467
+ {
468
+ data: [0, 5, 12, 20, 28, 25, 18, 10, 4],
469
+ color: '#2563eb',
470
+ strokeWidth: 2,
471
+ },
472
+ ]"
473
+ :height="200"
474
+ />
475
+ ```
476
+
477
+ </template>
478
+ </ComponentDemo>
479
+
480
+ ### Outline
481
+
482
+ Set `outline: true` on a series to draw a page-colored stroke behind the
483
+ line. This is useful when lines overlap, cross dense areas, or sit on a
484
+ busy background — the outline keeps each series visually distinct.
485
+
486
+ Override the outline's color with `outlineColor` (any CSS color; defaults
487
+ to the page background `var(--color-bg-0, #fff)`) and its thickness with
488
+ `outlineWidth` (extra width added to the line's `strokeWidth`, split evenly
489
+ per side; defaults to `4`).
490
+
491
+ <ComponentDemo>
492
+ <LineChart
493
+ :series="[
494
+ { data: [0, 10, 25, 45, 60, 55, 40, 20, 8], color: '#fb7e38', strokeWidth: 3, outline: true },
495
+ { data: [0, 12, 22, 40, 58, 58, 42, 22, 10], color: '#0057b7', strokeWidth: 3, outline: true },
496
+ ]"
497
+ :height="200"
498
+ />
499
+
500
+ <template #code>
501
+
502
+ ```vue
503
+ <LineChart
504
+ :series="[
505
+ {
506
+ data: [0, 10, 25, 45, 60, 55, 40, 20, 8],
507
+ color: '#fb7e38',
508
+ strokeWidth: 3,
509
+ outline: true,
510
+ },
511
+ {
512
+ data: [0, 12, 22, 40, 58, 58, 42, 22, 10],
513
+ color: '#0057b7',
514
+ strokeWidth: 3,
515
+ outline: true,
516
+ },
517
+ ]"
518
+ :height="200"
519
+ />
520
+ ```
521
+
522
+ </template>
523
+ </ComponentDemo>
524
+
525
+ ### Many trajectories with low opacity
526
+
527
+ <ComponentDemo>
528
+ <LineChart
529
+ :series="Array.from({ length: 20 }, (_, i) => ({
530
+ data: Array.from({ length: 50 }, (_, t) => Math.max(0, 30 * Math.sin(t / 8) + (Math.random() - 0.5) * 15 + i * 0.5)),
531
+ color: '#0057b7',
532
+ }))"
533
+ :height="250"
534
+ :line-opacity="0.15"
535
+ x-label="Days"
536
+ y-label="Incidence"
537
+ />
538
+
539
+ <template #code>
540
+
541
+ ```vue
542
+ <LineChart
543
+ :series="trajectories"
544
+ :height="250"
545
+ :line-opacity="0.15"
546
+ x-label="Days"
547
+ y-label="Incidence"
548
+ />
549
+ ```
550
+
551
+ </template>
552
+ </ComponentDemo>
553
+
554
+ ### Blend mode
555
+
556
+ Set `blendMode` on a `Series` to apply a CSS `mix-blend-mode` to that
557
+ series' line (and dots, if enabled). Useful when two thick or
558
+ high-contrast lines overlap — `"multiply"` darkens the crossing point
559
+ on light backgrounds, `"screen"` lightens on dark, `"difference"`
560
+ inverts. The white `outline`, if any, is unaffected.
561
+
562
+ <ComponentDemo>
563
+ <LineChart
564
+ :series="[
565
+ {
566
+ data: Array.from({ length: 30 }, (_, t) => 20 + 15 * Math.sin(t / 4)),
567
+ color: '#ef4444',
568
+ strokeWidth: 3,
569
+ blendMode: 'multiply',
570
+ legend: 'Strain A',
571
+ },
572
+ {
573
+ data: Array.from({ length: 30 }, (_, t) => 20 + 15 * Math.cos(t / 4)),
574
+ color: '#3b82f6',
575
+ strokeWidth: 3,
576
+ blendMode: 'multiply',
577
+ legend: 'Strain B',
578
+ },
579
+ ]"
580
+ :height="240"
581
+ x-label="Day"
582
+ y-label="Incidence"
583
+ />
584
+
585
+ <template #code>
586
+
587
+ ```vue
588
+ <LineChart
589
+ :series="[
590
+ {
591
+ data: strainA,
592
+ color: '#ef4444',
593
+ strokeWidth: 3,
594
+ blendMode: 'multiply',
595
+ legend: 'Strain A',
596
+ },
597
+ {
598
+ data: strainB,
599
+ color: '#3b82f6',
600
+ strokeWidth: 3,
601
+ blendMode: 'multiply',
602
+ legend: 'Strain B',
603
+ },
604
+ ]"
605
+ :height="240"
606
+ x-label="Day"
607
+ y-label="Incidence"
608
+ />
609
+ ```
610
+
611
+ </template>
612
+ </ComponentDemo>
613
+
614
+ ### Grid lines
615
+
616
+ <ComponentDemo>
617
+ <LineChart
618
+ :series="[
619
+ { data: [0, 10, 25, 45, 60, 55, 40, 20, 8], color: '#fb7e38', strokeWidth: 3 },
620
+ { data: [0, 5, 12, 20, 28, 25, 18, 10, 4], color: '#0057b7', strokeWidth: 3 },
621
+ ]"
622
+ :height="200"
623
+ x-label="Weeks"
624
+ y-label="Incidence"
625
+ x-grid
626
+ y-grid
627
+ />
628
+
629
+ <template #code>
630
+
631
+ ```vue
632
+ <LineChart
633
+ :series="[
634
+ {
635
+ data: [0, 10, 25, 45, 60, 55, 40, 20, 8],
636
+ color: '#fb7e38',
637
+ strokeWidth: 3,
638
+ },
639
+ {
640
+ data: [0, 5, 12, 20, 28, 25, 18, 10, 4],
641
+ color: '#0057b7',
642
+ strokeWidth: 3,
643
+ },
644
+ ]"
645
+ :height="200"
646
+ x-label="Weeks"
647
+ y-label="Incidence"
648
+ x-grid
649
+ y-grid
650
+ />
651
+ ```
652
+
653
+ </template>
654
+ </ComponentDemo>
655
+
656
+ ### Dots
657
+
658
+ <ComponentDemo>
659
+ <LineChart
660
+ :series="[
661
+ { data: [0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2], color: '#0057b7', strokeWidth: 2, dots: true, dotRadius: 4, dotFill: '#fff', dotStroke: '#0057b7' },
662
+ ]"
663
+ :height="200"
664
+ x-label="Days"
665
+ y-label="Cases"
666
+ />
667
+
668
+ <template #code>
669
+
670
+ ```vue
671
+ <LineChart
672
+ :series="[
673
+ {
674
+ data: [0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2],
675
+ color: '#0057b7',
676
+ strokeWidth: 2,
677
+ dots: true,
678
+ dotRadius: 4,
679
+ dotFill: '#fff',
680
+ dotStroke: '#0057b7',
681
+ },
682
+ ]"
683
+ :height="200"
684
+ x-label="Days"
685
+ y-label="Cases"
686
+ />
687
+ ```
688
+
689
+ </template>
690
+ </ComponentDemo>
691
+
692
+ ### Confidence band
693
+
694
+ Use the `areas` prop to fill a band between two y-series — useful for
695
+ confidence intervals or min/max envelopes around a mean line. Each `Area`
696
+ takes parallel `upper` and `lower` arrays (and an optional `x` array, just
697
+ like `Series`). Set `legend` on an `Area` to include the band in the inline
698
+ legend; use `showInLegend: false` to hide a legend label without removing
699
+ the field from shared config. Set `blendMode` on an `Area` to apply a CSS
700
+ `mix-blend-mode` to its fill so overlapping bands combine their colors
701
+ (e.g. `"multiply"`) instead of the later one obscuring the earlier.
702
+
703
+ <ComponentDemo>
704
+ <LineChart
705
+ :data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
706
+ :areas="[
707
+ {
708
+ upper: [2, 8, 14, 22, 30, 38, 36, 28, 19, 11, 7],
709
+ lower: [0, 1, 3, 9, 15, 22, 21, 13, 6, 1, 0],
710
+ color: '#0057b7',
711
+ opacity: 0.15,
712
+ legend: '95% interval',
713
+ },
714
+ ]"
715
+ :height="220"
716
+ x-label="Days"
717
+ y-label="Cases"
718
+ tooltip-trigger="hover"
719
+ />
720
+
721
+ <template #code>
722
+
723
+ ```vue
724
+ <LineChart
725
+ :data="mean"
726
+ :areas="[
727
+ {
728
+ upper: ci95Hi,
729
+ lower: ci95Lo,
730
+ color: '#0057b7',
731
+ opacity: 0.15,
732
+ legend: '95% interval',
733
+ },
734
+ ]"
735
+ :height="220"
736
+ x-label="Days"
737
+ y-label="Cases"
738
+ tooltip-trigger="hover"
739
+ />
740
+ ```
741
+
742
+ </template>
743
+ </ComponentDemo>
744
+
745
+ ### Area sections
746
+
747
+ Highlight a range of a series line by filling the area between the line and the x-axis. Labels are rendered below the chart and automatically stack when they overlap.
748
+
749
+ <ComponentDemo>
750
+ <LineChart
751
+ :series="[
752
+ { data: [0, 2, 5, 12, 25, 45, 70, 100, 130, 155, 170], color: '#000', strokeWidth: 1, legend: 'No interventions' },
753
+ { data: [0, 0, 0, 2, 8, 20, 40, 65, 90, 110, 120], color: '#999', strokeWidth: 1, dashed: true, legend: 'Interventions' },
754
+ ]"
755
+ :area-sections="[
756
+ { startIndex: 2, endIndex: 7, color: '#6366f1', strokeWidth: 0, legend: 'inline', label: 'Day 2–7', description: 'Rapid growth phase' },
757
+ { seriesIndex: 0, startIndex: 5, endIndex: 9, color: '#f43f5e', label: 'Day 5–9', description: 'Mitigation period' },
758
+ ]"
759
+ :height="250"
760
+ x-label="Days"
761
+ y-label="Cumulative count"
762
+ tooltip-trigger="hover"
763
+ :menu="false"
764
+ />
765
+
766
+ <template #code>
767
+
768
+ ```vue
769
+ <LineChart
770
+ :series="[
771
+ {
772
+ data: [0, 2, 5, 12, 25, 45, 70, 100, 130, 155, 170],
773
+ color: '#000',
774
+ strokeWidth: 1,
775
+ legend: 'No interventions',
776
+ },
777
+ {
778
+ data: [0, 0, 0, 2, 8, 20, 40, 65, 90, 110, 120],
779
+ color: '#999',
780
+ strokeWidth: 1,
781
+ dashed: true,
782
+ legend: 'Interventions',
783
+ },
784
+ ]"
785
+ :area-sections="[
786
+ {
787
+ startIndex: 2,
788
+ endIndex: 7,
789
+ color: '#6366f1',
790
+ strokeWidth: 0,
791
+ legend: 'inline',
792
+ label: 'Day 2–7',
793
+ description: 'Rapid growth phase',
794
+ },
795
+ {
796
+ seriesIndex: 0,
797
+ startIndex: 5,
798
+ endIndex: 9,
799
+ color: '#f43f5e',
800
+ label: 'Day 5–9',
801
+ description: 'Mitigation period',
802
+ },
803
+ ]"
804
+ :height="250"
805
+ x-label="Days"
806
+ y-label="Cumulative count"
807
+ tooltip-trigger="hover"
808
+ />
809
+ ```
810
+
811
+ </template>
812
+ </ComponentDemo>
813
+
814
+ ### Annotations
815
+
816
+ Pin callouts to data points with `annotations`. Each annotation anchors at
817
+ `(x, y)` in data coordinates (the same x-space as the chart axis, so it
818
+ respects `xMin` and explicit `x` values), with a pixel
819
+ `offset: { x, y }` for the label position. Text supports `\n` for line
820
+ breaks. A curved
821
+ pointer line connects the anchor to the label, and the label gets an
822
+ outline stroke matching the background so it stays legible over series
823
+ lines.
824
+
825
+ <ComponentDemo>
826
+ <LineChart
827
+ :data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
828
+ :annotations="[
829
+ { x: 5, y: 30, offset: { x: 24, y: -28 }, text: 'Peak\nDay 5' },
830
+ { x: 0, y: 0, offset: { x: 28, y: -22 }, text: 'Onset' },
831
+ ]"
832
+ :chart-padding="{ top: 40, right: 24 }"
833
+ :height="240"
834
+ x-label="Days"
835
+ y-label="Cases"
836
+ />
837
+
838
+ <template #code>
839
+
840
+ ```vue
841
+ <LineChart
842
+ :data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
843
+ :annotations="[
844
+ { x: 5, y: 30, offset: { x: 24, y: -28 }, text: 'Peak\nDay 5' },
845
+ { x: 0, y: 0, offset: { x: 28, y: -22 }, text: 'Onset' },
846
+ ]"
847
+ :chart-padding="{ top: 40, right: 24 }"
848
+ :height="240"
849
+ x-label="Days"
850
+ y-label="Cases"
851
+ />
852
+ ```
853
+
854
+ </template>
855
+ </ComponentDemo>
856
+
857
+ Use `chart-padding` to reserve room outside the plot so annotations (or
858
+ any other overlay) don't clip the data area. It accepts a number (same on
859
+ all sides) or an object with `top`, `right`, `bottom`, `left`.
860
+
861
+ Annotation text supports a small set of inline markers:
862
+
863
+ - `**bold**` — bold
864
+ - `_italic_` — italic
865
+ - `\n` — line break
866
+
867
+ Markers compose (`**_bold italic_**`).
868
+
869
+ <ComponentDemo>
870
+ <LineChart
871
+ :data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
872
+ :annotations="[
873
+ { x: 5, y: 30, offset: { x: 24, y: -28 }, text: '**Peak**\n_Day 5_' },
874
+ ]"
875
+ :chart-padding="{ top: 40, right: 24 }"
876
+ :height="240"
877
+ x-label="Days"
878
+ y-label="Cases"
879
+ />
880
+
881
+ <template #code>
882
+
883
+ ```vue
884
+ <LineChart
885
+ :data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
886
+ :annotations="[
887
+ { x: 5, y: 30, offset: { x: 24, y: -28 }, text: '**Peak**\n_Day 5_' },
888
+ ]"
889
+ :chart-padding="{ top: 40, right: 24 }"
890
+ :height="240"
891
+ x-label="Days"
892
+ y-label="Cases"
893
+ />
894
+ ```
895
+
896
+ </template>
897
+ </ComponentDemo>
898
+
899
+ Multi-line callouts attach to whichever edge of the text faces the anchor:
900
+ text **above** the point connects to its bottom edge, text **below**
901
+ connects to its top, and text to the side connects to its near vertical
902
+ edge — so the pointer never cuts through the lines. The demo below anchors
903
+ the same two-line label at one point and fans it out in every direction.
904
+
905
+ <ComponentDemo>
906
+ <LineChart
907
+ :data="[2, 10, 7, 6, 8, 4, 9]"
908
+ :annotations="[
909
+ { x: 3, y: 6, offset: { x: 0, y: -86 }, text: 'Cluster\ndetected' },
910
+ { x: 3, y: 6, offset: { x: 62, y: -62 }, text: 'Cluster\ndetected' },
911
+ { x: 3, y: 6, offset: { x: 96, y: 0 }, text: 'Cluster\ndetected' },
912
+ { x: 3, y: 6, offset: { x: 62, y: 62 }, text: 'Cluster\ndetected' },
913
+ { x: 3, y: 6, offset: { x: 0, y: 86 }, text: 'Cluster\ndetected' },
914
+ { x: 3, y: 6, offset: { x: -62, y: 62 }, text: 'Cluster\ndetected' },
915
+ { x: 3, y: 6, offset: { x: -96, y: 0 }, text: 'Cluster\ndetected' },
916
+ { x: 3, y: 6, offset: { x: -62, y: -62 }, text: 'Cluster\ndetected' },
917
+ ]"
918
+ :chart-padding="{ top: 70, right: 120, bottom: 50, left: 120 }"
919
+ :height="340"
920
+ x-label="Days"
921
+ y-label="Cases"
922
+ />
923
+
924
+ <template #code>
925
+
926
+ ```vue
927
+ <LineChart
928
+ :data="[2, 10, 7, 6, 8, 4, 9]"
929
+ :annotations="[
930
+ { x: 3, y: 6, offset: { x: 0, y: -86 }, text: 'Cluster\ndetected' },
931
+ { x: 3, y: 6, offset: { x: 62, y: -62 }, text: 'Cluster\ndetected' },
932
+ { x: 3, y: 6, offset: { x: 96, y: 0 }, text: 'Cluster\ndetected' },
933
+ { x: 3, y: 6, offset: { x: 62, y: 62 }, text: 'Cluster\ndetected' },
934
+ { x: 3, y: 6, offset: { x: 0, y: 86 }, text: 'Cluster\ndetected' },
935
+ { x: 3, y: 6, offset: { x: -62, y: 62 }, text: 'Cluster\ndetected' },
936
+ { x: 3, y: 6, offset: { x: -96, y: 0 }, text: 'Cluster\ndetected' },
937
+ { x: 3, y: 6, offset: { x: -62, y: -62 }, text: 'Cluster\ndetected' },
938
+ ]"
939
+ :chart-padding="{ top: 70, right: 120, bottom: 50, left: 120 }"
940
+ :height="340"
941
+ x-label="Days"
942
+ y-label="Cases"
943
+ />
944
+ ```
945
+
946
+ </template>
947
+ </ComponentDemo>
948
+
949
+ ```ts
950
+ interface ChartAnnotation {
951
+ x: number; // anchor in data coords (x-axis)
952
+ y: number; // anchor in data coords (y-axis)
953
+ text: string; // label text; \n produces line breaks
954
+ offset: { x: number; y: number }; // pixel offset from anchor to label
955
+ color?: string; // text / pointer color (default: currentColor)
956
+ fontSize?: number; // default: 13 (matches axis labels)
957
+ fontWeight?: string | number; // default: "normal"
958
+ outlineColor?: string; // background-matched outline (default: var(--color-bg-0, #fff))
959
+ outlineWidth?: number; // default: 3
960
+ align?: "left" | "center" | "right"; // default: derived from offset[0] sign
961
+ lineColor?: string; // connector-line color override (default: color)
962
+ lineWidth?: number; // default: 1
963
+ lineDash?: string | number | readonly number[]; // SVG stroke-dasharray
964
+ // default: "curved"
965
+ // "ruleX" / "ruleY" span the full plot on the named axis;
966
+ // "ruleUp" / "ruleDown" / "ruleFromLeft" / "ruleFromRight" run from an edge to the anchor.
967
+ pointer?:
968
+ | "curved"
969
+ | "straight"
970
+ | "none"
971
+ | "ruleX"
972
+ | "ruleY"
973
+ | "ruleUp"
974
+ | "ruleDown"
975
+ | "ruleFromLeft"
976
+ | "ruleFromRight";
977
+ arrow?: boolean; // triangle marker at the anchor end (default: true)
978
+ }
979
+ ```
980
+
981
+ ### Rules
982
+
983
+ Set `pointer` to one of the rule values to replace the curved /
984
+ straight connector with a straight line through the anchor:
985
+
986
+ - `"ruleX"` — vertical line spanning the plot height at the annotation's `x`.
987
+ - `"ruleY"` — horizontal line spanning the plot width at the annotation's `y`.
988
+ - `"ruleUp"` — vertical from the bottom edge up to the anchor.
989
+ - `"ruleDown"` — vertical from the top edge down to the anchor.
990
+ - `"ruleFromLeft"` — horizontal from the left edge in to the anchor.
991
+ - `"ruleFromRight"` — horizontal from the right edge in to the anchor.
992
+
993
+ `lineColor`, `lineWidth`, and `lineDash` style the line. The label is
994
+ positioned from the anchor as usual via `offset`.
995
+
996
+ <ComponentDemo>
997
+ <LineChart
998
+ :data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
999
+ :annotations="[
1000
+ {
1001
+ x: 5,
1002
+ y: 30,
1003
+ offset: { x: 8, y: 14 },
1004
+ text: 'Peak',
1005
+ pointer: 'ruleX',
1006
+ lineDash: '4 3',
1007
+ },
1008
+ {
1009
+ x: 5,
1010
+ y: 30,
1011
+ offset: { x: -8, y: -6 },
1012
+ text: 'Max',
1013
+ align: 'right',
1014
+ pointer: 'ruleFromLeft',
1015
+ lineDash: '4 3',
1016
+ },
1017
+ ]"
1018
+ :chart-padding="{ top: 24, right: 24 }"
1019
+ :height="240"
1020
+ x-label="Days"
1021
+ y-label="Cases"
1022
+ />
1023
+
1024
+ <template #code>
1025
+
1026
+ ```vue
1027
+ <LineChart
1028
+ :data="[0, 4, 8, 15, 22, 30, 28, 20, 12, 5, 2]"
1029
+ :annotations="[
1030
+ {
1031
+ x: 5,
1032
+ y: 30,
1033
+ offset: { x: 8, y: 14 },
1034
+ text: 'Peak',
1035
+ pointer: 'ruleX',
1036
+ lineDash: '4 3',
1037
+ },
1038
+ {
1039
+ x: 5,
1040
+ y: 30,
1041
+ offset: { x: -8, y: -6 },
1042
+ text: 'Max',
1043
+ align: 'right',
1044
+ pointer: 'ruleFromLeft',
1045
+ lineDash: '4 3',
1046
+ },
1047
+ ]"
1048
+ :chart-padding="{ top: 24, right: 24 }"
1049
+ :height="240"
1050
+ x-label="Days"
1051
+ y-label="Cases"
1052
+ />
1053
+ ```
1054
+
1055
+ </template>
1056
+ </ComponentDemo>
1057
+
1058
+ ### Chart menu
1059
+
1060
+ The chart menu (top-right) leads with Fullscreen and then Save as SVG,
1061
+ Save as PNG, and Download CSV. Fullscreen grows the chart to fill the browser
1062
+ window so the plot has more room; while expanded the menu trigger is replaced
1063
+ by a close (✕) button — click it or press <kbd>Esc</kbd> to return to the
1064
+ inline size. Set `menu="false"` to hide the trigger entirely.
1065
+
1066
+ While expanded the chart is teleported to `<body>` so it reliably covers the
1067
+ viewport even when an ancestor uses `transform`, `filter`, `contain`, or
1068
+ establishes a stacking context. If your app doesn't mount at the document root
1069
+ (e.g. inside a shadow root or a dedicated overlay container), point
1070
+ `fullscreenTarget` at a CSS selector or element to teleport there instead.
1071
+
1072
+ ### Custom CSV download
1073
+
1074
+ By default, the Download CSV menu item exports the chart series as CSV. Use
1075
+ the `csv` prop to supply your own content (for example, to include original
1076
+ dates, categorical labels, or extra columns that aren't plotted). Use
1077
+ `filename` to control the download filename (shared by SVG, PNG and CSV).
1078
+
1079
+ Pass `download-link` to also render a plain text link below the chart — set
1080
+ it to `true` for the default label, or pass a string to customize it. Use
1081
+ `download-button` instead to render a styled `<button>` (with the class
1082
+ `line-chart-download-button`, available for custom CSS) in place of the
1083
+ link.
1084
+
1085
+ <ComponentDemo>
1086
+ <LineChart
1087
+ :data="[10, 22, 35, 48]"
1088
+ :height="200"
1089
+ filename="weekly-cases"
1090
+ :csv="'week,cases\n2024-W01,10\n2024-W02,22\n2024-W03,35\n2024-W04,48'"
1091
+ x-label="Week"
1092
+ y-label="Cases"
1093
+ download-link="Download weekly cases (CSV)"
1094
+ />
1095
+
1096
+ <template #code>
1097
+
1098
+ ```vue
1099
+ <LineChart
1100
+ :data="[10, 22, 35, 48]"
1101
+ :height="200"
1102
+ filename="weekly-cases"
1103
+ :csv="`week,cases
1104
+ 2024-W01,10
1105
+ 2024-W02,22
1106
+ 2024-W03,35
1107
+ 2024-W04,48`"
1108
+ x-label="Week"
1109
+ y-label="Cases"
1110
+ download-link="Download weekly cases (CSV)"
1111
+ />
1112
+ ```
1113
+
1114
+ </template>
1115
+ </ComponentDemo>
1116
+
1117
+ `csv` also accepts a function, which is useful for deferring serialization
1118
+ until the user clicks Download:
1119
+
1120
+ ```vue
1121
+ <LineChart :data="cases" :csv="() => buildCsv(cases, dates)" />
1122
+ ```
1123
+
1124
+ ## Accessibility
1125
+
1126
+ The chart's `<svg>` is exposed as a single labeled image so screen readers
1127
+ announce one accessible name instead of wandering through the individual marks.
1128
+ When the chart has a `title`, the `<svg>` gets `role="img"` and an `aria-label`
1129
+ set to the title. The menu and download controls live outside the `<svg>`, so
1130
+ they stay reachable regardless.
1131
+
1132
+ Set `ariaLabel` to give screen readers a fuller summary than the visible title
1133
+ (it overrides `title` for the accessible name only):
1134
+
1135
+ ```vue
1136
+ <LineChart
1137
+ :data="cases"
1138
+ title="Daily ED visits"
1139
+ aria-label="Daily ED visits over 11 days, rising from 12 to a peak of 48"
1140
+ />
1141
+ ```
1142
+
1143
+ Pass `role` to override the default `"img"` (e.g. `role="figure"`, or a role of
1144
+ your own).
1145
+
1146
+ <!--@include: ./_api/line-chart.md-->
1147
+
1148
+ ### Data
1149
+
1150
+ `data`, `series[].data`, and `areas[].upper`/`lower` accept a plain
1151
+ `number[]` or any standard numeric typed array (`Float64Array`,
1152
+ `Int32Array`, etc.). This lets you pass the output of
1153
+ `ModelOutput.column()` directly — no `Array.from(...)` copy is needed:
1154
+
1155
+ ```vue
1156
+ <LineChart :data="outputs.series.column('values')" />
1157
+ ```
1158
+
1159
+ ```ts
1160
+ type LineChartData =
1161
+ | readonly number[]
1162
+ | Float64Array
1163
+ | Float32Array
1164
+ | Int32Array
1165
+ | Uint32Array
1166
+ | Int16Array
1167
+ | Uint16Array
1168
+ | Int8Array
1169
+ | Uint8Array
1170
+ | Uint8ClampedArray;
1171
+ ```
1172
+
1173
+ ### Series
1174
+
1175
+ ```ts
1176
+ interface Series {
1177
+ y?: LineChartData; // y-values (preferred)
1178
+ data?: LineChartData; // y-values (alternative name; one of y/data must be set)
1179
+ x?: LineChartData; // optional parallel x-values
1180
+ color?: string;
1181
+ dashed?: boolean;
1182
+ strokeWidth?: number;
1183
+ opacity?: number;
1184
+ line?: boolean;
1185
+ outline?: boolean; // page-colored stroke drawn behind the line
1186
+ outlineColor?: string; // outline stroke color (default: var(--color-bg-0, #fff))
1187
+ outlineWidth?: number; // extra width added to strokeWidth (default: 4)
1188
+ dots?: boolean;
1189
+ dotRadius?: number;
1190
+ dotFill?: string;
1191
+ dotStroke?: string;
1192
+ }
1193
+ ```
1194
+
1195
+ ### Area
1196
+
1197
+ ```ts
1198
+ interface Area {
1199
+ upper: LineChartData;
1200
+ lower: LineChartData;
1201
+ x?: LineChartData; // optional parallel x-values
1202
+ color?: string;
1203
+ opacity?: number;
1204
+ legend?: string; // inline legend label
1205
+ showInLegend?: boolean; // default true when legend is set
1206
+ blendMode?: BlendMode; // CSS mix-blend-mode for the fill
1207
+ }
1208
+ ```
1209
+
1210
+ ### AreaSection
1211
+
1212
+ ```ts
1213
+ interface AreaSection {
1214
+ seriesIndex?: number; // omit for full-height fill
1215
+ startIndex: number;
1216
+ endIndex: number;
1217
+ color?: string;
1218
+ opacity?: number; // default: 0.15
1219
+ label?: string;
1220
+ description?: string;
1221
+ strokeWidth?: number; // default: 2
1222
+ dashed?: boolean;
1223
+ legend?: "inline" | "below" | false; // default: "below"
1224
+ }
1225
+ ```