UNPKG

@mui/material

Version:

Material UI is an open-source React component library that implements Google's Material Design. It's comprehensive and can be used in production out of the box.

224 lines (170 loc) • 5.87 kB
# Right-to-left support Learn how to implement right-to-left (RTL) text with Material UI to support languages such as Arabic, Persian, and Hebrew. ## Setup This guide outlines the three steps necessary to change the direction of text-based components in Material UI to support RTL languages, as shown in the demo below: ```tsx import { createTheme, ThemeProvider, Theme } from '@mui/material/styles'; import TextField from '@mui/material/TextField'; import rtlPlugin from '@mui/stylis-plugin-rtl'; import { prefixer } from 'stylis'; import { CacheProvider } from '@emotion/react'; import createCache from '@emotion/cache'; // Consuming the outer theme is only required with coexisting themes, like in this documentation. // If your app/website doesn't deal with this, you can have just: // const theme = createTheme({ direction: 'rtl' }) const theme = (outerTheme: Theme) => createTheme({ direction: 'rtl', palette: { mode: outerTheme.palette.mode, }, }); const cacheRtl = createCache({ key: 'muirtl', stylisPlugins: [prefixer, rtlPlugin], }); export default function RtlDemo() { return ( <CacheProvider value={cacheRtl}> <ThemeProvider theme={theme}> <div dir="rtl"> <TextField label="ملصق" placeholder="العنصر النائب" helperText="هذا نص مساعد" variant="outlined" /> </div> </ThemeProvider> </CacheProvider> ); } ``` ### 1. Set the HTML direction You can set the text direction either globally (across the entire app) or locally (specific to individual components), depending on your use case. #### Globally Add `dir="rtl"` to the app's root `<html>` to set the global text direction: ```html <html dir="rtl"></html> ``` If you can't set the `dir` attribute directly on the root `<html>` element, as a workaround, use the JavaScript API before the page is rendered: ```js document.documentElement.setAttribute('dir', 'rtl'); ``` #### Locally Add the `dir="rtl"` attribute to any other HTML element or React component if you need to limit the scope of the text direction to that element and its children. :::warning Components that use React portals (like the [Dialog](/material-ui/react-dialog/)) do _not_ inherit the `dir` attribute from parents, because they actually render outside of their parental DOM trees. You must apply the `dir` attribute directly to these components if it's not globally defined as right-to-left: ```jsx <Box dir="rtl"> <Dialog /> // ❌ this Dialog will still be left-to-right (the default) </Box> <Box dir="rtl"> <Dialog dir="rtl" /> // ✅ this Dialog will be right-to-left as intended </Box> ``` ::: ### 2. Set the theme direction Use the `createTheme()` API to set the theme direction to `'rtl'`: ```js import { createTheme } from '@mui/material/styles'; const theme = createTheme({ direction: 'rtl', }); ``` ### 3. Configure RTL style plugin Install the `@mui/stylis-plugin-rtl` using one of the commands below: <codeblock storageKey="package-manager"> ```bash npm npm install stylis @mui/stylis-plugin-rtl ``` ```bash pnpm pnpm add stylis @mui/stylis-plugin-rtl ``` ```bash yarn yarn add stylis @mui/stylis-plugin-rtl ``` </codeblock> #### With Emotion If you're using Emotion, use the [CacheProvider](https://emotion.sh/docs/cache-provider) to create a new cache instance that uses `rtlPlugin` from `@mui/stylis-plugin-rtl` and add that to the top of your application tree: ```jsx import { CacheProvider } from '@emotion/react'; import createCache from '@emotion/cache'; import { prefixer } from 'stylis'; import rtlPlugin from '@mui/stylis-plugin-rtl'; // Create rtl cache const rtlCache = createCache({ key: 'muirtl', stylisPlugins: [prefixer, rtlPlugin], }); function Rtl(props) { return <CacheProvider value={rtlCache}>{props.children}</CacheProvider>; } ``` #### With styled-components If you're using styled-components, use the [StyleSheetManager](https://styled-components.com/docs/api#stylesheetmanager) and provide `rtlPlugin` to the `stylisPlugins` property: ```jsx import { StyleSheetManager } from 'styled-components'; import rtlPlugin from '@mui/stylis-plugin-rtl'; function Rtl(props) { return ( <StyleSheetManager stylisPlugins={[rtlPlugin]}> {props.children} </StyleSheetManager> ); } ``` ## Opting out of RTL locally To turn off RTL on specific components, use the template literal syntax and add the `/* @noflip */` directive: ```js const LeftToRightTextInRtlApp = styled('div')` /* @noflip */ text-align: left; `; ``` ```tsx import * as React from 'react'; import { prefixer } from 'stylis'; import rtlPlugin from '@mui/stylis-plugin-rtl'; import { CacheProvider } from '@emotion/react'; import createCache from '@emotion/cache'; import { styled } from '@mui/material/styles'; import Box from '@mui/material/Box'; import FormControlLabel from '@mui/material/FormControlLabel'; import Switch from '@mui/material/Switch'; const Normal = styled('div')` text-align: left; `; const Noflip = styled('div')` /* @noflip */ text-align: left; `; const rtlCache = createCache({ key: 'muirtl', stylisPlugins: [prefixer, rtlPlugin], }); const ltrCache = createCache({ key: 'mui', }); export default function RtlOptOut() { const [rtl, setRtl] = React.useState(false); const handleChange = () => { setRtl(!rtl); }; return ( <Box sx={{ width: '100%', display: 'flex' }}> <FormControlLabel control={<Switch onChange={handleChange} />} label="Toggle RTL" /> <CacheProvider value={rtl ? rtlCache : ltrCache}> <Box sx={{ flexGrow: 1, mx: 2 }} dir={rtl ? 'rtl' : undefined}> <Normal>RTL normal behavior</Normal> <Noflip>RTL noflip</Noflip> </Box> </CacheProvider> </Box> ); } ```