I have been creating a set of reusable components that I had been styling using classes prop to override the MUI classnames. I then extracted a lot of the common styling into a theme to avoid repetition in the more complex components. The theme is wrapping each of the components using the withTheme HOC.
I am now realising that there are places we need to override the style for one-off cases. I thought I should be able to do this using the withStyles HOC but it doesn't seem to work for me.
Codepen at https://codesandbox.io/s/overriding-a-withtheme-with-withstyle-hoc-0m9cm
MyReusableThemedComponent - is the reusable component (that is really just wrapping Material UI tabs with a theme)
CustomOverideTabs - is my implementation of the MyReusableThemedComponent where I am trying to override the Material-UI textTransform by making the text lower case.
const StyledTabs = withStyles({ root: { textTransform: "lowercase" } })(
MyReusableThemedComponent
);
I believe the transform: uppercase is the default for the MuiTab-root class, but even specifying it in the theme doesn't seem to make a difference.
TIA
The effect of withStyles is to inject a classes prop into the wrapped component (MyReusableThemedComponent in your case), but you aren't doing anything with that injected prop except passing the entire props object to useStyles during the creation of tabsStyle. This will merge the two sets of classes, but then you would need to leverage tabsStyle.root somewhere to have any effect.
You have the following code for rendering the Tab elements:
<Tab
key={index}
label={tab.tabTitle ? tab.tabTitle.toString() : "tab" + { index }}
disabled={tab.disabled}
classes={{
root: tabsStyle.tabRoot,
selected: tabsStyle.selectedTab
}}
/>
This is leveraging tabsStyle.tabRoot as the root class, but tabRoot hasn't been defined anywhere. The textTransform works as intended if you change this to root: tabsStyle.root, or if you leave the Tab rendering unchanged, you can get it to work by changing the rule name in your withStyles call to be tabRoot (e.g. withStyles({ tabRoot: { textTransform: "lowercase" } })).
Example using tabsStyle.tabRoot (i.e. only changing the withStyles argument): https://codesandbox.io/s/overriding-a-withtheme-with-withstyle-hoc-fxybe
Example using tabsStyle.root (i.e. only changing how the classes prop is specified when rendering the Tab elements): https://codesandbox.io/s/overriding-a-withtheme-with-withstyle-hoc-ptj87
A separate issue in your sandbox is that you appear to be trying to specify style overrides in the theme in ConditionalThemeWrapper, but the structure of the theme is incorrect. The MuiFab and MuiTab entries in the theme should be within an overrides key. Here is a modified version of your sandbox demonstrating this: https://codesandbox.io/s/overriding-a-withtheme-with-withstyle-hoc-ju296
Related documentation:
https://material-ui.com/customization/components/#global-theme-override
Related
import React from 'react';
export function App(props) {
return (
<div>
<h1
style={{
'&::hover': {
color: 'white'
},
color: 'red'
}}
>Hello React.</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
This hover does not work, but I wanted to be able to do it within the component's style, without a css file, class or objects.
Even if this method is not valid, there is some validity without using the components mentioned above.
The React JSX style attribute lets you provide an object of inline styles, but inline styles cannot include selectors like the pseudo-class :hover. Inline styles can only include properties. If you want to make inline styles more powerful, there are several methods of CSS-In-JS libraries that make this possible. Solutions I've tried include Emotion (which I like a lot) and styled-components (would not recommend).
Another possible option is TailwindCSS, which is a different kind of library that has a similar feel to what you want. I would personally recommend Tailwind as a go-to for this kind of thing.
Here's how you could do what you're looking for with Tailwind:
<h1 className="color-red hover:color-white">Hello React.</h1>
Again, you can't do this with just inline style attributes.
I'm trying to utilize the Autocomplete component from React Material-UI in my Website and I've already managed to customize the appearance of the List-Elements to display with a dark background, as you can see in this image:
The problem is that I cannot figure out how to style the group-labels of this list. In this project, I have to use class-components so I cannot use a solution that uses React-Hooks. I guess I could somehow achieve it by overriding the CSS of this Component, but I can't figure out how.
I already tried solving this by using the createMuiTheme() function and overriding the MuiListSubheader styling, but sadly this also didn't work.
In the documentation I saw that the Autocomplete component has a "groupLabel" key within the "classes" prop, but for some reason I can only enter a string into this key.
I managed to style the list items by using the "PaperComponent" Prop of the Autocomplete component, but I couldn't find a similar solution for the list subheaders.
Thanks in advance for any help!
I managed to do it by passing a PopperComponent to the Autocomplete like so :
<Autocomplete PopperComponent={StyledPopper}></Autocomplete>
This StyledPopper is defined as such with MUI v5 styled components :
const StyledPopper = styled(Popper)(({ theme }) => ({
'& .MuiAutocomplete-groupLabel': {
backgroundColor: theme.palette.primary.main,
color: theme.palette.common.white,
},
}));
You can also style the paper in it with '& .MuiAutocomplete-paper'
I'd like to change the color behind the dropdown options in my Material UI Autocomplete component.
I've reviewed the below sources, but they only describe how to use the renderOption prop to render the option text itself, which results in something like the below picture:
Change the color of Material UI Autocomplete option
How render a list of options with renderOption in material UI
Instead, I want the entire option rectangle to be a certain color. The entire rectangle encasing the dropdown options would be the color, not just the little bit surrounding the option text. I expect this to require some intelligent css styling, as it doesn't seem to be offered as a prop on the Autocomplete component, but I can't figure out the proper syntax/rules to change.
Bonus if you also explain how this could be done as global override. I've been unable to add an override, like this, even after extending the default theme. (See why extending the theme would be necessary here.)
You can do this by using the classes property of Autocomplete.
Checkout the CSS section of https://material-ui.com/api/autocomplete/
Here is an incomplete example that will hopefully help you get started.
const useStyles = makeStyles((theme) => ({
option: {
backgroundColor: 'red'
}
}));
<Autocomplete
classes={{
option: classes.option
}}
/>
I am not sure how you would do this as a global override.
I have my react app inside which i want to use vaadin-date-picker (v. 4.0.5).
I want to change some of the date pickers in a way that they would be above my modal by changing z-index to 1100 (for example)
and some to stay at 200.
In some examples, people put <style> tag inside
<vaadin-date-picker></vaadin-date-picker>
But react is not recognizing <style> attribute inside render function.
I can set class for
<vaadin-date-picker class='my-class'>
but it only changes control itself and not the backdrop part. Is there a way to change styles of some web components inside react app?
Make sure you are importing the file correctly
import './yourcssfile.css'; // if in same directory
also in react classes are applied using className keyword
<vaadin-date-picker className="my-class">
and lastly you have to follow the documentation vaadin. you can't add your own styles if the vaadin-date-picker doesn't support it.
Here in their documentation it says Vaadin Date Picker comes with both Lumo and Material design themes, and it can be customized to fit your application.
The cleanest way to use styles in my opinion is to use CSS files, so
import './classname.css';
Would be my default answer. However, if you want to set styles explicitly in your Component, these are two examples, how you can do it:
class Example extends Component {
getStyle1 = () => {
return {
fontWeight: 'bold'
};
}
render () {
return (
<div><div style={this.getStyle1()}>style1</div>
<div style={style2}>style2</div></div>
)
}
}
const style2 = {
fontStyle: 'italic'
}
Remember that it's JavaScript objects that you return with your styles, so you don't use CSS syntax with dashes (e.g. you type backgroundColor instead of background-color) and all values must be put in quotes.
Had a hard time figuring out how to apply css using Aphrodite on any vue plugins. I tried to override css on a vue-select plugin but the issue is I can't access the generated elements inside the plugin. I tried to get a class selector but no luck. Any help would be much appreciated.
Sample:
<v-select
v-model="filterDate"
:options="filterOptions"
:on-change="onFilterChange"
:class="css(styles.inputBordered)"
>
</v-select>
Script:
styles () {
return StyleSheet.create({
inputBordered: {
border: '1px solid ' + this.theme.backgroundColor,
borderRadius: '5px',
'.dropdown-toggle': {
//some css overrides in here
}
}
});
}
I don't think that this is possible for elements nested in the child component, unless the plugin has a props interface allowing you to pass in classnames yourself.
classes added like you show above are added to the root element of the component only.
Aphrodite requires that the generates class is directly added to the element, but you can't access that element from within Vue as it's controlled by the child.
Furthermore, even if possible, this is not a very reliable way of overwriting styles because it:
can only work if the CSS in the child component also has a specificity of 1
even if both have specificity of 1, it relies on the aphrodite class definitions appearing after the ones of the child, which can depend on your build setup.
So in short: I don't think that will work in any reliable way.