Skip to content

Core: Right To Left (RTL) Support #332

Description

@github-actions

Describe the feature you would like to see added

Right To Left support is not currently fully supported in PrimeReact. From PrimeTek:

We are currently only considering doing a study on PrimeReact. PrimeReact has modern CSS styles and this kind of improvement will indeed be easier than we expected. However, we cannot say the same for PrimeFaces. As you know, PrimeFaces is a proven 10-year project. We work every day to improve existing CSS styles. In the long run, of course, we plan to make improvements to PrimeFaces for RTL. Unfortunately, I can't give an exact date for now.

Issues opened previously:

Describe the feature you would like to see added

Improve CSS, so that components are rendered automatically and appropriately for right to left languages. This will require changes in:

  • Themes - for cases like where the buttons, spinners, etc. are positioned within respective widgets
  • PrimeFlex - for things like left/right margins and paddings
  • PrimeIcons - for icons, that represent some kind of arrow pointing left or right
  • Markup changes within PrimeReact, PrimeNg, etc. could probably avoided

Is your feature request related to a problem?

No response

Describe the solution you'd like

I think the best way is to use [dir='rtl'] in the CSS selectors and address the specific cases where left/right attributes are affected.

Describe alternatives you have considered

What I tried (and it worked well, but not perfect) is to include some additional CSS rules, as per the below example. You can observe the results in this Storybook https://master--626d34151d5489004a1c5228.chromatic.com/?path=/story/form--table-ar

import { createUseStyles } from 'react-jss';

const useStyles = createUseStyles({
    '@global': {
        html: {
            "&[dir='rtl']": {
                '& .left-0.right-0': {
                    left: '0px !important',
                    right: '0px !important'
                },
                '& .right-0': {
                    left: '0px !important',
                    right: 'unset !important'
                },
                '& .left-0': {
                    left: 'unset !important',
                    right: '0px !important'
                },
                '& .p-float-label > label': {
                    left: 'unset !important',
                    right: 'var(--inline-spacing)'
                },
                '& .mr-2': {
                    marginLeft: 'var(--inline-spacing) !important',
                    marginRight: 'unset !important'
                },
                '& .p-button-icon-left': {
                    marginLeft: 'var(--inline-spacing)',
                    marginRight: 'initial'
                },
                '& .pi-angle-double-left:before': {
                    content: '"\\e92e"'
                },
                '& .pi-angle-left:before': {
                    content: '"\\e932"'
                },
                '& .pi-angle-double-right:before': {
                    content: '"\\e92d"'
                },
                '& .pi-angle-right:before': {
                    content: '"\\e931"'
                },
                '& .p-datatable .p-datatable-tbody > tr > td': {
                    textAlign: 'right'
                },
                '& .p-calendar-w-btn-right .p-datepicker-trigger, & .p-buttonset .p-button:last-of-type': {
                    borderTopLeftRadius: 'var(--border-radius)',
                    borderBottomLeftRadius: 'var(--border-radius)',
                    borderTopRightRadius: '0px',
                    borderBottomRightRadius: '0px'
                },
                '& .p-calendar-w-btn-right .p-inputtext, & .p-inputnumber-buttons-stacked .p-inputnumber-input, & .p-buttonset .p-button:first-of-type': {
                    borderTopLeftRadius: '0px',
                    borderBottomLeftRadius: '0px',
                    borderTopRightRadius: 'var(--border-radius)',
                    borderBottomRightRadius: 'var(--border-radius)'
                },
                '& .p-inputnumber-buttons-stacked .p-button.p-inputnumber-button-up': {
                    borderTopLeftRadius: 'var(--border-radius)',
                    borderBottomLeftRadius: '0px',
                    borderTopRightRadius: '0px',
                    borderBottomRightRadius: '0px'
                },
                '& .p-inputnumber-buttons-stacked .p-button.p-inputnumber-button-down': {
                    borderTopLeftRadius: '0px',
                    borderBottomLeftRadius: 'var(--border-radius)',
                    borderTopRightRadius: '0',
                    borderBottomRightRadius: '0px'
                },
                '& .p-treeselect-close, & .p-multiselect-panel .p-multiselect-header .p-multiselect-close': {
                    marginLeft: 'initial',
                    marginRight: 'auto'
                },
                '& .p-tree .p-treenode-children': {
                    padding: '0 var(--content-padding) 0 0'
                },
                '& .p-multiselect-panel .p-multiselect-items .p-multiselect-item .p-checkbox, & .p-multiselect.p-multiselect-chip .p-multiselect-token, & .p-treeselect.p-treeselect-chip .p-treeselect-token, & .p-tabmenu .p-tabmenu-nav .p-tabmenuitem .p-menuitem-link .p-menuitem-icon': {
                    marginLeft: 'var(--inline-spacing)',
                    marginRight: '0px'
                },
                '& .p-multiselect.p-multiselect-chip .p-multiselect-token .p-multiselect-token-icon, & .p-chips .p-chips-multiple-container .p-chips-token .p-chips-token-icon, & .p-menubar-root-list > .p-menuitem > .p-menuitem-link .p-submenu-icon': {
                    marginLeft: '0px',
                    marginRight: 'var(--inline-spacing)'
                },
                '& .p-multiselect .p-multiselect-clear-icon': {
                    right: 'inherit',
                    left: '2.357rem'
                },
                '& ul.p-submenu-list': {
                    left: 0,
                    right: 'initial!important'
                },
                '& .p-buttonset .p-button:not(:last-child)': {
                    borderLeft: '0 none',
                    borderRight: '1px solid var(--surface-border)',
                    '&.p-highlight': {
                        borderColor: 'var(--primary-color)'
                    }
                },
                '& .pi-chevron-right, & .pi-chevron-left': {
                    rotate: '180deg'
                },
                '& .pi-caret-right:before': {
                    content: '"\\e904"'
                },
                '& .pi-caret-left:before': {
                    content: '"\\e905"'
                },
                '& .pi-arrow-right:before': {
                    content: '"\\e91a"'
                },
                '& .pi-arrow-left:before': {
                    content: '"\\e91b"'
                }
            }
        }
    }
});

Additional context

While my solution worked, it does not feel right. Let me know if you are interested in including RTL support in the libraries. I can help with ideas and also with providing proper Arabic translations to test with.


Original issue:
primefaces/primereact#3096

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions