Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[typescript] Upgrade types, use string index fallback for CSSProperties to allow nested pseudos #11007

Merged
merged 1 commit into from Apr 14, 2018

Conversation

pelotom
Copy link
Member

@pelotom pelotom commented Apr 12, 2018

Resolves #11004.

My PR to @types/react to make CSSProperties a closed type (sans string index fallback) indirectly broke Material UI, which was relying on it. The problem is that React's CSSProperties are only meant to capture what is expressible by inline styles, but Material UI's JSS API allows nested pseudo selectors, for example. So we need to make a new CSSProperties specific to Material UI, based on CSSType, which allows a string index.

@pelotom pelotom force-pushed the add-string-index-to-cssproperties branch from 79acc2d to fa06fe4 Compare April 12, 2018 22:48
@pelotom pelotom changed the title Upgrade types, use string index fallback for CSSProperties to allow nested pseudos [typescript] Upgrade types, use string index fallback for CSSProperties to allow nested pseudos Apr 12, 2018
@franklixuefei
Copy link
Contributor

So, from this on, we should be importing CSSProperties from material-ui rather than using React.CSSProperties, right?

@pelotom
Copy link
Member Author

pelotom commented Apr 13, 2018

@franklixuefei in the context of writing styles for use with withStyles, yes. Only use React.CSSProperties in the context of inline styles.

@franklixuefei
Copy link
Contributor

@pelotom Thanks. There can't be nested styles or psuedo selectors in inline styles of course... I understand it now.

@varoot
Copy link

varoot commented Apr 13, 2018

Material UI also supports array syntax and default unit (e.g. margin: [[2, 8]] translates to margin: 2px 8px) which is now broken with the new typings. Can we also fix this?

@pelotom
Copy link
Member Author

pelotom commented Apr 13, 2018

@varoot

Material UI also supports array syntax and default unit (e.g. margin: [[2, 8]] translates to margin: 2px 8px) which is now broken with the new typings. Can we also fix this?

Interesting, I wasn't aware of this. Is the outer array used for fallbacks?

It looks like this only worked before with the old anything-goes React.CSSProperties because margin was defined as

        margin?: CSSWideKeyword | any;

@varoot
Copy link

varoot commented Apr 13, 2018

According to JSS documentation, the outer array represents comma-separated values and the inner one for space-separated values.

Apparently JSS also accepts callback function as value but I'm not sure about whether Material UI supports this or how to use it.

@pelotom
Copy link
Member Author

pelotom commented Apr 13, 2018

According to JSS documentation, the outer array represents comma-separated values and the inner one for space-separated values.

Hm, currently @types/jss doesn't support these things, I guess that's a change that needs to be made there.

Apparently JSS also accepts callback function as value but I'm not sure about whether Material UI supports this or how to use it.

Yeah, in general I'm not sure which things from JSS are supported by Material UI and which not. My understanding was that it was a strict subset somehow, but I don't know exactly what the differences are. Maybe @oliviertassinari could shed some light on this?

@pelotom
Copy link
Member Author

pelotom commented Apr 14, 2018

I’m working on a PR for @types/jss to make all the examples in that link work, @varoot. There are lots of deficiencies currently. Then we can use those types (or whatever subset of them makes sense) in MUI. Until then I think this PR is good to merge as an intermediate improvement.

@oliviertassinari
Copy link
Member

oliviertassinari commented Apr 14, 2018

Material UI also supports array syntax and default unit (e.g. margin: [[2, 8]] translates to margin: 2px 8px) which is now broken with the new typings. Can we also fix this?

@varoot Material-UI doesn't support it out of the box. This feature is coming from: jss-expand. A JSS plugin that doesn't come by default (the plugin cost is 1.3 kB gzipped).

Apparently JSS also accepts callback function as value but I'm not sure about whether Material UI supports this or how to use it.

No, we don't support it yet. Not supporting it allows a better cache strategy and a lighter bundle.

@pelotom The pull-request looks good to me. Any blocker for merging it?

@pelotom
Copy link
Member Author

pelotom commented Apr 14, 2018

@oliviertassinari Thanks for the info. This is good to merge.

@pelotom pelotom merged commit 5ee6676 into mui:v1-beta Apr 14, 2018
@pelotom pelotom deleted the add-string-index-to-cssproperties branch April 14, 2018 15:34
@varoot
Copy link

varoot commented Apr 14, 2018

@oliviertassinari I could use the syntax without installing any other plugin so I'm pretty sure this is JSS's standard syntax (as documented on their Core JSON Syntax page). JSS Expand seems to offer different syntax (only one level of array needed and allowing object syntax).

I have a repository to prove it but you can also try it yourself. But since people don't seem to be aware of this feature, maybe I just shouldn't use it.

@oliviertassinari
Copy link
Member

@varoot I have never used it but I can trust you on this.

Copy link
Contributor

@xaviergonz xaviergonz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good mostly

@@ -1,5 +1,11 @@
import * as React from 'react';
import { Theme } from './createMuiTheme';
import * as CSS from 'csstype';

export interface CSSProperties extends CSS.Properties<number | string> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a new name that doesn't get confused with React.CSSProperties would be nice

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice, although it would be a breaking change 🤷‍♂️

withStyles<'listItem'>(theme => ({
listItem: {
'&:hover $listItemIcon': {
visibility: 'inherit',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could the test include a media query with css props?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but it's not testing anything different.


export interface CSSProperties extends CSS.Properties<number | string> {
// Allow pseudo selectors and media queries
[k: string]: CSS.Properties<number | string>[keyof CSS.Properties] | CSSProperties;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't CSS.Properties<number | string>[keyof CSS.Properties] already covered by extends CSS.Properties<number | string>?

Also doesn't that make this valid?

color: {
  color: 'red';
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't CSS.Properties<number | string>[keyof CSS.Properties] already covered by extends CSS.Properties<number | string>?

It's necessary for the string index to be compatible with the non-string properties. If you remove that it will be a type error.

Also doesn't that make this valid?

color: {
 color: 'red';
}

Allowing an arbitrary string index for nested pseudo selectors and media queries unavoidably means that invalid properties can get through. No way around it.

@pelotom
Copy link
Member Author

pelotom commented Apr 14, 2018

@varoot

@oliviertassinari I could use the syntax without installing any other plugin so I'm pretty sure this is JSS's standard syntax (as documented on their Core JSON Syntax page). JSS Expand seems to offer different syntax (only one level of array needed and allowing object syntax).

I have a repository to prove it but you can also try it yourself. But since people don't seem to be aware of this feature, maybe I just shouldn't use it.

It definitely seems to work, and I don't see why it shouldn't be supported by the typings!

From my further experimentation it looks like the function and observable options from that page are not supported by Material UI, probably because link: true isn't being specified? Though I think there has been some talk of someday allowing styles to depend on props using the function mechanism.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants