diff --git a/README.md b/README.md
index 3a56f10..c009737 100644
--- a/README.md
+++ b/README.md
@@ -190,6 +190,19 @@ $ yarn typeorm migration:run
+## 👉 UI RTL support
+
+> Change diretion in react-ui/src/config.js:
+
+```
+const config = {
+ ...,
+ direction: 'ltr' // change to 'rtl'
+};
+```
+
+
+
## [React Berry Dashboard](https://appseed.us/product/berry-dashboard-pro/full-stack/) `PRO Version`
> For more components, pages and priority on support, feel free to take a look at this amazing starter:
diff --git a/react-ui/public/index.html b/react-ui/public/index.html
index 6543edf..a32557c 100644
--- a/react-ui/public/index.html
+++ b/react-ui/public/index.html
@@ -54,6 +54,8 @@
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@400;500;600;700&family=Roboto:wght@400;500;700&display=swap"
rel="stylesheet"
/>
+
+
diff --git a/react-ui/src/App.js b/react-ui/src/App.js
index 903c01e..902bd75 100644
--- a/react-ui/src/App.js
+++ b/react-ui/src/App.js
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useEffect } from 'react';
import { useSelector } from 'react-redux';
import { ThemeProvider } from '@material-ui/core/styles';
@@ -17,10 +17,14 @@ import NavigationScroll from './layout/NavigationScroll';
const App = () => {
const customization = useSelector((state) => state.customization);
+ useEffect(() => {
+ document.body.setAttribute('dir', customization.direction);
+ document.documentElement.setAttribute('dir', customization.direction);
+ }, [customization.direction]);
return (
-
+
diff --git a/react-ui/src/config.js b/react-ui/src/config.js
index b581dde..035f07c 100644
--- a/react-ui/src/config.js
+++ b/react-ui/src/config.js
@@ -10,9 +10,10 @@ const config = {
// like '/berry-material-react/react/default'
basename: '',
defaultPath: '/dashboard/default',
- fontFamily: `'Roboto', sans-serif`,
+ fontFamily: `'Vazir', 'Roboto', sans-serif`,
borderRadius: 12,
- API_SERVER: BACKEND_SERVER
+ API_SERVER: BACKEND_SERVER,
+ direction: 'ltr'
};
export default config;
diff --git a/react-ui/src/layout/MainLayout/Header/NotificationSection/index.js b/react-ui/src/layout/MainLayout/Header/NotificationSection/index.js
index 4342b1b..6d6fb96 100644
--- a/react-ui/src/layout/MainLayout/Header/NotificationSection/index.js
+++ b/react-ui/src/layout/MainLayout/Header/NotificationSection/index.js
@@ -35,6 +35,9 @@ import { IconBell } from '@tabler/icons';
// style constant
const useStyles = makeStyles((theme) => ({
+ root: {
+ direction: 'ltr'
+ },
ScrollHeight: {
height: '100%',
maxHeight: 'calc(100vh - 205px)',
@@ -156,6 +159,7 @@ const NotificationSection = () => {
({
searchControl: {
width: '434px',
- marginLeft: '16px',
+ margin: '0 16px',
paddingRight: '16px',
paddingLeft: '16px',
'& input': {
diff --git a/react-ui/src/layout/MainLayout/Sidebar/index.js b/react-ui/src/layout/MainLayout/Sidebar/index.js
index cbb9a0f..2e7c576 100644
--- a/react-ui/src/layout/MainLayout/Sidebar/index.js
+++ b/react-ui/src/layout/MainLayout/Sidebar/index.js
@@ -28,6 +28,7 @@ const useStyles = makeStyles((theme) => ({
background: theme.palette.background.default,
color: theme.palette.text.primary,
borderRight: 'none',
+ right: 0,
[theme.breakpoints.up('md')]: {
top: '88px'
}
diff --git a/react-ui/src/layout/MainLayout/index.js b/react-ui/src/layout/MainLayout/index.js
index 5a4c32d..d2403cc 100644
--- a/react-ui/src/layout/MainLayout/index.js
+++ b/react-ui/src/layout/MainLayout/index.js
@@ -22,62 +22,71 @@ import { SET_MENU } from './../../store/actions';
import { IconChevronRight } from '@tabler/icons';
// style constant
-const useStyles = makeStyles((theme) => ({
- root: {
- display: 'flex'
- },
- appBar: {
- backgroundColor: theme.palette.background.default
- },
- appBarWidth: {
- transition: theme.transitions.create('width'),
- backgroundColor: theme.palette.background.default
- },
- content: {
- ...theme.typography.mainContent,
- borderBottomLeftRadius: 0,
- borderBottomRightRadius: 0,
- transition: theme.transitions.create('margin', {
- easing: theme.transitions.easing.sharp,
- duration: theme.transitions.duration.leavingScreen
- }),
- [theme.breakpoints.up('md')]: {
- marginLeft: -(drawerWidth - 20),
- width: `calc(100% - ${drawerWidth}px)`
+const useStyles = (dir) =>
+ makeStyles((theme) => ({
+ root: {
+ display: 'flex',
+ right: dir ? 0 : ''
},
- [theme.breakpoints.down('md')]: {
- marginLeft: '20px',
- width: `calc(100% - ${drawerWidth}px)`,
- padding: '16px'
+ appBar: {
+ backgroundColor: theme.palette.background.default
},
- [theme.breakpoints.down('sm')]: {
- marginLeft: '10px',
- width: `calc(100% - ${drawerWidth}px)`,
- padding: '16px',
- marginRight: '10px'
- }
- },
- contentShift: {
- transition: theme.transitions.create('margin', {
- easing: theme.transitions.easing.easeOut,
- duration: theme.transitions.duration.enteringScreen
- }),
- marginLeft: 0,
- borderBottomLeftRadius: 0,
- borderBottomRightRadius: 0,
- [theme.breakpoints.down('md')]: {
- marginLeft: '20px'
+ appBarWidth: {
+ transition: theme.transitions.create('width'),
+ backgroundColor: theme.palette.background.default
+ },
+ content: {
+ ...theme.typography.mainContent,
+ borderBottomLeftRadius: 0,
+ borderBottomRightRadius: 0,
+ transition: theme.transitions.create('margin', {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.leavingScreen
+ }),
+ [theme.breakpoints.up('md')]: {
+ marginLeft: dir ? -(drawerWidth - 20) : '',
+ marginRight: !dir ? -(drawerWidth - 20) : '',
+ width: `calc(100% - ${drawerWidth}px)`
+ },
+ [theme.breakpoints.down('md')]: {
+ marginLeft: dir ? '20px' : '',
+ marginRight: !dir ? '20px' : '',
+ width: `calc(100% - ${drawerWidth}px)`,
+ padding: '16px'
+ },
+ [theme.breakpoints.down('sm')]: {
+ marginLeft: '10px',
+ width: `calc(100% - ${drawerWidth}px)`,
+ padding: '16px',
+ marginRight: '10px'
+ }
},
- [theme.breakpoints.down('sm')]: {
- marginLeft: '10px'
+ contentShift: {
+ transition: theme.transitions.create('margin', {
+ easing: theme.transitions.easing.easeOut,
+ duration: theme.transitions.duration.enteringScreen
+ }),
+ marginLeft: dir ? '0' : '',
+ marginRight: !dir ? '0' : '',
+ borderBottomLeftRadius: 0,
+ borderBottomRightRadius: 0,
+ [theme.breakpoints.down('md')]: {
+ marginLeft: dir ? '20px' : '',
+ marginRight: !dir ? '20px' : ''
+ },
+ [theme.breakpoints.down('sm')]: {
+ marginLeft: dir ? '10px' : '',
+ marginRight: !dir ? '10px' : ''
+ }
}
- }
-}));
+ }));
//-----------------------|| MAIN LAYOUT ||-----------------------//
const MainLayout = ({ children }) => {
- const classes = useStyles();
+ const { direction } = useSelector((state) => state.customization);
+ // prop direction to handle the margin of main header
+ const classes = useStyles(direction === 'ltr')();
const theme = useTheme();
const matchDownMd = useMediaQuery(theme.breakpoints.down('md'));
diff --git a/react-ui/src/store/actions.js b/react-ui/src/store/actions.js
index 69e67b3..e59cc1e 100644
--- a/react-ui/src/store/actions.js
+++ b/react-ui/src/store/actions.js
@@ -8,3 +8,4 @@ export const SET_MENU = '@customization/SET_MENU';
export const MENU_OPEN = '@customization/MENU_OPEN';
export const SET_FONT_FAMILY = '@customization/SET_FONT_FAMILY';
export const SET_BORDER_RADIUS = '@customization/SET_BORDER_RADIUS';
+export const RTL_DESIGN = "@customization/RTL_DESIGN"
\ No newline at end of file
diff --git a/react-ui/src/store/customizationReducer.js b/react-ui/src/store/customizationReducer.js
index 7e2a5b3..781a34d 100644
--- a/react-ui/src/store/customizationReducer.js
+++ b/react-ui/src/store/customizationReducer.js
@@ -8,7 +8,8 @@ export const initialState = {
isOpen: [], //for active default menu
fontFamily: config.fontFamily,
borderRadius: config.borderRadius,
- opened: true
+ opened: true,
+ direction: config.direction.toLocaleLowerCase()
};
//-----------------------|| CUSTOMIZATION REDUCER ||-----------------------//
@@ -36,6 +37,11 @@ const customizationReducer = (state = initialState, action) => {
...state,
borderRadius: action.borderRadius
};
+ case actionTypes.RTL_DESIGN:
+ return {
+ ...state,
+ direction: action.direction
+ };
default:
return state;
}
diff --git a/react-ui/src/themes/index.js b/react-ui/src/themes/index.js
index fef896c..a60028c 100644
--- a/react-ui/src/themes/index.js
+++ b/react-ui/src/themes/index.js
@@ -12,7 +12,7 @@ import { themeTypography } from './typography';
* Represent theme style and structure as per Material-UI
* @param {JsonObject} customization customization parameter object
*/
-export function theme(customization) {
+export function theme(customization, direction) {
const color = colors;
let themeOption = {
@@ -31,7 +31,7 @@ export function theme(customization) {
};
return createTheme({
- direction: 'ltr',
+ direction: direction,
palette: themePalette(themeOption),
mixins: {
toolbar: {
diff --git a/react-ui/src/views/dashboard/Default/EarningCard.js b/react-ui/src/views/dashboard/Default/EarningCard.js
index bf6b5cc..b98154f 100644
--- a/react-ui/src/views/dashboard/Default/EarningCard.js
+++ b/react-ui/src/views/dashboard/Default/EarningCard.js
@@ -25,6 +25,10 @@ const useStyles = makeStyles((theme) => ({
color: '#fff',
overflow: 'hidden',
position: 'relative',
+ '&>div': {
+ position: 'relative',
+ zIndex: 5
+ },
'&:after': {
content: '""',
position: 'absolute',
@@ -32,6 +36,7 @@ const useStyles = makeStyles((theme) => ({
height: '210px',
background: theme.palette.secondary[800],
borderRadius: '50%',
+ zIndex: 1,
top: '-85px',
right: '-95px',
[theme.breakpoints.down('xs')]: {
diff --git a/react-ui/src/views/dashboard/Default/index.js b/react-ui/src/views/dashboard/Default/index.js
index 1fd51c1..2749a27 100644
--- a/react-ui/src/views/dashboard/Default/index.js
+++ b/react-ui/src/views/dashboard/Default/index.js
@@ -21,7 +21,7 @@ const Dashboard = () => {
}, []);
return (
-
+