zod icon indicating copy to clipboard operation
zod copied to clipboard

.color() function to validate that a string is a valid color.

Open BenjaminLindberg opened this issue 1 year ago • 2 comments

Hi, I would want a .color() function that you append on a z.string() to validate that it's a valid color.

This feature would be useful in many cases. For example if you want to make sure that payload coming from client/frontend contains valid color codes, directly with zod.

I believe that by default .color() should accept all of the standard forms of colors eg:

But also offer some way to only accept (a) certain color type(s), alternatively filter out unwanted color types.

Might not be that of a realistic feature, but some way to convert the payload to a specified color type. For example if a hex value gets inputted, it gets converted to the specified type, rgb for example . I know this might cause some inaccuracy when converting from certain types to others, but still a feature i would want.

I am open to make this feature myself later on if it gets decided that it's a needed feature.

BenjaminLindberg avatar Jul 10 '24 14:07 BenjaminLindberg

Hello! Just a suggestion that you can use z.string().refine() to implement a custom color validator. Maybe something simple like:

import color from "color-string";

export function colorValidator(val: string) {
  try {
    return color.get(val) != null;
  } catch {
    return false;
  }
}

const validColorSchema = z.string().refine(colorValidator);
validColorSchema.parse("#FFF");

eswarty avatar Jul 11 '24 21:07 eswarty

@eswarty thanks! Ill definitely try that out. Using .regex would also work I believe.

BenjaminLindberg avatar Aug 05 '24 14:08 BenjaminLindberg

According to the validation rule from MDN Web Docs - <input type="color"> - Validation - you might want to use this:


const htmlColorInputSchema = z.string().regex(
  /^#[0-9a-fA-F]{6}$/,
  { message: 'Invalid color format. Must be a 7-character hex code (e.g., #RRGGBB).' }
);

onyedikachi23 avatar May 31 '25 12:05 onyedikachi23

You can also simplify the regex by making it case-insensitive with the i flag: /^#[0-9a-f]{6}$/i

jprinaldi avatar Aug 21 '25 23:08 jprinaldi