passing default theme in material UI5 - javascript

can somebody explain how pass in the defauklt theme in Material UI5
in Material UI6 i use to do it like this
const useStyles = makeStyles((theme) => ({
home: {
display: "flex",
paddingTop: "8rem",
width: "100vw",
height: "100vh",
backgroundColor: theme.palette.primary.dark,
color: "white",
},
}));
but as i got throught M-UI5 docs (as far as i found) there is no explanation on how it can be done , the only part they mention about makeStyle it contains this code in this page docs
+import { makeStyles } from '#mui/styles';
+import { createTheme, ThemeProvider } from '#mui/material/styles';
+const theme = createTheme();
const useStyles = makeStyles((theme) => ({
background: theme.palette.primary.main,
}));
function Component() {
const classes = useStyles();
return <div className={classes.root} />
}
// In the root of your app
function App(props) {
- return <Component />;
+ return <ThemeProvider theme={theme}><Component {...props} /></ThemeProvider>;
}
so am i suppose to run createTheme() on every component to get the theme? , apology if i missed out an obvious thing in the docs , probably coz my poor english

The part you are missing is from this part of the migration guide: https://mui.com/material-ui/guides/migration-v4/#style-library.
if you are using JSS style overrides for your components (for example overrides created by makeStyles), you will need to take care of the CSS injection order. To do so, you need to have the StyledEngineProvider with the injectFirst option at the top of your component tree.
Without this, the default styles for the MUI Card in your About component win over the styles specified via classes.about where the styles overlap (e.g. background).
Changing your AllProviders component to the following (just adding <StyledEngineProvider injectFirst>) fixes it:
import React from "react";
import CountriesProvider from "./countries-context";
import QuestionsProvider from "./questions-context";
import {
ThemeProvider,
createTheme,
StyledEngineProvider
} from "#mui/material/styles";
const theme = createTheme();
const AllProviders = (props) => {
return (
<StyledEngineProvider injectFirst>
<QuestionsProvider>
<ThemeProvider theme={theme}>
<CountriesProvider>{props.children}</CountriesProvider>
</ThemeProvider>
</QuestionsProvider>
</StyledEngineProvider>
);
};
export default AllProviders;
https://codesandbox.io/s/funny-flower-w9dzen?file=/src/store/AllProviders.js:303-342
The theme was being passed in fine without this change (otherwise you would have had errors when it tried to access parts of the theme), but the CSS injection order was not correct.

Related

Kitten UI (React Native) Input Styles incorporate in React Native Google Places Auto Complete

I'm trying to use the exact style of React Native Kitten UI Auto Complete with Theme(light and dark) capability in the React Native Google Places Auto Complete
Have tried a few things like custom style in <GooglePlacesAutoComplete style={-CUSTOM-STYLE-}, but I believe there would be a lot of customization to be done.
Do we know of any better way to handle this?
Got a little closer to where I wanted. Still not able to style based on onFocus. But anything is better than nothing.
Will keep updating this answer.
import React, { useEffect, useRef } from 'react';
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
import { Text, useTheme } from '#ui-kitten/components';
import { withStyles } from '#ui-kitten/components';
const GooglePlacesInput = () => {
const ref = useRef();
const theme = useTheme();
useEffect(() => {
ref.current?.setAddressText('');
}, []);
return (
<>
<Text category='label' appearance='hint'>Place</Text>
<GooglePlacesAutocomplete
ref={ref}
placeholder='Search'
onPress={(data, details = null) => {
// 'details' is provided when fetchDetails = true
console.log(data, details);
}}
query={{
key: 'YOUR_API_KEY',
language: 'en',
}}
styles={{
poweredContainer:{display:'none'},
textInput:{
color:theme['text-basic-color'],
backgroundColor:theme['background-basic-color-2'],
borderColor: theme['border-basic-color-4'],
borderWidth:1,
height:40,
marginTop:5
}
}}
/>
</>
);
};
export default withStyles(GooglePlacesInput);

How to pass a custom style to MUI V5 styled component?

Using MUI V5, how can I pass a custom style to a button component? Here is what I have been trying to merge the old way with the new MUI v5 but it's not working.
import { Button } from "#mui/material";
import { styled } from "#mui/material/styles";
import React from "react";
const StyledButton = styled(Button)(({ theme }) => ({
root: {
minWidth: 0,
margin: theme.spacing(0.5),
},
secondary: {
backgroundColor: theme.palette.secondary.light,
"& .MuiButton-label": {
color: theme.palette.secondary.main,
},
},
primary: {
backgroundColor: theme.palette.primary.light,
"& .MuiButton-label": {
color: theme.palette.primary.main,
},
},
}));
export default function ActionButton(props) {
const { color, children, onClick } = props;
return (
<Button
className={`${StyledButton["root"]} ${StyledButton[color]}`}
onClick={onClick}
>
{children}
</Button>
);
}
Now I would like to call this Button and give it color="secondary"
import ActionButton from "./ActionButton";
import { Close } from "#mui/icons-material";
export default function Header() {
return (
<ActionButton color="secondary">
<Close />
</ActionButton>
)
}
It looks like your code was an attempt to migrate from code using makeStyles/useStyles, but styled works quite a bit differently. You can't use it to generate multiple CSS classes like makeStyles does (StyledButton["root"] and StyledButton[color] will be undefined). styled will generate a single CSS class that is then passed in the className prop to the wrapped component (e.g. Button). Instead of trying to create multiple CSS classes with logic to decide which class to apply, with styled you can leverage props (e.g. the color prop) to generate dynamic styles within the single CSS class that is generated.
Below is an example that I think achieves the effect your code was aiming for. My example doesn't do anything with MuiButton-label because that class doesn't exist in v5 (and the <span> that the class was applied to inside the <button in v4 also does not exist), and I believe the default Button styles set color as desired when the color prop is allowed to passed through to Button.
import Button from "#mui/material/Button";
import { styled } from "#mui/material/styles";
const StyledButton = styled(Button)(({ theme, color }) => ({
minWidth: 0,
margin: theme.spacing(0.5),
backgroundColor: color ? theme.palette[color].light : undefined
}));
export default StyledButton;

How to switch between global CSS onclick in Gatsby?

I'm building a portfolio site in Gatsby, and as I work more on the illustration and design side, would like to serve up multiple design options to showcase that work, based on a user selection via click. I've found some similar questions, but none that are specific to Gatsby.
I'm using styled components to create the layout, so It seems to me that just swapping between multiple Global stylesheets (with fonts, colors, etc) via a button would be the way to go, so the layout remains intact, but I'm honestly not sure how to go about this as I'm pretty beginner in Gatsby and Javascript in general.
Thanks in advance!
Given a simply <Layout> structure like:
import React from "react"
import { createGlobalStyle } from "styled-components"
const GlobalStyle = createGlobalStyle`
body {
color: ${props => (props.theme === "purple" ? "purple" : "white")};
}
`
export default function Layout({ children }) {
return (
<React.Fragment>
<GlobalStyle theme="purple" />
{children}
</React.Fragment>
)
}
You can easily attach an onClick event to the children by adding a boolean operator to switch your <GlobalStyle>, for example:
export default function somePage(){
const [defaultStyles, setDefaultStyles]=useState(false);
const handleChange=()=>setDefaultStyles(!defaultStyles)
return <Layout defaultStyles={defaultStyles}>
<h1 onClick={handleChange}> Click me to toggle the global styles</h1>
</Layout>
}
Basically, you are creating a boolean state (initially set as false) to change between default styles. The result of that state (toggled by clicking the <h1>) will be sent upwards to your <Layout> so, there:
import React from "react"
import { createGlobalStyle } from "styled-components"
const GlobalStyle = createGlobalStyle`
body {
color: ${props => (props.theme === "purple" ? "purple" : "white")};
}
`
export default function Layout({ children, defaultStyles }) {
return (
<React.Fragment>
{defaultStyles && <GlobalStyle theme="purple" />}
{children}
</React.Fragment>
)
}
The && operator will only render <GlobalStyle> if defaultStyles is true. Adapt it to your needs or add a ternary condition if needed.

How to override styles in a react-chartist component?

I have a simple React JS component that wraps around the really cool react ChartistGraph component. The only issue is that the styling is seemingly overridden by the ChartistGraph default CSS. There is a lot of info on the regular Chartist js package but not much on the React JS package.
As you can see, I'm trying to change the fill color two ways: through style classes and through a prop that supported on the component.
import React from 'react';
import { Paper, withStyles } from 'material-ui';
import ChartistGraph from 'react-chartist';
const styles = theme => ({
graphStyle: {
fill: 'red',
},
});
const CustomChart = ({ classes, graph }) => {
return (
<Paper>
<ChartistGraph
className={classes.graphStyle}
data={graph.data}
options={graph.options}
type={graph.type}
style={{ fill: 'red' }}
/>
</Paper>
);
};
export default withStyles(styles)(CustomChart);
A picture of the styles of the chart
You can use jss's nested rules (included by default in material-ui):
const styles = theme => ({
graphStyle: {
'& .ct-label': { fill: 'red' },
},
});
Full code:
import React from 'react';
import { Paper, withStyles } from 'material-ui';
import ChartistGraph from 'react-chartist';
const styles = theme => ({
graphStyle: {
'& .ct-label': { fill: 'red' },
},
});
const CustomChart = ({ classes, graph }) => {
return (
<Paper>
<ChartistGraph
className={classes.graphStyle}
data={graph.data}
options={graph.options}
type={graph.type}
// style={{ fill: 'red' }} // omitted
/>
</Paper>
);
};
export default withStyles(styles)(CustomChart);
I got into similar issue recently.React-Chartist is built on top of react not material-ui.When you inspect,you found regular css class names,not "material ui-ish" class-names(like MuiTable-root,MuiTable-selectedRow,etc).So ,imho,it won't support material-ui methods (withStyle/makeStyle) and rules.
But what you can do is:-
create a css file and put your styles there
And import it where you want
.You can import it on the main file of your app(index.js or whatever it is) since every css in your app will bundle in one file.

Using withStyles of material-ui v1 in a nested manner

So I have this component that I am trying to write in react manner. Where each of the major containers are separated as React class component.
Now I know how to use withStyles with one component :
export default withStyles(styles)(MyComponent);
But when you have more than two components, how do you use withStyles.
Here's the code :
class AtmanPage extends Component {
render() {
return (
<AtmanAppBar />
);
}
}
class AtmanAppBar extends Component {
render() {
return (
<div className= {this.props.classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton className= {this.props.classes.menubutton} color="contrast" aria-label="Menu">
<MenuIcon />
</IconButton>
<Typography type="title" color="inherit" className={this.props.classes.flex}>
Title
</Typography>
<Button color="contrast">Login</Button>
</Toolbar>
</AppBar>
</div>
);
}
}
const styles = theme => ({
root: {
marginTop: theme.spacing.unit * 3,
width: '100%',
},
flex: {
flex: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
});
export default withStyles(styles) AtmanPage ?;
Now the question mark is about what else should be done to pass the styles as a prop to AtmanAppBar through AtmanPage.
Your issue is not related to withStyles but in the way you organize your components and exports.
Solution 1:
You can put each component in a separate file and use
export default withStyles(styles)(MyComponent);
in each file as you have mentioned in your post.
Solution 2:
You can do a simple export for both of your classes if you wish to keep them in the same file:
export const StyledAtmanAppBar = withStyles(styles)(AtmanAppBar);
export const StylesAtmanPage = withStyles(styles)(AtmanPage);
Then you need to import them like so in another file:
import {StyledAtmanAppBar, StylesAtmanPage} from './path/to/your/file';
Looking to handle this shizzle myself I came across a helpful util to use Styled-Components™-like API via Material-UI.
Gist example
After importing it as:
import styled from '../utils/styled';
you can create many Styled-Components-lookalikes in one file:
const List = styled('ul')(theme => ({
padding: theme.spacing.unit,
margin: 0,
}));
One difference with default withStyles() API is, that this util applies the styles to the root class, so you cannot nest many styles styles for one component (probably could be easily upgraded to allow that tbh).
But it's really handy for simple styles re-usability without the need to create too many files.
Credit to the (probable) author

Categories