Skip to content

Commit 8e91a6a

Browse files
Barsnesmimarz
andauthored
feat(cli, themebuilder): invalidate systemcolors as name for color (#3194)
Co-authored-by: Michael Marszalek <[email protected]>
1 parent 7f268d6 commit 8e91a6a

File tree

5 files changed

+70
-7
lines changed

5 files changed

+70
-7
lines changed

.changeset/hungry-singers-fry.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@digdir/designsystemet": patch
3+
---
4+
5+
Invalidate system colors as color names (success, danger, warning, info, blue, green, orange, red, purple)

apps/theme/components/OverviewComponents/TableCard/TableCard.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export const TableCard = () => {
5151
</Search>
5252
</div>
5353
</div>
54-
<Table data-size='sm' border>
54+
<Table data-size='sm' border data-color='neutral'>
5555
<Table.Head>
5656
<Table.Row>
5757
<Table.HeaderCell onClick={function Ya() {}} sort='none'>

apps/theme/components/Sidebar/ColorPane/ColorPane.tsx

+31-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { RESERVED_COLORS } from '@digdir/designsystemet';
12
import {
23
Button,
34
Heading,
@@ -10,6 +11,7 @@ import { ColorPicker, type IColor } from 'react-color-palette';
1011
import { useThemeStore } from '../../../store';
1112

1213
import cl from 'clsx/lite';
14+
import { useState } from 'react';
1315
import classes from './ColorPane.module.css';
1416

1517
type ColorPaneProps = {
@@ -38,13 +40,36 @@ export const ColorPane = ({
3840
colorType,
3941
}: ColorPaneProps) => {
4042
const mainColors = useThemeStore((state) => state.colors.main);
43+
const [colorError, setColorError] = useState('');
44+
4145
const disableRemoveButton = colorType === 'main' && mainColors.length === 1;
4246

4347
const getHeading = () => {
4448
const t = colorType === 'main' ? 'hovedfarge' : 'støttefarge';
4549
return type === 'addColor' ? 'Legg til ' + t : 'Rediger farge';
4650
};
4751

52+
const checkNameIsValid = () => {
53+
if (name === '') {
54+
setColorError('Navnet på fargen kan ikke være tomt');
55+
return false;
56+
}
57+
58+
if (RESERVED_COLORS.includes(name.toLowerCase())) {
59+
setColorError(
60+
'Navnet på fargen kan ikke være det samme som våre systemfarger',
61+
);
62+
return false;
63+
}
64+
setColorError('');
65+
return true;
66+
};
67+
68+
const closeTab = () => {
69+
setColorError('');
70+
onClose();
71+
};
72+
4873
return (
4974
<div
5075
className={cl(classes.colorPage, type.includes('Color') && classes.show)}
@@ -53,7 +78,7 @@ export const ColorPane = ({
5378
<Button
5479
data-size='sm'
5580
variant='tertiary'
56-
onClick={() => onClose()}
81+
onClick={closeTab}
5782
className={classes.back}
5883
>
5984
<ChevronLeftIcon title='a11y-title' fontSize='1.5rem' /> Gå tilbake
@@ -102,6 +127,8 @@ export const ColorPane = ({
102127
.toLowerCase();
103128
setName(value);
104129
}}
130+
onBlur={checkNameIsValid}
131+
error={colorError}
105132
/>
106133
)}
107134
<div className={classes.label}>Farge</div>
@@ -122,6 +149,8 @@ export const ColorPane = ({
122149
data-size='sm'
123150
color='neutral'
124151
onClick={() => {
152+
/* Check here as well to disable sending new color */
153+
if (!checkNameIsValid()) return;
125154
onPrimaryClicked(color.hex, name);
126155
}}
127156
>
@@ -132,9 +161,7 @@ export const ColorPane = ({
132161
data-size='sm'
133162
color='neutral'
134163
variant='secondary'
135-
onClick={() => {
136-
onClose();
137-
}}
164+
onClick={closeTab}
138165
>
139166
Avbryt
140167
</Button>

packages/cli/bin/config.ts

+20-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as R from 'ramda';
22
import { z } from 'zod';
33
import { convertToHex } from '../src/colors/index.js';
4+
import { RESERVED_COLORS } from '../src/colors/theme.js';
45
import { cliOptions } from '../src/tokens/create.js';
56

67
export function mapPathToOptionName(path: (string | number)[]) {
@@ -20,14 +21,31 @@ const hexPatterns = [
2021
`#[0-9a-fA-F]{6}`,
2122
`#[0-9a-fA-F]{8}`,
2223
];
24+
const reservedColorsPattern = `^(?!(?:${RESERVED_COLORS.join('|')})$)`;
2325

2426
export const colorRegex = new RegExp(`^${hexPatterns.join('|')}$`);
2527

2628
const colorSchema = z
27-
.string({ description: 'A hex color, which is used for creating a color scale' })
29+
.string({
30+
description: `A hex color, which is used for creating a color scale. Invalid color names: ${RESERVED_COLORS.join(', ')}`,
31+
})
2832
.regex(colorRegex)
2933
.transform(convertToHex);
30-
const colorCategorySchema = z.record(colorSchema, { description: 'One or more color definitions' });
34+
35+
const colorCategorySchema = z
36+
.record(
37+
z.string().regex(new RegExp(reservedColorsPattern, 'i'), {
38+
message: `Color names cannot include reserved names: ${RESERVED_COLORS.join(', ')}`,
39+
}),
40+
colorSchema,
41+
{
42+
description: 'One or more color definitions',
43+
invalid_type_error: 'Color definitions must be hex color values',
44+
},
45+
)
46+
.refine((colors) => !Object.keys(colors).some((key) => RESERVED_COLORS.includes(key.toLowerCase())), {
47+
message: `Color names cannot include reserved names: ${RESERVED_COLORS.join(', ')}`,
48+
});
3149

3250
const themeSchema = z.object(
3351
{

packages/cli/src/colors/theme.ts

+13
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ import type { CssColor } from './types.js';
55
import type { Color, ColorNumber, ColorScheme, ThemeInfo } from './types.js';
66
import { getLightnessFromHex, getLuminanceFromLightness } from './utils.js';
77

8+
export const RESERVED_COLORS = [
9+
'neutral',
10+
'success',
11+
'warning',
12+
'danger',
13+
'info',
14+
'blue',
15+
'green',
16+
'orange',
17+
'purple',
18+
'red',
19+
];
20+
821
/**
922
* Generates a color scale based on a base color and a color mode.
1023
*

0 commit comments

Comments
 (0)