Agent Skills: RTL Web Development for AI Agents

|

UncategorizedID: AmmarCodes/dotfiles/rtl-web-development

Install this agent skill to your local

pnpm dlx add-skill https://github.com/AmmarCodes/dotfiles/tree/HEAD/skills/rtl-web-development

Skill Files

Browse the full folder contents for rtl-web-development.

Download Skill

Loading file tree…

skills/rtl-web-development/SKILL.md

Skill Metadata

Name
rtl-web-development
Description
|

RTL Web Development for AI Agents

You are generating frontend code. Unless explicitly told otherwise, assume the project may need RTL support. Following these conventions prevents layout bugs that are expensive to fix later.

The One Rule

Always use CSS logical properties and RTL-safe Tailwind classes. Never use physical direction properties (left, right, margin-left, margin-right) unless the positioning is intentionally physical and should NOT mirror.

Quick Mapping: Tailwind

| Never use | Always use | Why | | -------------- | -------------- | ----------------------------------- | | ml-* | ms-* | margin-left → margin-inline-start | | mr-* | me-* | margin-right → margin-inline-end | | pl-* | ps-* | padding-left → padding-inline-start | | pr-* | pe-* | padding-right → padding-inline-end | | left-* | start-* | left positioning | | right-* | end-* | right positioning | | text-left | text-start | text alignment | | text-right | text-end | text alignment | | border-l-* | border-s-* | border start | | border-r-* | border-e-* | border end | | rounded-l-* | rounded-s-* | border-radius start | | rounded-r-* | rounded-e-* | border-radius end | | rounded-tl-* | rounded-ts-* | top-start radius | | rounded-tr-* | rounded-te-* | top-end radius | | rounded-bl-* | rounded-bs-* | bottom-start radius | | rounded-br-* | rounded-be-* | bottom-end radius |

<!-- Bad -->
<div class="ml-4 mr-2 pl-3 pr-1 text-left rounded-l-lg border-l-2">
  <!-- Good -->
  <div class="ms-4 me-2 ps-3 pe-1 text-start rounded-s-lg border-s-2"></div>
</div>

Quick Mapping: CSS & CSS-in-JS

| Physical | Logical | | -------------------------------- | --------------------------------------------- | | margin-left / marginLeft | margin-inline-start / marginInlineStart | | margin-right / marginRight | margin-inline-end / marginInlineEnd | | padding-left / paddingLeft | padding-inline-start / paddingInlineStart | | padding-right / paddingRight | padding-inline-end / paddingInlineEnd | | border-left / borderLeft | border-inline-start / borderInlineStart | | border-right / borderRight | border-inline-end / borderInlineEnd | | left | inset-inline-start | | right | inset-inline-end | | width | inline-size | | height | block-size | | text-align: left | text-align: start | | text-align: right | text-align: end | | float: left | float: inline-start | | float: right | float: inline-end |

For the complete property table (border-color, border-width, border-style, min/max sizes), see references/mappings.md.

The dir Attribute

<html dir="rtl" lang="ar"></html>
<!-- OR -->
<html dir="ltr" lang="en"></html>
  • Always set dir and lang on <html>, not via CSS direction alone
  • Use dir="auto" on user-generated content containers where language is unknown
  • For mixed-content elements, set dir on the element for correct word ordering
<p dir="auto">مرحباً Welcome to the article about RTL design</p>

Flexbox & Grid Auto-Flip

Flexbox and CSS Grid automatically respect the writing mode. Items reorder when dir="rtl" is set.

.header {
  display: flex;
  justify-content: space-between;
} /* auto-flips */
.layout {
  display: grid;
  grid-template-columns: 220px 1fr;
} /* auto-flips */

Gotcha: flex-direction: row-reverse also reverses in RTL, causing a double-flip back to LTR order. Never use row-reverse to "fix" RTL layout -- flexbox handles direction automatically.

Gotcha: explicit order values in flexbox do NOT auto-flip. Handle manually for RTL.

The :dir() Pseudo-Class

Use :dir(rtl) for direction-based styling. Unlike [dir="rtl"], it matches elements that inherit direction from ancestors.

.element:dir(rtl) {
  /* RTL styles */
}
.element:dir(ltr) {
  /* LTR styles */
}

Browser support: Firefox, Chrome, Safari 16.4+, Edge.

Bidirectional Isolation: <bdi> and <bdo>

  • <bdi> isolates user-generated content whose direction is unknown (prevents corrupting surrounding text)
  • <bdo dir="ltr"> forces LTR for phone numbers, credit cards, code that must stay LTR
<p>Welcome back, <bdi>Ahmed</bdi>! Your score: <bdi>۳۵۰</bdi></p>
<bdo dir="ltr">+1 (555) 123-4567</bdo>
<bdo dir="ltr">4111-1111-1111-1111</bdo>

Tailwind rtl: Variant

Use rtl: for directional icons and components that need explicit flipping:

<button class="rtl:rotate-180"><ArrowLeftIcon /></button>
<div class="text-start rtl:text-right">
  <div class="ms-4 rtl:me-4 rtl:ms-0"></div>
</div>

Always prefer logical property utilities (ms-*, me-*, ps-*, pe-*, start-*, end-*) over rtl: variant hacks.

RTL Exceptions: When NOT to Flip

Never flip:

  • Symmetrical icons (home, search, user, settings, camera, star, heart)
  • Media player controls (play, pause, forward -- tape direction, not time)
  • Right-hand objects (icons per Material Design guideline)
  • Data visualizations (charts, graphs, maps)
  • Images, videos, code blocks -- keep original orientation
  • Phone numbers, credit cards, math expressions -- stay LTR
  • Music notation, clock faces

Force LTR when needed:

<span dir="ltr">+1 (555) 123-4567</span>
<code dir="ltr">console.log("hello");</code>

Bidirectional Icons

Flip (they indicate direction): arrows, breadcrumb separators, send icon, undo/redo, sort indicators.

Don't flip (universal/symmetrical): play/pause/stop, search, menu, close, plus, checkmark, home, settings, download/upload.

[dir="rtl"] .icon-arrow-right {
  transform: scaleX(-1);
}

Arabic Typography Pitfalls

See references/arabic-typography.md for the full guide. Critical rules:

  1. Letter-spacing: MUST be zero on Arabic text -- letters connect, spacing breaks them
  2. Use solid colors for Arabic text -- rgba() and opacity cause rendering artifacts between connected letters
  3. Underlines overlap Arabic dots -- use text-decoration-skip-ink: auto or box-shadow underlines
  4. Line height -- Arabic needs 1.6-1.8 vs Latin 1.4-1.5 (diacritics get cut off otherwise)
  5. Word-break: never break-all on Arabic -- connected letters can't break mid-word
  6. No abbreviations in Arabic -- letters must stay connected, "Sat" for "Saturday" doesn't work
  7. Provide min-width on buttons -- Arabic translations are often shorter or longer than English

Component RTL Patterns

See references/component-patterns.md for detailed examples covering:

  • Button icons (icon position flips)
  • Form inputs (email/URL stay LTR, name/address RTL)
  • Breadcrumbs (separator auto-flips)
  • Tables, tabs, cards, toasts, blockquotes, toggle switches
  • Page headers (logo and actions swap)

Search Input with Icon

.c-input--search {
  background-image: url("data:image/svg+xml,...");
  background-position: right 6px center;
  padding-inline-end: 32px;
}

Floats: Avoid Them

Floats do NOT auto-flip. If you must use them:

.media__photo {
  float: left;
  margin-right: 16px;
}
[dir="rtl"] .media__photo {
  float: right;
  margin-right: 0;
  margin-left: 16px;
}

Better: use flexbox instead.

Transform Animations in RTL

translateX() does NOT auto-flip. Use scaleX(-1) for arrow icons:

.c-link:hover svg {
  transform: translateX(6px);
}
[dir="rtl"] .c-link svg {
  transform: scaleX(-1);
}
[dir="rtl"] .c-link:hover svg {
  transform: scaleX(-1) translateX(6px);
}

CSS Naming Conventions

Use start/end in class names, not left/right:

/* Bad */
.c-header__left {
}
.c-header__right {
}

/* Good */
.c-header__start {
}
.c-header__end {
}

React / Next.js RTL Setup

<html dir={locale === "ar" ? "rtl" : "ltr"} lang={locale}>

CSS-in-JS (styled-components, Emotion) requires a Stylis plugin for RTL. MUI provides @mui/stylis-plugin-rtl:

import rtlPlugin from "stylis-plugin-rtl";
import { CacheProvider } from "@emotion/react";
import createCache from "@emotion/cache";

const cacheRtl = createCache({ key: "muirtl", stylisPlugins: [rtlPlugin] });

Testing RTL

  1. Toggle dir="rtl" on <html> in browser DevTools
  2. Test every component in both LTR and RTL
  3. Check for: text overflow, alignment, icon orientation, scrollbar position, truncation direction
  4. Test with actual Arabic content -- not just mirrored Lorem Ipsum

Companion: ESLint Plugin

For automated linting of physical direction properties, use eslint-plugin-tailwind-rtl. It catches RTL bugs in CI and code review that slip past generation:

npm install --save-dev eslint-plugin-tailwind-rtl

References