components created using safelySpreadBoxProps
have incorrect TS types
#1364
-
Hi team, there are many components that are a I'm wondering if it's possible to filter these props out from all Box-composed components. There might be a way by a combination of an paste/packages/paste-core/primitives/box/src/SafelySpreadProps.ts Lines 13 to 27 in 8de49d7 Side-note: the more root issue is that (by design) it's difficult to add custom styling to Paste components. For these edge cases I know teams have found less-than-optimal workarounds for their own use-case. Is this an issue that can be re-discussed? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
Hi Van! We are definitely going to be fixing the typing issue- the "allowing then filtering out" that happens now is going to change asap. The ticket is in our backlog here. For your side note: the lack of ways to custom style the Paste components is something we consider a feature- it allows for Paste to roll out fixes and design changes w/o breaking the application of anyone who's currently using it. You can read more about that in this discussion thread as well. As always, feel empowered to challenge some of our design choices as we are continually looking for ways to improve! |
Beta Was this translation helpful? Give feedback.
-
For a little extra context for those following along at home, I wrote this explanation of the problem for the team internally and we feel like it should live somewhere... A lot of our components are one to one replacements for HTML concepts. As such you want to be able to do with them, what you would ordinarily be able to do with the raw HTML element. Each HTML element can have a set of global HTML attributes applied to them https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes, they include event handlers such as onclick, ARIA attributes, display attributes and styling attributes such as class, style. Some Elements have an extra set of attributes that are specific to them. For example input elements have a set of data input related attributes that can't just be applied to a With a React component, you more than likely wrap an HTML element and expose an interface to the consumer, as to what they can do with it. You probably want that interface to include all the relevant global and element specific HTML attributes for that component too. After all it's just a replacement for the HTML element, and I wanna do HTML things with my HTML components. But with React to pass those interface properties to the underlying HTML element, you either need to pluck them off of the props argument: const Button = props => {
return (
<button hidden={props.hidden} onClick={props.onClick} aria-label={props['aria-label']}>{props.children}</button>
)
} Or just spread them down, as that list of attributes can be super long and a pain in the butt to maintain. Or worse, you miss one, and someone reports a bug that they can't add a specific data attribute to the rendered DOM and you need to add it. const Button = props => {
return (
<button {...props}>{props.children}</button>
)
} In typescript it's even worse as you now need to manage the props in the component and the interface. That would lead to a lot of duplication, so what is commonly done is you extend the type of HTML element you are exposing into the type interface. You'll see a lot of this in Paste: interface AnchorProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
...
} Which says, grab everything that is a valid HTML attribute for an Anchor element plus what ever else we set in the interface as a valid prop. But here's where it gets interesting. Because everything we build is a Box, and Box comes with a whole bunch of style props, spreading all props down to Box means the consumer can change everything about the look and feel of the component just by setting const Button = props => {
return (
<Box as="button" {...props}>{props.children}</Box>
)
} So to mitigate that, we created safelySpreadBoxProps helper function. const Button = props => {
return (
<Box as="button" {...safelySpreadBoxProps(props)}>{props.children}</Box>
)
} All that does is safely spread props on the Box component, by stripping out all the style props and all the Global HTML attributes that are associated with styling such as Cool, implementation safe. You can apply any HTML attribute you want, but we block you from changing the styles. (Why do we want to block you from changing the styles, go here. So why is it broken? Because we're extending the HTML element types into the interface, typescript thinks you are allowed to apply So to the typescript consumer, they've applied a valid prop, typescript compiled and didn't throw an error, but it didn't do anything. That's what @vnguyen94 is spotting. He can add The JIRA ticket is to create some form of Paste generic type, and automatically strips the props that we block in safely spread, from the HTML attribute type interfaces that we extend from. So that the types match the implementation, and if you try to set a blocked prop, typescript won't compile, but at least you won't think you're doing something wrong. As an aside, looking at that screenshot @vnguyen94, if you are potentially trying to create some kind of expandable table row, it'll likely be inaccessible unless you're building a Treegrid with full keyboard controls. Which is another reason we stop you from using Paste components like that, you probably shouldn't be doing it. (If you're not, then that's fine, but it seemed like a good example as to why). |
Beta Was this translation helpful? Give feedback.
Hi Van! We are definitely going to be fixing the typing issue- the "allowing then filtering out" that happens now is going to change asap. The ticket is in our backlog here.
For your side note: the lack of ways to custom style the Paste components is something we consider a feature- it allows for Paste to roll out fixes and design changes w/o breaking the application of anyone who's currently using it. You can read more about that in this discussion thread as well. As always, feel empowered to challenge some of our design choices as we are continually looking for ways to improve!