Hey,
I'm not sure if I should post the issue here or on DefinitelyTyped, so I'm sorry if it's not the right place.
I'd like to know if you think it would be possible to add a custom generics to types like ColorProps? That way it would be easier to enforce the use of the keys defined in my theme.
For example, I defined my Box like this :
import styled from 'styled-components'
import { color, ColorProps } from 'styled-system'
import { ColorsKeys } from 'theme'
const Box = styled.div<ColorProps>`
${color}
`
export default Box
and this is my theme :
// theme.js
export type ColorsKeys = 'black' | 'white' | 'blue' | 'navy'
export interface Theme {
colors: { [key in ColorsKeys]: string }
}
const theme: Theme = {
colors: {
black: '#000e1a',
white: '#fff',
blue: '#007ce0',
navy: '#004175',
},
}
export default theme
I would like typescript to throw an error on something like this:
<Box color="#00ff00" bg="tomato">Hello world</Box>
And even better if it can autocomplete for color, bg, ...
Right now to get this I would have to rewrite my BoxProps for bg, color, etc
If I can pass my ColorKeys to ColorProps and use that instead of CSS.ColorProperty to enforce my keys.
Does that sound impossible to add a generic to ColorProps, SpaceProps, etc so we can define custom keys and enforce those?
My team has a (private :cry: ) fork of styled-system that's been refactored for use in TS. Adding support for this is something we've been keen on adding, but I think it would require the addition of a createStyledSystem function or similar so that TS can provide typing via a generic. Usage would be something like:
interface YourTheme {
colors: "black" | "white" | "blue" | "navy";
}
const system = createStyledSystem<YourTheme>({ });
interface BoxProps extends system.ColorProps {}
const Box = styled.div<BoxProps>`
${system.colors};
`;
While we don't have a solution for themes at the moment, we do have a solution for typing style functions and variants. Here's an example usage:
type ButtonVariants = LiteralUnion<
"transparent" | "primary" | "outline" | "secondary" | "dark",
string
>;
const buttonVariant = system.variant<ButtonVariants>({ key: "buttons" });
interface IButtonVariantProps
extends system.StyleFnProps<typeof buttonVariant> {}
export interface IButtonProps
extends Merge<ButtonHTMLAttributes<any>, IBoxProps>, IButtonVariantProps {}
export const Button = styled(Box)<IButtonProps>`
${buttonVariant};
`;
Yeah this is kinda tricky, because that not how Styled System is designed.
Styled System is designed to:
So for example:
theme.colors: {
black: '#000',
white: '#fff'
};
<Box bg="white" />
// will use `theme.colors.white`
<Box bg="tomato" />
// will look for `theme.colors.tomato` - won't find it, so will use `"tomato"` instead
Same applies for the scales.
I 100% agree that what you're suggestion is a great feature, but I think this needs to be considered with @jxnblk - should Styled System be restrictive to only use values from the Theme?
Yeah, a style system in my mind is restrictive to force people to follow the style system so even if I'm not a big fan of a lot of options, maybe having a restrictive mode could be a good thing for style system ?
should Styled System be restrictive to only use values from the Theme
In my experience, locking down an API like that will just force people to use other means to achieve what they want to do, and allowing flexibility in the API can help avoid fragmentation/one-offs and general tech-debt.
Generally speaking, and from what I understand with TS, you'll want to define types for your own theme, and Styled System is meant to be somewhat agnostic to how you structure your theme.
I'm closing this issue out, since I don't think there's any actionable items from Styled System here, but feel free to open a new issue if needed.
Most helpful comment
My team has a (private :cry: ) fork of styled-system that's been refactored for use in TS. Adding support for this is something we've been keen on adding, but I think it would require the addition of a
createStyledSystemfunction or similar so that TS can provide typing via a generic. Usage would be something like:While we don't have a solution for themes at the moment, we do have a solution for typing style functions and variants. Here's an example usage: