frenic / csstype

Strict TypeScript and Flow types for style based on MDN data
MIT License
1.7k stars 69 forks source link

BoxShadow does not support TLength generic #135

Closed wintercounter closed 2 years ago

wintercounter commented 2 years ago

In many CSS-in-JS solutions the following declaration of box-shadow is allowed:

boxShadow: [5, 5, 10, '#000']

For example we're using custom generics to support such values. However CSS.Property.BoxShadow does not come with support for generics, so it'll ignore the passed TLength type property.

frenic commented 2 years ago

CSSType should be as close to the correct CSS-specification as possible. box-shadow are handled differently in different CSS-in-JS libraries and this issue should be addressed there, not here.

wintercounter commented 2 years ago

But it cannot be handled at library level. With extending CSSType I'll lose all that IntelliSense has to offer, unless I copy my own DocBlock. For border, margin, padding, background, etc. this work fine. I don't see why box-shadow needs to be different.

Anyway, thanks for checking, we will figure out something then on our own.

frenic commented 2 years ago

Can you provide an example of how you extend e.g. padding to give me a better understanding of your problem?

wintercounter commented 2 years ago
type ValueTypes =
    | string
    | number
    | boolean
    | (string | number | boolean)[]

interface Props extends CSS.PropertiesFallback<ValueTypes> {
   ...
}

This allows to do such for example: padding: [1, 2, 'auto', 4]. That's because padding supports TLength (which is the passed ValueTypes generic). But boxShadow doesn't, doing boxShadow: [1, 2, 3, '#000'] will throw TS error.

frenic commented 2 years ago

Ok, I understand. But for this to work out of the box, we'll need to put TLength on boxShadow and that isn't valid CSS. You can't do box-shadow: 10px. So that won't happen. But maybe something like this would help you?

type ValueTypes = string | number | boolean | (string | number | boolean)[];

type CustomProperties = { boxShadow: CSS.Property.BoxShadow | ValueTypes };

interface Props extends Omit<CSS.PropertiesFallback<ValueTypes>, keyof CustomProperties>, CustomProperties {}

const style: Props = {
  boxShadow: [1, 2, 3, '#000'], // OK 👌
};
wintercounter commented 2 years ago

Unfortunately with that I'm still losing the docs of the property, since I'm completely overriding it.

image image

frenic commented 2 years ago

This would solve that:


type ValueTypes = string | number | boolean | (string | number | boolean)[];

type CustomProperyNames = 'boxShadow';

type CustomProperties = {
  [property in keyof Pick<CSS.PropertiesFallback, CustomProperyNames>]: CSS.PropertiesFallback[property] | ValueTypes;
};

interface Props extends Omit<CSS.PropertiesFallback<ValueTypes>, keyof CustomProperties>, CustomProperties {}

const style: Props = {
  boxShadow: [1, 2, 3, '#000'], // OK 👌
};
wintercounter commented 2 years ago

Thanks, it does work. This is a fun workaround. Can I tip you somehow? :)

frenic commented 2 years ago

Thanks for offering a donation but this one's on me 🙂 Happy it worked!