@spteck/fluentui-react-charts 0.1.8

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 (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +462 -0
  3. package/dist/charts/BarChart/BarChart.d.ts +16 -0
  4. package/dist/charts/BarChart/index.d.ts +1 -0
  5. package/dist/charts/ComboChart/ComboChart.d.ts +16 -0
  6. package/dist/charts/ComboChart/index.d.ts +1 -0
  7. package/dist/charts/Doughnut/DoughnutChart.d.ts +14 -0
  8. package/dist/charts/Doughnut/index.d.ts +1 -0
  9. package/dist/charts/PieChart/PieChart.d.ts +14 -0
  10. package/dist/charts/PieChart/index.d.ts +1 -0
  11. package/dist/charts/areaChart/AreaChart.d.ts +15 -0
  12. package/dist/charts/areaChart/index.d.ts +1 -0
  13. package/dist/charts/barHorizontalChart/BarHotizontalChart.d.ts +15 -0
  14. package/dist/charts/barHorizontalChart/index.d.ts +1 -0
  15. package/dist/charts/bubbleChart/BubbleChart.d.ts +15 -0
  16. package/dist/charts/bubbleChart/index.d.ts +1 -0
  17. package/dist/charts/floatBarChart/FloatBarChart.d.ts +14 -0
  18. package/dist/charts/floatBarChart/index.d.ts +1 -0
  19. package/dist/charts/lineChart/LineChart.d.ts +14 -0
  20. package/dist/charts/lineChart/index.d.ts +1 -0
  21. package/dist/charts/polarChart/PolarChart.d.ts +14 -0
  22. package/dist/charts/polarChart/index.d.ts +1 -0
  23. package/dist/charts/radarChart/RadarChart.d.ts +14 -0
  24. package/dist/charts/radarChart/index.d.ts +1 -0
  25. package/dist/charts/scatterChart/ScatterChart.d.ts +14 -0
  26. package/dist/charts/scatterChart/index.d.ts +1 -0
  27. package/dist/charts/stackedLineChart/StackedLineChart.d.ts +14 -0
  28. package/dist/charts/stackedLineChart/index.d.ts +1 -0
  29. package/dist/charts/steamChart/SteamChart.d.ts +14 -0
  30. package/dist/charts/steamChart/index.d.ts +1 -0
  31. package/dist/components/DashBoard.d.ts +3 -0
  32. package/dist/components/RenderLegend/RenderLegend.d.ts +11 -0
  33. package/dist/components/RenderTooltip/RenderTooltip.d.ts +14 -0
  34. package/dist/components/buttonMenu/ButtonMenu.d.ts +3 -0
  35. package/dist/components/buttonMenu/IButtonMenuOption.d.ts +10 -0
  36. package/dist/components/buttonMenu/IButtonMenuProps.d.ts +37 -0
  37. package/dist/components/index.d.ts +15 -0
  38. package/dist/components/legendContainer/LegendContainer.d.ts +16 -0
  39. package/dist/components/legendeButton/LegendButton.d.ts +11 -0
  40. package/dist/components/renderSliceLegend/RenderSliceLegend.d.ts +9 -0
  41. package/dist/components/renderValueLegend/RenderValueLegend.d.ts +13 -0
  42. package/dist/components/stack/IStackProps.d.ts +76 -0
  43. package/dist/components/stack/Stack.d.ts +8 -0
  44. package/dist/components/themeProvider/ThemeProvider.d.ts +15 -0
  45. package/dist/constants/Constants.d.ts +1 -0
  46. package/dist/fluentui-react-charts.cjs.development.js +2916 -0
  47. package/dist/fluentui-react-charts.cjs.development.js.map +1 -0
  48. package/dist/fluentui-react-charts.cjs.production.min.js +2 -0
  49. package/dist/fluentui-react-charts.cjs.production.min.js.map +1 -0
  50. package/dist/fluentui-react-charts.esm.js +2905 -0
  51. package/dist/fluentui-react-charts.esm.js.map +1 -0
  52. package/dist/graphGlobalStyles/useGraphGlobalStyles.d.ts +5 -0
  53. package/dist/hooks/index.d.ts +1 -0
  54. package/dist/hooks/useGraphUtils.d.ts +38 -0
  55. package/dist/hooks/useResponsiveLegend.d.ts +8 -0
  56. package/dist/index.d.ts +3 -0
  57. package/dist/index.js +8 -0
  58. package/dist/models/IChart.d.ts +25 -0
  59. package/dist/models/index.d.ts +1 -0
  60. package/package.json +66 -0
  61. package/src/assets/sample1.png +0 -0
  62. package/src/assets/sample2.png +0 -0
  63. package/src/assets/sample3.png +0 -0
  64. package/src/charts/BarChart/BarChart.tsx +227 -0
  65. package/src/charts/BarChart/README.MD +335 -0
  66. package/src/charts/BarChart/index.ts +1 -0
  67. package/src/charts/ComboChart/ComboChart.tsx +209 -0
  68. package/src/charts/ComboChart/README.MD +347 -0
  69. package/src/charts/ComboChart/index.ts +1 -0
  70. package/src/charts/Doughnut/DoughnutChart.tsx +152 -0
  71. package/src/charts/Doughnut/README.MD +296 -0
  72. package/src/charts/Doughnut/index.ts +1 -0
  73. package/src/charts/PieChart/PieChart.tsx +148 -0
  74. package/src/charts/PieChart/README.MD +315 -0
  75. package/src/charts/PieChart/index.ts +1 -0
  76. package/src/charts/areaChart/AreaChart.tsx +195 -0
  77. package/src/charts/areaChart/README.MD +236 -0
  78. package/src/charts/areaChart/index.ts +1 -0
  79. package/src/charts/barHorizontalChart/BarHotizontalChart.tsx +200 -0
  80. package/src/charts/barHorizontalChart/README.MD +278 -0
  81. package/src/charts/barHorizontalChart/index.ts +2 -0
  82. package/src/charts/bubbleChart/BubbleChart.tsx +184 -0
  83. package/src/charts/bubbleChart/README.MD +275 -0
  84. package/src/charts/bubbleChart/index.ts +1 -0
  85. package/src/charts/floatBarChart/FloatBarChart.tsx +178 -0
  86. package/src/charts/floatBarChart/README.MD +354 -0
  87. package/src/charts/floatBarChart/index.ts +1 -0
  88. package/src/charts/lineChart/LineChart.tsx +200 -0
  89. package/src/charts/lineChart/README.MD +354 -0
  90. package/src/charts/lineChart/index.ts +1 -0
  91. package/src/charts/polarChart/PolarChart.tsx +161 -0
  92. package/src/charts/polarChart/README.MD +336 -0
  93. package/src/charts/polarChart/index.ts +1 -0
  94. package/src/charts/radarChart/README.MD +388 -0
  95. package/src/charts/radarChart/RadarChart.tsx +173 -0
  96. package/src/charts/radarChart/index.ts +1 -0
  97. package/src/charts/scatterChart/README.MD +335 -0
  98. package/src/charts/scatterChart/ScatterChart.tsx +155 -0
  99. package/src/charts/scatterChart/index.ts +1 -0
  100. package/src/charts/stackedLineChart/README.MD +396 -0
  101. package/src/charts/stackedLineChart/StackedLineChart.tsx +188 -0
  102. package/src/charts/stackedLineChart/index.ts +1 -0
  103. package/src/charts/steamChart/README.MD +414 -0
  104. package/src/charts/steamChart/SteamChart.tsx +236 -0
  105. package/src/charts/steamChart/index.ts +1 -0
  106. package/src/components/DashBoard.tsx +409 -0
  107. package/src/components/RenderLegend/RenderLegend.tsx +40 -0
  108. package/src/components/RenderTooltip/RenderTooltip.tsx +111 -0
  109. package/src/components/buttonMenu/ButtonMenu.tsx +186 -0
  110. package/src/components/buttonMenu/IButtonMenuOption.ts +9 -0
  111. package/src/components/buttonMenu/IButtonMenuProps.tsx +40 -0
  112. package/src/components/index.ts +15 -0
  113. package/src/components/legendContainer/LegendContainer.tsx +118 -0
  114. package/src/components/legendeButton/LegendButton.tsx +57 -0
  115. package/src/components/renderSliceLegend/RenderSliceLegend.tsx +46 -0
  116. package/src/components/renderValueLegend/RenderValueLegend.tsx +43 -0
  117. package/src/components/stack/IStackProps.tsx +94 -0
  118. package/src/components/stack/Stack.tsx +103 -0
  119. package/src/components/themeProvider/ThemeProvider.tsx +48 -0
  120. package/src/constants/Constants.tsx +23 -0
  121. package/src/graphGlobalStyles/useGraphGlobalStyles.ts +28 -0
  122. package/src/hooks/index.ts +1 -0
  123. package/src/hooks/useGraphUtils.tsx +314 -0
  124. package/src/hooks/useResponsiveLegend.ts +35 -0
  125. package/src/index.tsx +4 -0
  126. package/src/models/IChart.ts +50 -0
  127. package/src/models/index.ts +1 -0
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "version": "0.1.8",
3
+ "license": "MIT",
4
+ "main": "dist/index.js",
5
+ "typings": "dist/index.d.ts",
6
+ "keywords": [
7
+ "fluentui",
8
+ "react",
9
+ "charts",
10
+ "visualization"
11
+ ],
12
+ "files": [
13
+ "dist",
14
+ "src"
15
+ ],
16
+ "engines": {
17
+ "node": ">=10"
18
+ },
19
+ "scripts": {
20
+ "start": "tsdx watch",
21
+ "build": "tsdx build",
22
+ "test": "tsdx test --passWithNoTests",
23
+ "lint": "tsdx lint",
24
+ "prepare": "tsdx build",
25
+ "size": "size-limit",
26
+ "analyze": "size-limit --why"
27
+ },
28
+ "husky": {
29
+ "hooks": {
30
+ "pre-commit": "tsdx lint"
31
+ }
32
+ },
33
+ "prettier": {
34
+ "printWidth": 80,
35
+ "semi": true,
36
+ "singleQuote": true,
37
+ "trailingComma": "es5"
38
+ },
39
+ "name": "@spteck/fluentui-react-charts",
40
+ "author": "João Mendes",
41
+
42
+ "module": "dist/fluentui-react-charts.esm.js",
43
+ "devDependencies": {
44
+ "@size-limit/preset-small-lib": "^11.2.0",
45
+
46
+ "@types/react": "^18.3.23",
47
+ "@types/react-dom": "^18.3.7",
48
+ "husky": "^9.1.7",
49
+ "size-limit": "^11.2.0",
50
+ "tsdx": "^0.14.1",
51
+ "tslib": "^2.8.1",
52
+ "typescript": "^3.9.10"
53
+ },
54
+ "dependencies": {
55
+ "@emotion/css": "^11.13.5",
56
+ "@fluentui/react-components": "^9.66.2",
57
+ "@juggle/resize-observer": "^3.4.0",
58
+ "chart.js": "^4.5.0",
59
+ "chartjs-plugin-datalabels": "^2.2.0",
60
+ "react": "^18.3.1",
61
+ "react-chartjs-2": "^5.3.0",
62
+ "react-charts": "^3.0.0-beta.57",
63
+ "react-dom": "^18.3.1",
64
+ "recharts": "^2.15.4"
65
+ }
66
+ }
Binary file
Binary file
Binary file
@@ -0,0 +1,227 @@
1
+ import {
2
+ BarElement,
3
+ CategoryScale,
4
+ Chart as ChartJS,
5
+ ChartOptions,
6
+ Legend,
7
+ LinearScale,
8
+ Title,
9
+ Tooltip,
10
+ } from 'chart.js';
11
+ import React, { useMemo, useState } from 'react';
12
+ import { createAxisLabelFormatter, useGraphUtils } from '../../hooks/useGraphUtils';
13
+
14
+ import { Bar } from 'react-chartjs-2';
15
+ import ChartDataLabels from 'chartjs-plugin-datalabels';
16
+ import RenderLegend from '../../components/RenderLegend/RenderLegend';
17
+ import { Theme } from '@fluentui/react-components';
18
+ import { useGraphGlobalStyles } from '../../graphGlobalStyles/useGraphGlobalStyles';
19
+
20
+ ChartJS.register(
21
+ CategoryScale,
22
+ LinearScale,
23
+ BarElement,
24
+ Tooltip,
25
+ Legend,
26
+ ChartDataLabels,
27
+ Title
28
+ );
29
+
30
+ export interface BarProps<T> {
31
+ data: { label: string; data: T[]; type?: 'bar' | 'line' }[];
32
+ getPrimary: (datum: T) => string | number;
33
+ getSecondary: (datum: T) => number;
34
+ stacked?: boolean;
35
+ title?: string;
36
+ showDatalabels?: boolean;
37
+ theme: Theme;
38
+ }
39
+
40
+ export default function BarChart<T extends object>({
41
+ data,
42
+ getPrimary,
43
+ getSecondary,
44
+ title,
45
+ showDatalabels = false,
46
+ stacked = false,
47
+ theme,
48
+ }: BarProps<T>) {
49
+ const [visibleSeries, setVisibleSeries] = useState(() =>
50
+ data.length > 1 ? data.map(s => s.label) : [data[0]?.label]
51
+ );
52
+
53
+ const { lightenColor, getFluentPalette, createFluentTooltip } = useGraphUtils(
54
+ theme
55
+ );
56
+ const styles = useGraphGlobalStyles();
57
+ const seriesColors = useMemo(() => {
58
+ return data.reduce((acc, series, idx) => {
59
+ const base = getFluentPalette(theme)[
60
+ idx % getFluentPalette(theme).length
61
+ ];
62
+ const color = lightenColor(base, 0.3);
63
+ acc[series.label] = color;
64
+ return acc;
65
+ }, {} as Record<string, string>);
66
+ }, [data]);
67
+
68
+ const toggleSeries = (label: string) => {
69
+ setVisibleSeries(prev => {
70
+ const isVisible = prev.includes(label);
71
+ const next = isVisible ? prev.filter(l => l !== label) : [...prev, label];
72
+ return next.length === 0 && data.length > 0 ? [data[0].label] : next;
73
+ });
74
+ };
75
+
76
+ // Extract all unique x-axis categories (from all series)
77
+ const allCategories = useMemo(() => {
78
+ const categorySet = new Set<string | number>();
79
+ data.forEach(series => {
80
+ series.data.forEach(datum => {
81
+ categorySet.add(getPrimary(datum));
82
+ });
83
+ });
84
+ return Array.from(categorySet);
85
+ }, [data, getPrimary]);
86
+
87
+ // Construct Chart.js datasets
88
+ const chartData = useMemo(() => {
89
+ return {
90
+ labels: allCategories,
91
+ datasets: data
92
+ .filter(series => visibleSeries.includes(series.label))
93
+ .map(series => ({
94
+ label: series.label,
95
+ backgroundColor: seriesColors[series.label],
96
+ data: allCategories.map(cat => {
97
+ const found = series.data.find(d => getPrimary(d) === cat);
98
+ return found ? getSecondary(found) : 0;
99
+ }),
100
+ // Assign y-axis based on series type when stacked
101
+ yAxisID: stacked ? (series.type === 'line' ? 'y1' : 'y') : 'y',
102
+ })),
103
+ };
104
+ }, [data, visibleSeries, allCategories, seriesColors, stacked]);
105
+
106
+ const { fontFamily, fontSize, labelColor, gridColor } = useMemo(
107
+ () => ({
108
+ fontFamily: theme.fontFamilyBase,
109
+ fontSize: parseInt(theme.fontSizeBase200.replace('px', '')) || 14,
110
+ labelColor: theme.colorNeutralForeground1,
111
+ gridColor: theme.colorNeutralStroke2,
112
+ }),
113
+ [theme]
114
+ );
115
+
116
+ const options: ChartOptions<'bar'> = useMemo(
117
+ () => ({
118
+ responsive: true,
119
+ maintainAspectRatio: false,
120
+
121
+ plugins: {
122
+ title: {
123
+ display: !!title,
124
+ text: title,
125
+ font: {
126
+ size: 14,
127
+ family: theme.fontFamilyBase,
128
+ weight: theme.fontWeightSemibold,
129
+ },
130
+ color: theme.colorNeutralForeground1,
131
+ padding: {
132
+ top: 20,
133
+ bottom: 20,
134
+ },
135
+ },
136
+ datalabels: {
137
+ display: showDatalabels,
138
+ color: theme.colorNeutralForeground1,
139
+ font: {
140
+ family: theme.fontFamilyBase,
141
+ size: parseInt(theme.fontSizeBase200.replace('px', '')) || 14,
142
+ },
143
+ },
144
+ legend: {
145
+ display: false,
146
+ },
147
+ tooltip: createFluentTooltip<'bar'>(theme),
148
+ },
149
+ scales: {
150
+ x: {
151
+ stacked,
152
+ ticks: {
153
+ callback: createAxisLabelFormatter({ maxLength: 10 }),
154
+ color: labelColor,
155
+ font: {
156
+ family: fontFamily,
157
+ size: fontSize,
158
+ },
159
+ },
160
+ grid: {
161
+ color: gridColor,
162
+ },
163
+ },
164
+ y: {
165
+ type: 'linear',
166
+ position: 'left',
167
+ stacked,
168
+ ticks: {
169
+ callback: createAxisLabelFormatter({ maxLength: 10 }),
170
+ color: labelColor,
171
+ font: {
172
+ family: fontFamily,
173
+ size: fontSize,
174
+ },
175
+ },
176
+ grid: {
177
+ color: gridColor,
178
+ },
179
+ },
180
+ ...(stacked && {
181
+ y1: {
182
+ type: 'linear',
183
+ position: 'right',
184
+ ticks: {
185
+ callback: createAxisLabelFormatter({ maxLength: 10 }),
186
+ color: labelColor,
187
+ font: {
188
+ family: fontFamily,
189
+ size: fontSize,
190
+ },
191
+ },
192
+ grid: {
193
+ drawOnChartArea: false,
194
+ },
195
+ },
196
+ }),
197
+ },
198
+ }),
199
+ [
200
+ title,
201
+ showDatalabels,
202
+ theme,
203
+ fontFamily,
204
+ fontSize,
205
+ labelColor,
206
+ gridColor,
207
+ stacked,
208
+ createFluentTooltip,
209
+ ]
210
+ );
211
+
212
+ return (
213
+ <div className={styles.chartWithLegend}>
214
+ <div className={styles.chartArea}>
215
+ <Bar data={chartData} options={options} />
216
+ </div>
217
+ <div className={styles.legendArea}>
218
+ <RenderLegend
219
+ data={data}
220
+ visibleSeries={visibleSeries}
221
+ seriesColors={seriesColors}
222
+ toggleSeries={toggleSeries}
223
+ />
224
+ </div>
225
+ </div>
226
+ );
227
+ }
@@ -0,0 +1,335 @@
1
+ # BarChart Component
2
+
3
+ A versatile and interactive bar chart component built with Chart.js and Fluent UI React. This component supports multiple series, stacking, mixed chart types (bar + line), and provides an intuitive legend interface.
4
+
5
+ ## Features
6
+
7
+ - **Multiple Series Support**: Display multiple data series with different colors
8
+ - **Mixed Chart Types**: Support for both bar and line series in the same chart
9
+ - **Interactive Legend**: Toggle series visibility with click interactions
10
+ - **Stacked Charts**: Option to stack bars for comparative analysis
11
+ - **Fluent UI Integration**: Seamless integration with Fluent UI themes and design system
12
+ - **Data Labels**: Optional display of values directly on chart elements
13
+ - **Responsive Design**: Automatically adapts to container dimensions
14
+ - **TypeScript Support**: Full TypeScript support with generic types
15
+ - **Custom Tooltips**: Fluent UI styled tooltips with rich information
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install chart.js react-chartjs-2 chartjs-plugin-datalabels @fluentui/react-components
21
+ ```
22
+
23
+ ## Basic Usage
24
+
25
+ ```tsx
26
+ import React from 'react';
27
+ import { BarChart } from './components/BarChart/BarChart';
28
+ import { webLightTheme } from '@fluentui/react-components';
29
+
30
+ interface SalesData {
31
+ month: string;
32
+ revenue: number;
33
+ }
34
+
35
+ const salesData: SalesData[] = [
36
+ { month: 'Jan', revenue: 10000 },
37
+ { month: 'Feb', revenue: 15000 },
38
+ { month: 'Mar', revenue: 12000 },
39
+ { month: 'Apr', revenue: 18000 },
40
+ ];
41
+
42
+ function App() {
43
+ return (
44
+ <div style={{ width: '800px', height: '400px' }}>
45
+ <BarChart
46
+ data={[
47
+ { label: 'Monthly Sales', data: salesData }
48
+ ]}
49
+ getPrimary={(datum) => datum.month}
50
+ getSecondary={(datum) => datum.revenue}
51
+ title="Sales Performance"
52
+ theme={webLightTheme}
53
+ />
54
+ </div>
55
+ );
56
+ }
57
+ ```
58
+
59
+ ## Props
60
+
61
+ ### BarProps<T>
62
+
63
+ | Prop | Type | Required | Default | Description |
64
+ |------|------|----------|---------|-------------|
65
+ | `data` | `{ label: string; data: T[]; type?: 'bar' \| 'line' }[]` | Yes | - | Array of data series with labels, data points, and optional chart type |
66
+ | `getPrimary` | `(datum: T) => string \| number` | Yes | - | Function to extract the x-axis category from each data point |
67
+ | `getSecondary` | `(datum: T) => number` | Yes | - | Function to extract the y-axis value from each data point |
68
+ | `stacked` | `boolean` | No | `false` | Whether to stack the bars and enable dual y-axes for mixed types |
69
+ | `title` | `string` | No | - | Chart title displayed at the top |
70
+ | `showDatalabels` | `boolean` | No | `false` | Whether to show data values on chart elements |
71
+ | `theme` | `Theme` | Yes | - | Fluent UI theme object for styling |
72
+
73
+ ## Advanced Usage
74
+
75
+ ### Multiple Series
76
+
77
+ ```tsx
78
+ interface ProductData {
79
+ quarter: string;
80
+ product1: number;
81
+ product2: number;
82
+ product3: number;
83
+ }
84
+
85
+ const productData: ProductData[] = [
86
+ { quarter: 'Q1', product1: 15000, product2: 12000, product3: 8000 },
87
+ { quarter: 'Q2', product1: 18000, product2: 14000, product3: 9500 },
88
+ { quarter: 'Q3', product1: 16500, product2: 13500, product3: 8800 },
89
+ { quarter: 'Q4', product1: 20000, product2: 16000, product3: 11000 },
90
+ ];
91
+
92
+ <BarChart
93
+ data={[
94
+ {
95
+ label: 'Product A',
96
+ data: productData.map(d => ({ quarter: d.quarter, value: d.product1 }))
97
+ },
98
+ {
99
+ label: 'Product B',
100
+ data: productData.map(d => ({ quarter: d.quarter, value: d.product2 }))
101
+ },
102
+ {
103
+ label: 'Product C',
104
+ data: productData.map(d => ({ quarter: d.quarter, value: d.product3 }))
105
+ }
106
+ ]}
107
+ getPrimary={(datum) => datum.quarter}
108
+ getSecondary={(datum) => datum.value}
109
+ title="Quarterly Product Sales"
110
+ showDatalabels={true}
111
+ theme={webLightTheme}
112
+ />
113
+ ```
114
+
115
+ ### Stacked Bar Chart
116
+
117
+ ```tsx
118
+ <BarChart
119
+ data={[
120
+ { label: 'Desktop Sales', data: salesData },
121
+ { label: 'Mobile Sales', data: salesData },
122
+ { label: 'Tablet Sales', data: salesData }
123
+ ]}
124
+ getPrimary={(datum) => datum.region}
125
+ getSecondary={(datum) => datum.amount}
126
+ stacked={true}
127
+ title="Sales by Platform and Region"
128
+ theme={webLightTheme}
129
+ />
130
+ ```
131
+
132
+ ### Mixed Chart Types (Bar + Line)
133
+
134
+ ```tsx
135
+ <BarChart
136
+ data={[
137
+ {
138
+ label: 'Revenue',
139
+ data: monthlyData,
140
+ type: 'bar'
141
+ },
142
+ {
143
+ label: 'Growth Rate',
144
+ data: monthlyData,
145
+ type: 'line'
146
+ }
147
+ ]}
148
+ getPrimary={(datum) => datum.month}
149
+ getSecondary={(datum) => datum.value}
150
+ stacked={true} // Enables dual y-axes
151
+ title="Revenue vs Growth Rate"
152
+ theme={webLightTheme}
153
+ />
154
+ ```
155
+
156
+ ### Dark Theme
157
+
158
+ ```tsx
159
+ import { webDarkTheme } from '@fluentui/react-components';
160
+
161
+ <BarChart
162
+ data={chartData}
163
+ getPrimary={(datum) => datum.category}
164
+ getSecondary={(datum) => datum.value}
165
+ title="Dark Theme Chart"
166
+ theme={webDarkTheme}
167
+ />
168
+ ```
169
+
170
+ ## Data Structure
171
+
172
+ The component expects data in the following format:
173
+
174
+ ```tsx
175
+ interface ChartSeries<T> {
176
+ label: string; // Series name (appears in legend)
177
+ data: T[]; // Array of data points
178
+ type?: 'bar' | 'line'; // Chart type (default: 'bar')
179
+ }
180
+ ```
181
+
182
+ Each data point `T` should contain:
183
+ - A primary value (x-axis category) - string or number
184
+ - A secondary value (y-axis value) - number
185
+
186
+ ## Features in Detail
187
+
188
+ ### Interactive Legend
189
+ - Click legend items to show/hide series
190
+ - At least one series must remain visible
191
+ - Colors automatically assigned from Fluent UI theme palette
192
+ - Visual feedback on hover and selection states
193
+
194
+ ### Stacked Mode
195
+ When `stacked={true}`:
196
+ - Bar series stack on the left y-axis
197
+ - Line series display on the right y-axis (when mixed with bars)
198
+ - Enables comparative analysis between different data types
199
+
200
+ ### Responsive Behavior
201
+ - Chart automatically resizes to fit container
202
+ - Legend adapts to available space
203
+ - Maintains readability across different screen sizes
204
+ - Uses CSS Grid for optimal layout
205
+
206
+ ### Theme Integration
207
+ - Automatically uses theme colors, fonts, and spacing
208
+ - Supports both light and dark themes
209
+ - Consistent with Fluent UI design language
210
+ - Accessible color contrasts
211
+
212
+ ## Styling
213
+
214
+ The component uses Fluent UI theme tokens:
215
+
216
+ ```tsx
217
+ // Colors from theme palette
218
+ const seriesColors = getFluentPalette(theme);
219
+
220
+ // Typography
221
+ font-family: theme.fontFamilyBase;
222
+ font-size: theme.fontSizeBase200;
223
+ font-weight: theme.fontWeightSemibold;
224
+
225
+ // Colors
226
+ color: theme.colorNeutralForeground1;
227
+ grid-color: theme.colorNeutralStroke2;
228
+ ```
229
+
230
+ ## Performance Optimizations
231
+
232
+ The component includes several performance optimizations:
233
+
234
+ - `useMemo` for expensive color calculations
235
+ - `useMemo` for chart data transformation
236
+ - `useMemo` for chart options configuration
237
+ - Efficient series visibility state management
238
+ - Minimal re-renders on data changes
239
+
240
+ ## Examples
241
+
242
+ ### Sales Dashboard
243
+ ```tsx
244
+ interface SalesMetrics {
245
+ region: string;
246
+ currentYear: number;
247
+ previousYear: number;
248
+ }
249
+
250
+ <BarChart
251
+ data={[
252
+ { label: '2024', data: salesMetrics },
253
+ { label: '2023', data: salesMetrics }
254
+ ]}
255
+ getPrimary={(datum) => datum.region}
256
+ getSecondary={(datum) => datum.currentYear}
257
+ title="Sales by Region - Year over Year"
258
+ showDatalabels={true}
259
+ />
260
+ ```
261
+
262
+ ### Performance Metrics
263
+ ```tsx
264
+ interface PerformanceData {
265
+ metric: string;
266
+ actual: number;
267
+ target: number;
268
+ }
269
+
270
+ <BarChart
271
+ data={[
272
+ { label: 'Actual', data: performanceData, type: 'bar' },
273
+ { label: 'Target', data: performanceData, type: 'line' }
274
+ ]}
275
+ getPrimary={(datum) => datum.metric}
276
+ getSecondary={(datum) => datum.actual}
277
+ stacked={true}
278
+ title="Performance vs Targets"
279
+ />
280
+ ```
281
+
282
+ ## Accessibility
283
+
284
+ - Keyboard navigation support
285
+ - Screen reader compatible
286
+ - High contrast theme support
287
+ - Focus indicators on interactive elements
288
+ - ARIA labels for chart elements
289
+
290
+ ## Browser Support
291
+
292
+ - Modern browsers with ES6+ support
293
+ - Canvas API required for Chart.js
294
+ - ResizeObserver for responsive features
295
+ - CSS Grid for layout
296
+
297
+ ## Troubleshooting
298
+
299
+ ### Common Issues
300
+
301
+ 1. **Chart not rendering**: Ensure container has explicit width and height
302
+ 2. **Data not displaying**: Verify `getPrimary` and `getSecondary` return valid values
303
+ 3. **Legend not working**: Check that series labels are unique
304
+ 4. **Stacked mode issues**: Ensure mixed types are properly configured
305
+ 5. **Theme not applied**: Verify theme object is properly imported
306
+
307
+ ### Performance Tips
308
+
309
+ - Limit data points for optimal performance (< 500 points per series)
310
+ - Use `React.memo` for parent components when data changes frequently
311
+ - Consider data virtualization for very large datasets
312
+ - Debounce resize events if needed
313
+
314
+ ### Debug Mode
315
+
316
+ ```tsx
317
+ // Add this to see chart configuration
318
+ console.log('Chart Data:', chartData);
319
+ console.log('Chart Options:', options);
320
+ ```
321
+
322
+ ## API Reference
323
+
324
+ ### Utility Functions
325
+
326
+ The component uses several utility functions from `useGraphUtils`:
327
+
328
+ - `getFluentPalette(theme)`: Gets color palette from theme
329
+ - `lightenColor(color, amount)`: Lightens colors for better contrast
330
+ - `createFluentTooltip(theme)`: Creates theme-aware tooltips
331
+ - `createAxisLabelFormatter(options)`: Formats axis labels
332
+
333
+ ## License
334
+
335
+ This component is part of the FluentUI React Graphs library.
@@ -0,0 +1 @@
1
+ export * from './BarChart';