I am aware of custom theming process within react-admin.
I was wondering if in react-admin it is possible to implement a custom theme without needing to go component by component and theming them ourselves. Something like for example Material Ui premium themes (see here)
Yes, definitely. You can pass a custom theme to the <Admin> component:
const App = () => (
<Admin theme={myTheme} dataProvider={simpleRestProvider('http://path.to.my.api')}>
// ...
</Admin>
);
Here is an example custom theme:
import { defaultTheme } from 'react-admin';
import merge from 'lodash/merge';
import indigo from '#material-ui/core/colors/indigo';
import pink from '#material-ui/core/colors/pink';
import red from '#material-ui/core/colors/red';
const myTheme = merge({}, defaultTheme, {
palette: {
primary: indigo,
secondary: pink,
error: red,
contrastThreshold: 3,
tonalOffset: 0.2,
},
typography: {
// Use the system font instead of the default Roboto font.
fontFamily: ['-apple-system', 'BlinkMacSystemFont', '"Segoe UI"', 'Arial', 'sans-serif'].join(','),
},
overrides: {
MuiButton: { // override the styles of all instances of this component
root: { // Name of the rule
color: 'white', // Some CSS
},
},
},
});
You can find more information at https://marmelab.com/react-admin/Theming.html#writing-a-custom-theme, and a complete example of custom admin theme in the e-commerce demo (https://github.com/marmelab/react-admin/blob/master/examples/demo/src/layout/themes.ts).
Related
I am using Flutters built-in themes like this:
return MaterialApp(
theme: ThemeData.light().copyWith(
primaryColor: const Color(0xFF5E975A),
bottomAppBarColor: const Color(0xff282828),
// ... And so on
),
As you can see I am modifying the existing theme with copyWith. Now let's say I want a certain button to always have the Color(0xFFFF0000). Is there a way to add a new key to the existing theme?
Something like this:
ThemeData.light().copyWith(
...
).addKey(myCustomColor: const Color(0xFFFF0000))
If not, what is the best-practice way to define my custom color? I feel like just declaring a global static variable is not the intended way to implement this.
Update for Flutter 3:
Flutter has answered this exact question in the newest version of Flutter. You can now create ThemeExtensions.
This can look something like this (after defining your ThemeExtension):
MaterialApp(
theme: ThemeData.light().copyWith(
extensions: <ThemeExtension<dynamic>>[
CustomColors.light,
],
),
darkTheme: ThemeData.dark().copyWith(
extensions: <ThemeExtension<dynamic>>[
CustomColors.dark,
],
),
// other parameters...
);
In the future there will be definitely more information about this but for now have a look at this article. I took the sample from there.
I am still finding the best practice way of defining ThemeData. For now, I have already used 2 ways to achieve the custom colors:
1 Use Extension
// use it with "Theme.of(context).myCustomColor"
extension CustomThemeDataExt on ThemeData {
Color get myCustomColor {
if(brightness == Brightness.light){
return Color(0xFFFF0000);
} else {
...
}
}
...
}
...
2 Define a custom theme
// use it with "CustomTheme.of(context).myCustomColor"
class CustomTheme {
final BuildContext context;
const CustomTheme(this.context);
static CustomTheme of(BuildContext context) => CustomTheme(context);
Color get myCustomColor {
if(Theme.of(context).brightness == Brightness.light){
return Color(0xFFFF0000);
} else {
...
}
}
}
Both need to import the relative file.
I have recently started using Material ui (v5) and I am facing some issues with theme customization. I want to change the font-family for all the components through the ThemeProvider and creating a new theme. I am able to see the theme in the react inspector with the correct values but those values don't get applied to the components (specifically fontFamily but nothing works really).
This is what my ThemeProvider looks like:
import React from "react";
import {
createTheme,
ThemeProvider as MUIThemeProvider,
} from "#mui/material/styles";
const theme = createTheme({
typography: {
fontFamily: "serif",
},
});
type ThemeProviderProps = {
children: React.ReactNode;
};
const ThemeProvider = ({ children }: ThemeProviderProps) => (
<MUIThemeProvider theme={theme}>{children}</MUIThemeProvider>
);
export default ThemeProvider;
The ThemeProvider then wraps every story (using storybook):
<div
style={{
height: "100%",
width: "100%",
}}
>
<ThemeProvider>
<Story {...context} />
</ThemeProvider>
</div>
);
export const decorators = [withThemeProvider];```
I am able to see the theme I created if I use the useTheme hook or in the ThemeProvider in the components inspector (please ignore the different fontFamily in the screenshot below):
When I look at the actual component I see that it is still getting the default styles:
I am sure I am doing something stupid somewhere?
I have made customTheme using createMuiTheme() and I used it in the <ThemeProvider>.
Now, I want to make some custom styles using that customTheme inside the makeStyles() function. But makeStyles() is not getting my customTheme. It gets the default theme.
Code:
import React from 'react';
import { createMuiTheme, makeStyles, ThemeProvider } from '#material-ui/core';
const customTheme = createMuiTheme({
palette: {
primary: {
main: '#f0f'
},
}
});
const useStyles = makeStyles((theme) => ({
box: {
height: '100px',
width: '100px',
backgroundColor: theme.palette.primary.main
}
}));
export default function App() {
const classes = useStyles();
return (
<ThemeProvider theme={customTheme}>
<div className={classes.box}>
makeStyles
</div>
<div style={{
height: '100px',
width: '100px',
backgroundColor: customTheme.palette.primary.main
}}>
inline style
</div>
</ThemeProvider>
);
}
Screenshot:
Screenshot Image
As can see in the Screenshot, the first <div> has default deep blue color of Material-UI that is using makeStyles.
The second <div> has the custom color, that is using inline style.
So, how can I use the customTheme in makeStyles()?
Try ThemeProvider to wrap over App component, as per my understanding theme provided will be applied to react components wrapped under it. since "makeStyles div" is just an element styles didn't apply to it.
Codesandbox Link - https://codesandbox.io/s/mui-custom-theme-f354x
I want to override the color of some icons based on theme.type to a native PaletteColor. I can check the type and conditionally set the color like this:
const useStyles = makeStyles((theme: Theme) =>
createStyles({
someIcon: {
color:
theme.palette.type === "dark"
? theme.palette.warning.dark
: theme.palette.warning.light,
},
})
);
This is pretty verbose every time I want to override something though, so it can be refactored to themeColor below:
const themeColor = (theme: Theme, color: PaletteColor) =>
theme.palette.type === "dark"
? color.dark
: color.light;
const useStyles = makeStyles((theme: Theme) =>
createStyles({
someIcon: {
color: themeColor(theme, theme.palette.warning)
},
})
);
Which now makes me think, does Material-UI have some native helper that already does this?
I digged in the Material-UI source code for a while and here is what I found:
You can see any potential helper methods related to Material-UI style here.
There is this commit that changed palette.type to palette.mode, if you Ctrl+F to search for 'light' ? or 'dark' ?, you'll see that they also use ternary operator to assign the colors based on the dark | light mode so I doubt they have any helper method like what you described in the second snippet.
I'm trying to integrate material-ui to my project and I have some issues with custom theme settings
I created a custom theme this way
App.js
const theme = createMuiTheme({
palette: {
primary: green,
secondary: red,
},
});
class App extends Component {
render() {
return (
<MuiThemeProvider theme={theme}>
<BrowserRouter>
<Switch>
...}}
Then in a component in the substructure I create some specific css.
Now my issue is that I'm obliged to define style appBar with a backgroud color and apply it explicitely on the AppBar component. If I don't do one of these two operations, the bg of the appBar remains light gray
What is weired is that I get the correct green from theme.palette.primary["500"], which means the theme is correctly configured
Header.js
const styles = theme => ({
root: {
flexGrow: 1,
},
grow: {
flexGrow: 1,
},
appBar: {
backgroundColor: theme.palette.primary["500"]
},//...)}
class Header extends Component {
constructor(props) {
super(props)
this.classes = props.classes
}
render() {
return (<I18n>
{(tsl, {i18n, t, ready}) => {
return (
<div className={this.classes.root}>
<AppBar position="static" color="default" className={this.classes.appBar}>
<Toolbar>...(irrelevant code)
I followed the examples in https://material-ui.com/demos/app-bar/ where the first example has the light gray color, then all the other examples have a blue bg, but there's nothing in the source code that was added to apply the blue color (in my opinion)
Any help please? thanks folks
Use <AppBar position="static" color="primary">.
By default AppBar is using the colors from the grey palette.
We are considering defaulting to primary for the color prop since it's not following the spec and having grey as a default for something as prominent as the app bar is a bad idea anyway.