How to make react-admin default theme RTL - reactjs

I need to make react-admin which uses material-ui underneath into RTL, so far nothing works because there are styles on each element overriding dir="rtl" on body tag, creating a custom theme like:
const theme = {
direction: 'rtl',
isRtl: true
};
const themeWithDirection = createMuiTheme({...defaultTheme, ...theme});
and using it on Admin component like:
<Admin locale="ar" dataProvider={dataProvider} i18nProvider={i18nProvider} theme={themeWithDirection} layout={layout}>
did not work. also usign StyleProvider on custom layout did not work:
import React from 'react';
import { Layout } from 'react-admin';
import { create } from 'jss';
import rtl from 'jss-rtl';
import { jssPreset } from '#material-ui/core/styles';
import { StylesProvider } from '#material-ui/core/styles';
const jss = create({ plugins: [...jssPreset().plugins, rtl()] });
const MyLayout = props =>
<StylesProvider jss={jss}>
<Layout
{...props}
/>
</StylesProvider>;
The problem is that components like TextField use text-align: left;, so how can I flip their css without overriding them in a custom css file?

Using the ListGuesser I had no luck switching the grid to RTL, however, after writing a custom list component and JssProvider it now works:
import React from 'react';
import { List, Datagrid, TextField, EmailField } from 'react-admin';
import { create } from 'jss';
import rtl from 'jss-rtl';
import JssProvider from 'react-jss/lib/JssProvider';
import { jssPreset } from '#material-ui/core/styles';
const jss = create({ plugins: [...jssPreset().plugins, rtl()] });
export const UserList = props => (
<JssProvider jss={jss}>
<List {...props}>
<Datagrid rowClick="edit">
<TextField source="id" />
<TextField source="name" />
<TextField source="username" />
<EmailField source="email" />
<TextField source="address.street" />
<TextField source="phone" />
<TextField source="website" />
<TextField source="company.name" />
</Datagrid>
</List>
</JssProvider>
);

Related

Cannot override styles with styled component in react-phone-input-2

Styles can be overridden with additional CSS file imported but not with the styled component. Why?
import React from "react";
import styled from "styled-components/macro";
import PhoneInput from "react-phone-input-2";
import "react-phone-input-2/lib/style.css";
const Phone = styled(PhoneInput)`
#phone-input {
background: red !important;
}
`;
function InputMobile({value}) {
function change(value) {
...
}
return (
<Phone
country={"us"}
inputProps={{
id: "phone-input"
}}
value={value}
onChange={change}
/>
);
}
export default InputMobile;
Such properties as dropdownStyle, inputStyle are not enough for me as I also need to style .arrow in .selected-flag
To use styled-component with custom component you need to wrap it. Example:
const Wrapper = ({ className, ...props }) => (
<div className={className}>
<PhoneInput {...props} />
</div>
);
You can test it live:

override component mui v5 react

I'm using mui v5 and I'm trying to override the Container component to be have a padding of 4rem.
here is a simple code example:
import * as React from "react";
import { Container } from "#mui/material";
import Navbar from "./components/Navbar";
import { styled } from "#mui/system";
import CssBaseline from "#mui/material/CssBaseline";
import { ThemeProvider, StyledEngineProvider } from "#mui/material/styles";
import theme from "./theme";
const MyContainer = styled(Container, {})`
padding-left: 4rem;
background-color: aqua;
`;
export default function App() {
return (
<ThemeProvider theme={theme}>
<StyledEngineProvider injectFirst>
<CssBaseline />
<MyContainer maxWidth="xl">
<div>test</div>
</MyContainer>
</StyledEngineProvider>
</ThemeProvider>,
);
}
But this yields no results.
here is a sandbox:
https://codesandbox.io/s/wizardly-leakey-xumyd
You can use make use of shouldForwardProp of mui v5.
const MyContainer = styled(Container, {
shouldForwardProp: (prop) => prop
})(({ padding }) => ({
padding: padding,
backgroundColor: "aqua"
}));
You can check forked codesandbox here
open this

TextField Material UI in dark mode

I have a basic implementation of dark mode with material UI and React, the question is how to make TextField helper text, label, border changing according to dark and light mode toggled.
TextField is:
<TextField helperText='Sample text' label="Title" variant="outlined" />
Updated:
It's necessary TextField to have dark colored helperText, label, border in light mode, and light coloured in dark mode.
There is basic implementation of dark, light mode:
import { createTheme, ThemeProvider } from '#material-ui/core/styles'
import Paper from '#material-ui/core/Paper'
import Switch from '#material-ui/core/Switch'
function App() {
const [dark, setDark] = useState(false)
const theme = createTheme({
palette: {
type: dark ? 'dark' : 'light',
},
})
return (
<Router>
<ThemeProvider theme={theme}>
<Paper>
<Header></Header>
<Switch checked={dark} onChange={() => setDark(!dark)} />
<main className='py-3'>
<Container>
<Routes>
<Route exact path="/" element={<HomeScreen />}></Route>
...
</Routes>
</Container>
</main>
<Footer></Footer>
</Paper>
</ThemeProvider>
</Router>
);
}
export default App;
Some of the elements correspond to light, dark mode toggling, TextField not.
You can do it like this, as answered here Theme dark turns textfield to white
I added the helper text:
import React from "react";
import TextField from "#material-ui/core/TextField";
import { createMuiTheme } from "#material-ui/core/styles";
import { ThemeProvider } from "#material-ui/styles";
import CssBaseline from "#material-ui/core/CssBaseline";
const theme = createMuiTheme({
palette: {
type: "dark"
}
});
export default function FilledTextFields() {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<TextField
id="myfilled-name"
helperText='Sample text'
label="Name"
variant="filled"
/>
</ThemeProvider>
);
}
If what you ask for is to change the style of hintText and label, you should see the Customization section of Material-UI
On the other hand, if you want to change the hintText itself on theme mode change, you have to use a global state to keep track of your theme mode.
const App = () => {
const [isDark, setIsDark] = useState(false)
return (
<TextField helperText={!isDark ? 'Sample text' : 'Some other text'} label="Title" variant="outlined" />
)
}

Why is the custom palette ignored in MUI?

Using MUI 4.12 and I have set the type to dark and used CssBaseline which was the solution I have seen for other answers but still it seems the type is completely ignored.
import {React, Fragment} from 'react'
import {
createTheme,
ThemeProvider,
makeStyles,
Zoom,
Fab,
useScrollTrigger,
Box,
CircularProgress
} from "#material-ui/core";
import CssBaseline from '#mui/material/CssBaseline';
import KeyboardArrowUpIcon from "#material-ui/icons/KeyboardArrowUp";
import "./App.css";
import Footer from "./Components/Footer/footer";
import { AppRouter } from "./Router/Router";
const theme = createTheme({
palette: {
type: "dark",
primary: {
main: "#d32f2f",
},
secondary: {
main: "#ef5350",
},
inherit: {
main: "white",
},
},
overrides : {
MuiTab : {
textColorInherit : {
opacity :1,
}
}
}
});
function App(props) {
return (
<Fragment>
<div className="App">
<Box id="back-to-top-anchor" />
<ThemeProvider theme={theme}>
<CssBaseline/>
<AppRouter />
<ScrollTop {...props}>
<Fab color="primary" size="small" aria-label="scroll back to top">
<KeyboardArrowUpIcon />
</Fab>
</ScrollTop>
</ThemeProvider>
</div>
<Footer />
</Fragment>
);
}
You're importing CssBaseline from #mui/material which is the package for MUI v5. In v5, MUI uses emotion instead of JSS (different style library internally), so your code doesn't work. You need to import the components from the same version to fix the problem:
V5
import { createTheme, ThemeProvider, CssBaseline, ... } from '#mui/material';
V4
import { createTheme, ThemeProvider, CssBaseline, ... } from '#material-ui/core';
Related answer
Material UI Dark Mode

Prevent Chip component to send a REST request

I have the following code:
import React from 'react';
import PropTypes from 'prop-types';
import Chip from '#material-ui/core/Chip';
import withStyles from '#material-ui/core/styles/withStyles';
const styles = {
root: {
margin: 4,
},
};
function CustomChipField({ root, classes, record, onClick }) {
return (
<Chip className={classes.root} label={`${record.name}`} onClick={onClick} />
);
}
CustomChipField.propTypes = {
classes: PropTypes.shape({}).isRequired,
record: PropTypes.shape({}),
onClick: PropTypes.func.isRequired,
};
CustomChipField.defaultProps = {
record: {},
};
export default withStyles(styles)(CustomChipField);
What is it? It is a custom Chip component inheriting material-ui's chip.
But what I haven't figured out yet is why it sends REST request when I click it.
The example of such a request: http://localhost:3000/#/users/{"name"3A"whatever_name"}
I have an onClick prop overriden, and it was my attempt to override it but it doesn't do anything.
I use this component in the SingleFieldList of react-admin, and maybe the problem in react-admin but I use custom Chip component directly inherited from material-ui.
The code from react-admin:
export const UserList = props => (
<List {...props}>
<Datagrid rowClick="edit">
<TextField source="id" />
<TextField source="username" />
<ArrayField source="some_array">
<SingleFieldList>
<CustomChipField
source="name"
size="small"
clickable={true}
onClick={handleClick}
/>
</SingleFieldList>
</ArrayField>
</Datagrid>
</List>
);
And once again - onClick prop doesn't work.
So the question is: how to whether prevent Chip component sending a REST-request, whether to customize it.
This worked for me:
<SingleFieldList linkType={false}>
<CustomChipField />
</SingleFieldList>

Resources