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 ( - +