@cdc/core 4.25.8 → 4.25.10
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.
- package/components/AdvancedEditor/AdvancedEditor.tsx +29 -8
- package/components/DataTable/DataTable.tsx +56 -38
- package/components/DataTable/components/ChartHeader.tsx +44 -14
- package/components/DataTable/components/ExpandCollapse.tsx +10 -1
- package/components/DataTable/components/MapHeader.tsx +24 -13
- package/components/DataTable/data-table.css +6 -0
- package/components/DataTable/helpers/chartCellMatrix.tsx +11 -8
- package/components/DataTable/helpers/mapCellMatrix.tsx +19 -1
- package/components/DownloadButton.tsx +40 -14
- package/components/EditorPanel/components/MarkupHighlightedTextField.tsx +227 -0
- package/components/EditorPanel/components/MarkupVariablesEditor.tsx +411 -0
- package/components/EditorPanel/components/PanelMarkup.tsx +59 -0
- package/components/ErrorBoundary.jsx +3 -1
- package/components/Filters/Filters.tsx +27 -20
- package/components/Filters/components/Tabs.tsx +1 -0
- package/components/Legend/Legend.Gradient.tsx +3 -6
- package/components/LegendShape.tsx +121 -3
- package/components/MediaControls.tsx +51 -3
- package/components/PaletteConversionModal.tsx +87 -0
- package/components/PaletteSelector/DeveloperPaletteRollback.tsx +114 -0
- package/components/PaletteSelector/PaletteSelector.css +51 -0
- package/components/PaletteSelector/PaletteSelector.tsx +112 -0
- package/components/PaletteSelector/index.ts +2 -0
- package/components/RichTooltip/RichTooltip.tsx +1 -0
- package/components/Table/Table.tsx +3 -1
- package/components/_stories/BlurStrokeTest.stories.tsx +1 -1
- package/components/_stories/DataTable.stories.tsx +1 -1
- package/components/_stories/Filters.stories.tsx +1 -1
- package/components/_stories/Footnotes.stories.tsx +1 -1
- package/components/_stories/Inputs.stories.tsx +1 -1
- package/components/_stories/MultiSelect.stories.tsx +3 -3
- package/components/_stories/NestedDropdown.stories.tsx +1 -1
- package/components/_stories/Table.stories.tsx +1 -1
- package/components/elements/_stories/Button.stories.tsx +1 -1
- package/components/elements/_stories/Card.stories.tsx +1 -1
- package/components/inputs/InputToggle.tsx +2 -0
- package/components/managers/DataDesigner.tsx +10 -9
- package/components/managers/_stories/DataDesigner.stories.tsx +1 -1
- package/components/ui/Tooltip.tsx +2 -1
- package/components/ui/_stories/Accordion.stories.tsx +1 -1
- package/components/ui/_stories/ColorPaletteMigration.stories.mdx +275 -0
- package/components/ui/_stories/Colors.stories.tsx +330 -0
- package/components/ui/_stories/IconGallery.stories.tsx +316 -0
- package/components/ui/_stories/Title.stories.tsx +1 -1
- package/contexts/EditorContext.ts +18 -0
- package/contexts/editor.actions.ts +28 -0
- package/contexts/editor.reducer.ts +94 -0
- package/data/chartColorPalettes.ts +118 -0
- package/data/colorPalettes.ts +9 -0
- package/data/mapColorPalettes.ts +45 -0
- package/data/sharedPalettes.ts +50 -0
- package/dist/cove-main.css +14 -11
- package/dist/cove-main.css.map +1 -1
- package/generateViteConfig.js +80 -0
- package/helpers/addValuesToFilters.ts +2 -3
- package/helpers/cloneConfig.ts +31 -0
- package/helpers/configDataHelpers.ts +128 -0
- package/helpers/configHelpers.ts +27 -0
- package/helpers/constants.ts +5 -2
- package/helpers/coveUpdateWorker.ts +13 -3
- package/helpers/filterColorPalettes.ts +152 -0
- package/helpers/generateColorsArray.ts +13 -0
- package/helpers/getColorPaletteVersion.ts +33 -0
- package/helpers/getPaletteAccessor.ts +18 -0
- package/helpers/markupProcessor.ts +205 -0
- package/helpers/metrics/helpers.ts +42 -19
- package/helpers/metrics/types.ts +48 -9
- package/helpers/metrics/utils.ts +34 -0
- package/helpers/palettes/colorDistributions.ts +56 -0
- package/helpers/palettes/migratePaletteName.ts +150 -0
- package/helpers/palettes/standardizePaletteNames.ts +77 -0
- package/helpers/palettes/utils.ts +267 -0
- package/helpers/queryStringUtils.ts +13 -0
- package/helpers/testing.ts +345 -0
- package/helpers/tests/addValuesToFilters.test.ts +1 -2
- package/helpers/tests/generateColorsArray.test.ts +24 -0
- package/helpers/tests/markupProcessor.test.ts +538 -0
- package/helpers/tests/testStandaloneBuild.ts +44 -0
- package/helpers/useMarkupVariables.ts +31 -0
- package/helpers/vegaConfig.ts +0 -1
- package/helpers/ver/4.24.10.ts +2 -1
- package/helpers/ver/4.24.11.ts +2 -1
- package/helpers/ver/4.24.3.ts +2 -1
- package/helpers/ver/4.24.4.ts +2 -1
- package/helpers/ver/4.24.5.ts +2 -1
- package/helpers/ver/4.24.7.ts +2 -1
- package/helpers/ver/4.24.9.ts +2 -1
- package/helpers/ver/4.25.1.ts +2 -1
- package/helpers/ver/4.25.10.ts +36 -0
- package/helpers/ver/4.25.3.ts +2 -1
- package/helpers/ver/4.25.4.ts +2 -1
- package/helpers/ver/4.25.6.ts +2 -1
- package/helpers/ver/4.25.7.ts +2 -1
- package/helpers/ver/4.25.8.ts +2 -1
- package/helpers/ver/4.25.9.ts +293 -0
- package/helpers/ver/tests/4.25.10.test.ts +204 -0
- package/helpers/ver/tests/4.25.8.test.ts +1 -1
- package/helpers/ver/tests/4.25.9.test.ts +51 -0
- package/hooks/useColorPalette.ts +79 -0
- package/package.json +12 -4
- package/styles/_global.scss +7 -5
- package/styles/base.scss +8 -5
- package/styles/v2/components/button.scss +4 -3
- package/styles/v2/components/editor.scss +2 -1
- package/styles/v2/layout/_data-table.scss +3 -2
- package/styles/v2/themes/_color-definitions.scss +18 -17
- package/testBuild.js +0 -0
- package/testing-setup.js +32 -0
- package/types/MarkupInclude.ts +6 -1
- package/types/MarkupVariable.ts +19 -0
- package/types/VizFilter.ts +1 -0
- package/vitest.config.ts +16 -0
- package/components/ui/_stories/Colors.stories.mdx +0 -220
- package/components/ui/_stories/IconGallery.stories.mdx +0 -14
- package/data/colorPalettes.js +0 -171
- package/helpers/formatConfigBeforeSave.ts +0 -135
- package/helpers/tests/formatConfigBeforeSave.test.ts +0 -68
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import type { Meta } from '@storybook/react'
|
|
2
|
+
import { mapColorPalettesV2, colorPalettesChartV2, twoColorPalette, sequentialPalettes } from '../../../data/colorPalettes'
|
|
3
|
+
|
|
4
|
+
// Get the v2 palettes for consistency
|
|
5
|
+
const twoColorPaletteV2 = twoColorPalette.v2
|
|
6
|
+
|
|
7
|
+
const meta: Meta = {
|
|
8
|
+
title: 'Components/Atoms/Colors',
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
page: () => (
|
|
12
|
+
<div style={{ padding: '20px' }}>
|
|
13
|
+
<h1>Color Palettes</h1>
|
|
14
|
+
<p>This guide showcases all available color palettes in the CDC Open Viz system.</p>
|
|
15
|
+
|
|
16
|
+
<h2>Qualitative Palettes</h2>
|
|
17
|
+
<p>These palettes are designed for categorical data where each color represents a different category.</p>
|
|
18
|
+
|
|
19
|
+
<h3>Chart Palettes</h3>
|
|
20
|
+
{Object.entries(colorPalettesChartV2).map(([name, colors]) => (
|
|
21
|
+
<div key={name} style={{ marginBottom: '20px' }}>
|
|
22
|
+
<h4 style={{ textTransform: 'capitalize', marginBottom: '10px' }}>{name.replace(/-/g, ' ')}</h4>
|
|
23
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
|
|
24
|
+
<div style={{ display: 'flex' }}>
|
|
25
|
+
{colors.map((color, index) => (
|
|
26
|
+
<div
|
|
27
|
+
key={index}
|
|
28
|
+
style={{
|
|
29
|
+
width: '40px',
|
|
30
|
+
height: '40px',
|
|
31
|
+
backgroundColor: color,
|
|
32
|
+
border: '1px solid #ccc',
|
|
33
|
+
display: 'flex',
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
justifyContent: 'center',
|
|
36
|
+
fontSize: '10px',
|
|
37
|
+
color: index < 3 ? '#000' : '#fff'
|
|
38
|
+
}}
|
|
39
|
+
title={color}
|
|
40
|
+
/>
|
|
41
|
+
))}
|
|
42
|
+
</div>
|
|
43
|
+
<code style={{ marginLeft: '10px', fontSize: '12px', color: '#666' }}>
|
|
44
|
+
{colors.join(', ')}
|
|
45
|
+
</code>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
))}
|
|
49
|
+
|
|
50
|
+
<h3>Sequential Palettes</h3>
|
|
51
|
+
<p>These palettes are designed for ordered data that progresses from low to high values.</p>
|
|
52
|
+
{Object.entries(sequentialPalettes).map(([name, colors]) => (
|
|
53
|
+
<div key={name} style={{ marginBottom: '20px' }}>
|
|
54
|
+
<h4 style={{ marginBottom: '10px' }}>{name}</h4>
|
|
55
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
|
|
56
|
+
<div style={{ display: 'flex' }}>
|
|
57
|
+
{colors.map((color, index) => (
|
|
58
|
+
<div
|
|
59
|
+
key={index}
|
|
60
|
+
style={{
|
|
61
|
+
width: '40px',
|
|
62
|
+
height: '40px',
|
|
63
|
+
backgroundColor: color,
|
|
64
|
+
border: '1px solid #ccc',
|
|
65
|
+
display: 'flex',
|
|
66
|
+
alignItems: 'center',
|
|
67
|
+
justifyContent: 'center',
|
|
68
|
+
fontSize: '10px',
|
|
69
|
+
color: index < colors.length / 2 ? '#000' : '#fff'
|
|
70
|
+
}}
|
|
71
|
+
title={color}
|
|
72
|
+
/>
|
|
73
|
+
))}
|
|
74
|
+
</div>
|
|
75
|
+
<code style={{ marginLeft: '10px', fontSize: '12px', color: '#666' }}>
|
|
76
|
+
{colors.join(', ')}
|
|
77
|
+
</code>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
))}
|
|
81
|
+
|
|
82
|
+
<h3>Two-Color Palettes</h3>
|
|
83
|
+
<p>These palettes are designed for paired comparisons and side-by-side visualizations.</p>
|
|
84
|
+
{Object.entries(twoColorPaletteV2).map(([name, colors]) => (
|
|
85
|
+
<div key={name} style={{ marginBottom: '20px' }}>
|
|
86
|
+
<h4 style={{ textTransform: 'capitalize', marginBottom: '10px' }}>{name.replace(/-/g, ' ')}</h4>
|
|
87
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
|
|
88
|
+
<div style={{ display: 'flex' }}>
|
|
89
|
+
{colors.map((color, index) => (
|
|
90
|
+
<div
|
|
91
|
+
key={index}
|
|
92
|
+
style={{
|
|
93
|
+
width: '60px',
|
|
94
|
+
height: '40px',
|
|
95
|
+
backgroundColor: color,
|
|
96
|
+
border: '1px solid #ccc',
|
|
97
|
+
display: 'flex',
|
|
98
|
+
alignItems: 'center',
|
|
99
|
+
justifyContent: 'center',
|
|
100
|
+
fontSize: '10px',
|
|
101
|
+
color: '#fff',
|
|
102
|
+
textShadow: '1px 1px 1px rgba(0,0,0,0.7)'
|
|
103
|
+
}}
|
|
104
|
+
title={color}
|
|
105
|
+
/>
|
|
106
|
+
))}
|
|
107
|
+
</div>
|
|
108
|
+
<code style={{ marginLeft: '10px', fontSize: '12px', color: '#666' }}>
|
|
109
|
+
{colors.join(', ')}
|
|
110
|
+
</code>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
))}
|
|
114
|
+
|
|
115
|
+
<h2>Map Palettes</h2>
|
|
116
|
+
<p>These palettes are primarily used for geographic visualizations and maps.</p>
|
|
117
|
+
{Object.entries(mapColorPalettesV2).map(([name, colors]) => (
|
|
118
|
+
<div key={name} style={{ marginBottom: '20px' }}>
|
|
119
|
+
<h4 style={{ textTransform: 'capitalize', marginBottom: '10px' }}>{name.replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase()}</h4>
|
|
120
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
|
|
121
|
+
<div style={{ display: 'flex' }}>
|
|
122
|
+
{colors.map((color, index) => (
|
|
123
|
+
<div
|
|
124
|
+
key={index}
|
|
125
|
+
style={{
|
|
126
|
+
width: '30px',
|
|
127
|
+
height: '40px',
|
|
128
|
+
backgroundColor: color,
|
|
129
|
+
border: '1px solid #ccc',
|
|
130
|
+
display: 'flex',
|
|
131
|
+
alignItems: 'center',
|
|
132
|
+
justifyContent: 'center',
|
|
133
|
+
fontSize: '8px',
|
|
134
|
+
color: index < colors.length / 2 ? '#000' : '#fff'
|
|
135
|
+
}}
|
|
136
|
+
title={color}
|
|
137
|
+
/>
|
|
138
|
+
))}
|
|
139
|
+
</div>
|
|
140
|
+
<code style={{ marginLeft: '10px', fontSize: '11px', color: '#666' }}>
|
|
141
|
+
[{colors.slice(0, 3).join(', ')}...] ({colors.length} colors)
|
|
142
|
+
</code>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
))}
|
|
146
|
+
|
|
147
|
+
<h2>Usage Guidelines</h2>
|
|
148
|
+
<ul>
|
|
149
|
+
<li><strong>Accessibility</strong>: All palettes are designed to meet WCAG accessibility guidelines</li>
|
|
150
|
+
<li><strong>Color Blind Friendly</strong>: The "colorblindsafe" palette is specifically designed for color blind users</li>
|
|
151
|
+
<li><strong>Sequential Data</strong>: Use sequential palettes for ordered data (low to high values)</li>
|
|
152
|
+
<li><strong>Categorical Data</strong>: Use qualitative palettes for distinct categories</li>
|
|
153
|
+
<li><strong>Comparisons</strong>: Use two-color palettes for side-by-side comparisons</li>
|
|
154
|
+
<li><strong>Geographic Data</strong>: Use map palettes for choropleth and geographic visualizations</li>
|
|
155
|
+
</ul>
|
|
156
|
+
|
|
157
|
+
<h2>Implementation</h2>
|
|
158
|
+
<p>Import color palettes in your components:</p>
|
|
159
|
+
<pre><code>{`import { mapColorPalettesV2, colorPalettesChartV2, twoColorPalette, sequentialPalettes } from '@cdc/core/data/colorPalettes'
|
|
160
|
+
|
|
161
|
+
// Use in your visualization
|
|
162
|
+
const colors = colorPalettesChartV2['qualitative-bold']
|
|
163
|
+
const twoColors = twoColorPalette.v2['divergent-blue-orange']
|
|
164
|
+
const mapColors = mapColorPalettesV2.sequential_blue`}</code></pre>
|
|
165
|
+
</div>
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export default meta
|
|
172
|
+
|
|
173
|
+
export const Guide = {
|
|
174
|
+
render: () => (
|
|
175
|
+
<div style={{ padding: '20px' }}>
|
|
176
|
+
<h1>Color Palettes</h1>
|
|
177
|
+
<p>This guide showcases all available color palettes in the CDC Open Viz system.</p>
|
|
178
|
+
|
|
179
|
+
<h2>Qualitative Palettes</h2>
|
|
180
|
+
<p>These palettes are designed for categorical data where each color represents a different category.</p>
|
|
181
|
+
|
|
182
|
+
<h3>Chart Palettes</h3>
|
|
183
|
+
{Object.entries(colorPalettesChartV2).map(([name, colors]) => (
|
|
184
|
+
<div key={name} style={{ marginBottom: '20px' }}>
|
|
185
|
+
<h4 style={{ textTransform: 'capitalize', marginBottom: '10px' }}>{name.replace(/-/g, ' ')}</h4>
|
|
186
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
|
|
187
|
+
<div style={{ display: 'flex' }}>
|
|
188
|
+
{colors.map((color, index) => (
|
|
189
|
+
<div
|
|
190
|
+
key={index}
|
|
191
|
+
style={{
|
|
192
|
+
width: '40px',
|
|
193
|
+
height: '40px',
|
|
194
|
+
backgroundColor: color,
|
|
195
|
+
border: '1px solid #ccc',
|
|
196
|
+
display: 'flex',
|
|
197
|
+
alignItems: 'center',
|
|
198
|
+
justifyContent: 'center',
|
|
199
|
+
fontSize: '10px',
|
|
200
|
+
color: index < 3 ? '#000' : '#fff'
|
|
201
|
+
}}
|
|
202
|
+
title={color}
|
|
203
|
+
/>
|
|
204
|
+
))}
|
|
205
|
+
</div>
|
|
206
|
+
<code style={{ marginLeft: '10px', fontSize: '12px', color: '#666' }}>
|
|
207
|
+
{colors.join(', ')}
|
|
208
|
+
</code>
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
))}
|
|
212
|
+
|
|
213
|
+
<h3>Sequential Palettes</h3>
|
|
214
|
+
<p>These palettes are designed for ordered data that progresses from low to high values.</p>
|
|
215
|
+
{Object.entries(sequentialPalettes).map(([name, colors]) => (
|
|
216
|
+
<div key={name} style={{ marginBottom: '20px' }}>
|
|
217
|
+
<h4 style={{ marginBottom: '10px' }}>{name}</h4>
|
|
218
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
|
|
219
|
+
<div style={{ display: 'flex' }}>
|
|
220
|
+
{colors.map((color, index) => (
|
|
221
|
+
<div
|
|
222
|
+
key={index}
|
|
223
|
+
style={{
|
|
224
|
+
width: '40px',
|
|
225
|
+
height: '40px',
|
|
226
|
+
backgroundColor: color,
|
|
227
|
+
border: '1px solid #ccc',
|
|
228
|
+
display: 'flex',
|
|
229
|
+
alignItems: 'center',
|
|
230
|
+
justifyContent: 'center',
|
|
231
|
+
fontSize: '10px',
|
|
232
|
+
color: index < colors.length / 2 ? '#000' : '#fff'
|
|
233
|
+
}}
|
|
234
|
+
title={color}
|
|
235
|
+
/>
|
|
236
|
+
))}
|
|
237
|
+
</div>
|
|
238
|
+
<code style={{ marginLeft: '10px', fontSize: '12px', color: '#666' }}>
|
|
239
|
+
{colors.join(', ')}
|
|
240
|
+
</code>
|
|
241
|
+
</div>
|
|
242
|
+
</div>
|
|
243
|
+
))}
|
|
244
|
+
|
|
245
|
+
<h3>Two-Color Palettes</h3>
|
|
246
|
+
<p>These palettes are designed for paired comparisons and side-by-side visualizations.</p>
|
|
247
|
+
{Object.entries(twoColorPaletteV2).map(([name, colors]) => (
|
|
248
|
+
<div key={name} style={{ marginBottom: '20px' }}>
|
|
249
|
+
<h4 style={{ textTransform: 'capitalize', marginBottom: '10px' }}>{name.replace(/-/g, ' ')}</h4>
|
|
250
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
|
|
251
|
+
<div style={{ display: 'flex' }}>
|
|
252
|
+
{colors.map((color, index) => (
|
|
253
|
+
<div
|
|
254
|
+
key={index}
|
|
255
|
+
style={{
|
|
256
|
+
width: '60px',
|
|
257
|
+
height: '40px',
|
|
258
|
+
backgroundColor: color,
|
|
259
|
+
border: '1px solid #ccc',
|
|
260
|
+
display: 'flex',
|
|
261
|
+
alignItems: 'center',
|
|
262
|
+
justifyContent: 'center',
|
|
263
|
+
fontSize: '10px',
|
|
264
|
+
color: '#fff',
|
|
265
|
+
textShadow: '1px 1px 1px rgba(0,0,0,0.7)'
|
|
266
|
+
}}
|
|
267
|
+
title={color}
|
|
268
|
+
/>
|
|
269
|
+
))}
|
|
270
|
+
</div>
|
|
271
|
+
<code style={{ marginLeft: '10px', fontSize: '12px', color: '#666' }}>
|
|
272
|
+
{colors.join(', ')}
|
|
273
|
+
</code>
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
))}
|
|
277
|
+
|
|
278
|
+
<h2>Map Palettes</h2>
|
|
279
|
+
<p>These palettes are primarily used for geographic visualizations and maps.</p>
|
|
280
|
+
{Object.entries(mapColorPalettesV2).map(([name, colors]) => (
|
|
281
|
+
<div key={name} style={{ marginBottom: '20px' }}>
|
|
282
|
+
<h4 style={{ textTransform: 'capitalize', marginBottom: '10px' }}>{name.replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase()}</h4>
|
|
283
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
|
|
284
|
+
<div style={{ display: 'flex' }}>
|
|
285
|
+
{colors.map((color, index) => (
|
|
286
|
+
<div
|
|
287
|
+
key={index}
|
|
288
|
+
style={{
|
|
289
|
+
width: '30px',
|
|
290
|
+
height: '40px',
|
|
291
|
+
backgroundColor: color,
|
|
292
|
+
border: '1px solid #ccc',
|
|
293
|
+
display: 'flex',
|
|
294
|
+
alignItems: 'center',
|
|
295
|
+
justifyContent: 'center',
|
|
296
|
+
fontSize: '8px',
|
|
297
|
+
color: index < colors.length / 2 ? '#000' : '#fff'
|
|
298
|
+
}}
|
|
299
|
+
title={color}
|
|
300
|
+
/>
|
|
301
|
+
))}
|
|
302
|
+
</div>
|
|
303
|
+
<code style={{ marginLeft: '10px', fontSize: '11px', color: '#666' }}>
|
|
304
|
+
[{colors.slice(0, 3).join(', ')}...] ({colors.length} colors)
|
|
305
|
+
</code>
|
|
306
|
+
</div>
|
|
307
|
+
</div>
|
|
308
|
+
))}
|
|
309
|
+
|
|
310
|
+
<h2>Usage Guidelines</h2>
|
|
311
|
+
<ul>
|
|
312
|
+
<li><strong>Accessibility</strong>: All palettes are designed to meet WCAG accessibility guidelines</li>
|
|
313
|
+
<li><strong>Color Blind Friendly</strong>: The "colorblindsafe" palette is specifically designed for color blind users</li>
|
|
314
|
+
<li><strong>Sequential Data</strong>: Use sequential palettes for ordered data (low to high values)</li>
|
|
315
|
+
<li><strong>Categorical Data</strong>: Use qualitative palettes for distinct categories</li>
|
|
316
|
+
<li><strong>Comparisons</strong>: Use two-color palettes for side-by-side comparisons</li>
|
|
317
|
+
<li><strong>Geographic Data</strong>: Use map palettes for choropleth and geographic visualizations</li>
|
|
318
|
+
</ul>
|
|
319
|
+
|
|
320
|
+
<h2>Implementation</h2>
|
|
321
|
+
<p>Import color palettes in your components:</p>
|
|
322
|
+
<pre><code>{`import { mapColorPalettesV2, colorPalettesChartV2, twoColorPalette, sequentialPalettes } from '@cdc/core/data/colorPalettes'
|
|
323
|
+
|
|
324
|
+
// Use in your visualization
|
|
325
|
+
const colors = colorPalettesChartV2['qualitative-bold']
|
|
326
|
+
const twoColors = twoColorPalette.v2['divergent-blue-orange']
|
|
327
|
+
const mapColors = mapColorPalettesV2.sequential_blue`}</code></pre>
|
|
328
|
+
</div>
|
|
329
|
+
)
|
|
330
|
+
}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import type { Meta } from '@storybook/react'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
// Import all icons
|
|
5
|
+
import AreaChartIcon from '../../../assets/icon-area-chart.svg'
|
|
6
|
+
import CaretDownIcon from '../../../assets/icon-caret-down.svg'
|
|
7
|
+
import CaretFilledDownIcon from '../../../assets/icon-caret-filled-down.svg'
|
|
8
|
+
import CaretFilledUpIcon from '../../../assets/icon-caret-filled-up.svg'
|
|
9
|
+
import CaretUpIcon from '../../../assets/icon-caret-up.svg'
|
|
10
|
+
import BarPairedIcon from '../../../assets/icon-chart-bar-paired.svg'
|
|
11
|
+
import BarStackedIcon from '../../../assets/icon-chart-bar-stacked.svg'
|
|
12
|
+
import BarChartIcon from '../../../assets/icon-chart-bar.svg'
|
|
13
|
+
import BoxWhiskerIcon from '../../../assets/icon-chart-box-whisker.svg'
|
|
14
|
+
import ForecastIcon from '../../../assets/icon-chart-forecast.svg'
|
|
15
|
+
import ForestPlotIcon from '../../../assets/icon-chart-forest-plot.svg'
|
|
16
|
+
import LineChartIcon from '../../../assets/icon-chart-line.svg'
|
|
17
|
+
import PieChartIcon from '../../../assets/icon-chart-pie.svg'
|
|
18
|
+
import ScatterplotIcon from '../../../assets/icon-chart-scatterplot.svg'
|
|
19
|
+
import StackedAreaIcon from '../../../assets/icon-chart-stacked-area.svg'
|
|
20
|
+
import CheckIcon from '../../../assets/icon-check.svg'
|
|
21
|
+
import CloseIcon from '../../../assets/icon-close.svg'
|
|
22
|
+
import CodeIcon from '../../../assets/icon-code.svg'
|
|
23
|
+
import ComboChartIcon from '../../../assets/icon-combo-chart.svg'
|
|
24
|
+
import CommandIcon from '../../../assets/icon-command.svg'
|
|
25
|
+
import DashboardIcon from '../../../assets/icon-dashboard.svg'
|
|
26
|
+
import DataBiteIcon from '../../../assets/icon-databite.svg'
|
|
27
|
+
import DeviationBarIcon from '../../../assets/icon-deviation-bar.svg'
|
|
28
|
+
import EditIcon from '../../../assets/icon-edit.svg'
|
|
29
|
+
import EpiChartIcon from '../../../assets/icon-epi-chart.svg'
|
|
30
|
+
import FileUploadIcon from '../../../assets/icon-file-upload.svg'
|
|
31
|
+
import FilterBarsIcon from '../../../assets/icon-filter-bars.svg'
|
|
32
|
+
import FilterDropdownsIcon from '../../../assets/icon-filter-dropdowns.svg'
|
|
33
|
+
import FilteredTextIcon from '../../../assets/icon-filtered-text.svg'
|
|
34
|
+
import GearIcon from '../../../assets/icon-gear.svg'
|
|
35
|
+
import GearMultiIcon from '../../../assets/icon-gear-multi.svg'
|
|
36
|
+
import GridIcon from '../../../assets/icon-grid.svg'
|
|
37
|
+
import InfoIcon from '../../../assets/icon-info.svg'
|
|
38
|
+
import LinearGaugeIcon from '../../../assets/icon-linear-gauge.svg'
|
|
39
|
+
import LinkIcon from '../../../assets/icon-link.svg'
|
|
40
|
+
import MapAlabamaIcon from '../../../assets/icon-map-alabama.svg'
|
|
41
|
+
import MapUSAIcon from '../../../assets/icon-map-usa.svg'
|
|
42
|
+
import MapWorldIcon from '../../../assets/icon-map-world.svg'
|
|
43
|
+
import MinusIcon from '../../../assets/icon-minus.svg'
|
|
44
|
+
import MoveIcon from '../../../assets/icon-move.svg'
|
|
45
|
+
import PlusIcon from '../../../assets/icon-plus.svg'
|
|
46
|
+
import QuestionCircleIcon from '../../../assets/icon-question-circle.svg'
|
|
47
|
+
import RotateLeftIcon from '../../../assets/icon-rotate-left.svg'
|
|
48
|
+
import SankeyIcon from '../../../assets/icon-sankey.svg'
|
|
49
|
+
import TableIcon from '../../../assets/icon-table.svg'
|
|
50
|
+
import ToolsIcon from '../../../assets/icon-tools.svg'
|
|
51
|
+
import UploadIcon from '../../../assets/icon-upload.svg'
|
|
52
|
+
import WarningCircleIcon from '../../../assets/icon-warning-circle.svg'
|
|
53
|
+
import WarningTriangleIcon from '../../../assets/icon-warning-triangle.svg'
|
|
54
|
+
import ExternalLinkIcon from '../../../assets/external-link.svg'
|
|
55
|
+
import MapFoldedIcon from '../../../assets/map-folded.svg'
|
|
56
|
+
import USARegionGraphicIcon from '../../../assets/usa-region-graphic.svg'
|
|
57
|
+
|
|
58
|
+
const iconList = [
|
|
59
|
+
{ name: 'Area Chart', component: AreaChartIcon, category: 'Charts' },
|
|
60
|
+
{ name: 'Bar Chart', component: BarChartIcon, category: 'Charts' },
|
|
61
|
+
{ name: 'Bar Chart Paired', component: BarPairedIcon, category: 'Charts' },
|
|
62
|
+
{ name: 'Bar Chart Stacked', component: BarStackedIcon, category: 'Charts' },
|
|
63
|
+
{ name: 'Box & Whisker', component: BoxWhiskerIcon, category: 'Charts' },
|
|
64
|
+
{ name: 'Combo Chart', component: ComboChartIcon, category: 'Charts' },
|
|
65
|
+
{ name: 'Deviation Bar', component: DeviationBarIcon, category: 'Charts' },
|
|
66
|
+
{ name: 'Epi Chart', component: EpiChartIcon, category: 'Charts' },
|
|
67
|
+
{ name: 'Forecast', component: ForecastIcon, category: 'Charts' },
|
|
68
|
+
{ name: 'Forest Plot', component: ForestPlotIcon, category: 'Charts' },
|
|
69
|
+
{ name: 'Line Chart', component: LineChartIcon, category: 'Charts' },
|
|
70
|
+
{ name: 'Linear Gauge', component: LinearGaugeIcon, category: 'Charts' },
|
|
71
|
+
{ name: 'Pie Chart', component: PieChartIcon, category: 'Charts' },
|
|
72
|
+
{ name: 'Sankey', component: SankeyIcon, category: 'Charts' },
|
|
73
|
+
{ name: 'Scatterplot', component: ScatterplotIcon, category: 'Charts' },
|
|
74
|
+
{ name: 'Stacked Area', component: StackedAreaIcon, category: 'Charts' },
|
|
75
|
+
|
|
76
|
+
{ name: 'Map Alabama', component: MapAlabamaIcon, category: 'Maps' },
|
|
77
|
+
{ name: 'Map USA', component: MapUSAIcon, category: 'Maps' },
|
|
78
|
+
{ name: 'Map World', component: MapWorldIcon, category: 'Maps' },
|
|
79
|
+
{ name: 'Map Folded', component: MapFoldedIcon, category: 'Maps' },
|
|
80
|
+
{ name: 'USA Region Graphic', component: USARegionGraphicIcon, category: 'Maps' },
|
|
81
|
+
|
|
82
|
+
{ name: 'Dashboard', component: DashboardIcon, category: 'Components' },
|
|
83
|
+
{ name: 'Data Bite', component: DataBiteIcon, category: 'Components' },
|
|
84
|
+
{ name: 'Filtered Text', component: FilteredTextIcon, category: 'Components' },
|
|
85
|
+
{ name: 'Table', component: TableIcon, category: 'Components' },
|
|
86
|
+
|
|
87
|
+
{ name: 'Filter Bars', component: FilterBarsIcon, category: 'Filters' },
|
|
88
|
+
{ name: 'Filter Dropdowns', component: FilterDropdownsIcon, category: 'Filters' },
|
|
89
|
+
|
|
90
|
+
{ name: 'Caret Down', component: CaretDownIcon, category: 'Navigation' },
|
|
91
|
+
{ name: 'Caret Filled Down', component: CaretFilledDownIcon, category: 'Navigation' },
|
|
92
|
+
{ name: 'Caret Filled Up', component: CaretFilledUpIcon, category: 'Navigation' },
|
|
93
|
+
{ name: 'Caret Up', component: CaretUpIcon, category: 'Navigation' },
|
|
94
|
+
|
|
95
|
+
{ name: 'Check', component: CheckIcon, category: 'Actions' },
|
|
96
|
+
{ name: 'Close', component: CloseIcon, category: 'Actions' },
|
|
97
|
+
{ name: 'Edit', component: EditIcon, category: 'Actions' },
|
|
98
|
+
{ name: 'File Upload', component: FileUploadIcon, category: 'Actions' },
|
|
99
|
+
{ name: 'Minus', component: MinusIcon, category: 'Actions' },
|
|
100
|
+
{ name: 'Move', component: MoveIcon, category: 'Actions' },
|
|
101
|
+
{ name: 'Plus', component: PlusIcon, category: 'Actions' },
|
|
102
|
+
{ name: 'Rotate Left', component: RotateLeftIcon, category: 'Actions' },
|
|
103
|
+
{ name: 'Upload', component: UploadIcon, category: 'Actions' },
|
|
104
|
+
|
|
105
|
+
{ name: 'Code', component: CodeIcon, category: 'Interface' },
|
|
106
|
+
{ name: 'Command', component: CommandIcon, category: 'Interface' },
|
|
107
|
+
{ name: 'External Link', component: ExternalLinkIcon, category: 'Interface' },
|
|
108
|
+
{ name: 'Gear', component: GearIcon, category: 'Interface' },
|
|
109
|
+
{ name: 'Gear Multi', component: GearMultiIcon, category: 'Interface' },
|
|
110
|
+
{ name: 'Grid', component: GridIcon, category: 'Interface' },
|
|
111
|
+
{ name: 'Info', component: InfoIcon, category: 'Interface' },
|
|
112
|
+
{ name: 'Link', component: LinkIcon, category: 'Interface' },
|
|
113
|
+
{ name: 'Question Circle', component: QuestionCircleIcon, category: 'Interface' },
|
|
114
|
+
{ name: 'Tools', component: ToolsIcon, category: 'Interface' },
|
|
115
|
+
{ name: 'Warning Circle', component: WarningCircleIcon, category: 'Interface' },
|
|
116
|
+
{ name: 'Warning Triangle', component: WarningTriangleIcon, category: 'Interface' },
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
const categories = [...new Set(iconList.map(icon => icon.category))]
|
|
120
|
+
|
|
121
|
+
const meta: Meta = {
|
|
122
|
+
title: 'Components/Atoms/Icon Gallery',
|
|
123
|
+
parameters: {
|
|
124
|
+
docs: {
|
|
125
|
+
page: () => (
|
|
126
|
+
<div style={{ padding: '20px' }}>
|
|
127
|
+
<h1>Icon Gallery</h1>
|
|
128
|
+
<p>This gallery showcases all available icons in the CDC Open Viz system, organized by category.</p>
|
|
129
|
+
|
|
130
|
+
{categories.map(category => (
|
|
131
|
+
<div key={category} style={{ marginBottom: '40px' }}>
|
|
132
|
+
<h2>{category}</h2>
|
|
133
|
+
<div style={{
|
|
134
|
+
display: 'grid',
|
|
135
|
+
gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))',
|
|
136
|
+
gap: '20px',
|
|
137
|
+
marginBottom: '20px'
|
|
138
|
+
}}>
|
|
139
|
+
{iconList
|
|
140
|
+
.filter(icon => icon.category === category)
|
|
141
|
+
.map(icon => (
|
|
142
|
+
<div
|
|
143
|
+
key={icon.name}
|
|
144
|
+
style={{
|
|
145
|
+
display: 'flex',
|
|
146
|
+
flexDirection: 'column',
|
|
147
|
+
alignItems: 'center',
|
|
148
|
+
padding: '15px',
|
|
149
|
+
border: '1px solid #e0e0e0',
|
|
150
|
+
borderRadius: '8px',
|
|
151
|
+
backgroundColor: '#fafafa'
|
|
152
|
+
}}
|
|
153
|
+
>
|
|
154
|
+
<icon.component
|
|
155
|
+
width="48"
|
|
156
|
+
height="48"
|
|
157
|
+
style={{ marginBottom: '10px' }}
|
|
158
|
+
/>
|
|
159
|
+
<span style={{
|
|
160
|
+
fontSize: '12px',
|
|
161
|
+
fontWeight: 'bold',
|
|
162
|
+
textAlign: 'center',
|
|
163
|
+
color: '#333'
|
|
164
|
+
}}>
|
|
165
|
+
{icon.name}
|
|
166
|
+
</span>
|
|
167
|
+
<code style={{
|
|
168
|
+
fontSize: '10px',
|
|
169
|
+
color: '#666',
|
|
170
|
+
marginTop: '5px',
|
|
171
|
+
textAlign: 'center',
|
|
172
|
+
wordBreak: 'break-all'
|
|
173
|
+
}}>
|
|
174
|
+
{icon.component.toString().includes('icon-')
|
|
175
|
+
? icon.component.toString().match(/icon-[^.]+/)?.[0] || 'icon'
|
|
176
|
+
: icon.component.toString().match(/[^/]+(?=\.svg)/)?.[0] || 'icon'
|
|
177
|
+
}.svg
|
|
178
|
+
</code>
|
|
179
|
+
</div>
|
|
180
|
+
))}
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
))}
|
|
184
|
+
|
|
185
|
+
<h2>Usage</h2>
|
|
186
|
+
<p>Import and use icons as React components:</p>
|
|
187
|
+
<pre><code>{`import WarningIcon from '@cdc/core/assets/icon-warning-circle.svg'
|
|
188
|
+
|
|
189
|
+
// Basic usage
|
|
190
|
+
<WarningIcon width="24" height="24" />
|
|
191
|
+
|
|
192
|
+
// With styling
|
|
193
|
+
<WarningIcon
|
|
194
|
+
width="32"
|
|
195
|
+
height="32"
|
|
196
|
+
className="warning-icon"
|
|
197
|
+
style={{ color: '#ff6b6b' }}
|
|
198
|
+
/>`}</code></pre>
|
|
199
|
+
|
|
200
|
+
<h2>Guidelines</h2>
|
|
201
|
+
<ul>
|
|
202
|
+
<li><strong>Consistent Sizing</strong>: Use standard sizes (16px, 24px, 32px, 48px) for consistency</li>
|
|
203
|
+
<li><strong>Accessibility</strong>: Always provide meaningful alt text or aria-labels when needed</li>
|
|
204
|
+
<li><strong>Color</strong>: Icons inherit the current text color by default, can be overridden with CSS</li>
|
|
205
|
+
<li><strong>Context</strong>: Choose icons that clearly represent their function or content</li>
|
|
206
|
+
<li><strong>Performance</strong>: SVG icons are optimized for fast loading and scalability</li>
|
|
207
|
+
</ul>
|
|
208
|
+
|
|
209
|
+
<h2>File Location</h2>
|
|
210
|
+
<p>All icons are located in <code>packages/core/assets/</code> and follow the naming convention:</p>
|
|
211
|
+
<ul>
|
|
212
|
+
<li><code>icon-[name].svg</code> for interface and action icons</li>
|
|
213
|
+
<li><code>[descriptive-name].svg</code> for specialized graphics</li>
|
|
214
|
+
</ul>
|
|
215
|
+
</div>
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export default meta
|
|
222
|
+
|
|
223
|
+
export const Gallery = {
|
|
224
|
+
render: () => (
|
|
225
|
+
<div style={{ padding: '20px' }}>
|
|
226
|
+
<h1>Icon Gallery</h1>
|
|
227
|
+
<p>This gallery showcases all available icons in the CDC Open Viz system, organized by category.</p>
|
|
228
|
+
|
|
229
|
+
{categories.map(category => (
|
|
230
|
+
<div key={category} style={{ marginBottom: '40px' }}>
|
|
231
|
+
<h2>{category}</h2>
|
|
232
|
+
<div style={{
|
|
233
|
+
display: 'grid',
|
|
234
|
+
gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))',
|
|
235
|
+
gap: '20px',
|
|
236
|
+
marginBottom: '20px'
|
|
237
|
+
}}>
|
|
238
|
+
{iconList
|
|
239
|
+
.filter(icon => icon.category === category)
|
|
240
|
+
.map(icon => (
|
|
241
|
+
<div
|
|
242
|
+
key={icon.name}
|
|
243
|
+
style={{
|
|
244
|
+
display: 'flex',
|
|
245
|
+
flexDirection: 'column',
|
|
246
|
+
alignItems: 'center',
|
|
247
|
+
padding: '15px',
|
|
248
|
+
border: '1px solid #e0e0e0',
|
|
249
|
+
borderRadius: '8px',
|
|
250
|
+
backgroundColor: '#fafafa'
|
|
251
|
+
}}
|
|
252
|
+
>
|
|
253
|
+
<icon.component
|
|
254
|
+
width="48"
|
|
255
|
+
height="48"
|
|
256
|
+
style={{ marginBottom: '10px' }}
|
|
257
|
+
/>
|
|
258
|
+
<span style={{
|
|
259
|
+
fontSize: '12px',
|
|
260
|
+
fontWeight: 'bold',
|
|
261
|
+
textAlign: 'center',
|
|
262
|
+
color: '#333'
|
|
263
|
+
}}>
|
|
264
|
+
{icon.name}
|
|
265
|
+
</span>
|
|
266
|
+
<code style={{
|
|
267
|
+
fontSize: '10px',
|
|
268
|
+
color: '#666',
|
|
269
|
+
marginTop: '5px',
|
|
270
|
+
textAlign: 'center',
|
|
271
|
+
wordBreak: 'break-all'
|
|
272
|
+
}}>
|
|
273
|
+
{icon.component.toString().includes('icon-')
|
|
274
|
+
? icon.component.toString().match(/icon-[^.]+/)?.[0] || 'icon'
|
|
275
|
+
: icon.component.toString().match(/[^/]+(?=\.svg)/)?.[0] || 'icon'
|
|
276
|
+
}.svg
|
|
277
|
+
</code>
|
|
278
|
+
</div>
|
|
279
|
+
))}
|
|
280
|
+
</div>
|
|
281
|
+
</div>
|
|
282
|
+
))}
|
|
283
|
+
|
|
284
|
+
<h2>Usage</h2>
|
|
285
|
+
<p>Import and use icons as React components:</p>
|
|
286
|
+
<pre><code>{`import WarningIcon from '@cdc/core/assets/icon-warning-circle.svg'
|
|
287
|
+
|
|
288
|
+
// Basic usage
|
|
289
|
+
<WarningIcon width="24" height="24" />
|
|
290
|
+
|
|
291
|
+
// With styling
|
|
292
|
+
<WarningIcon
|
|
293
|
+
width="32"
|
|
294
|
+
height="32"
|
|
295
|
+
className="warning-icon"
|
|
296
|
+
style={{ color: '#ff6b6b' }}
|
|
297
|
+
/>`}</code></pre>
|
|
298
|
+
|
|
299
|
+
<h2>Guidelines</h2>
|
|
300
|
+
<ul>
|
|
301
|
+
<li><strong>Consistent Sizing</strong>: Use standard sizes (16px, 24px, 32px, 48px) for consistency</li>
|
|
302
|
+
<li><strong>Accessibility</strong>: Always provide meaningful alt text or aria-labels when needed</li>
|
|
303
|
+
<li><strong>Color</strong>: Icons inherit the current text color by default, can be overridden with CSS</li>
|
|
304
|
+
<li><strong>Context</strong>: Choose icons that clearly represent their function or content</li>
|
|
305
|
+
<li><strong>Performance</strong>: SVG icons are optimized for fast loading and scalability</li>
|
|
306
|
+
</ul>
|
|
307
|
+
|
|
308
|
+
<h2>File Location</h2>
|
|
309
|
+
<p>All icons are located in <code>packages/core/assets/</code> and follow the naming convention:</p>
|
|
310
|
+
<ul>
|
|
311
|
+
<li><code>icon-[name].svg</code> for interface and action icons</li>
|
|
312
|
+
<li><code>[descriptive-name].svg</code> for specialized graphics</li>
|
|
313
|
+
</ul>
|
|
314
|
+
</div>
|
|
315
|
+
)
|
|
316
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { WCMSProps } from '@cdc/core/types/WCMSProps'
|
|
2
|
+
import { Dispatch, createContext } from 'react'
|
|
3
|
+
import EditorActions from './editor.actions'
|
|
4
|
+
import { EditorState } from '@cdc/core/contexts/editor.reducer'
|
|
5
|
+
|
|
6
|
+
export type EditorCTX = WCMSProps &
|
|
7
|
+
EditorState & {
|
|
8
|
+
displayName?: string
|
|
9
|
+
setTempConfig: Function
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const ConfigContext = createContext<EditorCTX>({
|
|
13
|
+
displayName: 'ConfigContext',
|
|
14
|
+
setTempConfig: () => {}
|
|
15
|
+
} as unknown as EditorCTX)
|
|
16
|
+
|
|
17
|
+
export default ConfigContext
|
|
18
|
+
export const EditorDispatchContext = createContext<Dispatch<EditorActions>>(() => {})
|