chakra-ui icon indicating copy to clipboard operation
chakra-ui copied to clipboard

Allow specifying custom variant props

Open a463 opened this issue 3 years ago • 0 comments

Description

I was trying to create a variant of a Button that would use a gradient border. It sounds simple, but it seems that custom props cannot be passed to the variant, without them also being passed all the way down to the DOM element, which triggers a React Warning: React does not recognize the ... prop on a DOM element.

I am trying to pass two props gradientFrom and gradientTo. There is already a discussion on this without an answer.

Problem Statement/Justification

The code I implemented is very simple:

// create the custom props
export type GradientButtonProps = {
  gradientFrom?: ButtonProps['borderColor']
  gradientTo?: ButtonProps['borderColor']
}

// export a Button that extends Chakra's button and includes the props above
export const Button = chakra<typeof ChakraButton, GradientButtonProps>(ChakraButton)

// create the variant
const gradient = defineStyle(({ colorScheme, theme, gradientFrom, gradientTo, ...props }) => {
  ...
})

// extend the theme
...

Trying to use it: <Button variant="gradient" gradientFrom="blue.200" gradientTo="green.200" /> throws two warnings: React does not recognize the `gradientFrom` prop on a DOM element and another for gradientTo.

Proposed Solution or API

One solution I can think of is to add and an additional prop, such as themingProps which would be an array for example:

<Button 
  variant="gradient"
  gradientFrom="red.200"
  gradientTo="blue.200"
  themingProps={['gradientFrom', 'gradientTo']} />

then changing omitThemingProps to remove themingProps itself and it's contents, something like:

export function omitThemingProps<T extends ThemingProps>(props: T) {
  const themingProps = props.themingProps ?? []
  return omit(props, ["styleConfig", "size", "variant", "colorScheme", "themingProps", ...themingProps])
}

This way the props would still be passed to the variant props, but not to the DOM element. There may be a better solution for this, without having to pass themingProps like above and instead somehow defining them when creating the variant, but I am not very familiar with the code, so I am not sure. (Maybe useStyleConfig can return the props that need to be omitted alongside styles? That would likely be a breaking change as useStyleConfig currently doesn't return an object)

Alternatives

One ugly alternative is to use either kebab-case or none at all, so gradient-from or gradientfrom. They are still both passed to the DOM element, but at least neither show the react warning.

The second is to create a completely different component, which strips these custom props, and sends them to useStyleConfig as shown in Advanced Theming. Not a good alternative either, as it beats the purpose of being able to define variants, plus we lose a lot of already implemented Button features, such as loading state or adding icons.

Additional Information

No response

a463 avatar Sep 16 '22 17:09 a463