From 8d2180b362ca07b9d779a94fab70ceb949fb98e6 Mon Sep 17 00:00:00 2001 From: Nadav011 Date: Sat, 28 Mar 2026 18:04:43 +0300 Subject: [PATCH 1/5] docs: flesh out rtl toolkit first pass --- README.md | 49 ++++++++++++++++---------- SKILL.md | 19 ++++++++--- biome/policy.md | 45 +++++++++++++++++++----- ci/rtl-validator-workflow.md | 41 +++++++++++++++++----- flutter/patterns.md | 66 ++++++++++++++++++++++++++++++------ nextjs/proxy-and-dir.md | 54 ++++++++++++++++++++++++----- tailwind/mapping.md | 59 ++++++++++++++++++++++++++------ 7 files changed, 264 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index cdb37c7..d2520a2 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,20 @@ # RTL First Dev Kit -Local scaffold for the RTL-first toolkit planned in Phase 3. +Local draft for a reusable RTL toolkit covering Tailwind, Flutter, Next.js, Biome policy, and CI validation. ## Status -This is a draft structure only. It does not claim the toolkit is complete, published, or battle-tested. +This repository now contains a first practical pass of the core guidance. It is still a draft, but the main files are no longer placeholders only. -## Layout +## What It Covers -- `tailwind/` - logical-direction mapping notes and examples -- `flutter/` - directional Flutter patterns -- `nextjs/` - App Router and `dir` propagation notes -- `biome/` - RTL linting ideas and policy notes -- `ci/` - validation workflow sketches +- Tailwind logical-direction mapping and examples +- Flutter directional primitives and common replacement patterns +- Next.js 16 `proxy.ts` and `dir` propagation examples +- Biome policy rules for blocking physical-direction regressions +- CI workflow sketch for RTL validation in pull requests -## Draft Structure +## Layout ```text rtl-first-dev-kit/ @@ -22,27 +22,40 @@ rtl-first-dev-kit/ ├── SKILL.md ├── tailwind/ │ ├── README.md +│ ├── logical-properties.md │ └── mapping.md ├── flutter/ │ ├── README.md +│ ├── directional-primitives.md │ └── patterns.md ├── nextjs/ │ ├── README.md -│ └── dir-propagation.md +│ ├── dir-propagation.md +│ └── proxy-and-dir.md ├── biome/ │ ├── README.md -│ └── policy.md +│ ├── policy.md +│ └── rtl-policy.md └── ci/ ├── README.md + ├── rtl-validator-workflow.md └── workflow-sketch.md ``` -## Scratch Notes +## Intended Use + +Use this repo as a source pack for teams that already know they need RTL-safe defaults but want one place to copy patterns from. + +Start here: + +1. Tailwind apps: [mapping.md](/home/nadavcohen/Desktop/rtl-first-dev-kit/tailwind/mapping.md) +2. Flutter apps: [patterns.md](/home/nadavcohen/Desktop/rtl-first-dev-kit/flutter/patterns.md) +3. Next.js apps: [proxy-and-dir.md](/home/nadavcohen/Desktop/rtl-first-dev-kit/nextjs/proxy-and-dir.md) +4. Repo policy: [policy.md](/home/nadavcohen/Desktop/rtl-first-dev-kit/biome/policy.md) +5. CI enforcement: [rtl-validator-workflow.md](/home/nadavcohen/Desktop/rtl-first-dev-kit/ci/rtl-validator-workflow.md) -Additional draft notes exist alongside the main skeleton files for early iteration: +## Draft Constraints -- `tailwind/logical-properties.md` -- `flutter/directional-primitives.md` -- `nextjs/proxy-and-dir.md` -- `biome/rtl-policy.md` -- `ci/rtl-validator-workflow.md` +- No publication claim yet +- No benchmark or adoption claim yet +- No promise of automated fixes beyond the policy sketches already written diff --git a/SKILL.md b/SKILL.md index b7cfece..9e6217c 100644 --- a/SKILL.md +++ b/SKILL.md @@ -5,11 +5,11 @@ description: Local scaffold for an RTL-first toolkit covering Tailwind, Flutter, # RTL First Dev Kit -This directory is a scaffold for future Phase 3 content. +Use this skill when the goal is to build or audit RTL-safe foundations across web and Flutter codebases. ## Status -This is a local draft only. It should not be presented as a published toolkit or a finished standard. +This is still a local draft, but it now includes real first-pass content instead of skeleton placeholders. ## Focus areas @@ -19,6 +19,17 @@ This is a local draft only. It should not be presented as a published toolkit or - RTL linting and policy enforcement - CI validation examples -## Working Rule +## Working Rules -Keep every example RTL-safe, conservative, and self-contained. +1. Prefer logical properties and directional APIs over left/right APIs. +2. Keep examples short enough to transplant directly into a repo. +3. Block physical-direction regressions in both code review and CI. +4. Treat mixed Hebrew/English text and numeric rendering as first-class cases. + +## Primary Files + +- [mapping.md](/home/nadavcohen/Desktop/rtl-first-dev-kit/tailwind/mapping.md) +- [patterns.md](/home/nadavcohen/Desktop/rtl-first-dev-kit/flutter/patterns.md) +- [proxy-and-dir.md](/home/nadavcohen/Desktop/rtl-first-dev-kit/nextjs/proxy-and-dir.md) +- [policy.md](/home/nadavcohen/Desktop/rtl-first-dev-kit/biome/policy.md) +- [rtl-validator-workflow.md](/home/nadavcohen/Desktop/rtl-first-dev-kit/ci/rtl-validator-workflow.md) diff --git a/biome/policy.md b/biome/policy.md index 7118bf8..522cb33 100644 --- a/biome/policy.md +++ b/biome/policy.md @@ -1,15 +1,42 @@ # Biome RTL Policy Sketch -This file is a skeleton for later examples. +This file defines the practical policy the repo should enforce, even before a custom Biome plugin exists. -## Placeholder Sections +## Scope -- rule scope -- autofix expectations -- false positive handling -- review workflow +Block physical-direction utilities and APIs in: -## Notes +- `*.tsx` +- `*.jsx` +- `*.ts` +- `*.js` +- `*.css` -- Keep the policy focused on preventing physical-direction regressions. -- Do not claim custom lint coverage until it is implemented. +## What To Flag + +- Tailwind classes: `ml-`, `mr-`, `pl-`, `pr-`, `left-`, `right-`, `text-left`, `text-right` +- CSS properties: `margin-left`, `margin-right`, `padding-left`, `padding-right`, `left`, `right` +- JSX class strings that embed any of the above + +## Expected Autofix Direction + +- `ml-` -> `ms-` +- `mr-` -> `me-` +- `pl-` -> `ps-` +- `pr-` -> `pe-` +- `left-*` -> `inset-s-*` +- `right-*` -> `inset-e-*` +- `text-left` -> `text-start` +- `text-right` -> `text-end` + +## False Positive Policy + +- Ignore comments and documentation unless the lint mode is explicitly `docs`. +- Allow one-off documented escapes only with a marker such as `rtl-ok`. +- Do not silently autofix ambiguous icon or animation cases. + +## Review Workflow + +1. Lint blocks merge on physical-direction regressions. +2. Reviewer checks that autofixes did not invert meaning. +3. Any exception must include a short comment explaining why logical utilities could not be used. diff --git a/ci/rtl-validator-workflow.md b/ci/rtl-validator-workflow.md index 3aaa743..23fc96e 100644 --- a/ci/rtl-validator-workflow.md +++ b/ci/rtl-validator-workflow.md @@ -1,14 +1,39 @@ # RTL Validator Workflow -This file will hold the CI workflow sketch for RTL validation. +This is the first practical workflow sketch for blocking RTL regressions in pull requests. -## Sections to fill +## Trigger -- Trigger conditions -- Validation steps -- failure reporting -- future automation hooks +- `pull_request` to `main` or `master` +- `push` to protected branches if the repo wants hard enforcement after merge -## Notes +## Minimal Workflow Shape -- Keep the workflow conservative until the underlying checks are proven. +```yaml +name: RTL Validator + +on: + pull_request: + branches: [main] + +jobs: + rtl-validate: + runs-on: [self-hosted, linux, x64, pop-os] + steps: + - uses: actions/checkout@v4 + - name: Scan physical-direction utilities + run: | + ! rg -n "ml-|mr-|pl-|pr-|left-|right-|text-left|text-right" src app components +``` + +## Reporting Rule + +- Fail the job on the first regression +- Print file and line references from `rg` +- Keep the message short enough that the developer can act without opening the full logs + +## Future Hooks + +- Optional autofix preview job that comments a suggested patch +- Optional Flutter mode that scans `EdgeInsets.only(left|right)` and `Alignment.*Left|Right` +- Optional allowlist file for legacy migrations that are still in progress diff --git a/flutter/patterns.md b/flutter/patterns.md index aac617c..2654efa 100644 --- a/flutter/patterns.md +++ b/flutter/patterns.md @@ -1,16 +1,62 @@ # Flutter RTL Patterns -This file is a skeleton for later examples. +Prefer directional APIs everywhere. Left/right APIs should be treated as migration targets. -## Placeholder Sections +## Direct Replacements -- padding and margin -- alignment -- positioned layout -- border radius -- text direction aware widgets +| Never | Use Instead | +|---|---| +| `EdgeInsets.only(left: 16)` | `EdgeInsetsDirectional.only(start: 16)` | +| `EdgeInsets.symmetric(horizontal: 12)` | keep, this is already logical | +| `Alignment.topLeft` | `AlignmentDirectional.topStart` | +| `Alignment.centerRight` | `AlignmentDirectional.centerEnd` | +| `Positioned(left: 0)` | `PositionedDirectional(start: 0)` | +| `BorderRadius.only(topLeft: ...)` | `BorderRadiusDirectional.only(topStart: ...)` | +| `TextAlign.left` | `TextAlign.start` | +| `TextAlign.right` | `TextAlign.end` | -## Notes +## Layout Example -- Prefer directional APIs over left/right APIs. -- Keep examples short and easy to port into apps. +```dart +Padding( + padding: const EdgeInsetsDirectional.only(start: 16, end: 12), + child: Align( + alignment: AlignmentDirectional.centerStart, + child: Text( + 'שלום עולם', + textAlign: TextAlign.start, + ), + ), +) +``` + +## Stack Example + +```dart +Stack( + children: [ + PositionedDirectional( + start: 12, + top: 8, + child: Chip(label: const Text('חדש')), + ), + ], +) +``` + +## Border And Shape Example + +```dart +Container( + decoration: const BoxDecoration( + borderRadius: BorderRadiusDirectional.only( + topStart: Radius.circular(20), + topEnd: Radius.circular(12), + ), + ), +) +``` + +## Review Rule + +If a widget diff introduces `left`, `right`, `topLeft`, `topRight`, `bottomLeft`, or `bottomRight`, replace them with directional APIs before merge. diff --git a/nextjs/proxy-and-dir.md b/nextjs/proxy-and-dir.md index ebd5fab..c1b5cb9 100644 --- a/nextjs/proxy-and-dir.md +++ b/nextjs/proxy-and-dir.md @@ -1,14 +1,50 @@ -# Next.js Proxy and Direction +# Next.js Proxy And Direction -This file will hold App Router and direction notes. +Use `proxy.ts` in Next.js 16, not `middleware.ts`, when steering locale or direction at the edge. -## Sections to fill +## `proxy.ts` Example -- `proxy.ts` routing patterns -- layout-level `dir` propagation -- route grouping ideas -- locale and direction handling +```ts +import { NextResponse, type NextRequest } from 'next/server'; -## Notes +const RTL_LOCALES = new Set(['he', 'ar']); -- Keep the examples aligned with Next.js 16 conventions. +export function proxy(request: NextRequest) { + const locale = request.cookies.get('locale')?.value ?? 'he'; + const response = NextResponse.next(); + response.headers.set('x-locale', locale); + response.headers.set('x-dir', RTL_LOCALES.has(locale) ? 'rtl' : 'ltr'); + return response; +} +``` + +## Layout Propagation + +Read the headers once at the layout boundary and set `lang` + `dir` there: + +```tsx +import { headers } from 'next/headers'; + +export default async function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + const headerStore = await headers(); + const locale = headerStore.get('x-locale') ?? 'he'; + const dir = headerStore.get('x-dir') ?? 'rtl'; + + return ( + + {children} + + ); +} +``` + +## Rules + +- Set `dir` once at the document layout, not ad hoc per component. +- Keep locale and direction derivation deterministic. +- When a route depends on `cookies()` or `headers()`, treat it as dynamic and cache accordingly. +- Component code should still use logical utilities even when the layout already has `dir=\"rtl\"`. diff --git a/tailwind/mapping.md b/tailwind/mapping.md index b9c8615..97b5002 100644 --- a/tailwind/mapping.md +++ b/tailwind/mapping.md @@ -1,17 +1,54 @@ # Tailwind RTL Mapping -This file is a skeleton for later examples. +Use logical utilities only. Treat any physical-direction utility as a regression. -## Placeholder Sections +## Core Mapping -- margin and padding -- inset and positioning -- text alignment -- border radius -- border side utilities -- icon direction +| Never | Use Instead | Purpose | +|---|---|---| +| `ml-*` | `ms-*` | margin-inline-start | +| `mr-*` | `me-*` | margin-inline-end | +| `pl-*` | `ps-*` | padding-inline-start | +| `pr-*` | `pe-*` | padding-inline-end | +| `left-*` | `inset-s-*` | logical start inset | +| `right-*` | `inset-e-*` | logical end inset | +| `text-left` | `text-start` | logical text alignment | +| `text-right` | `text-end` | logical text alignment | +| `rounded-l-*` | `rounded-s-*` | logical start corners | +| `rounded-r-*` | `rounded-e-*` | logical end corners | +| `border-l-*` | `border-s-*` | logical start border | +| `border-r-*` | `border-e-*` | logical end border | -## Notes +## Examples -- Keep examples logical-property first. -- Avoid any claims about framework-wide completeness until the examples are validated. +```tsx +