-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
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
[Button] Custom variant #21648
[Button] Custom variant #21648
Changes from 52 commits
97aac4e
dd57f8e
5c3d592
8ba964e
6e0ab4d
5c8364c
653c1e7
1755be6
8c0ae69
036a172
1b94f50
9370c1c
df60098
f430770
2375c98
7db6a98
c032672
22d5f4a
3fcb966
212db32
f92dbaa
ce2369f
0e67339
ccaf13f
070ffe0
a86137e
628e8fd
132c930
5036d2d
5e79126
fa883ea
0ab15a6
fed904b
9fcc431
313f8bf
60787ab
f04ccb4
1b81481
7f12e68
e1c2d6d
4f34120
4f0a648
beab317
0c00ea9
70b713d
bb687a4
4efaf62
18de558
4cb0b03
e780712
eb02491
bb5baa1
3e1ea72
90609ff
c4df879
7d4fa1d
7ae76f7
c0a9d55
f888036
b26d20d
75cd3b6
5365b71
2916cd6
e185968
2b32fe8
efe2e7d
4ce2381
048cd39
57e4700
4196182
515933e
1d240c0
b9ac3ca
af088c9
4e8de25
20477c6
0aa43ad
c71e4ba
2bb3a29
52d11c8
55f0507
44e2f1d
a55dfe4
6b1742a
bcae6ef
704e2f2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import React from 'react'; | ||
import { | ||
createMuiTheme, | ||
makeStyles, | ||
ThemeProvider, | ||
} from '@material-ui/core/styles'; | ||
import Button from '@material-ui/core/Button'; | ||
|
||
const useStyles = makeStyles((theme) => ({ | ||
root: { | ||
'& > *': { | ||
margin: theme.spacing(1), | ||
}, | ||
}, | ||
})); | ||
|
||
const defaultTheme = createMuiTheme(); | ||
|
||
const inputTheme = createMuiTheme({ | ||
variants: { | ||
MuiButton: [ | ||
{ | ||
matcher: { variant: 'dashed' }, | ||
styles: { | ||
padding: '5px 15px', | ||
border: `5px dashed ${defaultTheme.palette.primary.main}`, | ||
}, | ||
}, | ||
{ | ||
matcher: { variant: 'dashed', color: 'secondary' }, | ||
styles: { | ||
border: `5px dashed ${defaultTheme.palette.secondary.main}`, | ||
}, | ||
}, | ||
], | ||
}, | ||
}); | ||
|
||
export default function GlobalThemeVariants() { | ||
const classes = useStyles(); | ||
|
||
return ( | ||
<div className={classes.root}> | ||
<ThemeProvider theme={inputTheme}> | ||
<Button variant="dashed">Dashed</Button> | ||
<Button variant="dashed" color="secondary"> | ||
Dashed secondary | ||
</Button> | ||
</ThemeProvider> | ||
</div> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import React from 'react'; | ||
import { | ||
createMuiTheme, | ||
makeStyles, | ||
Theme, | ||
ThemeProvider, | ||
} from '@material-ui/core/styles'; | ||
import Button from '@material-ui/core/Button'; | ||
|
||
declare module '@material-ui/core/Button/Button' { | ||
interface ButtonPropsVariantOverrides { | ||
dashed: true; | ||
} | ||
} | ||
|
||
const useStyles = makeStyles((theme: Theme) => ({ | ||
root: { | ||
'& > *': { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mentioning this for later, I have seen a growing trend toward the |
||
margin: theme.spacing(1), | ||
}, | ||
}, | ||
})); | ||
|
||
const defaultTheme = createMuiTheme(); | ||
|
||
const inputTheme = createMuiTheme({ | ||
variants: { | ||
MuiButton: [ | ||
{ | ||
matcher: { variant: 'dashed' }, | ||
styles: { | ||
padding: '5px 15px', | ||
border: `5px dashed ${defaultTheme.palette.primary.main}`, | ||
}, | ||
}, | ||
{ | ||
matcher: { variant: 'dashed', color: 'secondary' }, | ||
styles: { | ||
border: `5px dashed ${defaultTheme.palette.secondary.main}`, | ||
}, | ||
}, | ||
], | ||
}, | ||
}); | ||
|
||
export default function GlobalThemeVariants() { | ||
const classes = useStyles(); | ||
|
||
return ( | ||
<div className={classes.root}> | ||
<ThemeProvider theme={inputTheme}> | ||
<Button variant="dashed">Dashed</Button> | ||
<Button variant="dashed" color="secondary"> | ||
Dashed secondary | ||
</Button> | ||
</ThemeProvider> | ||
</div> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -408,7 +408,10 @@ Button.propTypes = { | |
/** | ||
* The variant to use. | ||
*/ | ||
variant: PropTypes.oneOf(['contained', 'outlined', 'text']), | ||
variant: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ | ||
PropTypes.oneOf(['contained', 'outlined', 'text']), | ||
PropTypes.string, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't have to solve this right now but we should probably narrow this down before release by checking if any matcher matched. Right now vanilla users don't get runtime validation if the added the wrong There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thinking about this, we can actually use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would looking at
There is a new warning added by Marija that aim to mitigate with the problem (we get a warning but we don't have the full component stack trace) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking as these validations are per prop, we can check for only that prop in the classes? But if I understand your point correctly, it can exists in combination with other props, not just itself, right? In that case I will need to update the warning I added, because currently it is checking only for the variant itself. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My assumptions were:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
We can add this even now, with a simple hook like: const useThemeVariants = (props, name) => {
const theme = useTheme();
const variantsClasses = [];
if(theme && theme.variants && theme.variants[name]) {
const themeVariants = theme.variants[name];
themeVariants.forEach(themeVariant => {
let isMatch = true;
Object.keys(themeVariant.props).forEach(key => {
if(props[key] !== themeVariant.props[key]) {
isMatch = false;
}
});
if(isMatch) {
variantsClasses.push(classes[propsToClassKey(themeVariant.props)]);
}
})
}
return variantsClasses;
} Some of the things are recalcuated two times but I will refactor it if we want to go with something like this. This will allow us to even support new props 👍 I can clean this up and add it in the PR even now. For the warnings, we can extend it further, but I would like to see what would be the feedback, as I don't want to add a lot of overload for just warning, the one that is in place now it's pretty simple and I am not sure if we will need more complicated one.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Testing more this hook, I definitely think we should add it, as it will guarantee that whatever combination of props the clients will use, will be supported inside the component. @oliviertassinari @eps1lon thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that it makes sense. As far as I can think about it, for JSS, we will need to both generate the class names from the theme, and to apply them from the props, I don't see any other way. For styled-components, we will be able to bundle the logic at the same place, under the styled call. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added this in the |
||
]), | ||
}; | ||
|
||
export default withStyles(styles, { name: 'MuiButton' })(Button); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { CSSProperties, CreateCSSProperties, PropsFunc } from '@material-ui/styles/withStyles'; | ||
import { ComponentsPropsList } from './props'; | ||
|
||
export type Variants = { | ||
[Name in keyof ComponentsPropsList]?: Array<{ | ||
matcher: Partial<ComponentsPropsList[Name]>; | ||
styles: // JSS property bag | ||
| CSSProperties | ||
// JSS property bag where values are based on props | ||
| CreateCSSProperties<Partial<ComponentsPropsList[Name]>> | ||
// JSS property bag based on props | ||
| PropsFunc< | ||
Partial<ComponentsPropsList[Name]>, | ||
CreateCSSProperties<Partial<ComponentsPropsList[Name]>> | ||
>; | ||
}>; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
string
shouldn't be allowed by default. Will take a look later. Nothing that holds back this PR since it would also affect breakpoints.