Lorsque vous utilisez createStyleSheet
, il n'y a aucun moyen (du moins à ma connaissance) d'accéder aux accessoires du composant. Je pense que c'est important, car il est parfois nécessaire de transmettre des tailles, des images d'URL et d'autres styles en tant qu'accessoires au composant.
Aujourd'hui, la seule solution à cela est de séparer ces éléments en styles en ligne, mais pour autant que je sache, material-ui v1 utilise jss
et react-jss
, et ces deux vous donnent déjà la possibilité d'accéder aux props via des fonctions qui reçoivent les props puis retournent le style souhaité, comme ça :
const styles = {
button: {
background: props => props.color
},
root: {
backgroundImage: props => `url(${props.backgroundImage})`
}
}
// Reference: https://github.com/cssinjs/react-jss#example
Que pensez-vous d'implémenter quelque chose comme ça sur material-ui aussi ?
react-jss implémente cette fonctionnalité. Vous pouvez toujours l'utiliser sur notre solution de coiffage. La véritable motivation pour implémenter cette fonctionnalité ici devrait être une implémentation interne plus simple/meilleure des composants.
react-jss injectStyles() le fait aussi, mais il semble qu'il serait préférable d'ajouter des accessoires au StyleRuleCallback
.
const styles = (props, theme) => ({})
De cette façon, vous n'êtes pas limité aux seules valeurs en fonction des accessoires.
Les commentaires de color
à nos composants, au lieu de celui prédéfini. L'impact de la taille CSS n'est pas clair, mais cela rendrait le remplacement de la couleur du composant encore plus simple. C'est quelque chose à enquêter. Ensuite, une fois que la prise en charge des variables CSS par le navigateur est suffisamment élevée (dans 2 ans ?), nous pouvons nous y fier.
@oliviertassinari la taille des css ne diminuerait-elle pas réellement dans certains cas ?
D'après ce que je comprends, nous définissons actuellement toutes les classes pour ...Primary
et ...Accent
- ce changement ne signifierait-il pas que nous n'aurions à maintenir les classes que pour ...Colorized
? Ou êtes-vous préoccupé par le css généré?
Quoi qu'il en soit, je pense que cela améliorerait énormément dx car nous devons essentiellement réimplémenter des classes complexes comme https://github.com/callemall/material-ui/blob/v1-beta/src/Button/Button.js#L11 lorsque nous voulez utiliser des couleurs non palette.
la taille du css ne diminuerait-elle pas réellement dans certains cas ?
@sakulstra Difficile à dire. Cela dépendra de la mise en œuvre. Peut-être :).
Du point de vue du typage TypeScript, ce serait bien si _both_ props
et theme
pouvaient être accédés de cette façon dans une spécification de styles :
const styles = {
button: {
background: ({ theme }) => theme.palette.primary[200]
},
root: {
backgroundImage: ({ props }) => `url(${props.backgroundImage})`
}
};
La raison en est que TypeScript ne parvient souvent pas à déduire le bon type pour withStyles
lorsqu'il est passé à un objet fonction, vous devez donc fournir des annotations de type supplémentaires pour le faire fonctionner, par exemple
withStyles<'button' | 'root'>(theme => ...)
Si des accessoires sont également transmis, cela deviendra
withStyles<'button' | 'root', Props>((theme, props) => ...)
Quel est l'état actuel de cela? Ce serait vraiment sympa d'avoir cette fonction
@lucasmafra J'ai ajouté cette fonctionnalité au jalon de publication post v1. Plus tôt nous pourrons sortir la v1, mieux ce sera.
Cette fonctionnalité est essentielle pour pouvoir écrire des règles de style expressif qui combinent des accessoires, des requêtes multimédias et des états interactifs. Vous ne pouvez pas remplacer cette fonctionnalité par des styles en ligne. Malheureusement, withStyles
est inutilisable dans aucun de mes projets jusqu'à ce que cela soit ajouté.
Vous pouvez toujours configurer un thème personnalisé et utiliser cette convention : nous aimons vraiment la façon dont les composants stylisés vous donnent accès à props.theme en imbriquant ThemeProvider dans MuiThemeProvider lorsque les deux sont appelés theme={theme}. Il étend le thème par défaut que mui expose
//inline with HOC Method
h1 style= {{ 'color: this.props.theme.palette.primary[500]' }}
//styled components ( no method necessary )
const Heading = styled.h1`
color: ${p => p.theme.palette.primary['500']};
`
J'avais juste besoin d'utiliser des valeurs de fonction, j'ai donc utilisé la fonction injectSheet()
react-jss. J'ai l'habitude d'utiliser la fonction withStyles()
Mui, donc y a-t-il un inconvénient à utiliser injectSheet au lieu de withStyles ?
@damien-monni Vous n'avez pas accès à votre thème MUI.
Bonjour à tous, je voulais juste partager ma version de l'API Material-UI styled-components-like . Ce n'est pas "lourdement" testé mais il semble bien fonctionner et fournit :
props
et theme
pour styler la fonction.props
au composant encapsuléReact.forwardRef
function
ou object
prop-types, et en vérifiant les composants sans état s'il faut passer à child )Problèmes connexes : #10825, #7633
stylisé.js
import React, { Component } from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
function styled(WrappedComponent, customProps) {
return (style, options) => {
class StyledComponent extends Component {
render() {
let {
forwardRef,
classes,
className,
...passThroughProps
} = this.props;
return (
<WrappedComponent
ref={forwardRef}
className={classNames(classes.root, className)}
{...passThroughProps}
{...customProps}
/>
);
}
}
StyledComponent.propTypes = {
classes: PropTypes.object.isRequired,
className: PropTypes.string,
};
let hoistedProps = {};
const styles =
typeof style === 'function'
? theme => {
return { root: style({ ...theme, theme, props: hoistedProps }) };
}
: { root: style };
const WithRef = withStyles(styles, options)(StyledComponent);
return React.forwardRef((props, ref) => {
hoistedProps = props;
return <WithRef {...props} forwardRef={ref} />;
});
};
}
export default styled;
Exemple d'utilisation
const MobileNav = styled('nav')(({ theme, props }) => ({
'&.pos-fixed': {
top: 0,
position: props.fixed ? 'fixed' : 'absolute',
zIndex: 99,
animation: 'fadeInDown 0.3s ease-out forwards',
backgroundColor: theme.palette.common.white,
},
}));
Avec des accessoires personnalisés
const StyledButton = styled(Button, { component: Link })(
({ theme, props }) => ({
color: props.disabled ? 'gray' : 'blue',
[theme.breakpoints.down('sm')]: {
color: 'red',
},
})
);
@oliviertassinari Pour résoudre ce problème, j'utilise la solution ci-dessous :
componentWillMount() {
const {color} = this.props;
jss.setup(jssPreset());
const stylesheet = jss.createStyleSheet({
underline: {
"&:after": {
backgroundColor: `${color} !important`
}
}
}).attach();
this.underlineClass = stylesheet.classes.underline;
}
Cela fonctionne très bien, mais y a-t-il des problèmes potentiels que je ne vois pas ? Je n'aime pas que je doive appeler jss.setup deux fois par exemple 😅. Je ne suis pas sûr de comprendre le cycle jss
vie de setup()
ici.
Cela fonctionne très bien, mais y a-t-il des problèmes potentiels que je ne vois pas ?
@wcandillon Certains problèmes potentiels que je peux voir: 1. Vous injecterez de nouveaux noms de classe à chaque fois qu'une instance du composant est montée. 2. Vous ne pourrez pas rendre votre composant côté serveur. 3. Vous n'obtiendrez pas le bon ordre d'injection de substitution CSS.
J'ai développé cette bibliothèque pour avoir des accessoires avec style :
https://github.com/JacquesBonet/jss-material-ui
Testé avec succès sur un projet.
Au début, j'utilise la solution danielmahon, mais j'ai un problème d'héritage de style.
@oliviertassinari Avons-nous une approche alternative pour créer des css/animations dynamiques en ce moment ? Merci :)
@HunderlineK Quelques alternatives : https://material-ui.com/customization/overrides/#2 -dynamic-variation-for-a-one-time-situation.
@danielmahon, votre approche est exactement ce que je recherche en ce moment pour résoudre mon problème, bien que le "composant stylisé" ne soit pas restitué lorsqu'il reçoit de nouveaux accessoires. As-tu essayé autre chose ?
Je penserai à quelque chose de différent, et si je trouve quelque chose je te le ferai savoir
💰 Je viens d'attacher une prime de 50 $ à celui-là :)
Comme l'a dit @lewisdiamond , const styles = (props, theme) => ({})
serait vraiment chouette.
Ou const styles = (theme, props) => ({})
pour être incassable peut-être.
J'ajoute ce problème dans le
@oliviertassinari cela a probablement des implications importantes pour la saisie de withStyles
, faites-moi savoir si je peux vous aider avec ça
@pelotom Merci, je vous tiens au courant. J'espère pouvoir commencer à étudier la question ce mois-ci.
Y a-t-il des travaux en cours à ce sujet? C'est une fonctionnalité clé de l'OMI, je pourrais peut-être vous aider.
EDIT : j'ai commencé à travailler dessus. J'ai réussi à transmettre des accessoires à la fonction styles
que withStyles
accepte, le seul problème est que les styles ne sont pas mis à jour lorsque les accessoires changent. Créera un PR lorsque cela sera résolu.
Salut, je viens de tomber sur un cas d'utilisation où j'en avais besoin pour personnaliser les couleurs du composant avatar et il n'y a pas d'autre moyen de contrôler le style pour toutes les variantes du composant autre que celui-ci.
const styles = theme => ({
chip:{
},
separator: {
marginRight: theme.spacing.unit,
},
fright: {
float: 'right',
},
fleft: {
float: 'left',
},
outlinedPrimary:{
color: props => stringToColor( props.username),
border: props => `1px solid ${fade(stringToColor(props.username), 0.5)}`,
'$clickable&:hover, $clickable&:focus, $deletable&:focus': props => ({
backgroundColor: fade(stringToColor(props.username), theme.palette.action.hoverOpacity),
border: `1px solid ${stringToColor(props.username)}`,
}),
},
outlined: {
backgroundColor: 'transparent',
border: props => `1px solid ${
theme.palette.type === 'light' ? stringToColor(props.username) : fade(stringToColor(props.username))
}`,
'$clickable&:hover, $clickable&:focus, $deletable&:focus': props => ({
backgroundColor: fade(stringToColor(props.username), theme.palette.action.hoverOpacity),
}),
},
});
Vous pouvez consulter ma solution Japrogramer : https://github.com/JacquesBonet/jss-material-ui
merci, je vais y jeter un oeil.
J'avais besoin de cette fonctionnalité plus tôt dans la journée, j'ai donc écrit un HOC. withStyles
fait de la mise en cache par lui-même, donc je ne peux pas vraiment dire à quel point cela affecte cela, mais je vais regarder l'implémentation de la mise en cache de withStyles
dans mon temps libre, pour l'instant, tous ceux qui recherchent un un moyen rapide d'obtenir des accessoires et un thème pour bien jouer
Ce composant effectuera un remontage complet si les accessoires changent quelque chose à voir avec le numéro d'index de la classe de feuille de style changeant ou quelque chose dans le withStyles HOC
import React from 'react';
import { withStyles } from '@material-ui/core/styles';
const { createElement, forwardRef } = React
const withPropsStyles = ( style ) => {
const withPropsStyles = ( component ) => {
return forwardRef( (props, ref) => {
const proxy = (theme) => style(props, theme)
const hoc = withStyles(proxy)(component)
return props.children ?
createElement(hoc, { ...props, ref}, props.children) :
createElement(hoc, {...props, ref})
})
}
return withPropsStyles
}
export default withPropsStyles
const styles = (props, theme) => ({
root:{
backgroundColor: props.light ? theme.palette.primary.light : theme.palette.primary.main
},
})
const SomeComponent = ({classes}) => <div className={classes.root}/>
export default withPropsStyles(styles)(SomeComponent)
Simple et fonctionne (mais rem le coût de remontage complet aussi)
Avec ce changement, pouvons-nous supprimer l'utilisation du style en ligne de la bibliothèque en faveur de 100 % JSS ? Mon application ne fonctionne pas avec les styles en ligne et lorsque je suis allé remplacer l'effet d'entraînement par JSS, j'ai réalisé que j'avais besoin de cette fonctionnalité. Peut-être un petit coup de performance, mais semble plus propre.
@koshea abandonne le style en ligne. Je n'aime pas non plus les styles en ligne, cela devrait très bien fonctionner en remplacement de withStyles
tant que décorateur ou comme dans l'exemple.
Je voulais également mentionner que l'utilisation de styles en ligne ne permet pas d'activer une politique de sécurité du contenu solide.
Cela nécessite l'ajout unsafe-inline
indicateur
Les styles dynamiques avec la prise en charge des accessoires devraient résoudre ce problème
Salut les gars, désolé d'entrer dans la discussion "juste comme ça". J'ai récemment commencé à utiliser Mui (avec Typescript) et même si je trouve que c'est une bibliothèque extrêmement puissante, elle a certainement ses complexités.
J'ai remarqué dans certains commentaires ci-dessus qu'il y a un peu de discussion pour savoir si cette fonctionnalité devrait être (props, theme) => {}
ou (theme, props) => {}
. J'aimerais renforcer ce que @pelotom a dit à propos de la création de propriétés nommées props
et theme
dans son commentaire . Le faire de cette façon nous permettra probablement de refactoriser plus facilement les définitions de style une fois ce changement effectué (ce que j'attends vraiment avec impatience). Bravo
Merci à tous pour la patience ! Ce problème est traité dans le #13503. C'est une exigence pour les assistants de composants que nous voulons implémenter. Nous avons également commencé à expérimenter l'API hook : https://twitter.com/olivtassinari/status/1058805751404261376.
Est-ce que cela en a fait 4.0 ? Il semble que le rappel makeStyles
n'ait pas props
paramètre
@city41 const classes = useStyles(props);
Je vois. Donc on dirait que c'est
const useStyles = makeStyles(theme => {
return {
foo: {
color: theme.props.danger ? '#ff0000' : '#00ff00'
}
};
});
function MyComponent(props) {
const classes = useStyles(props);
return <div className={classes.foo}>...</div>;
}
Je ne vois pas cela documenté dans la section API de styles sur le site Web. Laissez-moi voir si je peux envoyer un PR.
@city41 Il y a un début de documentation dans https://material-ui.com/styles/basics/#adapting -based-on-props.
cool, content de voir que la doc est mise à jour. pour tous ceux qui abordent ce problème, voici comment j'ai combiné le thème et les accessoires pour styliser un composant
import React from 'react';
import { Button, Theme, makeStyles } from '@material-ui/core';
interface ButtonProps {
destructive: boolean;
}
const useButtonStyles = makeStyles<Theme, ButtonProps>(theme => {
return {
root: props => ({
backgroundColor: props.destructive ? theme.palette.error.main : theme.palette.primary.main
})
};
});
export const PrimaryButton: React.FunctionComponent<ButtonProps> = props => {
const classes = useButtonStyles(props);
return <Button {...props} className={classes.root} variant="contained" />;
};
Comment puis-je utiliser prop dans un fichier json de styles externes ?
par exemple c'est un fichier externe
const typographyStyle = {
title2: {
fontFamily:"Montserrat",
fontStyle:"normal",
fontWeight:"800",
fontSize:"72px",
lineHeight:"88px",
letterSpacing:"-0.02em",
// color:"#304C82"
color : props => {
console.log(props,'c1');
return props.color
}
}
};
export default typographyStyle;
j'importe ce fichier et répands l'objet
import typographyStyle from "../assets/jss/material-kit-pro-react/views/componentsSections/typographyStyle";
const styles = theme => ({
...typographyStyle,
homeSearch:{
width: '100%',
'& div':{
'& input':{
"color":"#304C82",
height: 65,
fontFamily: 'Open Sans',
fontStyle: 'normal',
fontWeight: 800,
fontSize: '48px',
lineHeight: '65px',
letterSpacing: '-0.03em',
'&::placeholder':{
fontFamily: 'Open Sans',
fontStyle: 'normal',
fontWeight: 800,
fontSize: '48px',
lineHeight: '65px',
letterSpacing: '-0.03em',
color: '#EAEAEA'
}
}
}
},
});
maintenant sur la fonction de couleur, j'obtiens des accessoires = {} .
quelqu'un peut-il m'aider à cet égard ?
METTRE À JOUR:
il semble que je fasse quelque chose de mal car j'obtiens un objet vide même dans mon fichier styles.js principal
homeSearch: props => {
console.log(props);
return {
width: '100%',
border: `1px solid ${props.color}`
,
'& div':{
'& input':{
"color":"#304C82",
height: 65,
fontFamily: 'Open Sans',
fontStyle: 'normal',
fontWeight: 800,
fontSize: '48px',
lineHeight: '65px',
letterSpacing: '-0.03em',
'&::placeholder':{
fontFamily: 'Open Sans',
fontStyle: 'normal',
fontWeight: 800,
fontSize: '48px',
lineHeight: '65px',
letterSpacing: '-0.03em',
color: '#EAEAEA'
}
}
}
}
},
Commentaire le plus utile
J'ajoute ce problème dans le