ui
ui copied to clipboard
RTL Support
RTL support for all components in the registry.
Mainly replaced physical properties with logical properties and added rtl:space-x-reverse where space-x-* is used.
This fixes #530, fixes #4877 , fixes #5776, fixes #5658 , fixes #2759 , fixes #2736 , fixes #1919
Up to date list of adjusted components:
"๐ธ" means the component didn't need any changes to be compatible with RTL layouts
- [x] Accordion ๐ธ
- [x] Alert Dialog
- [x] Alert
- [x] Aspect Ratio ๐ธ
- [x] Avatar ๐ธ
- [x] Badge ๐ธ
- [x] Breadcrumb
- [x] Button ๐ธ
- [x] Calendar
- [x] Card ๐ธ
- [x] Carousel
- [x] Chart๐ธ
- [x] Checkbox ๐ธ
- [x] Collapsible ๐ธ
- [x] Command
- [x] Context Menu
- [x] Dialog
- [x] Drawer
- [x] Dropdown Menu
- [x] Form
- [x] Hover Card
- [x] Input OTP
- [x] Input ๐ธ
- [x] Label ๐ธ
- [x] Menubar
- [x] Navigation Menu
- [x] Pagination
- [x] Popover ๐ธ
- [x] Progress๐ธ
- [x] Radio Group ๐ธ
- [x] Resizable ๐ธ
- [x] Scroll Area ๐ธ
- [x] Select
- [x] Separator ๐ธ
- [x] Sheet
- [x] Skeleton
- [x] Slider ๐ธ
- [x] Sonner ๐ธ
- [x] Switch
- [x] Table
- [x] Tabs ๐ธ
- [x] Textarea ๐ธ
- [x] Toast
- [x] Toaster
- [x] Toggle Group ๐ธ
- [x] Toggle ๐ธ
- [x] Tooltip ๐ธ
- [x] Sidebar
Someone is attempting to deploy a commit to the shadcn-pro Team on Vercel.
A member of the Team first needs to authorize it.
This is interesting. I wonder if we could have this as an option via the cli. Turn on rtl in components.json and we automatically apply those updates for you.
This is interesting. I wonder if we could have this as an option via the cli. Turn on
rtlin components.json and we automatically apply those updates for you.
That's a great idea!
The changes I have added result in support of both RTL and LTR directions, by simply adding dir=rtl to the html element <html dir="rtl"> and finally wrapping the app with Radix's direction provider <DirectionProvider dir=rtl> to switch to RTL. Furthermore, when changing the properties from directional to logical I realised some icons like ChevronLeft or ChevronRight also need to be adjusted for RTL. One more minor change would be adjusting the animation directions.
Acheiving all of this via the cli would result in full RTL support, but I am not sure how can it be done.
@nahasco I can take a look at this. Having this in the cli would be awesome. Adding it to the next milestone. I'll push to this PR and make sure you're credited for the work you've done here. Thank you.
@nahasco I can take a look at this. Having this in the cli would be awesome. Adding it to the next milestone. I'll push to this PR and make sure you're credited for the work you've done here. Thank you.
Regarding the choice between physical and logical properties, I'd like to clarify whether you intend to use logical properties as the default for all languages. Logical properties offer the flexibility needed for seamless direction switching, and I believe they could simplify the codebase and improve adaptability for various languages.
For other specific elements like icons and HTML or radix direction values, there could be an option to manage these through the CLI to give a starting ground to the user. This approach allows us to make logical properties the primary choice for simplicity and flexibility while maintaining control over other elements that may require manual adjustments.
I'm curious to know your thoughts on this approach and whether logical properties are indeed the direction you're leaning towards. Your input on this would be highly valuable. Once again, thank you for your contribution to this!
please keep in mind the use case of supporting both LTR and RTL in the same codebase.
It would be great to have it rn ๐
It's really shocking that a modern UI library doesn't fully support RTL or Internationalization (like calendar). Love shadcn but I with they would consider these stuff more seriously.
any update on this?
Waiting for updates!
I will continue working on this in the next few days. I am hoping I add RTL support to as much components as I can before I open the PR again. Then we will have to wait for it to get merged. In the meantime, you may copy the RTL supported components from this PR.
Hey @shadcn , can you share some input on this? Any plans of merging?
@nahasco Yes. Let me add this to the roadmap. I have had this on my list for a while. This should be easier now I think with the new cli and registry.
@nahasco question. is there a 1:1 mapping for those utility classes? I wonder if we could write a transformer to do these on install?
Thank you @shadcn
@nahasco question. is there a 1:1 mapping for those utility classes? I wonder if we could write a transformer to do these on install?
I am not sure what that means. But I didn't just adjust the classes, in some components I used radix ui's direction provider to pass the dir value to the component.
For example the carousel component requires a dir value to make it rtl or ltr.
I believe RTL support should be the default for the entire library and not just an option in the cli. The changes I made make the components support rtl and ltr dynamically based on the html dir value and radix's direction provider.
In a case where a user chooses not to support RTL in the cli, but later on decides to support RTL, they will have to refactor everything. So why not make RTL support the default?
My app support both RTL and LTR, For my usecase, I updated the code for RTL support by globally replacing left- with start- and right- with end-. This included properties like margins ml mr to ms me, padding pl pr to ps pe, and text alignment text-left to text-start, ...etc.
also some bugs occurred from the translate-x class so for every translate-x i would append rtl:-translate-x.
For the sidebar, I just changed the side based on the lang
for dialogs, popovers, anything that would use a portal, i wrapped the children with a div with dir tag because it's not inherited from the root
// src/components/ui/dialog.tsx
const DialogContent = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<DialogPortal>
<div dir={languageTag() == "ar" ? "rtl" : "ltr"}>
<DialogOverlay />
<DialogPrimitive.Content
ref={ref}
className={cn(
"fixed start-[50%] top-[50%] z-50 grid w-full max-w-lg rtl:translate-x-[50%] translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
className,
)}
{...props}
>
{children}
<DialogPrimitive.Close className="absolute end-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
<Cross2Icon className="h-4 w-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</div>
</DialogPortal>
));
Still facing small bugs here and there but nothing major
Subscribing to this!
Great work! anything I can help with to push this ASAP?
Great work! anything I can help with to push this ASAP?
Could you help with the remaining components?
This is mazing following ๐
My app support both RTL and LTR, For my usecase, I updated the code for RTL support by globally replacing
left-withstart-andright-withend-. This included properties like marginsmlmrtomsme, paddingplprtopspe, and text alignmenttext-lefttotext-start, ...etc. also some bugs occurred from the translate-x class so for everytranslate-xi would appendrtl:-translate-x.For the sidebar, I just changed the side based on the lang
for dialogs, popovers, anything that would use a portal, i wrapped the children with a div with dir tag because it's not inherited from the root
// src/components/ui/dialog.tsx const DialogContent = React.forwardRef< React.ElementRef<typeof DialogPrimitive.Content>, React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> >(({ className, children, ...props }, ref) => ( <DialogPortal> <div dir={languageTag() == "ar" ? "rtl" : "ltr"}> <DialogOverlay /> <DialogPrimitive.Content ref={ref} className={cn( "fixed start-[50%] top-[50%] z-50 grid w-full max-w-lg rtl:translate-x-[50%] translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg", className, )} {...props} > {children} <DialogPrimitive.Close className="absolute end-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"> <Cross2Icon className="h-4 w-4" /> <span className="sr-only">Close</span> </DialogPrimitive.Close> </DialogPrimitive.Content> </div> </DialogPortal> ));Still facing small bugs here and there but nothing major
This is similar to what I did in this PR. Additionally, I also added a dir state to some components and added rtl:rotate-180 to left and right chevron icons to fully support RTL.
@nahasco You are a legend! I cant wait for this to be merged๐๐
The latest updates on your projects. Learn more about Vercel for Git โ๏ธ
| Name | Status | Preview | Updated (UTC) |
|---|---|---|---|
| ui | โ Failed (Inspect) | Dec 11, 2024 7:22pm |
Thanks to @jjeem , all components are completed and the PR is ready to merge.
@shadcn
@nahasco wow, great work. I'll review.
This is amazing cant wait for it be merged !
Can we do something to speed up the merge ?
@shadcn We are waiting for the merged
Waiting for this to be merged
Same here, would love to see it too