@scality/core-ui 0.167.0 → 0.169.0

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 (45) hide show
  1. package/.github/workflows/github-pages.yml +5 -3
  2. package/.storybook/preview.js +1 -0
  3. package/dist/components/barchartv2/Barchart.component.d.ts +5 -1
  4. package/dist/components/barchartv2/Barchart.component.d.ts.map +1 -1
  5. package/dist/components/barchartv2/Barchart.component.js +12 -7
  6. package/dist/components/barchartv2/ChartTooltip.d.ts +9 -13
  7. package/dist/components/barchartv2/ChartTooltip.d.ts.map +1 -1
  8. package/dist/components/barchartv2/ChartTooltip.js +14 -4
  9. package/dist/components/barchartv2/utils.d.ts +9 -2
  10. package/dist/components/barchartv2/utils.d.ts.map +1 -1
  11. package/dist/components/barchartv2/utils.js +14 -18
  12. package/dist/components/buttonv2/Buttonv2.component.d.ts.map +1 -1
  13. package/dist/components/buttonv2/Buttonv2.component.js +27 -6
  14. package/dist/components/date/FormattedDateTime.d.ts +20 -1
  15. package/dist/components/date/FormattedDateTime.d.ts.map +1 -1
  16. package/dist/components/date/FormattedDateTime.js +36 -0
  17. package/dist/components/linetemporalchart/ChartUtil.d.ts.map +1 -1
  18. package/dist/components/linetemporalchart/ChartUtil.js +6 -0
  19. package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts +7 -1
  20. package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts.map +1 -1
  21. package/dist/components/linetimeseriechart/linetimeseriechart.component.js +36 -32
  22. package/dist/components/linetimeseriechart/utils.d.ts +16 -0
  23. package/dist/components/linetimeseriechart/utils.d.ts.map +1 -0
  24. package/dist/components/linetimeseriechart/utils.js +28 -0
  25. package/dist/style/theme.d.ts +2 -2
  26. package/dist/style/theme.d.ts.map +1 -1
  27. package/dist/style/theme.js +26 -0
  28. package/package.json +5 -4
  29. package/src/lib/components/barchartv2/Barchart.component.test.tsx +12 -8
  30. package/src/lib/components/barchartv2/Barchart.component.tsx +29 -9
  31. package/src/lib/components/barchartv2/ChartTooltip.test.tsx +119 -0
  32. package/src/lib/components/barchartv2/ChartTooltip.tsx +49 -19
  33. package/src/lib/components/barchartv2/utils.test.ts +31 -46
  34. package/src/lib/components/barchartv2/utils.ts +24 -31
  35. package/src/lib/components/buttonv2/Buttonv2.component.tsx +27 -6
  36. package/src/lib/components/date/FormattedDateTime.tsx +43 -1
  37. package/src/lib/components/linetemporalchart/ChartUtil.ts +6 -0
  38. package/src/lib/components/linetimeseriechart/linetimeseriechart.component.tsx +81 -54
  39. package/src/lib/components/linetimeseriechart/linetimeseriechart.test.tsx +71 -0
  40. package/src/lib/components/linetimeseriechart/utils.test.ts +87 -0
  41. package/src/lib/components/linetimeseriechart/utils.ts +43 -0
  42. package/src/lib/style/theme.ts +26 -0
  43. package/stories/BarChart/barchart.stories.tsx +108 -13
  44. package/stories/color.mdx +12 -0
  45. package/stories/linetimeseriechart.stories.tsx +97 -0
@@ -8,7 +8,8 @@ import {
8
8
  YAxis,
9
9
  CartesianGrid,
10
10
  } from 'recharts';
11
- import { useMemo, useRef } from 'react';
11
+ import type { Payload } from 'recharts/types/component/DefaultTooltipContent';
12
+ import { useCallback, useMemo, useRef } from 'react';
12
13
  import { useTheme } from 'styled-components';
13
14
  import { addMissingDataPoint } from '../linetemporalchart/ChartUtil';
14
15
  import styled from 'styled-components';
@@ -20,10 +21,15 @@ import { spacing } from '../../spacing';
20
21
  import { getUnitLabel } from '../linetemporalchart/ChartUtil';
21
22
  import { Icon } from '../icon/Icon.component';
22
23
  import { Tooltip as TooltipComponent } from '../tooltip/Tooltip.component';
23
- import {
24
- DAY_MONTH_ABBREVIATED_HOUR_MINUTE,
25
- FormattedDateTime,
26
- } from '../date/FormattedDateTime';
24
+ import { FormattedDateTime } from '../date/FormattedDateTime';
25
+ import { Box } from '../box/Box';
26
+ import { formatXAxisLabel } from './utils';
27
+
28
+ type TooltipPayload = Payload<number, string> & {
29
+ value: number;
30
+ name: string;
31
+ color: string;
32
+ };
27
33
 
28
34
  const LineTemporalChartWrapper = styled.div`
29
35
  display: flex;
@@ -60,6 +66,8 @@ const TooltipValue = styled.div`
60
66
  color: ${(props) => props.theme.textSecondary};
61
67
  display: flex;
62
68
  align-items: flex-start;
69
+ justify-content: space-between;
70
+ width: 100%;
63
71
  `;
64
72
 
65
73
  const TooltipLegend = styled.div<{ color: string }>`
@@ -71,21 +79,23 @@ const TooltipLegend = styled.div<{ color: string }>`
71
79
  margin-top: 8px;
72
80
  `;
73
81
 
74
- const TooltipContent = styled.div`
82
+ const TooltipLeftGroup = styled.div`
75
83
  display: flex;
84
+ align-items: flex-start;
76
85
  min-width: 0;
77
86
  flex: 1;
78
87
  `;
79
88
 
80
89
  const TooltipName = styled.div`
81
- margin-right: 4px;
82
90
  word-wrap: break-word;
83
91
  word-break: break-word;
84
- justify-content: flex-start;
92
+ flex: 1;
85
93
  `;
86
94
 
87
95
  const TooltipInstanceValue = styled.div`
88
- justify-content: flex-end;
96
+ margin-left: 16px;
97
+ flex-shrink: 0;
98
+ text-align: right;
89
99
  `;
90
100
 
91
101
  export type Serie = {
@@ -129,6 +139,12 @@ export type LineChartProps = (
129
139
  label: string;
130
140
  }[];
131
141
  isLoading?: boolean;
142
+ /**
143
+ * The format of the x axis, default is 'date-time' which is like 01 Sep 16:00
144
+ * If you want to display the date only, you can set it to 'date' which is like 2025-09-01
145
+ * This will affect the format of the tooltip as well
146
+ */
147
+ timeFormat?: 'date-time' | 'date';
132
148
  yAxisTitle?: string;
133
149
  helpText?: string;
134
150
  };
@@ -138,23 +154,20 @@ const CustomTooltip = ({
138
154
  payload,
139
155
  label,
140
156
  unitLabel,
157
+ timeFormat,
141
158
  }: {
142
159
  active?: boolean;
143
- payload?: Array<{
144
- value: number;
145
- name: string;
146
- color: string;
147
- dataKey: string;
148
- }>;
160
+ payload?: Array<TooltipPayload>;
149
161
  label?: string;
150
162
  unitLabel?: string;
163
+ timeFormat?: 'date-time' | 'date';
151
164
  }) => {
152
165
  if (!active || !payload || !payload.length || !label) return null;
153
166
  // We can't use the default itemSorter method because it's a custom tooltip.
154
167
  // Sort the payload here instead
155
168
  const sortedPayload = [...payload].sort((a, b) => {
156
- const aValue = Number(a.value);
157
- const bValue = Number(b.value);
169
+ const aValue = a.value;
170
+ const bValue = b.value;
158
171
 
159
172
  if (aValue >= 0 && bValue >= 0) {
160
173
  return bValue - aValue; // Higher positive values first
@@ -169,21 +182,25 @@ const CustomTooltip = ({
169
182
  <TooltipContainer>
170
183
  <TooltipTime>
171
184
  <FormattedDateTime
172
- format="day-month-abbreviated-hour-minute-second"
185
+ format={
186
+ timeFormat === 'date-time'
187
+ ? 'day-month-abbreviated-hour-minute-second'
188
+ : 'long-date-without-weekday'
189
+ }
173
190
  value={new Date(label)}
174
191
  />
175
192
  </TooltipTime>
176
193
  {sortedPayload.map((entry, index) => (
177
194
  <TooltipValue key={index}>
178
- <TooltipLegend color={entry.color} />
179
- <TooltipContent>
195
+ <TooltipLeftGroup>
196
+ <TooltipLegend color={entry.color} />
180
197
  <TooltipName>{entry.name}</TooltipName>
181
- <TooltipInstanceValue>
182
- {isNaN(Number(entry.value))
183
- ? '-'
184
- : `${Number(entry.value).toFixed(2)}${unitLabel}`}
185
- </TooltipInstanceValue>
186
- </TooltipContent>
198
+ </TooltipLeftGroup>
199
+ <TooltipInstanceValue>
200
+ {!Number.isFinite(entry.value)
201
+ ? '-'
202
+ : `${entry.value.toFixed(2)} ${unitLabel}`}
203
+ </TooltipInstanceValue>
187
204
  </TooltipValue>
188
205
  ))}
189
206
  </TooltipContainer>
@@ -205,6 +222,7 @@ export function LineTimeSerieChart({
205
222
  duration,
206
223
  unitRange,
207
224
  isLoading = false,
225
+ timeFormat = 'date-time',
208
226
  yAxisType = 'default',
209
227
  yAxisTitle,
210
228
  helpText,
@@ -291,7 +309,7 @@ export function LineTimeSerieChart({
291
309
  );
292
310
  }, [series, startingTimeStamp, duration, interval, yAxisType]);
293
311
 
294
- // Calculate 5 perfectly evenly spaced ticks
312
+ // Calculate evenly spaced ticks that avoid the very beginning and end
295
313
  const xAxisTicks = useMemo(() => {
296
314
  if (!chartData || chartData.length === 0) return [];
297
315
 
@@ -299,20 +317,23 @@ export function LineTimeSerieChart({
299
317
  const minTimestamp = Math.min(...timestamps);
300
318
  const maxTimestamp = Math.max(...timestamps);
301
319
 
302
- // Calculate 5 perfectly evenly spaced ticks
303
320
  const timeRange = maxTimestamp - minTimestamp;
304
- const interval = timeRange / 4; // 4 intervals create 5 points
305
-
306
- const exactEvenTicks = [
307
- minTimestamp,
308
- minTimestamp + interval,
309
- minTimestamp + interval * 2,
310
- minTimestamp + interval * 3,
311
- maxTimestamp,
312
- ];
313
-
314
- // Return perfectly even ticks (guaranteed to be evenly divided)
315
- return exactEvenTicks;
321
+ // Add padding to avoid labels at the very edges (10% padding on each side)
322
+ const padding = timeRange * 0.1;
323
+ const paddedStart = minTimestamp + padding;
324
+ const paddedEnd = maxTimestamp - padding;
325
+ const paddedRange = paddedEnd - paddedStart;
326
+
327
+ // Create 5 evenly spaced ticks within the padded range
328
+ const numTicks = 5;
329
+ const tickInterval = paddedRange / (numTicks - 1);
330
+
331
+ const evenlySpacedTicks = Array.from(
332
+ { length: numTicks },
333
+ (_, index) => paddedStart + index * tickInterval,
334
+ );
335
+
336
+ return evenlySpacedTicks;
316
337
  }, [chartData]);
317
338
 
318
339
  // 3. Transform the data base on the valuebase
@@ -393,12 +414,9 @@ export function LineTimeSerieChart({
393
414
  }, [series, getColor]);
394
415
 
395
416
  // Format time for display the tick in the x axis
396
- const formatTime = useMemo(
397
- () => (timestamp: number) => {
398
- const date = new Date(timestamp);
399
- return DAY_MONTH_ABBREVIATED_HOUR_MINUTE.format(date).replace(',', '');
400
- },
401
- [],
417
+ const formatXAxisLabelCallback = useCallback(
418
+ (timestamp: number) => formatXAxisLabel(timestamp, timeFormat, chartData),
419
+ [timeFormat, chartData],
402
420
  );
403
421
 
404
422
  return (
@@ -408,12 +426,14 @@ export function LineTimeSerieChart({
408
426
  {title} {unitLabel && `(${unitLabel})`}
409
427
  </ChartTitleText>
410
428
  {helpText && (
411
- <TooltipComponent
412
- placement={'right'}
413
- overlay={<SmallerText>{helpText}</SmallerText>}
414
- >
415
- <Icon name="Info" color={theme.buttonSecondary} />
416
- </TooltipComponent>
429
+ <Box ml={spacing.r4}>
430
+ <TooltipComponent
431
+ placement={'right'}
432
+ overlay={<SmallerText>{helpText}</SmallerText>}
433
+ >
434
+ <Icon name="Info" color={theme.buttonSecondary} />
435
+ </TooltipComponent>
436
+ </Box>
417
437
  )}
418
438
  {isLoading && <Loader />}
419
439
  </ChartHeader>
@@ -438,7 +458,7 @@ export function LineTimeSerieChart({
438
458
  type="number"
439
459
  domain={['dataMin', 'dataMax']}
440
460
  ticks={xAxisTicks}
441
- tickFormatter={formatTime}
461
+ tickFormatter={formatXAxisLabelCallback}
442
462
  tickCount={5}
443
463
  tick={{
444
464
  fill: theme.textSecondary,
@@ -472,8 +492,14 @@ export function LineTimeSerieChart({
472
492
  fontSize: fontSize.smaller,
473
493
  }}
474
494
  tickFormatter={(value) => Math.round(value).toString()}
495
+ tickCount={5}
496
+ interval={'preserveStartEnd'}
497
+ />
498
+ <Tooltip
499
+ content={
500
+ <CustomTooltip unitLabel={unitLabel} timeFormat={timeFormat} />
501
+ }
475
502
  />
476
- <Tooltip content={<CustomTooltip unitLabel={unitLabel} />} />
477
503
  {/* Add horizontal line at y=0 for symmetrical charts */}
478
504
  {yAxisType === 'symmetrical' && (
479
505
  <ReferenceLine y={0} stroke={theme.border} />
@@ -493,6 +519,7 @@ export function LineTimeSerieChart({
493
519
  dataKey={label}
494
520
  stroke={colorMapping[resource]}
495
521
  dot={false}
522
+ isAnimationActive={false}
496
523
  />
497
524
  );
498
525
  }),
@@ -0,0 +1,71 @@
1
+ import { render } from '@testing-library/react';
2
+ import React from 'react';
3
+ import {
4
+ LineChartProps,
5
+ LineTimeSerieChart,
6
+ } from './linetimeseriechart.component';
7
+ import { ChartLegendWrapper } from '../chartlegend/ChartLegendWrapper';
8
+ import { ThemeProvider } from 'styled-components';
9
+ import { coreUIAvailableThemes } from '../../style/theme';
10
+
11
+ const TestSeries = [
12
+ {
13
+ resource: 'Series 1',
14
+ getTooltipLabel: () => `Series 1`,
15
+ data: [
16
+ [1622505600000, 10],
17
+ [1622509200000, 20],
18
+ [1622512800000, 30],
19
+ ] as [number, number][],
20
+ },
21
+ {
22
+ resource: 'Series 2',
23
+ getTooltipLabel: () => `Series 2`,
24
+ data: [
25
+ [1622505600000, 15],
26
+ [1622509200000, 25],
27
+ [1622512800000, 35],
28
+ ] as [number, number][],
29
+ },
30
+ ];
31
+
32
+ const ColorSet = {
33
+ 'Series 1': '#FF0000',
34
+ 'Series 2': '#00FF00',
35
+ };
36
+
37
+ const renderLineTimeSerieChart = (props: Partial<LineChartProps> = {}) => {
38
+ return render(
39
+ <ThemeProvider theme={coreUIAvailableThemes.artescaLight}>
40
+ <ChartLegendWrapper colorSet={ColorSet}>
41
+ <LineTimeSerieChart
42
+ {...({
43
+ title: 'Test Chart',
44
+ yAxisType: 'default',
45
+ series: TestSeries,
46
+ height: 400,
47
+ startingTimeStamp: TestSeries[0].data[0][0],
48
+ interval: TestSeries[0].data[1][0] - TestSeries[0].data[0][0],
49
+ duration:
50
+ TestSeries[0].data[TestSeries[0].data.length - 1][0] -
51
+ TestSeries[0].data[0][0],
52
+ unitRange: [{ label: 'units', value: 1 }],
53
+ ...props,
54
+ } as LineChartProps)}
55
+ />
56
+ </ChartLegendWrapper>
57
+ </ThemeProvider>,
58
+ );
59
+ };
60
+
61
+ describe('LineTimeSerieChart', () => {
62
+ it('should render when with basic parameters', async () => {
63
+ const { container } = renderLineTimeSerieChart();
64
+ expect(container).toBeInTheDocument();
65
+ });
66
+
67
+ it('should render when no unitRange is provided', async () => {
68
+ const { container } = renderLineTimeSerieChart({ unitRange: undefined });
69
+ expect(container).toBeInTheDocument();
70
+ });
71
+ });
@@ -0,0 +1,87 @@
1
+ import { formatXAxisLabel } from './utils';
2
+
3
+ const createChartData = (startDate: Date, endDate: Date) => [
4
+ { timestamp: startDate.getTime() },
5
+ { timestamp: endDate.getTime() },
6
+ ];
7
+
8
+ describe('formatXAxisLabel', () => {
9
+ const mockTimestamp = new Date('2025-09-15T14:30:00Z').getTime();
10
+
11
+ describe('date-time format', () => {
12
+ it('should format timestamp with day-month-abbreviated-hour-minute format', () => {
13
+ const chartData = createChartData(
14
+ new Date('2022-01-01'),
15
+ new Date('2022-01-02'),
16
+ );
17
+ const result = formatXAxisLabel(mockTimestamp, 'date-time', chartData);
18
+ expect(result).toBe('15 Sept 14:30');
19
+ });
20
+ });
21
+
22
+ describe('date format', () => {
23
+ it('should use YYYY-MM-DD format for time ranges greater than 1 year', () => {
24
+ const startDate = new Date('2022-01-01');
25
+ const endDate = new Date('2024-01-01'); // More than 1 year
26
+ const chartData = createChartData(startDate, endDate);
27
+
28
+ const result = formatXAxisLabel(mockTimestamp, 'date', chartData);
29
+ expect(result).toBe('2025-09-15');
30
+ });
31
+
32
+ it('should use MM-DD format for time ranges less than 1 year', () => {
33
+ const startDate = new Date('2023-09-01');
34
+ const endDate = new Date('2023-12-01'); // Less than 1 year
35
+ const chartData = createChartData(startDate, endDate);
36
+
37
+ const result = formatXAxisLabel(mockTimestamp, 'date', chartData);
38
+ expect(result).toBe('09-15');
39
+ });
40
+
41
+ it('should use YYYY-MM-DD format when chartData is empty', () => {
42
+ const result = formatXAxisLabel(mockTimestamp, 'date', []);
43
+ expect(result).toBe('2025-09-15');
44
+ });
45
+
46
+ it('should handle edge case of exactly 1 year time range', () => {
47
+ const startDate = new Date('2022-09-15');
48
+ const endDate = new Date('2023-09-15'); // Exactly 1 year
49
+ const chartData = createChartData(startDate, endDate);
50
+
51
+ const result = formatXAxisLabel(mockTimestamp, 'date', chartData);
52
+ expect(result).toBe('09-15');
53
+ });
54
+
55
+ it('should handle leap year calculation correctly', () => {
56
+ const startDate = new Date('2023-01-01');
57
+ const endDate = new Date('2024-01-02'); // Just over 1 year including leap year
58
+ const chartData = createChartData(startDate, endDate);
59
+
60
+ const result = formatXAxisLabel(mockTimestamp, 'date', chartData);
61
+
62
+ expect(result).toBe('2025-09-15');
63
+ });
64
+ });
65
+
66
+ describe('chartData with various scenarios', () => {
67
+ it('should handle chartData with single data point', () => {
68
+ const chartData = [{ timestamp: mockTimestamp }];
69
+
70
+ const result = formatXAxisLabel(mockTimestamp, 'date', chartData);
71
+
72
+ expect(result).toBe('09-15');
73
+ });
74
+
75
+ it('should handle chartData with mixed timestamp values', () => {
76
+ const chartData = [
77
+ { timestamp: new Date('2023-01-01').getTime() },
78
+ { timestamp: new Date('2023-06-01').getTime() },
79
+ { timestamp: new Date('2023-12-01').getTime() },
80
+ ];
81
+
82
+ const result = formatXAxisLabel(mockTimestamp, 'date', chartData);
83
+
84
+ expect(result).toBe('09-15');
85
+ });
86
+ });
87
+ });
@@ -0,0 +1,43 @@
1
+ import {
2
+ DAY_MONTH_ABBREVIATED_HOUR_MINUTE,
3
+ YEAR_MONTH_DAY_FORMATTER,
4
+ MONTH_DAY_FORMATTER,
5
+ } from '../date/FormattedDateTime';
6
+
7
+ export const ONE_YEAR_MILLISECONDS = 366 * 24 * 60 * 60 * 1000;
8
+
9
+ export type ChartDataPoint = {
10
+ timestamp: number;
11
+ } & Record<string, number | null>;
12
+
13
+ /**
14
+ * Formats timestamp for X-axis labels based on time format and data range:
15
+ * For 'date-time' format, return day-month-abbreviated-hour-minute format
16
+ * For 'date' format, return YYYY-MM-DD format if time range is greater than 1 year, otherwise return MM-DD format
17
+ *
18
+ * @param timestamp - The timestamp to format in milliseconds
19
+ * @param timeFormat - The format type ('date-time' or 'date')
20
+ * @param chartData - The chart data to determine time range for optimal formatting
21
+ * @returns Formatted string for display on X-axis
22
+ */
23
+ export const formatXAxisLabel = (
24
+ timestamp: number,
25
+ timeFormat: 'date-time' | 'date' = 'date-time',
26
+ chartData: ChartDataPoint[] = [],
27
+ ): string => {
28
+ const date = new Date(timestamp);
29
+ if (!chartData.length) {
30
+ return YEAR_MONTH_DAY_FORMATTER.format(date);
31
+ }
32
+ if (timeFormat === 'date-time') {
33
+ return DAY_MONTH_ABBREVIATED_HOUR_MINUTE.format(date).replace(',', '');
34
+ }
35
+ const timestamps = chartData.map((d) => d.timestamp);
36
+ const minTimestamp = Math.min(...timestamps);
37
+ const maxTimestamp = Math.max(...timestamps);
38
+ const timeRangeMilliseconds = maxTimestamp - minTimestamp;
39
+
40
+ return timeRangeMilliseconds >= ONE_YEAR_MILLISECONDS
41
+ ? YEAR_MONTH_DAY_FORMATTER.format(date)
42
+ : MONTH_DAY_FORMATTER.format(date);
43
+ };
@@ -60,6 +60,7 @@ export const coreUIAvailableThemesNames = [
60
60
  'darkRebrand',
61
61
  'artescaLight',
62
62
  'ring9dark',
63
+ 'G-Dark'
63
64
  ] as const;
64
65
  export type CoreUIThemeName = (typeof coreUIAvailableThemesNames)[number];
65
66
 
@@ -139,6 +140,31 @@ export const coreUIAvailableThemes: Record<CoreUIThemeName, CoreUITheme> = {
139
140
  textReverse: '#000000',
140
141
  textLink: '#71AEFF',
141
142
  },
143
+ 'G-Dark': {
144
+ statusHealthy: '#0AADA6',
145
+ statusHealthyRGB: '10,173,166',
146
+ statusWarning: '#F8F32B',
147
+ statusWarningRGB: '248,243,43',
148
+ statusCritical: '#E84855',
149
+ statusCriticalRGB: '232,72,85',
150
+ selectedActive: '#037AFF',
151
+ highlight: '#1A3C75',
152
+ border: '#4A4A4A',
153
+ buttonPrimary: 'linear-gradient(130deg, #9355E7 0%, #2E4AA3 100%)',
154
+ buttonSecondary: 'linear-gradient(130deg, #595A78 0%, #44455F 100%)',
155
+ buttonDelete: '#3D0808',
156
+ infoPrimary: '#8E8EAC',
157
+ infoSecondary: '#333366',
158
+ backgroundLevel1: '#121219',
159
+ backgroundLevel2: '#323245',
160
+ backgroundLevel3: '#232331',
161
+ backgroundLevel4: '#1B1B27',
162
+ textPrimary: '#EAEAEA',
163
+ textSecondary: '#B5B5B5',
164
+ textTertiary: '#DFDFDF',
165
+ textReverse: '#000000',
166
+ textLink: '#71AEFF',
167
+ },
142
168
  };
143
169
 
144
170
  /**