Skip to content

Commit

Permalink
RTL Languages Support (#6138)
Browse files Browse the repository at this point in the history
* Update TailwindCSS & Install rtl-detect
1- Update TailwindCSS to use the logical properities such as `ps-1` instead of `pl-1`.
there are logical properities for margin, padding, inset, and text direction.

2- Install `rtl-detect` detect if the language is RTL direction.
Note: this might be uninstalled if we use the manual way to specify rtl language.

* add `siteConfig.isRTL`

* add `dir` attribute to the root element

* edit some tw classes to utilize logical properties
instead of directions properties
(e.g. `pr-0` to `pe-0`)

* edit some tw classes to utilize logical properties
instead of directions properties
(e.g. `pr-0` to `pe-0`)

* edit some tw classes to utilize logical properties
instead of directions properties
(e.g. `pr-0` to `pe-0`)

* edit some tw classes to utilize logical properties
instead of directions properties
(e.g. `pr-0` to `pe-0`)

* Refactor TW classes: Use logical properties over directional properties.

* Revert "Refactor TW classes: Use logical properties over directional properties."

This reverts commit df9620d944d9a47c5394b26fe4e3536ba3031333.

* Refactor TW classes: Use logical properties over directional properties.

* Refactor TW classes: Use logical properties over directional properties.

* Refactor TW classes: Use logical properties over directional properties.

* Add `start` and `end` directions to the `IconNavArrow`

* Add Note about `isRTL` prop

* Refactor TW classes: Use logical properties over directional properties.

* Refactor TW classes: Use logical properties over directional properties.

* Refactor TW classes: use logical properties over directional properties

* Refactor TW classes: use logical properties over directional properties

* Refactor TW classes: use logical properties over directional properties

* set dir attr of `CodeBlock` to `ltr` even the page dir is `rtl`

* Refactor TW classes: use logical properties over directional properties

* Refactor TW classes: use logical properties over directional properties

* Add `start` and `end` directions to some icons

* Refactor TW classes: use logical properties over directional properties

* Refactor TW classes: use logical properties over directional properties

* Refactor TW classes: use logical properties over directional properties

* Refactor TW classes: use logical properties over directional properties

* set dir attr of `ConsoleBlock` to `ltr` to overwrite the dir of root element

* Refactor TW classes: use logical properties over directional properties

* set dir=ltr on inline code blocks to overwrite <html dir="rtl"> in some languages

* Refactor TW classes: use logical properties over directional properties

* Refactor TW classes: use logical properties over directional properties

* Refactor TW classes: use logical properties over directional properties

* Refactor TW classes: use logical properties over directional properties

* set translate=no, dir=ltr on `TerminalBlock` to overwrite <html dir="rtl"> in rtl languages

* Refactor TW classes: use logical properties over directional properties

* Refactor TW classes: use logical properties over directional properties

* Refactor TW classes: use logical properties over directional properties

* fix some direction styles

* fix arrow directions in rtl

* remove `rtl-detect` and set `siteConfig.isRTL` manually

* fix `Breadcrumbs`'s arrow direction in rtl languages

* fix some directions of the search modal for RTL languages

* hard setting dir=ltr to Sandpack to overwrite rtl languages dir

* Refactor TW classes: use logical properties over directional properties

* remove my notes

* fix: rerverse space-x-* in rtl

* rebase with the main branch

* remove unnecessary alt

* add `start` & `end` display directions to the Chevron Icon

* rebase with the main branch
  • Loading branch information
AhmedBaset authored Aug 11, 2023
1 parent 79560d6 commit 819518c
Show file tree
Hide file tree
Showing 47 changed files with 417 additions and 266 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
"retext": "^7.0.1",
"retext-smartypants": "^4.0.0",
"rss": "^1.2.2",
"tailwindcss": "^3.0.22",
"tailwindcss": "^3.3.2",
"typescript": "^4.0.2",
"unist-util-visit": "^2.0.3",
"webpack-bundle-analyzer": "^4.5.0"
Expand Down
4 changes: 2 additions & 2 deletions src/components/Breadcrumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ function Breadcrumbs({breadcrumbs}: {breadcrumbs: RouteItem[]}) {
<Fragment key={crumb.path}>
<Link
href={crumb.path}
className="text-link dark:text-link-dark text-sm tracking-wide font-bold uppercase mr-1 hover:underline">
className="text-link dark:text-link-dark text-sm tracking-wide font-bold uppercase me-1 hover:underline">
{crumb.title}
</Link>
<span className="inline-block mr-1 text-link dark:text-link-dark text-lg">
<span className="inline-block me-1 text-link dark:text-link-dark text-lg rtl:rotate-180">
<svg
width="20"
height="20"
Expand Down
4 changes: 2 additions & 2 deletions src/components/DocsFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,12 @@ function FooterLink({
className={cn(
'flex gap-x-4 md:gap-x-6 items-center w-full md:w-80 px-4 md:px-5 py-6 border-2 border-transparent text-base leading-base text-link dark:text-link-dark rounded-lg group focus:text-link dark:focus:text-link-dark focus:bg-highlight focus:border-link dark:focus:bg-highlight-dark dark:focus:border-link-dark focus:border-opacity-100 focus:border-2 focus:ring-1 focus:ring-offset-4 focus:ring-blue-40 active:ring-0 active:ring-offset-0 hover:bg-gray-5 dark:hover:bg-gray-80',
{
'flex-row-reverse justify-self-end text-right': type === 'Next',
'flex-row-reverse justify-self-end text-end': type === 'Next',
}
)}>
<IconNavArrow
className="text-tertiary dark:text-tertiary-dark inline group-focus:text-link dark:group-focus:text-link-dark"
displayDirection={type === 'Previous' ? 'left' : 'right'}
displayDirection={type === 'Previous' ? 'start' : 'end'}
/>
<span>
<span className="block no-underline text-sm tracking-wide text-secondary dark:text-secondary-dark uppercase font-bold group-focus:text-link dark:group-focus:text-link-dark group-focus:text-opacity-100">
Expand Down
8 changes: 7 additions & 1 deletion src/components/Icon/IconArrow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ import cn from 'classnames';

export const IconArrow = memo<
JSX.IntrinsicElements['svg'] & {
displayDirection: 'left' | 'right' | 'up' | 'down';
/**
* The direction the arrow should point.
* `start` and `end` are relative to the current locale.
* for example, in LTR, `start` is left and `end` is right.
*/
displayDirection: 'start' | 'end' | 'right' | 'left' | 'up' | 'down';
}
>(function IconArrow({displayDirection, className, ...rest}) {
return (
Expand All @@ -20,6 +25,7 @@ export const IconArrow = memo<
{...rest}
className={cn(className, {
'rotate-180': displayDirection === 'right',
'rotate-180 rtl:rotate-0': displayDirection === 'end',
})}>
<path fill="none" d="M0 0h24v24H0z" />
<path d="M7.828 11H20v2H7.828l5.364 5.364-1.414 1.414L4 12l7.778-7.778 1.414 1.414z" />
Expand Down
8 changes: 7 additions & 1 deletion src/components/Icon/IconArrowSmall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@ import cn from 'classnames';

export const IconArrowSmall = memo<
JSX.IntrinsicElements['svg'] & {
displayDirection: 'left' | 'right' | 'up' | 'down';
/**
* The direction the arrow should point.
* `start` and `end` are relative to the current locale.
* for example, in LTR, `start` is left and `end` is right.
*/
displayDirection: 'start' | 'end' | 'right' | 'left' | 'up' | 'down';
}
>(function IconArrowSmall({displayDirection, className, ...rest}) {
const classes = cn(className, {
'rotate-180': displayDirection === 'left',
'rotate-180 rtl:rotate-0': displayDirection === 'start',
'rotate-90': displayDirection === 'down',
});
return (
Expand Down
9 changes: 8 additions & 1 deletion src/components/Icon/IconChevron.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ import cn from 'classnames';

export const IconChevron = memo<
JSX.IntrinsicElements['svg'] & {
displayDirection: 'up' | 'down' | 'left' | 'right';
/**
* The direction the arrow should point.
* `start` and `end` are relative to the current locale.
* for example, in LTR, `start` is left and `end` is right.
*/
displayDirection: 'start' | 'end' | 'right' | 'left' | 'up' | 'down';
}
>(function IconChevron({className, displayDirection}) {
const classes = cn(
Expand All @@ -16,6 +21,8 @@ export const IconChevron = memo<
'rotate-90': displayDirection === 'left',
'rotate-180': displayDirection === 'up',
'-rotate-90': displayDirection === 'right',
'rotate-90 rtl:-rotate-90': displayDirection === 'start',
'-rotate-90 rtl:rotate-90': displayDirection === 'end',
},
className
);
Expand Down
13 changes: 10 additions & 3 deletions src/components/Icon/IconNavArrow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,22 @@ import cn from 'classnames';

export const IconNavArrow = memo<
JSX.IntrinsicElements['svg'] & {
displayDirection: 'right' | 'down' | 'left';
/**
* The direction the arrow should point.
* `start` and `end` are relative to the current locale.
* for example, in LTR, `start` is left and `end` is right.
*/
displayDirection: 'start' | 'end' | 'right' | 'left' | 'down';
}
>(function IconNavArrow({displayDirection = 'right', className}) {
>(function IconNavArrow({displayDirection = 'start', className}) {
const classes = cn(
'duration-100 ease-in transition',
{
'rotate-0': displayDirection === 'down',
'-rotate-90': displayDirection === 'right',
'rotate-90': displayDirection === 'left',
'-rotate-90': displayDirection === 'right',
'rotate-90 rtl:-rotate-90': displayDirection === 'start',
'-rotate-90 rtl:rotate-90': displayDirection === 'end',
},
className
);
Expand Down
4 changes: 2 additions & 2 deletions src/components/Layout/Feedback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ function SendFeedback({onSubmit}: {onSubmit: () => void}) {
const [isSubmitted, setIsSubmitted] = useState(false);
return (
<div className="max-w-xs w-80 lg:w-auto py-3 shadow-lg rounded-lg m-4 bg-wash dark:bg-gray-95 px-4 flex">
<p className="w-full font-bold text-primary dark:text-primary-dark text-lg mr-4">
<p className="w-full font-bold text-primary dark:text-primary-dark text-lg me-4">
{isSubmitted ? 'Thank you for your feedback!' : 'Is this page useful?'}
</p>
{!isSubmitted && (
<button
aria-label="Yes"
className="bg-secondary-button dark:bg-secondary-button-dark rounded-lg text-primary dark:text-primary-dark px-3 mr-2"
className="bg-secondary-button dark:bg-secondary-button-dark rounded-lg text-primary dark:text-primary-dark px-3 me-2"
onClick={() => {
setIsSubmitted(true);
onSubmit();
Expand Down
6 changes: 4 additions & 2 deletions src/components/Layout/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function Footer() {
return (
<footer className={cn('text-secondary dark:text-secondary-dark')}>
<div className="grid grid-cols-2 md:grid-cols-3 xl:grid-cols-5 gap-x-12 gap-y-8 max-w-7xl mx-auto">
<div className="col-span-2 md:col-span-1 justify-items-start mt-3.5 text-left">
<div className="col-span-2 md:col-span-1 justify-items-start mt-3.5">
<ExternalLink
href="https://opensource.fb.com/"
aria-label="Meta Open Source">
Expand Down Expand Up @@ -280,7 +280,9 @@ export function Footer() {
</div>
</ExternalLink>

<div className="text-xs text-left mt-2 pr-0.5">
<div
className="text-xs text-left rtl:text-right mt-2 pe-0.5"
dir="ltr">
&copy;{new Date().getFullYear()}
</div>
</div>
Expand Down
54 changes: 28 additions & 26 deletions src/components/Layout/HomeContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,11 @@ const recentPosts = blogSidebar.routes.slice(0, 4).map((entry) => ({
export function HomeContent() {
return (
<>
<div className="pl-0">
<div className="ps-0">
<div className="mx-5 mt-12 lg:mt-24 mb-20 lg:mb-32 flex flex-col justify-center">
<Logo
className={cn(
'mt-4 mb-3 text-link dark:text-link-dark w-24 lg:w-28 self-center text-sm mr-0 flex origin-center transition-all ease-in-out'
'mt-4 mb-3 text-link dark:text-link-dark w-24 lg:w-28 self-center text-sm me-0 flex origin-center transition-all ease-in-out'
)}
/>
<h1 className="text-5xl font-display lg:text-6xl self-center flex font-semibold leading-snug text-primary dark:text-primary-dark">
Expand Down Expand Up @@ -379,7 +379,7 @@ export function HomeContent() {
more. They look and feel native because their UIs{' '}
<i>are</i> truly native. It’s not a web view—your
React components render real Android and iOS views
provided by the platform.
provided by the platform.
</p>
</div>
</div>
Expand All @@ -406,7 +406,7 @@ export function HomeContent() {
<Section background="right-card">
<div className="max-w-7xl mx-auto flex flex-col lg:flex-row px-5">
<div className="max-w-3xl lg:max-w-7xl gap-5 flex flex-col lg:flex-row lg:px-5">
<div className="w-full lg:w-6/12 max-w-3xl flex flex-col items-start justify-start lg:pl-5 lg:pr-10">
<div className="w-full lg:w-6/12 max-w-3xl flex flex-col items-start justify-start lg:ps-5 lg:pe-10">
<Header>Upgrade when the future is ready</Header>
<Para>
React approaches changes with care. Every React commit is
Expand All @@ -433,14 +433,14 @@ export function HomeContent() {
<IconChevron />
Latest React News
</p>
<div className="flex-col sm:flex-row flex-wrap flex gap-5 text-left my-5">
<div className="flex-1 min-w-[40%]">
<div className="flex-col sm:flex-row flex-wrap flex gap-5 text-start my-5">
<div className="flex-1 min-w-[40%] text-start">
<BlogCard {...recentPosts[0]} />
</div>
<div className="flex-1 min-w-[40%]">
<div className="flex-1 min-w-[40%] text-start">
<BlogCard {...recentPosts[1]} />
</div>
<div className="flex-1 min-w-[40%]">
<div className="flex-1 min-w-[40%] text-start">
<BlogCard {...recentPosts[2]} />
</div>
<div className="hidden sm:flex-1 sm:inline">
Expand Down Expand Up @@ -491,7 +491,7 @@ export function HomeContent() {
<div className="mt-20 px-5 lg:px-0 mb-6 max-w-4xl text-center text-opacity-80">
<Logo className="text-link dark:text-link-dark w-24 lg:w-28 mb-10 lg:mb-8 mt-12 h-auto mx-auto self-start" />
<Header>
Welcome to the <br className="" />
Welcome to the <br className="hidden lg:inline" />
React community
</Header>
<ButtonLink
Expand Down Expand Up @@ -524,7 +524,7 @@ function CTA({children, icon, href}) {
className="focus:outline-none focus-visible:outline focus-visible:outline-link focus:outline-offset-2 focus-visible:dark:focus:outline-link-dark group cursor-pointer w-auto justify-center inline-flex font-bold items-center mt-10 outline-none hover:bg-gray-40/5 active:bg-gray-40/10 hover:dark:bg-gray-60/5 active:dark:bg-gray-60/10 leading-tight hover:bg-opacity-80 text-lg py-2.5 rounded-full px-4 sm:px-6 ease-in-out shadow-secondary-button-stroke dark:shadow-secondary-button-stroke-dark text-primary dark:text-primary-dark">
{icon === 'native' && (
<svg
className="mr-2.5 text-primary dark:text-primary-dark"
className="me-2.5 text-primary dark:text-primary-dark"
fill="none"
width="24"
height="24"
Expand Down Expand Up @@ -555,7 +555,7 @@ function CTA({children, icon, href}) {
)}
{icon === 'framework' && (
<svg
className="mr-2.5 text-primary dark:text-primary-dark"
className="me-2.5 text-primary dark:text-primary-dark"
fill="none"
width="24"
height="24"
Expand All @@ -578,7 +578,7 @@ function CTA({children, icon, href}) {
)}
{icon === 'code' && (
<svg
className="mr-2.5 text-primary dark:text-primary-dark"
className="me-2.5 text-primary dark:text-primary-dark"
fill="none"
width="24"
height="24"
Expand Down Expand Up @@ -607,7 +607,7 @@ function CTA({children, icon, href}) {
)}
{icon === 'news' && (
<svg
className="mr-2.5 text-primary dark:text-primary-dark"
className="me-2.5 text-primary dark:text-primary-dark"
fill="none"
width="24"
height="24"
Expand All @@ -623,7 +623,7 @@ function CTA({children, icon, href}) {
)}
{children}
<svg
className="text-primary dark:text-primary-dark"
className="text-primary dark:text-primary-dark rtl:rotate-180"
fill="none"
width="24"
height="24"
Expand Down Expand Up @@ -826,12 +826,12 @@ function ExampleLayout({
}
}, [activeArea, hoverTopOffset]);
return (
<div className="lg:pl-10 lg:pr-5 w-full">
<div className="lg:ps-10 lg:pe-5 w-full">
<div className="mt-12 mb-2 lg:my-16 max-w-7xl mx-auto flex flex-col w-full lg:rounded-2xl lg:bg-card lg:dark:bg-card-dark">
<div className="flex-col gap-0 lg:gap-5 lg:rounded-2xl lg:bg-gray-10 lg:dark:bg-gray-70 shadow-inner-border dark:shadow-inner-border-dark lg:flex-row flex grow w-full mx-auto items-center bg-cover bg-center lg:bg-right lg:bg-[length:60%_100%] bg-no-repeat bg-meta-gradient dark:bg-meta-gradient-dark">
<div className="flex-col gap-0 lg:gap-5 lg:rounded-2xl lg:bg-gray-10 lg:dark:bg-gray-70 shadow-inner-border dark:shadow-inner-border-dark lg:flex-row flex grow w-full mx-auto items-center bg-cover bg-center lg:bg-right ltr:lg:bg-[length:60%_100%] bg-no-repeat bg-meta-gradient dark:bg-meta-gradient-dark">
<div className="lg:-m-5 h-full shadow-nav dark:shadow-nav-dark lg:rounded-2xl bg-wash dark:bg-gray-95 w-full flex grow flex-col">
<div className="w-full bg-card dark:bg-wash-dark lg:rounded-t-2xl border-b border-black/5 dark:border-white/5">
<h3 className="text-sm my-1 mx-5 text-tertiary dark:text-tertiary-dark select-none">
<h3 className="text-sm my-1 mx-5 text-tertiary dark:text-tertiary-dark select-none text-start">
{filename}
</h3>
</div>
Expand All @@ -849,7 +849,7 @@ function ExampleLayout({
{overlayStyles.map((styles, i) => (
<div
key={i}
className="top-0 left-0 bg-blue-30/5 border-2 border-link dark:border-link-dark absolute rounded-lg"
className="inset-x-0 bg-blue-30/5 border-2 border-link dark:border-link-dark absolute rounded-lg"
style={styles}
/>
))}
Expand Down Expand Up @@ -1270,7 +1270,7 @@ function BrowserChrome({children, hasPulse, hasRefresh, domain, path}) {
{hasRefresh && <div className="h-4 w-6" />}
<div className="w-full leading-snug flex flex-row items-center justify-center">
<svg
className="text-tertiary mr-1 opacity-60"
className="text-tertiary me-1 opacity-60"
width="12"
height="12"
viewBox="0 0 44 44"
Expand Down Expand Up @@ -1317,7 +1317,7 @@ function BrowserChrome({children, hasPulse, hasRefresh, domain, path}) {
{restartId > 0 && (
<div
key={restartId}
className="z-10 loading h-0.5 bg-link transition-all duration-200 absolute bottom-0 left-0"
className="z-10 loading h-0.5 bg-link transition-all duration-200 absolute bottom-0 start-0"
style={{
animation: `progressbar ${loadTalksDelay + 100}ms ease-in-out`,
}}
Expand Down Expand Up @@ -1464,13 +1464,13 @@ function SearchInput({value, onChange}) {
Search
</label>
<div className="relative w-full">
<div className="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none">
<div className="absolute inset-y-0 start-0 flex items-center ps-4 pointer-events-none">
<IconSearch className="text-gray-30 w-4" />
</div>
<input
type="text"
id={id}
className="flex pl-11 py-4 h-10 w-full bg-secondary-button outline-none betterhover:hover:bg-opacity-80 pointer items-center text-left text-primary rounded-full align-middle text-base"
className="flex ps-11 py-4 h-10 w-full text-start bg-secondary-button outline-none betterhover:hover:bg-opacity-80 pointer items-center text-primary rounded-full align-middle text-base"
placeholder="Search"
value={value}
onChange={(e) => onChange(e.target.value)}
Expand Down Expand Up @@ -1499,7 +1499,7 @@ function ConferenceLayout({conf, children}) {
navigate(e.target.value);
});
}}
className="appearance-none pr-8 bg-transparent text-primary-dark text-2xl font-bold mb-0.5"
className="appearance-none pe-8 bg-transparent text-primary-dark text-2xl font-bold mb-0.5"
style={{
backgroundSize: '4px 4px, 4px 4px',
backgroundRepeat: 'no-repeat',
Expand Down Expand Up @@ -1565,9 +1565,11 @@ function Video({video}) {

function Code({children}) {
return (
<span className="font-mono inline rounded-lg bg-gray-15/40 dark:bg-secondary-button-dark py-0.5 px-1">
<code
dir="ltr"
className="font-mono inline rounded-lg bg-gray-15/40 dark:bg-secondary-button-dark py-0.5 px-1 text-left">
{children}
</span>
</code>
);
}

Expand Down Expand Up @@ -1610,7 +1612,7 @@ function Thumbnail({video}) {
</div>
<div className="mt-1">
<span className="inline-flex text-xs font-normal items-center text-primary-dark py-1 whitespace-nowrap outline-link px-1.5 rounded-lg">
<Logo className="text-xs mr-1 w-4 h-4 text-link-dark" />
<Logo className="text-xs me-1 w-4 h-4 text-link-dark" />
React Conf
</span>
</div>
Expand Down
8 changes: 4 additions & 4 deletions src/components/Layout/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export function Page({children, toc, routeTree, meta, section}: PageProps) {
content = <HomeContent />;
} else {
content = (
<div className="pl-0">
<div className="ps-0">
<div
className={cn(
section === 'blog' && 'mx-auto px-0 lg:px-4 max-w-5xl'
Expand Down Expand Up @@ -124,7 +124,7 @@ export function Page({children, toc, routeTree, meta, section}: PageProps) {
)}>
{showSidebar && (
<div className="lg:-mt-16">
<div className="lg:pt-16 fixed lg:sticky top-0 left-0 right-0 py-0 shadow lg:shadow-none">
<div className="lg:pt-16 fixed lg:sticky top-0 start-0 end-0 py-0 shadow lg:shadow-none">
<SidebarNav
key={section}
routeTree={routeTree}
Expand Down Expand Up @@ -166,8 +166,8 @@ export function Page({children, toc, routeTree, meta, section}: PageProps) {
target="_blank">
Take our survey!
<IconNavArrow
displayDirection="right"
className="inline ml-1"
displayDirection="end"
className="inline ms-1"
/>
</ButtonLink>
</div>
Expand Down
Loading

0 comments on commit 819518c

Please sign in to comment.