Override Material UI Tab Indicator Emotion Styled - css

Trying to figure out how to override the styles of the tabs indicator using styled from Emotion. I am not sure how to access nested classes. This is what I have, but it isn't getting me there:
const StyledTabs = styled(Tabs)(
{
classes: {
indicator: {
background: 'black',
},
},
}
);
Any help would be awesome!

There are a couple issues. styled from Emotion only supports generating a single class name per usage. It doesn't provide any support for the classes: {indicator: {styles}} structure in your example.
Below is a syntax that allows you to use styled to provide a class name for the "indicator" class of Tabs:
const StyledTabs = styled(({ className, ...other }) => {
return <Tabs {...other} classes={{ indicator: className }} />;
})({
backgroundColor: "black"
});
However, this does not work completely robustly because the <style> element for the Emotion styles does not consistently occur after the <style> elements from JSS (used for Material-UI's styling) in the <head> of the document. I'm not sure how to alter the insertion point for Emotion's styles, but you can read here about how to change the insertion point for JSS. I've included this approach in my sandbox below.
Here's a sandbox that shows this working:
Another syntax option is the following which will allow you to control more than one Tabs class:
const StyledTabs = styled(({ className, ...other }) => {
return <Tabs {...other} classes={{ root: className, flexContainer: "flexContainer", indicator: "indicator" }} />;
})({
"& .indicator": {
background: "black"
},
"& .flexContainer": {
flexDirection: "row-reverse"
}
});

Related

Trouble styling TablePagination to-from on material-table

I am attempting to style the from-to of x rows number on a Material-Table, via
import MaterialTable from 'material-table'
import { TablePagination, withStyles } from '#material-ui/core'
const StyledPagination = withStyles({
caption: {
'&.MuiTypography-caption': {
fontSize: '1.5rem !important'
},
fontSize: '1.5rem !important'
}
})(TablePagination)
<MaterialTable
**Other Props Here**
components={{
Pagination: props => (
<StyledPagination
{...props}
labelRowsPerPage={<div>{props.labelRowsPerPage}</div>}
labelDisplayedRows={row => (
<div>{props.labelDisplayedRows(row)}</div>
)}
/>
)
}}
/>
I feel like those two css selectors should be redundant, but neither is working. I feel like material-table is overriding them as the computed font size is 0.75rem .MuiTypography-caption. Have also attempted styling via the root rather than caption with no difference there either.
I have been able to style the dropdown selector for number of rows to display, which seems like the same should apply to this. Originally started with this approach, which also did not work.
Ended up solving this with MuiThemeProvider, I dont think the normal ThemeProvider is working with Material-table
import { createMuiTheme, MuiThemeProvider } from '#material-ui/core/styles'
const theme = createMuiTheme({
overrides: {
MuiTypography: {
caption: {
fontSize: '1.5rem'
}
}
})
then,
<MuiThemeProvider theme={theme}>
<MaterialTable />
</MuiThemeProvider>
Although, this will style anything with class MuiTypography-caption

Material UI and ReactJS, how to style a selected ListItem using withStyles?

I want to change the style of the selected ListItem as shown in this codesandbox.
In the sandbox I use a global css stylesheet, but I would like to use the withStyle technique.
How can I do it?
What className should I use in order to target the selected ListItem?
If you are using stateless functional component, you should use makeStyles() instead of withStyles().
withStyles() is HOC which is often used with class-based component.
makeStyles() on the other hand is a hook creator, and hooks are more suitable in functional components. I'd advice you and your children to use this approach since more and more libraries are adopting hooks as the primary API instead of HOC.
You can see a list of ListItem css classes and class keys here to know which class to apply to.
const useStyles = makeStyles({
root: {
"& .Mui-selected": {
backgroundColor: "pink",
color: "red",
fontWeight: "bold"
},
"& .Mui-selected:hover": {
backgroundColor: "tomato"
}
}
});
function App() {
const [selected, setSelected] = React.useState("home");
const styles = useStyles();
return (
<List className={styles.root}>
...
</List>
);
}
If you want to use class key (selected) instead of css class (Mui-selected), you can write it like this
const useStyles = makeStyles({
root: {
"&$selected": {
backgroundColor: "pink",
color: "red",
"&:hover": {
backgroundColor: "tomato"
}
}
},
selected: {}
});
And apply to the component like this
<List>
<ListItem
classes={{
root: styles.root,
selected: styles.selected
}}
...
>
...
</ListItem>
...
</List>
At this point you should consider refactor ListItem to a separate component to clean up the duplicated code.
Live Example

Failed to override styles with classes in material-ui

I was implementing a table with TableRow component from material-ui, which has a property called "selected". Whenever "selected" is true, a pink background-color(from the default theme) is applied for it.
I was trying to change this default pink color, according to the docs, i chose to override the css classes like:
const styles = theme => ({
rowSelected: {
backgroundColor: theme.palette.grey[700]
}
})
class CustomTableRow extends React.Component {
// basic component logic
render() {
const {classes, className, style } = this.props;
<TableRow
key={key}
component="div"
selected={true}
hover={true}
className={className}
classes={{ selected: classes.rowSelected}}
style={style}
>
// some children
</TableRow>
}
export default withStyles(styles, { withTheme: true })(CustomTableRow);
But this didn't work, which was very confusing. Because i had succeeded to do the same thing somewhere else for a Drawer component with the same method above.
I debugged every css properties with Chrome Dev Tools. What i am suspecting most now is, the pink color applied on this component with this way below:
.MuiTableRow-root.Mui-selected, .MuiTableRow-root.Mui-selected:hover {
background-color: rgba(245, 0, 87, 0.16);
And my custom class style had lower precedence than this one, which was greyed out.
UPDATE1:
My project is too big, i don't know how to simplify it for codesandbox.io.
Maybe we can check the material-ui source code directly, TableRow Source Code.
What i was doing is to override this css declaration in root
'&$selected, &$selected:hover': {
backgroundColor: fade(theme.palette.secondary.main, theme.palette.action.selectedOpacity),
},
by passing in another selected declaration below. I realized it's because this &$selected, &$selected:hover is not normally css, even if i copy this into rowSelected, it doesn't work either.
UPDATE2:
I managed to override that backgroundColor, with '!important' keyword:
const styles = theme => ({
rowSelected: {
backgroundColor: theme.palette.grey[700] + " !important",
}
})
I don't know whether this is one ideal solution. This clearly shows the problem is about css classes precedence. So how to override that already defined backgroundColor in class root with class selected.
Some help please, thank you.
To provide specifity for selected class you can apply the $selected and $selected:hover classes to your overrides like below
const styles = theme => ({
rowSelected: {
"&$selected, &$selected:hover": {
backgroundColor: theme.palette.grey[800]
}
}
})
Sample demo

Apply style to ButtonBase in a Tab component

I am trying to figure out Material UI style overriding with a nested component. Say I want to increase bottom border height on a active Tab. This border is applied by the underlying ButtonBase.
Here is the style definition:
const useStyles = makeStyles(theme => ({
root: {
// an example brutal overriding, not clean, I'd like a better approach for the button
"& .MuiSvgIcon-root": {
marginRight: "8px"
}
},
// override Tab
tabWrapper: {
flexDirection: "row"
},
tabSelected: {
color: theme.palette.primary.main
},
tabLabelIcon: theme.mixins.toolbar, // same minHeight than toolbar
// TODO override buttonBase ???
// ...
}));
An example usage:
<Tab
value="/"
classes={{
wrapper: classes.tabWrapper,
selected: classes.tabSelected,
labelIcon: classes.tabLabelIcon
}}
icon={
<React.Fragment>
<DashboardIcon />
</React.Fragment>
}
label="Home"
// TODO: is this the expected syntax? TypeScript is not happy with this prop...
buttonBaseProps={{ classes: {} }}
/>
I have no idea how to define the ButtonBase classes in this example.
How should I define my props to override the ButtonBase style?
Edit: doc is here https://material-ui.com/api/tab/, the last section describe the inheritance process but the documentation is very terse.
Edit 2: the example use case is bad as you should override ".MuiTabs-indicator" to increase the bottom border height (it's actually an additional span not a border) but the question stands. Imagine that I want to change the ButtonBase background-color for example.
So as it turns out, There is no separate ButtonBase component inside the Tab component. So you won't find prop called buttonBaseProps. The tab itself is rendered as the button component.
Whatever style you wanna pass, pass it to the root inside classes. See below
<Tab classes={{
root: classes.customButtonBaseRoot,
wrapper: classes.tabWrapper,
selected: classes.tabSelected,
labelIcon: classes.tabLabelIcon
}}
/>
https://codesandbox.io/s/apply-style-to-buttonbase-in-a-tab-component-izgj5

How to customise DateTimePicker from Material-UI

I am trying to customise the DateTimePicker from Material-UI. Here is its documentation: https://material-ui-pickers.dev/api/DateTimePicker
There is no section for the styling. I want to change the main color for all the coloured components. What I've tried so far is using the general theme documentation and try to change the style of the theme:
const theme = createMuiTheme({
status: {
danger: '#FF72B1',
},
dateTimePicker: {
headerColor: '#FF72B1',
selectColor: '#FF72B1',
},
datePicker: {
selectColor: '#FF72B1',
headerColor: '#FF72B1'
}
});
function App() {
return (
<ThemeProvider theme={theme}>
<Routes />
</ThemeProvider>
)
}
As far as I understood from the theme documentation, the only thing that I've done so far is defining variables with styles, but they are not going to be applied. I have to specify them in the exact component, and here comes the tricky part.
In my Material-UI DateTimePicker:
function MaterialDateTimePicker() {
const classes = useStyles()
return (
<Fragment>
<DateTimePicker
label={label}
inputVariant="outlined"
value={value}
onChange={onChange}
classes={{
root: classes.root,
checked: classes.checked,
}}
/>
</Fragment>
);
}
I have tried to applied the styling:
const useStyles = makeStyles(theme => ({
root: {
color: '#FF72B1',
backgroundColor: 'orange',
'& > .MuiPickerDTToolbar-toolbar.MuiToolbar-root': {
backgroundColor: 'green'
}
},
checked: {},
}));
This is how I've been trying to style components with this library, based on research, reading the docu, and some SO answers:
How to change material UI select border and label
So basically you have to go to the documentation, try to find the .XXX class that matches the component that you want to customise, and if documentation is missing, you have to go to the DOM, and start looking for this class.
I did that, but I have a couple of questions:
1) In my particular case, I have the problem that on my DateTimePicker I apply the root classes, which are on the input component level. The calendar that pops up, is not a children of this component, it's open by javascript, therefore I don't know how to access it.
This syntax does not work any longer:
root: {
color: '#FF72B1',
backgroundColor: 'orange',
'& > .MuiPickerDTToolbar-toolbar.MuiToolbar-root': {
backgroundColor: 'green'
}
},
Because root is the input, not the calendar that pop ups.
2) Is this really the way to go with this library? Because all the answers on SO and complains go on this direction. Does anybody know another strategy?
3) In #material-ui/pickers node_modules folder I couldn't find the css file. I would like to pick it and customise there, like it's possible for react-dates library etc. Is that possible? Where are the css stylings?
I've prepared a sandbox with what I've tried:
https://codesandbox.io/s/inspiring-napier-zh4os
(Unfortunately the utils library is installed but not working, locally in my computer the picker works fine, I just can't style it)
I'm working with this right now, wat i did to partially override the styles is to wrap in a ThemeProvider (you can pass your theme trow your component)
<MuiPickersUtilsProvider locale={deLocale} utils={DateFnsUtils}>
<Grid container justify="space-around">
<ThemeProvider theme={defaultMaterialTheme}>
<KeyboardDatePicker
...
/>
</ThemeProvider>
</Grid>
</MuiPickersUtilsProvider>
And your theme could be something, like this
import { createMuiTheme } from '#material-ui/core'
const defaultMaterialTheme = createMuiTheme({
overrides: {
MuiPickersCalendarHeader: {
switchHeader: {
color: '#6A148E',
textTransform: 'uppercase',
},
dayLabel: {
textTransform: 'uppercase',
},
},
MuiPickersDay: {
day: {
color: '#707070',
},
daySelected: {
backgroundColor: '#6A148E',
'&:hover': {
backgroundColor: '#6A148E',
},
},
current: {
color: '#6A148E',
},
},
MuiSvgIcon: {
root: {
fill: '#6A148E',
},
},
MuiOutlinedInput: {
root: {
'&:hover': {
border: '10px solid red !important', // i'm struggling with this :/
},
},
},
},
})
export default defaultMaterialTheme
Hope it's help
I think you just need to cancel out the webkit appearance. There are a couple of ways to cancel out specific webkit styles (so you can add your own).
Try the following:
-webkit-appearance: none;
ReactJS inline styles: webkitAppearance: "none";
Also check out other -webkit-[] functions... There are functions for more specific elements such as borders, colours, etc...
Hope this helps :)

Resources