@neo4j-ndl/react-charts 1.2.11 → 1.2.13

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 (59) hide show
  1. package/lib/cjs/charts/LegendLayout.js +1 -1
  2. package/lib/cjs/charts/LegendLayout.js.map +1 -1
  3. package/lib/cjs/charts/hooks/use-legend-interactions.js +4 -4
  4. package/lib/cjs/charts/hooks/use-legend-interactions.js.map +1 -1
  5. package/lib/cjs/charts/hooks/use-legend-series.js +1 -1
  6. package/lib/cjs/charts/hooks/use-legend-series.js.map +1 -1
  7. package/lib/cjs/charts/hooks/use-legend-visibility.js +1 -1
  8. package/lib/cjs/charts/hooks/use-legend-visibility.js.map +1 -1
  9. package/lib/cjs/charts/tests/ChartZoomHarness.js +3 -1
  10. package/lib/cjs/charts/tests/ChartZoomHarness.js.map +1 -1
  11. package/lib/cjs/charts/tests/PieChartWithRerender.js +1 -1
  12. package/lib/cjs/charts/tests/PieChartWithRerender.js.map +1 -1
  13. package/lib/cjs/charts/tests/chart-test-utils.js +19 -8
  14. package/lib/cjs/charts/tests/chart-test-utils.js.map +1 -1
  15. package/lib/cjs/charts/utils/aria-description.js +7 -7
  16. package/lib/cjs/charts/utils/aria-description.js.map +1 -1
  17. package/lib/cjs/charts/utils/build-chart-option.js +1 -1
  18. package/lib/cjs/charts/utils/build-chart-option.js.map +1 -1
  19. package/lib/cjs/charts/utils/chart-types.js.map +1 -1
  20. package/lib/cjs/charts/utils/format-utils.js.map +1 -1
  21. package/lib/cjs/charts/utils/legend-utils.js +2 -2
  22. package/lib/cjs/charts/utils/legend-utils.js.map +1 -1
  23. package/lib/cjs/charts/utils/user-option-utils.js +2 -2
  24. package/lib/cjs/charts/utils/user-option-utils.js.map +1 -1
  25. package/lib/esm/charts/LegendLayout.js +1 -1
  26. package/lib/esm/charts/LegendLayout.js.map +1 -1
  27. package/lib/esm/charts/hooks/use-legend-interactions.js +4 -4
  28. package/lib/esm/charts/hooks/use-legend-interactions.js.map +1 -1
  29. package/lib/esm/charts/hooks/use-legend-series.js +1 -1
  30. package/lib/esm/charts/hooks/use-legend-series.js.map +1 -1
  31. package/lib/esm/charts/hooks/use-legend-visibility.js +1 -1
  32. package/lib/esm/charts/hooks/use-legend-visibility.js.map +1 -1
  33. package/lib/esm/charts/tests/ChartZoomHarness.js +3 -1
  34. package/lib/esm/charts/tests/ChartZoomHarness.js.map +1 -1
  35. package/lib/esm/charts/tests/PieChartWithRerender.js +1 -1
  36. package/lib/esm/charts/tests/PieChartWithRerender.js.map +1 -1
  37. package/lib/esm/charts/tests/chart-test-utils.js +19 -8
  38. package/lib/esm/charts/tests/chart-test-utils.js.map +1 -1
  39. package/lib/esm/charts/utils/aria-description.js +7 -7
  40. package/lib/esm/charts/utils/aria-description.js.map +1 -1
  41. package/lib/esm/charts/utils/build-chart-option.js +1 -1
  42. package/lib/esm/charts/utils/build-chart-option.js.map +1 -1
  43. package/lib/esm/charts/utils/chart-types.js.map +1 -1
  44. package/lib/esm/charts/utils/format-utils.js.map +1 -1
  45. package/lib/esm/charts/utils/legend-utils.js +2 -2
  46. package/lib/esm/charts/utils/legend-utils.js.map +1 -1
  47. package/lib/esm/charts/utils/user-option-utils.js +2 -2
  48. package/lib/esm/charts/utils/user-option-utils.js.map +1 -1
  49. package/lib/types/charts/hooks/use-legend-visibility.d.ts.map +1 -1
  50. package/lib/types/charts/tests/ChartZoomHarness.d.ts.map +1 -1
  51. package/lib/types/charts/tests/chart-test-utils.d.ts.map +1 -1
  52. package/lib/types/charts/utils/aria-description.d.ts.map +1 -1
  53. package/lib/types/charts/utils/chart-types.d.ts.map +1 -1
  54. package/lib/types/charts/utils/format-utils.d.ts.map +1 -1
  55. package/lib/types/charts/utils/user-option-utils.d.ts.map +1 -1
  56. package/package.json +3 -3
  57. package/skills/ndl-react-charts/SKILL.md +31 -0
  58. package/skills/ndl-react-charts/components/charts.md +91 -22
  59. package/skills/ndl-react-charts/references/styling.md +142 -0
@@ -103,18 +103,24 @@ const Component = () => {
103
103
  },
104
104
  {
105
105
  datasetIndex: 0,
106
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
107
+ // oxlint-disable-next-line id-length
106
108
  encode: { x: 'a', y: 'b' },
107
109
  name: 'first (dataset 0, dimension b)',
108
110
  type: 'line',
109
111
  },
110
112
  {
111
113
  datasetIndex: 0,
114
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
115
+ // oxlint-disable-next-line id-length
112
116
  encode: { x: 'a', y: 'c' },
113
117
  name: 'second (dataset 0, dimension c)',
114
118
  type: 'line',
115
119
  },
116
120
  {
117
121
  datasetIndex: 1,
122
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
123
+ // oxlint-disable-next-line id-length
118
124
  encode: { x: 'x', y: 'y' },
119
125
  name: 'third (dataset 1, dimension y)',
120
126
  symbol: 'emptyCircle',
@@ -130,6 +136,8 @@ const Component = () => {
130
136
  [390, 180],
131
137
  [470, 220],
132
138
  ],
139
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
140
+ // oxlint-disable-next-line id-length
133
141
  encode: { x: 'x', y: 'y' },
134
142
  name: 'fourth (inlined data)',
135
143
  type: 'line',
@@ -145,6 +153,8 @@ const Component = () => {
145
153
  [450, 200],
146
154
  [500, 100],
147
155
  ],
156
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
157
+ // oxlint-disable-next-line id-length
148
158
  encode: { x: 'x', y: 'y' },
149
159
  name: 'fifth (inlined data)',
150
160
  symbol: 'emptyCircle',
@@ -231,6 +241,8 @@ const Component = () => {
231
241
  origin: 'start',
232
242
  },
233
243
  datasetIndex: 1,
244
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
245
+ // oxlint-disable-next-line id-length
234
246
  encode: { x: 'x', y: 'y' },
235
247
  name: 'min',
236
248
  stack: 'the stack id',
@@ -239,6 +251,8 @@ const Component = () => {
239
251
  {
240
252
  areaStyle: {},
241
253
  datasetIndex: 2,
254
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
255
+ // oxlint-disable-next-line id-length
242
256
  encode: { x: 'x', y: 'y' },
243
257
  name: 'average',
244
258
  stack: 'the stack id',
@@ -249,6 +263,8 @@ const Component = () => {
249
263
  origin: 'start',
250
264
  },
251
265
  datasetIndex: 0,
266
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
267
+ // oxlint-disable-next-line id-length
252
268
  encode: { x: 'x', y: 'y' },
253
269
  name: 'max',
254
270
  stack: 'the stack id',
@@ -299,10 +315,9 @@ const Component = () => {
299
315
  }}
300
316
  series={[
301
317
  {
302
- encode: {
303
- x: 'month',
304
- y: 'Revenue',
305
- },
318
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
319
+ // oxlint-disable-next-line id-length
320
+ encode: { x: 'month', y: 'Revenue' },
306
321
  name: 'Revenue',
307
322
  type: 'line',
308
323
  },
@@ -368,26 +383,23 @@ const Component = () => {
368
383
  }}
369
384
  series={[
370
385
  {
371
- encode: {
372
- x: 'First',
373
- y: 'day',
374
- },
386
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
387
+ // oxlint-disable-next-line id-length
388
+ encode: { x: 'First', y: 'day' },
375
389
  name: 'First',
376
390
  type: 'bar',
377
391
  },
378
392
  {
379
- encode: {
380
- x: 'Second',
381
- y: 'day',
382
- },
393
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
394
+ // oxlint-disable-next-line id-length
395
+ encode: { x: 'Second', y: 'day' },
383
396
  name: 'Second',
384
397
  type: 'bar',
385
398
  },
386
399
  {
387
- encode: {
388
- x: 'Third',
389
- y: 'day',
390
- },
400
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
401
+ // oxlint-disable-next-line id-length
402
+ encode: { x: 'Third', y: 'day' },
391
403
  name: 'Third',
392
404
  type: 'bar',
393
405
  },
@@ -444,12 +456,16 @@ const Component = () => {
444
456
  }}
445
457
  series={[
446
458
  {
459
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
460
+ // oxlint-disable-next-line id-length
447
461
  encode: { x: 'People', y: 'day' },
448
462
  name: 'People',
449
463
  stack: 'total',
450
464
  type: 'bar',
451
465
  },
452
466
  {
467
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
468
+ // oxlint-disable-next-line id-length
453
469
  encode: { x: 'Beer', y: 'day' },
454
470
  itemStyle: { color: '#f28e1c' },
455
471
  name: 'Beer',
@@ -625,10 +641,9 @@ const Component = () => {
625
641
  }}
626
642
  series={[
627
643
  {
628
- encode: {
629
- x: 'Country',
630
- y: 'Sales',
631
- },
644
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
645
+ // oxlint-disable-next-line id-length
646
+ encode: { x: 'Country', y: 'Sales' },
632
647
  name: 'Sales',
633
648
  type: 'bar' as const,
634
649
  },
@@ -684,30 +699,40 @@ const Component = () => {
684
699
  series={[
685
700
  {
686
701
  datasetIndex: 0,
702
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
703
+ // oxlint-disable-next-line id-length
687
704
  encode: { x: 'x', y: 'a' },
688
705
  name: 'Alpha',
689
706
  type: 'line',
690
707
  },
691
708
  {
692
709
  datasetIndex: 0,
710
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
711
+ // oxlint-disable-next-line id-length
693
712
  encode: { x: 'x', y: 'b' },
694
713
  name: 'Beta',
695
714
  type: 'line',
696
715
  },
697
716
  {
698
717
  datasetIndex: 0,
718
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
719
+ // oxlint-disable-next-line id-length
699
720
  encode: { x: 'x', y: 'c' },
700
721
  name: 'Gamma',
701
722
  type: 'line',
702
723
  },
703
724
  {
704
725
  datasetIndex: 0,
726
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
727
+ // oxlint-disable-next-line id-length
705
728
  encode: { x: 'x', y: 'd' },
706
729
  name: 'Delta',
707
730
  type: 'line',
708
731
  },
709
732
  {
710
733
  datasetIndex: 0,
734
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
735
+ // oxlint-disable-next-line id-length
711
736
  encode: { x: 'x', y: 'e' },
712
737
  name: 'Epsilon',
713
738
  type: 'line',
@@ -742,7 +767,7 @@ const outliers = new Map<number, [number, number]>([
742
767
 
743
768
  const sampleData = [
744
769
  ['time', 'response time', 'request volume'],
745
- ...Array.from({ length: 180 }, (_, index) => {
770
+ ...Array.from({ length: 180 }, (_unused, index) => {
746
771
  const normalResponseTime =
747
772
  38 + Math.sin(index / 6) * 13 + Math.cos(index / 17) * 7;
748
773
  const normalRequestVolume =
@@ -801,11 +826,15 @@ const Component = () => {
801
826
  yAxis: 110,
802
827
  },
803
828
  {
829
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
830
+ // oxlint-disable-next-line id-length
804
831
  encode: { x: 'time', y: 'response time' },
805
832
  name: 'Response time',
806
833
  type: 'line',
807
834
  },
808
835
  {
836
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
837
+ // oxlint-disable-next-line id-length
809
838
  encode: { x: 'time', y: 'request volume' },
810
839
  name: 'Request volume',
811
840
  type: 'line',
@@ -925,18 +954,24 @@ const Component = () => {
925
954
  },
926
955
  {
927
956
  datasetIndex: 0,
957
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
958
+ // oxlint-disable-next-line id-length
928
959
  encode: { x: 'a', y: 'b' },
929
960
  name: 'first (dataset 0, dimension b)',
930
961
  type: 'line',
931
962
  },
932
963
  {
933
964
  datasetIndex: 0,
965
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
966
+ // oxlint-disable-next-line id-length
934
967
  encode: { x: 'a', y: 'c' },
935
968
  name: 'second (dataset 0, dimension c)',
936
969
  type: 'line',
937
970
  },
938
971
  {
939
972
  datasetIndex: 1,
973
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
974
+ // oxlint-disable-next-line id-length
940
975
  encode: { x: 'x', y: 'y' },
941
976
  name: 'third (dataset 1, dimension y)',
942
977
  symbol: 'emptyCircle',
@@ -952,6 +987,8 @@ const Component = () => {
952
987
  [390, 180],
953
988
  [470, 220],
954
989
  ],
990
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
991
+ // oxlint-disable-next-line id-length
955
992
  encode: { x: 'x', y: 'y' },
956
993
  name: 'fourth (inlined data)',
957
994
  type: 'line',
@@ -967,6 +1004,8 @@ const Component = () => {
967
1004
  [450, 200],
968
1005
  [500, 100],
969
1006
  ],
1007
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
1008
+ // oxlint-disable-next-line id-length
970
1009
  encode: { x: 'x', y: 'y' },
971
1010
  name: 'fifth (inlined data)',
972
1011
  symbol: 'emptyCircle',
@@ -1129,18 +1168,24 @@ const Component = () => {
1129
1168
  },
1130
1169
  {
1131
1170
  datasetIndex: 0,
1171
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
1172
+ // oxlint-disable-next-line id-length
1132
1173
  encode: { x: 'a', y: 'b' },
1133
1174
  name: 'first (dataset 0, dimension b)',
1134
1175
  type: 'line',
1135
1176
  },
1136
1177
  {
1137
1178
  datasetIndex: 0,
1179
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
1180
+ // oxlint-disable-next-line id-length
1138
1181
  encode: { x: 'a', y: 'c' },
1139
1182
  name: 'second (dataset 0, dimension c)',
1140
1183
  type: 'line',
1141
1184
  },
1142
1185
  {
1143
1186
  datasetIndex: 1,
1187
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
1188
+ // oxlint-disable-next-line id-length
1144
1189
  encode: { x: 'x', y: 'y' },
1145
1190
  name: 'third (dataset 1, dimension y)',
1146
1191
  symbol: 'emptyCircle',
@@ -1156,6 +1201,8 @@ const Component = () => {
1156
1201
  [390, 180],
1157
1202
  [470, 220],
1158
1203
  ],
1204
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
1205
+ // oxlint-disable-next-line id-length
1159
1206
  encode: { x: 'x', y: 'y' },
1160
1207
  name: 'fourth (inlined data)',
1161
1208
  type: 'line',
@@ -1171,6 +1218,8 @@ const Component = () => {
1171
1218
  [450, 200],
1172
1219
  [500, 100],
1173
1220
  ],
1221
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
1222
+ // oxlint-disable-next-line id-length
1174
1223
  encode: { x: 'x', y: 'y' },
1175
1224
  name: 'fifth (inlined data)',
1176
1225
  symbol: 'emptyCircle',
@@ -1265,18 +1314,24 @@ const Component = () => {
1265
1314
  },
1266
1315
  {
1267
1316
  datasetIndex: 0,
1317
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
1318
+ // oxlint-disable-next-line id-length
1268
1319
  encode: { x: 'a', y: 'b' },
1269
1320
  name: 'first (dataset 0, dimension b)',
1270
1321
  type: 'line',
1271
1322
  },
1272
1323
  {
1273
1324
  datasetIndex: 0,
1325
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
1326
+ // oxlint-disable-next-line id-length
1274
1327
  encode: { x: 'a', y: 'c' },
1275
1328
  name: 'second (dataset 0, dimension c)',
1276
1329
  type: 'line',
1277
1330
  },
1278
1331
  {
1279
1332
  datasetIndex: 1,
1333
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
1334
+ // oxlint-disable-next-line id-length
1280
1335
  encode: { x: 'x', y: 'y' },
1281
1336
  name: 'third (dataset 1, dimension y)',
1282
1337
  symbol: 'emptyCircle',
@@ -1292,6 +1347,8 @@ const Component = () => {
1292
1347
  [390, 180],
1293
1348
  [470, 220],
1294
1349
  ],
1350
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
1351
+ // oxlint-disable-next-line id-length
1295
1352
  encode: { x: 'x', y: 'y' },
1296
1353
  markArea: {
1297
1354
  data: [
@@ -1324,6 +1381,8 @@ const Component = () => {
1324
1381
  [450, 200],
1325
1382
  [500, 100],
1326
1383
  ],
1384
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
1385
+ // oxlint-disable-next-line id-length
1327
1386
  encode: { x: 'x', y: 'y' },
1328
1387
  name: 'fifth (inlined data)',
1329
1388
  symbol: 'emptyCircle',
@@ -1416,7 +1475,7 @@ const Component = () => {
1416
1475
  const handleToggleYDimension = (yDimension: (typeof yDimensions)[number]) => {
1417
1476
  setCheckedYDimensions(
1418
1477
  (checkedYDimensions.includes(yDimension)
1419
- ? checkedYDimensions.filter((d) => d !== yDimension)
1478
+ ? checkedYDimensions.filter((dimension) => dimension !== yDimension)
1420
1479
  : [...checkedYDimensions, yDimension]
1421
1480
  ).sort(),
1422
1481
  );
@@ -1447,6 +1506,8 @@ const Component = () => {
1447
1506
  },
1448
1507
  },
1449
1508
  series: checkedYDimensions.map((yDimension) => ({
1509
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
1510
+ // oxlint-disable-next-line id-length
1450
1511
  encode: { x: 'x', y: yDimension },
1451
1512
  id: yDimension,
1452
1513
  name: yDimensionNames[yDimension],
@@ -1845,12 +1906,16 @@ const Component = () => {
1845
1906
  },
1846
1907
  {
1847
1908
  datasetIndex: 0,
1909
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
1910
+ // oxlint-disable-next-line id-length
1848
1911
  encode: { x: 'a', y: 'b' },
1849
1912
  name: 'this is one',
1850
1913
  type: 'line',
1851
1914
  },
1852
1915
  {
1853
1916
  datasetIndex: 1,
1917
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
1918
+ // oxlint-disable-next-line id-length
1854
1919
  encode: { x: 'x', y: 'y' },
1855
1920
  name: 'This is two',
1856
1921
  symbol: 'emptyCircle',
@@ -2011,12 +2076,16 @@ const Component = () => {
2011
2076
  },
2012
2077
  {
2013
2078
  datasetIndex: 0,
2079
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
2080
+ // oxlint-disable-next-line id-length
2014
2081
  encode: { x: 'time', y: 'querySuccessRate' },
2015
2082
  name: 'Query success rate',
2016
2083
  type: 'line',
2017
2084
  },
2018
2085
  {
2019
2086
  datasetIndex: 0,
2087
+ // E-Charts uses encode.x and encode.y - https://echarts.apache.org/en/option.html#series-line.encode
2088
+ // oxlint-disable-next-line id-length
2020
2089
  encode: { x: 'time', y: 'pageCacheHitRate' },
2021
2090
  name: 'Page cache hit rate',
2022
2091
  type: 'line',
@@ -0,0 +1,142 @@
1
+ # Styling reference
2
+
3
+ The stylesheet is the source of truth for which classes and custom properties
4
+ exist. **Never hardcode a class name or token value from memory** — verify it
5
+ against the shipped CSS first.
6
+
7
+ ## Where the stylesheet lives
8
+
9
+ ```
10
+ node_modules/@neo4j-ndl/base/lib/neo4j-ds-styles.css
11
+ ```
12
+
13
+ When checking whether a class or custom property exists, grep the built file —
14
+ not the source `.pcss` — because Tailwind tree-shakes classes that no source
15
+ file uses.
16
+
17
+ ### Quick verification
18
+
19
+ ```sh
20
+ CSS=node_modules/@neo4j-ndl/base/lib/neo4j-ds-styles.css
21
+ grep -qE '\.n-flex\b' "$CSS" && echo "exists" || echo "MISSING"
22
+ grep -qE -- '--space-8:' "$CSS" && echo "exists" || echo "MISSING"
23
+ ```
24
+
25
+ ## Tokens only — never raw color values
26
+
27
+ Chart colors and surrounding UI must **never** contain hardcoded `hex`,
28
+ `rgb()`, `oklch()`, or arbitrary Tailwind color values. All colors come from
29
+ Needle's token system:
30
+
31
+ ### Chart-specific tokens
32
+
33
+ For ECharts color options, import the token object and reference data-viz
34
+ tokens:
35
+
36
+ ```tsx
37
+ import { tokens } from '@neo4j-ndl/base';
38
+
39
+ // Categorical series colors
40
+ const seriesColors = Object.values(tokens.categorical);
41
+
42
+ // Graph palette
43
+ const nodeColor = tokens.graph.nodeDefault;
44
+ ```
45
+
46
+ These are raw palette values appropriate for chart series, not theme-aware
47
+ semantic colors.
48
+
49
+ ### Semantic theme tokens (for surrounding UI)
50
+
51
+ For layout, labels, and controls around the chart, use semantic custom
52
+ properties that adapt to light/dark theme:
53
+
54
+ ```css
55
+ /* ✅ Token — adapts to theme */
56
+ color: var(--theme-color-neutral-text-default);
57
+ background: var(--theme-color-primary-bg-weak);
58
+
59
+ /* ❌ Hardcoded — breaks dark mode */
60
+ color: #1a1b1d;
61
+ background: rgb(10 97 144);
62
+ ```
63
+
64
+ | Family | CSS custom property prefix |
65
+ |--------|---------------------------|
66
+ | Neutral | `--theme-color-neutral-*` |
67
+ | Primary | `--theme-color-primary-*` |
68
+ | Danger | `--theme-color-danger-*` |
69
+ | Warning | `--theme-color-warning-*` |
70
+ | Success | `--theme-color-success-*` |
71
+ | Discovery | `--theme-color-discovery-*` |
72
+
73
+ Each family provides: `text`, `icon`, `bg-weak`, `bg-strong`, `bg-status`,
74
+ `border-strong`, `border-weak` (primary/danger also have `hover-*`,
75
+ `pressed-*`).
76
+
77
+ ### Space and border-radius tokens
78
+
79
+ | Token | Value |
80
+ |-------|-------|
81
+ | `--space-2` | 2px |
82
+ | `--space-4` | 4px |
83
+ | `--space-6` | 6px |
84
+ | `--space-8` | 8px |
85
+ | `--space-12` | 12px |
86
+ | `--space-16` | 16px |
87
+ | `--space-20` | 20px |
88
+ | `--space-24` | 24px |
89
+ | `--space-32` | 32px |
90
+ | `--space-48` | 48px |
91
+ | `--space-64` | 64px |
92
+
93
+ | Token | Value |
94
+ |-------|-------|
95
+ | `--border-radius-none` | 0 |
96
+ | `--border-radius-sm` | 4px |
97
+ | `--border-radius-md` | 6px |
98
+ | `--border-radius-lg` | 8px |
99
+ | `--border-radius-xl` | 12px |
100
+ | `--border-radius-2xl` | 16px |
101
+ | `--border-radius-3xl` | 24px |
102
+ | `--border-radius-full` | 9999px |
103
+
104
+ Prefer `Flex`, `Box`, and `Typography` from `@neo4j-ndl/react` with typed token
105
+ props over raw utility classes for layout.
106
+
107
+ ## The `n-` prefix
108
+
109
+ The Tailwind preset sets `prefix: 'n-'`. With the published preset and no
110
+ override, `n-flex`, `n-gap-4`, `n-bg-primary-bg-weak` work. If the consuming
111
+ app sets its own `prefix` (including `prefix: ''`), the app's config wins.
112
+ Check the app's `tailwind.config` before assuming `n-` is correct.
113
+
114
+ ## How to verify before writing
115
+
116
+ 1. **Check component props first.** `Flex`, `Box`, `Typography` from
117
+ `@neo4j-ndl/react` accept typed token values — prefer them over classes or
118
+ `htmlAttributes`. See the customization hierarchy below.
119
+ 2. **Check the stylesheet**: grep `neo4j-ds-styles.css` for the exact class
120
+ or property.
121
+ 3. **Never copy a class from another library** (MUI, Radix, Chakra, plain
122
+ Tailwind). They won't exist in the Needle stylesheet.
123
+
124
+ ## Customization hierarchy
125
+
126
+ When adjusting surrounding UI from `@neo4j-ndl/react`, work through these in
127
+ order. Each level is more error-prone than the one before it:
128
+
129
+ 1. **Component props** — typed, token-constrained, and type-checked. Always the
130
+ first choice. Examples: `gap="8"`, `padding="12"`, `variant="danger"`,
131
+ `size="small"`, `ariaLabel`.
132
+
133
+ 2. **`className`** — for utility classes the component doesn't cover. Verify
134
+ every class against
135
+ `node_modules/@neo4j-ndl/base/lib/neo4j-ds-styles.css`. A wrong class compiles
136
+ and silently renders nothing.
137
+
138
+ 3. **`htmlAttributes`** — escape hatch for native HTML attributes, `aria-*`, and
139
+ `data-*` the component doesn't expose as props (e.g. `id` for
140
+ `aria-controls` references, `aria-haspopup` on a trigger, `type="email"` on
141
+ a `TextInput`, `href` on `Typography` with `as="a"`). Do **not** use it to
142
+ override behavior the component already provides via props, or for styling.