رابط راست‌چین

persian-rtl-uiمهارت

همان قوانین طراحی وایب‌فارسی، به شکل یک مهارت: راست‌چین با کلاس‌های منطقی، فونت فارسی بدون letter-spacing، اعداد فارسی و تومان، فرم ایرانی و رنگ فقط از توکن. برای پروژه‌هایی که MCP ندارن.

کی به کار می‌آد

  • ساخت هر صفحه یا کامپوننت React با Tailwind
  • تبدیل قالب چپ‌چین به راست‌چین
  • وقتی مدل ml- و text-left می‌نویسه
  • پروژه‌هایی که سرور MCP ندارن

شرط فعال شدن (description)

Build right-to-left Persian (Farsi) UI in React and Tailwind the way an Iranian product team would: logical CSS only, Persian fonts without letter-spacing, Persian digits and «تومان», Jalali dates, Iranian form fields, colors from theme tokens. Use for any UI work in a Persian or Iranian project (راست‌چین، فارسی، RTL، رابط فارسی، Next.js فارسی), before writing the first component. These are the VibeFarsi design rules in skill form, for projects without the MCP server.

مدل با همین چند خط تصمیم می‌گیره مهارت را بخونه یا نه. اگر می‌خواید در موقعیت‌های دیگری هم فعال بشه، همین را عوض کنید.

Persian RTL UI (رابط راست‌چین)

Models default to English UI: Inter, Latin digits, ml-4, text-left, Monday calendars. Wrapping that in dir="rtl" does not make it Persian. Apply the rules below to every component, then run the checklist in section 10.

1. Direction

  • Document: <html lang="fa" dir="rtl">. Do not set dir per component.

  • Logical classes only: ms-/me-, ps-/pe-, start-/end-, text-start/text-end, border-s/border-e, rounded-s-/rounded-e-, inset-s-/inset-e-. Never ml-, pl-, left-, text-left, border-l.

  • Flex and grid read first-to-last in document order; RTL flips them. Do not add flex-row-reverse to "fix" it.

  • space-x-* breaks in RTL; use gap-*.

  • Directional icons flip: "next" and "submit" chevrons point left (ArrowLeft, ChevronLeft). Non-directional icons (search, trash) stay.

  • Keep these LTR inside the RTL page, with dir="ltr" on the control, not on the form: phone, email, OTP, IBAN, card number, URL, code, Latin SKU.

  • Drawers and sheets open from the start edge; toasts stack at the start-bottom or top-center.

WrongRight
ml-2 / pl-4ms-2 / ps-4
text-lefttext-start
left-0 / right-0start-0 / end-0
rounded-l-lgrounded-s-lg
border-lborder-s
space-x-2gap-2
<ArrowRight/> for "next"<ArrowLeft/>
flex-row-reverse(remove)

2. Typography

  • Font: the project's Persian sans (Vazirmatn, IRANSans, or --font-sans). Never Inter, Roboto, Geist or system-ui alone.

  • letter-spacing: 0 on Persian, always. Tracking breaks letter joining. No tracking-tight on Persian headlines.

  • Body ~16px, line-height 1.7–1.9. Headlines 1.2–1.3, never below 1.15.

  • No fake bold or italic; use weights the font ships.

  • Mixed strings («کد سفارش SKU-2048»): let the bidi algorithm isolate the Latin run; do not force the paragraph LTR. Wrap codes in <bdi> or dir="ltr".

  • Truncate with CSS line-clamp; a naive slice() cuts letters mid-join.

  • Do not uppercase Persian; uppercase only affects Latin and looks wrong next to it.

3. Numbers, money, dates

  • Visible digits are Persian ۰۱۲۳۴۵۶۷۸۹. Convert at the display layer (fa() / faNumber() from lib/utils.ts in VibeFarsi).

  • Thousands separator «٬» (U+066C), decimal «٫» (U+066B), percent «٪» after the number.

  • Money: «۱۲٬۴۵۰٬۰۰۰ تومان». Unit after the number. Never «$», never «Toman». Default unit is تومان; if you must show ریال, label it and never mix.

  • Form values, URLs, JSON and API payloads keep Latin digits.

  • Calendar is Jalali (شمسی); week starts Saturday; Friday is the weekend. Use a real converter (lib/jalali.ts), not toLocaleDateString alone.

  • Relative time in Persian: «۲ ساعت پیش», «دیروز».

  • Numeric table columns: tabular-nums so digits line up, aligned to the start (right) like the rest of the RTL table. Do not text-right them.

4. Forms

  • Label above the field with htmlFor; placeholder is an example, not a label.

  • Phone: dir="ltr", inputMode="tel", accept 09xxxxxxxxx (11 digits) and +98…. Start addon «+98» is optional. Operator name is a hint, not a gate.

  • OTP: separate cells, dir="ltr" on the group, Persian glyphs on screen, Latin string on submit, autoComplete="one-time-code", paste fills all.

  • Email, password, IBAN, card, URL: LTR input under an RTL label.

  • Persian and Arabic-Indic digits typed by the user are normalized before validation; never reject «۰۹۱۲…» because it is not ASCII.

  • Errors under the field with aria-invalid; red from --destructive.

  • Primary button at the start of a button row; full-width stacks put the primary on top.

  • Inputs must compute to at least 16px on iOS or Safari zooms on focus.

5. Colors and shape

  • Every color comes from a token already mapped to Tailwind: background, foreground, card, primary, secondary, muted, accent, border, input, ring, brand, destructive, success, warning.

  • No hex or oklch inside components; no new blue because it looked nice.

  • Radius from --radius; do not mix 6px and 16px corners in one view.

  • Borders border-border, not border-white/10 (light themes exist).

6. Motion

  • 150–300ms for UI; decorative backgrounds may be slower.

  • Respect prefers-reduced-motion: stop loops, skip enter animations.

  • Directional motion follows RTL: enter from the start edge.

  • Animate transform and opacity, not top/left/width.

7. Accessibility

  • Visible focus ring from the ring token; never outline-none without a replacement.

  • Icon-only buttons get a Persian aria-label.

  • Dialogs trap and restore focus; Escape closes.

  • lang="fa" on the document so screen readers switch voices.

  • Muted text stays readable on both dark and light themes.

8. Iranian product patterns

English kits will not get these right; use a VibeFarsi component when one exists (npx vibefarsi add …) instead of re-implementing.

  • Phone «۰۹…», national ID (کد ملی, 10 digits with checksum), Sheba/IBAN (IR + 24 digits), bank card (16 digits, Luhn, BIN → bank), postal code (10 digits), plate («۱۲ ب ۳۴۵ ایران ۱۱»).

  • Address fields: استان، شهر، خیابان، پلاک، واحد، کد پستی.

  • Shipping: پست، تیپاکس، پیک. Payment result states: موفق، در انتظار، ناموفق.

  • Working week Saturday–Thursday (often half-day Thursday); Friday off.

  • Copy is Persian and specific: never «Oops», never «Something went wrong».

9. Copy inside components

All visible strings are Persian: labels, placeholders, empty states, errors, aria-label. Code identifiers, props and file names stay English. See the persian-ui-copy skill for wording.

10. Checklist before returning code

  1. No ml-/mr-/pl-/pr-/left-/right-/text-left/text-right/space-x.

  2. Font from the project, letter-spacing: 0, no tracking-* on Persian.

  3. Every visible number Persian; money «تومان» after the number.

  4. Dates Jalali, week starts Saturday.

  5. Phone/OTP/IBAN/card fields dir="ltr", labels RTL.

  6. Colors only from tokens; radius from --radius.

  7. "Next" arrows point left; drawers open from the start edge.

  8. Focus ring visible; icon buttons labelled in Persian.

  9. All copy Persian, register consistent.

نمونه

پرامپت: «یک کارت محصول با قیمت و دکمه‌ی خرید بساز»

بدون مهارت

<div className="flex ml-4 text-left"> … $12,000 … <ArrowRight />

با مهارت

<div className="flex ms-4 text-start"> … ۱۲٬۰۰۰ تومان … <ArrowLeft />

نمونه برای نشان دادن جهت تغییره؛ خروجی واقعی به مدل و پرامپت شما بستگی داره.

نصب

  1. با CLI

    این دستور فایل را در .claude/skills/persian-rtl-ui/SKILL.md می‌نویسه. CLI به init نیاز نداره؛ فقط باید داخل پوشه‌ی پروژه باشید.

    $npx vibefarsi add persian-rtl-ui
  2. دستی

    محتوای تب SKILL.md را کپی کنید و در مسیر ابزار خودتون بگذارید:

    • Claude Code.claude/skills/persian-rtl-ui/SKILL.md برای همین پروژه، یا ~/.claude/skills/persian-rtl-ui/SKILL.md برای همه‌ی پروژه‌ها
    • Cursor.cursor/skills/persian-rtl-ui/SKILL.md
    • Codex.agents/skills/persian-rtl-ui/SKILL.md
    • بقیه‌ی ابزارهاهمان فایل را در پروژه بگذارید و یک خط به AGENTS.md اضافه کنید:For any Persian task, read .claude/skills/persian-rtl-ui/SKILL.md first.
    کپی کل فایلregistry json

می‌خواید همه‌ی قوانین را یک‌جا داشته باشید؟ قوانین فارسی برای CLAUDE.md خلاصه‌ی همه‌ی مهارت‌ها در یک صفحه‌ست و قوانین کرافت رابط طرف طراحی را پوشش میده. npx vibefarsi init هر دو را داخل پروژه می‌نویسه.