Ao usar createStyleSheet
, não há como (pelo menos que eu conheça) acessar os adereços do componente. Acho isso importante, pois às vezes é necessário passar tamanhos, imagens de urls e outros estilos como adereços para o componente.
Hoje, a única solução para isso é separar essas coisas em estilos embutidos, mas até onde eu sei, o material-ui v1 usa jss
e react-jss
, e esses dois já lhe dão a possibilidade de acessar os adereços por meio de funções que recebem os adereços e depois retornam o estilo desejado, assim:
const styles = {
button: {
background: props => props.color
},
root: {
backgroundImage: props => `url(${props.backgroundImage})`
}
}
// Reference: https://github.com/cssinjs/react-jss#example
O que você acha de implementar algo assim no material-ui também?
react-jss implementa esse recurso. Você sempre pode usá-lo sobre nossa solução de estilo. A verdadeira motivação para implementar esse recurso aqui deve ser em torno de uma implementação interna mais simples / melhor dos componentes.
react-jss injectStyles () também faz isso, mas parece que seria melhor adicionar adereços a StyleRuleCallback
.
const styles = (props, theme) => ({})
Dessa forma, você não está limitado a apenas valores dependendo dos adereços.
O feedback do color
aos nossos componentes, em vez do predefinido. O impacto do tamanho do CSS não está claro, mas tornaria a substituição da cor do componente ainda mais simples. Isso é algo para investigar. Então, uma vez que o suporte do navegador de variáveis css seja alto o suficiente (daqui a 2 anos?), Podemos confiar nele.
@oliviertassinari o tamanho do css não diminuiria em alguns casos?
Pelo que entendi, atualmente definimos todas as classes para ...Primary
e ...Accent
- essa mudança não significaria que teríamos apenas que manter as classes para ...Colorized
? Ou você está preocupado com o css gerado?
De qualquer forma, acho que isso melhoraria enormemente o dx, pois basicamente temos que reimplementar classes complexas como https://github.com/callemall/material-ui/blob/v1-beta/src/Button/Button.js#L11 quando deseja usar cores que não sejam da paleta.
o tamanho do css não diminuiria em alguns casos?
@sakulstra Difícil dizer. Vai depender da implementação. Pode ser :).
De uma perspectiva de digitação TypeScript, seria bom se _both_ props
e theme
pudessem ser acessados desta forma dentro de uma especificação de estilos:
const styles = {
button: {
background: ({ theme }) => theme.palette.primary[200]
},
root: {
backgroundImage: ({ props }) => `url(${props.backgroundImage})`
}
};
A razão é que o TypeScript freqüentemente falha em inferir o tipo certo para withStyles
quando é passado um objeto de função, então você deve fornecer anotações de tipo extras para fazê-lo funcionar, por exemplo,
withStyles<'button' | 'root'>(theme => ...)
Se os adereços forem passados também, isso se tornará
withStyles<'button' | 'root', Props>((theme, props) => ...)
Qual é o status atual disso? Seria muito bom ter esse recurso
@lucasmafra Eu adicionei esse recurso ao marco pós-lançamento v1. Quanto mais cedo pudermos lançar a v1, melhor.
Essa funcionalidade é fundamental para poder escrever regras de estilo expressivas que combinam adereços, consultas de mídia e estados interativos. Você não pode substituir essa funcionalidade por estilos embutidos. Infelizmente, withStyles
ser usado em nenhum dos meus projetos até que seja adicionado.
Você sempre pode configurar um tema personalizado e usar esta convenção: Nós realmente gostamos de como os componentes estilizados fornecem acesso ao props.theme pronto para uso, aninhando ThemeProvider dentro de MuiThemeProvider quando ambos chamados theme = {theme}. Ele estende o tema padrão que o mui expõe
//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']};
`
Eu só precisava usar valores de função, então usei a função react-jss ' injectSheet()
. Estou acostumado a usar a função withStyles()
do Mui, então há alguma desvantagem em usar injetSheet em vez de withStyles?
@ damien-monni Você não tem acesso ao seu tema MUI.
Olá a todos, só queria compartilhar minha versão da API com estilo de componentes de interface do usuário Material. Não é "pesadamente" testado, mas parece funcionar bem e fornece:
props
e theme
içados para a função de estilo.props
customizado para o componente empacotadoReact.forwardRef
function
ou object
prop-types e verificando os componentes sem estado para passar para o filho)Problemas relacionados: # 10825, # 7633
styled.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;
Exemplo de uso
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,
},
}));
Com adereços personalizados
const StyledButton = styled(Button, { component: Link })(
({ theme, props }) => ({
color: props.disabled ? 'gray' : 'blue',
[theme.breakpoints.down('sm')]: {
color: 'red',
},
})
);
@oliviertassinari Para resolver esse problema, estou usando a solução abaixo:
componentWillMount() {
const {color} = this.props;
jss.setup(jssPreset());
const stylesheet = jss.createStyleSheet({
underline: {
"&:after": {
backgroundColor: `${color} !important`
}
}
}).attach();
this.underlineClass = stylesheet.classes.underline;
}
Funciona muito bem, mas há alguns problemas em potencial que não estou vendo? Eu não gosto de ter que chamar jss.setup duas vezes, por exemplo 😅. Não tenho certeza se entendi o ciclo de vida de jss
. Fiquei surpreso por precisar invocar setup()
aqui.
Funciona muito bem, mas há alguns problemas em potencial que não estou vendo?
@wcandillon Algum problema potencial que posso ver: 1. Você injetará novos nomes de classe toda vez que uma instância do componente for montada. 2. Você não poderá renderizar seu componente no lado do servidor. 3. Você não obterá a ordem correta de injeção de substituição de CSS.
Desenvolvi esta biblioteca para ter adereços com estilo:
https://github.com/JacquesBonet/jss-material-ui
Testado com sucesso em um projeto.
No início, eu uso a solução danielmahon, mas obtenho problema de herança de estilo.
@oliviertassinari Temos uma abordagem alternativa para criar css / animações dinâmicas no momento? Obrigado :)
@HunderlineK Algumas alternativas: https://material-ui.com/customization/overrides/#2 -dynamic-variação-para-uma-situação-única.
@danielmahon, sua abordagem é exatamente o que estou procurando agora para resolver meu problema, embora o "Componente com estilo" não seja renderizado novamente ao receber novos acessórios. Você já tentou mais alguma coisa?
Vou pensar em algo diferente, e se eu vier com algo, eu vou te dizer
💰 Acabei de anexar uma recompensa de $ 50 a esse :)
Como @lewisdiamond disse, const styles = (props, theme) => ({})
seria muito legal.
Ou const styles = (theme, props) => ({})
para ser talvez ininterrupto.
Estou adicionando esse problema no marco v1.x. Muitas pessoas estão solicitando isso. Em breve chegaremos a ele.
@oliviertassinari isso provavelmente tem implicações significativas para a digitação de withStyles
, deixe-me saber se eu posso ajudar com isso
@pelotom Obrigado,
Há algum trabalho em andamento a respeito disso? É um recurso chave da IMO, talvez eu possa ajudar com isso.
EDIT: Comecei a trabalhar nisso. Conseguiu passar adereços para a função styles
que withStyles
aceita, o único problema é que os estilos não são atualizados quando os adereços mudam. Criará um PR quando isso for resolvido.
Olá, acabei de encontrar um caso de uso em que preciso personalizar as cores do componente avatar e não há outra maneira de controlar o estilo de todas as variantes do componente além desta.
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),
}),
},
});
Você pode verificar minha solução Japrogramer: https://github.com/JacquesBonet/jss-material-ui
obrigado, vou dar uma olhada nisso.
Eu precisava desse recurso hoje cedo, então escrevi um HOC. withStyles
faz algum cache por conta própria, então eu realmente não posso dizer o quanto isso afeta isso, mas vou olhar para a implementação de cache de withStyles
em meu tempo livre, por enquanto, quem estiver procurando por um maneira rápida de obter adereços e tema para tocar bem, pronto
Este componente fará uma remontagem completa se os adereços mudarem algo a ver com o número do índice da classe da folha de estilo mudando ou algo no HOC withStyles
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)
Simples e funciona (mas remova o custo total da remontagem também)
Com essa mudança, podemos remover o uso de estilo embutido da biblioteca em favor de 100% JSS? Meu aplicativo não funciona com estilos embutidos e quando fui substituir o efeito cascata por JSS, percebi que precisava desse recurso. Talvez um pequeno impacto no desempenho, mas parece mais limpo.
@koshea abandonou o estilo embutido. Eu também realmente não gosto de estilos embutidos, ele deve funcionar muito bem como um substituto para withStyles
como decorador ou como no exemplo.
Também gostaria de mencionar que o uso de estilos embutidos não permite habilitar uma forte política de segurança de conteúdo.
Requer a adição da bandeira unsafe-inline
às diretivas de estilos, o que não é seguro.
Estilos dinâmicos com suporte de adereços devem resolver esse problema
Oi pessoal, desculpe entrar na discussão "assim". Recentemente, comecei a usar o Mui (com Typescript) e, embora a ache uma biblioteca extremamente poderosa, ela certamente tem suas complexidades.
Notei em alguns comentários acima que há uma pequena discussão sobre se esse recurso deveria ser (props, theme) => {}
ou (theme, props) => {}
. Eu gostaria de reforçar o que @pelotom disse sobre fazer props
e theme
propriedades nomeadas em seu comentário . Tornar assim provavelmente tornará mais fácil para nós refatorar as definições de estilo, uma vez que essa mudança aconteça (o que estou realmente ansioso para ver). Saúde 🙂
Obrigado a todos pela paciência! Este problema está sendo resolvido em # 13503. É um requisito para os auxiliares de componente que desejamos implementar. Também começamos a experimentar a API de gancho: https://twitter.com/olivtassinari/status/1058805751404261376.
Isso chegou ao 4.0? Parece que o retorno de chamada makeStyles
não tem um parâmetro props
.
@ city41 const classes = useStyles(props);
Entendo. Então parece que é
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>;
}
Não vejo isso documentado na seção de estilos da API no site. Deixe-me ver se posso enviar um PR.
@ city41 Há um início de documentação em https://material-ui.com/styles/basics/#adapting -based-on-props.
legal, fico feliz em ver que os documentos estão sendo atualizados. para qualquer pessoa que venha a este problema, aqui está como eu combinei tema e adereços para estilizar um componente
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" />;
};
Como posso usar prop em um arquivo json de estilos externos?
por exemplo, este é um arquivo externo
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;
eu importo este arquivo e divulgo o objeto
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'
}
}
}
},
});
agora na função de cor, obtenho adereços = {}.
alguem pode me ajudar nesse sentido?
ATUALIZAR:
parece que estou fazendo algo errado porque estou recebendo um objeto vazio mesmo no meu arquivo 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'
}
}
}
}
},
Comentários muito úteis
Estou adicionando esse problema no marco v1.x. Muitas pessoas estão solicitando isso. Em breve chegaremos a ele.