From 8e91a6a0b87d4b1394f16586cd10afae58a06fd8 Mon Sep 17 00:00:00 2001 From: Tobias Barsnes Date: Wed, 26 Feb 2025 13:38:06 +0100 Subject: [PATCH] feat(cli, themebuilder): invalidate systemcolors as name for color (#3194) Co-authored-by: Michael Marszalek --- .changeset/hungry-singers-fry.md | 5 +++ .../TableCard/TableCard.tsx | 2 +- .../Sidebar/ColorPane/ColorPane.tsx | 35 ++++++++++++++++--- packages/cli/bin/config.ts | 22 ++++++++++-- packages/cli/src/colors/theme.ts | 13 +++++++ 5 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 .changeset/hungry-singers-fry.md diff --git a/.changeset/hungry-singers-fry.md b/.changeset/hungry-singers-fry.md new file mode 100644 index 0000000000..7b77706c35 --- /dev/null +++ b/.changeset/hungry-singers-fry.md @@ -0,0 +1,5 @@ +--- +"@digdir/designsystemet": patch +--- + +Invalidate system colors as color names (success, danger, warning, info, blue, green, orange, red, purple) diff --git a/apps/theme/components/OverviewComponents/TableCard/TableCard.tsx b/apps/theme/components/OverviewComponents/TableCard/TableCard.tsx index 966f94c44c..dc4d4fba9f 100644 --- a/apps/theme/components/OverviewComponents/TableCard/TableCard.tsx +++ b/apps/theme/components/OverviewComponents/TableCard/TableCard.tsx @@ -51,7 +51,7 @@ export const TableCard = () => { - +
diff --git a/apps/theme/components/Sidebar/ColorPane/ColorPane.tsx b/apps/theme/components/Sidebar/ColorPane/ColorPane.tsx index 0684cadbd3..4bfa443d66 100644 --- a/apps/theme/components/Sidebar/ColorPane/ColorPane.tsx +++ b/apps/theme/components/Sidebar/ColorPane/ColorPane.tsx @@ -1,3 +1,4 @@ +import { RESERVED_COLORS } from '@digdir/designsystemet'; import { Button, Heading, @@ -10,6 +11,7 @@ import { ColorPicker, type IColor } from 'react-color-palette'; import { useThemeStore } from '../../../store'; import cl from 'clsx/lite'; +import { useState } from 'react'; import classes from './ColorPane.module.css'; type ColorPaneProps = { @@ -38,6 +40,8 @@ export const ColorPane = ({ colorType, }: ColorPaneProps) => { const mainColors = useThemeStore((state) => state.colors.main); + const [colorError, setColorError] = useState(''); + const disableRemoveButton = colorType === 'main' && mainColors.length === 1; const getHeading = () => { @@ -45,6 +49,27 @@ export const ColorPane = ({ return type === 'addColor' ? 'Legg til ' + t : 'Rediger farge'; }; + const checkNameIsValid = () => { + if (name === '') { + setColorError('Navnet på fargen kan ikke være tomt'); + return false; + } + + if (RESERVED_COLORS.includes(name.toLowerCase())) { + setColorError( + 'Navnet på fargen kan ikke være det samme som våre systemfarger', + ); + return false; + } + setColorError(''); + return true; + }; + + const closeTab = () => { + setColorError(''); + onClose(); + }; + return (
onClose()} + onClick={closeTab} className={classes.back} > Gå tilbake @@ -102,6 +127,8 @@ export const ColorPane = ({ .toLowerCase(); setName(value); }} + onBlur={checkNameIsValid} + error={colorError} /> )}
Farge
@@ -122,6 +149,8 @@ export const ColorPane = ({ data-size='sm' color='neutral' onClick={() => { + /* Check here as well to disable sending new color */ + if (!checkNameIsValid()) return; onPrimaryClicked(color.hex, name); }} > @@ -132,9 +161,7 @@ export const ColorPane = ({ data-size='sm' color='neutral' variant='secondary' - onClick={() => { - onClose(); - }} + onClick={closeTab} > Avbryt diff --git a/packages/cli/bin/config.ts b/packages/cli/bin/config.ts index d2e2f0f87f..dca0585e85 100644 --- a/packages/cli/bin/config.ts +++ b/packages/cli/bin/config.ts @@ -1,6 +1,7 @@ import * as R from 'ramda'; import { z } from 'zod'; import { convertToHex } from '../src/colors/index.js'; +import { RESERVED_COLORS } from '../src/colors/theme.js'; import { cliOptions } from '../src/tokens/create.js'; export function mapPathToOptionName(path: (string | number)[]) { @@ -20,14 +21,31 @@ const hexPatterns = [ `#[0-9a-fA-F]{6}`, `#[0-9a-fA-F]{8}`, ]; +const reservedColorsPattern = `^(?!(?:${RESERVED_COLORS.join('|')})$)`; export const colorRegex = new RegExp(`^${hexPatterns.join('|')}$`); const colorSchema = z - .string({ description: 'A hex color, which is used for creating a color scale' }) + .string({ + description: `A hex color, which is used for creating a color scale. Invalid color names: ${RESERVED_COLORS.join(', ')}`, + }) .regex(colorRegex) .transform(convertToHex); -const colorCategorySchema = z.record(colorSchema, { description: 'One or more color definitions' }); + +const colorCategorySchema = z + .record( + z.string().regex(new RegExp(reservedColorsPattern, 'i'), { + message: `Color names cannot include reserved names: ${RESERVED_COLORS.join(', ')}`, + }), + colorSchema, + { + description: 'One or more color definitions', + invalid_type_error: 'Color definitions must be hex color values', + }, + ) + .refine((colors) => !Object.keys(colors).some((key) => RESERVED_COLORS.includes(key.toLowerCase())), { + message: `Color names cannot include reserved names: ${RESERVED_COLORS.join(', ')}`, + }); const themeSchema = z.object( { diff --git a/packages/cli/src/colors/theme.ts b/packages/cli/src/colors/theme.ts index 4bd163ca1f..419c21528d 100644 --- a/packages/cli/src/colors/theme.ts +++ b/packages/cli/src/colors/theme.ts @@ -5,6 +5,19 @@ import type { CssColor } from './types.js'; import type { Color, ColorNumber, ColorScheme, ThemeInfo } from './types.js'; import { getLightnessFromHex, getLuminanceFromLightness } from './utils.js'; +export const RESERVED_COLORS = [ + 'neutral', + 'success', + 'warning', + 'danger', + 'info', + 'blue', + 'green', + 'orange', + 'purple', + 'red', +]; + /** * Generates a color scale based on a base color and a color mode. *