Using custom styles from theme in material ui without makeStyles - javascript

I'm wondering if there is a way to access theme.customElements.acitonButton in MyComponent without having to use makeStyles? For example, can I somehow enter className={theme.customElements.actionButton}?
theme.js
const theme = createMuiTheme({
customElements: {
actionButton: {
backgroundColor: '#007AFF'
}
}
})
export default theme
MyComponent.tsx
import { makeStyles, createStyles, Theme } from '#material-ui/core'
// wondering if i can remove makeStyles and somehow access styles set in theme.js and add to <IconButton />?
const useStyles: any = makeStyles((theme: Theme) => {
return createStyles({
actionButton: theme.customElements.actionButton
})
})
const MyComponent: React.FunctionComponent<MyComponentProps> = props => {
const classes = useStyles()
<IconButton className={classes.actionButton} />
}

You can override the style of a Component or Element in the theme.
To do that, you need to create the a folder called overrides in theme folder and create a file with the same name as the component whose theme you want to override.
Then you can change the component style like this.
export default {
elevation1: {
boxShadow: '0 0 0 1px rgba(63,63,68,0.05), 0 1px 3px 0 rgba(63,63,68,0.15)'
}
};
Also you need to add the theme provider to App.js.
import React from 'react';
import ThemeProvider from '#material-ui/styles/ThemeProvider';
import CssBaseline from '#material-ui/core/CssBaseline';
import {darkBlueTheme} from './theme';
import Routes from './Routes';
function App() {
return (
<StateProvider reducer={appReducer} initialState={getInitialState()}>
<ThemeProvider theme={darkBlueTheme}>
App CODE HERE
</ThemeProvider>
</StateProvider>
);
}
export default App;

Related

Why is the keyword 'default' necessary when exporting a component withStyles

When I implement a simple React component with Mui's withStyles HOC, I have to use the keyword "default" when exporting the component. Why can't I use the HOC in the return statement within the functional component?
Is there something about Js or ReactJs that I'm missing?
Since I am forced to export this component as default, I lose the possibility to use the named import functionality, without using another import/export layer in between.
Below is the current working code:
// Card.js
import React from "react";
import {
Card,
withStyles
} from "#material-ui/core";
const styles = theme => ({
card: {
margin: theme.spacing(2)
}
});
function CustomCard(props) {
const {classes} = props;
return (
<Card className={classes.card}>
Export me without being the default component.
</Card>
);
}
export default withStyles(styles)(MediaCard);
// Elsewhere.js
import CustomCard from "Card";
...
But i'd rather write something like this:
// Cards.js
import React from "react";
import {
Card,
withStyles
} from "#material-ui/core";
const styles = theme =\> ({
card: {
margin: theme.spacing(2)
},
anotherCard: {
margin: theme.spacing(4)
}
});
export function CustomCard(props) {
const {classes} = props;
return withStyles(styles)(
<Card className={classes.card}>
Jeah. I'm not the default component.
</Card>
);
}
export function AnotherCard(props) {
const {classes} = props;
return withStyles(styles)(
<Card className={classes.anotherCard}>
Jeah. I'm not the default component either.
</Card>
);
}
// Elsewhere.js
import { CustomCard, AnotherCard } from "Cards";
...
You can do it the way you want to but you to change the way you define your components. The technical reason is that all exports except default need to be named, otherwise you can't import them and know what's what. Since withStyles() returns a statement and not a named variable/function you can't export it without a name.
export const AnotherCard = withStyles(styles)((props) => {
const {classes} = props;
return (
<Card className={classes.anotherCard}>
Jeah. I'm not the default component either.
</Card>
);
});
The downside of this is of course now your components aren't hoisted.

How to theme components with Styled-Component and Material-UI

I've tried to follow exactly what's documented here:
How to theme components with styled-components and Material-UI?
import React from "react";
import { withTheme } from "#material-ui/core/styles";
import styled from "styled-components";
const StyledDiv = withTheme(styled.div`
background: ${props => props.theme.palette.primary.main};
color: ${props => props.theme.palette.primary.contrastText};
`);
export default function App() {
return (
<StyledDiv>
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</StyledDiv>
);
}
But instead of using a "standard" HTML component like above I tried against a Material-UI Button with no luck. Can someone please help me with what I am doing wrong?
This is what I am trying:
styles.ts
import styled from 'styled-components';
import { withTheme } from "#material-ui/core/styles";
import { Button } from '#material-ui/core';
export const StyledInnerSignInButton = withTheme(styled(Button)`
margin: ${props => props.theme.spacing(3, 0, 2)};
`)
index.tsx
import { StyledInnerSignInButton } from './styles';
[...]
<StyledInnerSignInButton
type="submit"
fullWidth
variant="contained"
color="primary"
>
Sign In
</StyledInnerSignInButton>
I'm stuck here and still a React newbie. Any help is greatly appreciated!
I managed to resolve my issue. It was due to specificity. There are two ways to mitigate that, one is by wrapping the new component style with &&, for example:
export const StyledInnerSignInButton = withTheme(styled(Button)`
&& { margin: ${props => props.theme.spacing(3, 0, 2)}; }
`)
Or by manipulating the CSS Injection Order, as documented here
In your "master" index.tsx file, you will set up your code this way:
import React from 'react';
import { render } from 'react-dom';
import { StylesProvider } from '#material-ui/core/styles';
import Home from './pages/Home';
render(
<React.StrictMode>
<StylesProvider injectFirst>
{/* component name */}
<Home />
</StylesProvider>
</React.StrictMode>,
document.getElementById('root')
)
I hope that helps someone with the same problem as me.

Importing a dynamic MaterialUI theme object from a separate file?

Can someone help me understand the correct syntax for allowing a dynamic theme object to be imported from a separate file?
I am trying to get the system theme from a media query and then set the theme dynamically.
This works fine if I leave everything all in the main App function like this:
https://stackblitz.com/edit/theme-builder-working-all-in-one?file=index.js
But I want to have it broken up into different files for organization in the example below but my attempt is broken, I get the error: themeProvider_js_1.default is not a function
broken example:
https://stackblitz.com/edit/theme-builder-broken?file=index.js
This is a second try of refactoring, no errors, I can see the ThemeObject existing in the console log but the system theme isn't being applied:
https://stackblitz.com/edit/theme-builder-broken-btyufg?file=index.js
Code for the future:
working code, but I want to refactor this so the theme and media query objects are outside of the App component:
import React from 'react';
import { render } from 'react-dom';
import useMediaQuery from '#material-ui/core/useMediaQuery';
import { createMuiTheme, ThemeProvider } from '#material-ui/core/styles';
import CssBaseline from '#material-ui/core/CssBaseline';
function App() {
const prefersDarkMode = useMediaQuery('(prefers-color-scheme)');
const theme = React.useMemo(
() =>
createMuiTheme({
palette: {
type: prefersDarkMode ? 'dark' : 'light',
},
}),
[prefersDarkMode],
);
return (
<ThemeProvider theme={theme}>
<CssBaseline/>
<p>
Start editing to see some magic happen :)
</p>
</ThemeProvider>
);
}
render(<App />, document.getElementById('root'));
broken refactor attempt:
App component
import React from 'react';
import { render } from 'react-dom';
import useMediaQuery from '#material-ui/core/useMediaQuery';
import { createMuiTheme, ThemeProvider } from '#material-ui/core/styles';
import themeBuilder from './themeProvider.js'
function App() {
return (
<ThemeProvider theme={themeBuilder()}>
<p>
Start editing to see some magic happen :)
</p>
</ThemeProvider>
);
}
render(<App />, document.getElementById('root'));
themeBuilder
import React from 'react';
import { createMuiTheme } from '#material-ui/core/styles';
import useMediaQuery from '#material-ui/core/useMediaQuery';
function themeBuilder() {
const prefersDarkMode = useMediaQuery('(prefers-color-scheme)');
const theme = React.useMemo(
() =>
createMuiTheme({
palette: {
type: prefersDarkMode ? 'dark' : 'light',
},
}),
[prefersDarkMode],
);
return theme
}
I think you're missing export default in themeProvider.js
export default function themeBuilder() {
const prefersDarkMode = useMediaQuery('(prefers-color-scheme)');
const theme = React.useMemo(
() =>
createMuiTheme({
palette: {
type: prefersDarkMode ? 'dark' : 'light',
},
}),
[prefersDarkMode],
);
return theme
}

React and Material-Ui define class in .js and pass it as string to a component

Im trying to define a class inside my .js file, so i can make use of material-uis theme object and pass it as a string to a component as the components prop only accepts strings. The React-Dropzone import only accepts a string as a parameter and not a class object.
codesandbox:
https://codesandbox.io/s/x74qvqxww4
or:
import React, { Fragment } from "react";
import Dropzone from "react-dropzone";
import { withStyles } from "#material-ui/core/styles";
const styles = theme => ({
green: {
color: "blue"
}
});
function CustomDropzone(props) {
return (
<Fragment>
<Dropzone acceptClassName="dropzoneAccept" />
<div className={props.classes.green}>
Thats how i appy styles normally
</div>
</Fragment>
);
}
export default withStyles(styles, { withTheme: true })(CustomDropzone);
How can i achieve it? Importing a .css file works but then the styles in my projects arent consistent.
Thanks for any help in advance!
All you would need to do is to declare the class like so:
import React, { Fragment } from "react";
import Dropzone from "react-dropzone";
import { withStyles } from "#material-ui/core/styles";
const styles = theme => ({
green: {
color: "blue"
}
});
class CustomDropzone extends React.Component {
render() {
return (
<Fragment>
<Dropzone acceptClassName="dropzoneAccept" />
<div className={this.props.classes.green}>
Thats how i appy styles normally
</div>
</Fragment>
);
}
}
export default withStyles(styles, { withTheme: true })(CustomDropzone);

React Css Themr not working

My target is to have one main theme for the app and load custom vendor styles if one is set.
I have been following the tutorial of react-css-themr and I can't get it to work. The minimalistic example I could come up with is this:
my module:
import {render} from 'react-dom'
import React from 'react';
import {Item} from './components/presentational/Item';
import {ThemeProvider} from 'react-css-themr';
import style from './theme/ItemDefault.scss';
const contextTheme = {
Item: require('./theme/ItemVendor.scss'),
};
const About = () => {
return (
<ThemeProvider theme={contextTheme}>
<Item theme={style} className={style.red}/>
</ThemeProvider>
)
};
ItemDefault.scss:
.button{
color:deeppink;
}
ItemVendor.scss:
.button{
color:orangered;
}
That doesn't seem to give my any classes or any styling. Any ideas please?
The way I was wiring components was incorrect. The way to do this is as follows:
In the root component you need to have your theme provider and theme attached to it. This theme will override any child component theming.
import {render} from 'react-dom'
import React from 'react';
import {ThemeProvider} from 'react-css-themr';
import inlineCss from './page.scss';
import {Item} from './components/Item';
const contextTheme = {
Item: require('./theme/ItemVendor.scss'),
};
render((
<ThemeProvider theme={contextTheme}>
<Item />
</ThemeProvider>
), document.getElementById('app'));
The component itself will have it's default theming and then will be wrapped with themr API to overwrite the it's default settings.
import {render} from 'react-dom'
import React from 'react';
import { themr } from 'react-css-themr';
import defaultTheme from './Item.scss';
const DefaultItem = ({theme}) => {
return (
<div className={theme.button} >
Example item
</div>
)
};
export const Item = themr('Item', defaultTheme)(DefaultItem);
I put together a github repo showing how to use this:
https://github.com/adamgajzlerowicz/react-css-themr

Categories