I'm creating a Material UI table what I believe is the default way, and I'm getting huge padding internally.
I have tried using withStyles and passing the resulting class into through the component property, like this:
const StyledPaper = withStyles(theme => ({
root: {
padding: "0",
},
}), Paper);
...
<Table component={StyledPaper}>
I have tried making classes and passing them in:
const useStyles = makeStyles(theme => ({
root: {
padding: "0",
},
}));
...
const classes = useStyles();
...
<Table classes={classes}>
I have futzed around endlessly and I'm not having any effect at all.
Any suggestions?
If you look at the DOM element class name, you would find out that it starts with MuiPaper-root under the MuiGrid-root element.
Perhaps use nesting selector is a good approach in this situation for customized styles
import { withStyles } from "#material-ui/core/styles";
const styles = {
root: {
"& .MuiPaper-root": {
padding: 0
}
}
};
...
const { classes } = this.props;
...
export default withStyles(styles)(App);
usage
Notice it's not inside the Table so you may want to add the padding for Grid
<Grid container>
<Grid item className={classes.root} // ...>
// ...
</Grid>
</Grid>
Similar online demo and related QA:
How to change material-ui Textfield label styles in react
Related
I'm working with styled-components in atomic system.
I have my <Atom title={title} onClick={onClick}/>
And I have molecule that extends that atom, by just adding some functionality to it without wrapping element:
const Molecule = ({}) => {
const [title, setTitle] = useState('Base title')
const onClick = () => {
// some actions
}
useEffect(()=>{
setTitle('New title')
},[conditions changed])
return(
<Atom title={title} onClick={onClick}/>
)
}
I have base styling in <Atom/> but I would like to add some more to it in <Molecule/>. Is it possible to do it without creating extra wrapper?
It is possible, but the question is if it's worthy the effort - the most anticipated way would be to do it as the documentation says - to wrap the styled component and extend the styles (but this is what you want to avoid). So either:
you could assign a className to Atom, so you can adjust/overwrite the styles with CSS
pass the extraStyles props to Atom and then pass to the styled component and just use inside after the previous, default styles to overwrite them
or either pass some extraStyles as CSSProperties object and just use them as inline styling.
https://codesandbox.io/s/withered-leftpad-znip6b?file=/src/App.js:64-545
/* styles.css */
.extraClass {
color: green;
}
const AtomStyled = styled.div`
font-size: 17px;
color: blue;
font-weight: 600;
`;
const Atom = ({ children, className, extraStyles }) => {
return (
<AtomStyled style={extraStyles} className={className}>
{children}
</AtomStyled>
);
};
const Molecule = () => {
return (
<Atom className={'extraClass'} extraStyles={{ fontSize: 27 }}>
Atom
</Atom>
);
};
In the old way material ui (version 4 and earlier) styled components you could use className property to "Select" which styles are active, ie a component could be styled like:
const styles = (theme: ThemeTy) => ({
root: {
width: '100%',
},
rootLight: {
color: theme.palette.getContrastText(theme.palette.primary.main),
},
})
const useStyles = makeStyles(styles);
function MyComp() {
const classes = useLocalStyles();
return <Input
className=classNames(classes.root, highContrast ? classes.rootLight : undefined)}
value={100}
/>
}
However in the new api one would define the classes outside the component similar to styled-components does it:
const StyledInput = styled(Input)(({theme}) => `
width: '100%',
`);
function MyComp() {
return <StyledInput
value={100}
/>
}
However how would I add the conditional styling? Would I have to use the sx element? And thus use conditional styling everywhere?
You can pass any props to your StyledInput and then style the component based on them:
const StyledInput = styled(Input)(({ theme, showborders }) => ({
width: "100%",
border: showborders ? "3px solid red" : "none"
}));
...
const [showBorders, setShowBorders] = React.useState(false);
return (
<Box>
<StyledInput showBorders={showborders ? 1 : 0} value={100} />
</Box>
);
Demo
I have an object which I map through and convert the key/value pairs to Material-UI TreeItems. Is it a way to add unique styling (font-weight bold) to TreeItems if they are expandable?
TreeItem is expandable when it has any children. Otherwise, the children is undefined. You can conditionally render different styles after checking if any children exist:
import TreeView from "#material-ui/lab/TreeView";
import MuiTreeItem from "#material-ui/lab/TreeItem";
const useTreeItemStyles = makeStyles({
label: {
fontWeight: (props) => (props.children ? "bold" : "initial")
}
});
function TreeItem(props) {
const classes = useTreeItemStyles(props);
return <MuiTreeItem {...props} classes={{ label: classes.label }} />;
}
Live Demo
Let's say i have a file with themes:
themes.js:
import {createMuiTheme} from "#material-ui/core/styles";
export const myTheme = createMuiTheme({
palette: {
text: {
color: "#545F66",
},
},
});
And file with App.js, where render looks something like this:
return (
<MuiThemeProvider theme={myTheme}>
<CssBaseline />
<MyComponent />
</MuiThemeProvider>
);
Now i know that i can access the theme via withStyles:
const StyledMyComponent = withStyles(theme => ({
something: {
color: theme.palette.text.color
}
}))(props => <MyComponent {...props} />);
But what i want to achieve is something different.
MyComponent is a very big component and has for example class called "react-table-1"
And the thing i want is to set the class color "react-table-1" to theme.palette.text
so something like this:
const StyledMyComponent = withStyles(theme => ({
"react-table-1": {
color: theme.palette.text
}
}))(props => <MyComponent {...props} />);
But obviously it doesn't work.
Does anyone know if this is possible ? And how can i achieve that.
I can set "react-table-1" color in css file but i want to change it inside
react via button, and that's why i need something like this.
Live demo:
https://stackblitz.com/edit/react-jt9xs1
You may want to try nesting-selectors for className
I found that you can't simply add className to ReactDataGrid, it's probably related to this lib, you can make a workaround for it.
Some notice points:
If you check the DOM structure, you would find out that the ReactDataGrid Root class is react-grid-Container, not react-grid-Main
Material-UI withStyles is used as a HOC for component, for specific usage plz refer to the link at the bottom.
The problem in the post is rarely related to Theme, you can use your Theme as normal.
If you want to bind your button with styles, make an outer layer of styles hooks and pass the state down to makeStyles would be fine.
import React, { useState } from "react";
import ReactDataGrid from "react-data-grid";
import { makeStyles } from "#material-ui/core";
const columns = [
{ key: "id", name: "ID" },
{ key: "title", name: "Title" },
{ key: "complete", name: "Complete" }
];
const rows = [
{ id: 0, title: "Task 1", complete: 20 },
{ id: 1, title: "Task 2", complete: 40 },
{ id: 2, title: "Task 3", complete: 60 }
];
const useStyles = makeStyles(theme => ({
root: {
"& div.react-grid-Container": {
color: "red",
// color: theme.palette.text.color
}
}
}));
const App = () => {
const classes = useStyles();
const [row, setRow] = useState([]);
const onBrutForce = e => {};
return (
<div className={classes.root}>
<ReactDataGrid
columns={columns}
rowGetter={i => rows[i]}
rowsCount={3}
enableCellSelect={true}
/>
<br />
This is what i want to achieve but with "ChangeTheme" button. <br />
Because i want to set the style to other components too. <br />
<button onClick={onBrutForce} style={{ margin: "10px" }}>
(click me)
</button>
</div>
);
};
export default App;
Related styling QA:
Functional and classical styling
Convert functional to classical
I'll try to give a minimal example for what I'm trying to achieve, I am using Material UI Styles to style my components, I wanted to style all the <Link> tags in my component, so for example:
const useStyles = makeStyles(theme => ({
menuLink: theme.styles.menuLinkStyle,
}));
function DrawerContents() {
const classes = useStyles();
// noinspection JSUnresolvedVariable
return (
<div>
<div className={classes.toolbar}>
<Link to='/' className={classes.menuLink}> {/*<==== This*/}
Hello
</Link>
</div>
<Divider/>
<List>
<Link to={'/users'} className={classes.menuLink}> {/*<==== This*/}
World
</Link>
</List>
</div>
);
}
export default DrawerContents;
As you can see, I need to manually give the className={classes.menuLink} to each and every <Link> tag, I was wondering if there is a possibility to assign the classes.menuLink to every <Link> tag by default, something like this:
const useStyles = makeStyles(theme => ({
Link: theme.styles.menuLinkStyle,
}));
Without the need to write className={classes.menuLink} for each <Link> tag in my component.
Is there such a thing?
The way I would handle this is to create a new component that takes care of the styling:
const useStyles = makeStyles(theme => ({
menuLink: theme.styles.menuLinkStyle,
}));
function MenuLink(props) {
const classes = useStyles(props);
return <Link {...props} className={classes.menuLink}/>;
}
Then import this component and use it instead of Link.