Skip to content

feat: add direction option for RTL menu support - #797

Open
bbrala wants to merge 4 commits into
masterfrom
feat/issue-742-rtl-direction-option
Open

feat: add direction option for RTL menu support#797
bbrala wants to merge 4 commits into
masterfrom
feat/issue-742-rtl-direction-option

Conversation

@bbrala

@bbrala bbrala commented Jul 28, 2026

Copy link
Copy Markdown
Member

Closes #742

Summary

Adds a direction option to $.contextMenu({...}) (default 'ltr'). When set to 'rtl':

  • A context-menu-rtl class is added to the root menu and every sub-menu (including detached sub-menus that get moved to <body> when their parent menu is scrollable, see Overflow / visibility issue if contextmenu longer than screen height #775, so they don't lose the styling when they're no longer a DOM descendant of the root).
  • CSS mirrors: text alignment (direction: rtl; text-align: right), icon placement (icon moves to the right edge instead of the left, covering both the icon-font and FontAwesome-5 code paths), checkbox/radio spacing, and the submenu-arrow triangle (now points left and sits on the left edge instead of the right).
  • The submenu positioning logic (positionSubmenu in src/jquery.contextMenu.js) flips the jQuery UI .position() my/at arguments (and the equivalent fallback/detached-submenu math) so sub-menus open to the left of their parent item instead of the right, with the same flipfit/edge-clamping behavior as the existing LTR code so it still flips back to the right if there isn't enough room on the left.

Scope notes

This covers the two things asked for in #742 (menu item text direction/alignment, and RTL support in general): a CSS hook for styling and a real flip of which side sub-menus open on. Root-menu placement itself already has viewport collision handling (fit) that isn't direction-specific, so it needed no changes.

Files changed

  • src/jquery.contextMenu.js – new direction default option, class applied at menu-creation time, positionSubmenu flip for both the jQuery UI code path and the plain-JS/detached-submenu fallback paths.
  • src/sass/jquery.contextMenu.scss.context-menu-rtl rules mirroring text alignment, icon placement, submenu arrow and initial submenu position.
  • documentation/docs.md – documents the new direction option with an example.
  • test/unit/direction-rtl.test.js – new QUnit regression tests: default menu has no rtl class, direction: 'rtl' adds the class to both the root menu and its sub-menus, and a sub-menu opens to the left of its parent item in rtl mode vs. to the right in the default ltr mode.

Test plan

  • npm run test-unit (karma + qunit, ChromeHeadless) – 34/34 passing, including the 3 new RTL tests.
  • npm run test:fixtures && npx playwright test – 15/15 passing, no regressions.
  • Compiled the SCSS standalone (npx sass) to confirm it has no syntax errors.

dist/ was intentionally left untouched per this repo's convention of rebuilding it at publish time.

Adds a `direction` option (default 'ltr') that, when set to 'rtl',
applies a `context-menu-rtl` class to the menu and its sub-menus. CSS
mirrors text alignment, icon placement and the submenu arrow, and the
submenu positioning logic flips so sub-menus open to the left of their
parent item instead of the right.

Closes #742

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3655bdfd16

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/jquery.contextMenu.js
Comment on lines +269 to +273
if (isRtl) {
if (left < $win.scrollLeft()) {
// doesn't fit to the left of the item, flip to the right
left = itemOffset.left + this.outerWidth() - 5;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clamp flipped RTL submenus against the right viewport edge

When a detached RTL submenu cannot fit to the left of an opener near the viewport's left edge, this branch flips it to the right but never checks whether left + menuWidth now exceeds the viewport's right edge. If neither side has enough room, the submenu therefore remains partially off-screen instead of receiving the edge-clamping behavior described here; clamp the flipped result against the right boundary before applying the existing left clamp.

Useful? React with 👍 / 👎.

Addresses Codex review feedback on PR #797: when a detached RTL
submenu didn't fit to the left of its opener and flipped to the
right, it wasn't checked against the right viewport edge (only the
existing left-edge clamp applied, which was the wrong side to guard
after flipping right).
@bbrala

bbrala commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

Addressed the Codex review feedback in 58794b2:

  • Clamp flipped RTL submenus against the right viewport edge (src/jquery.contextMenu.js:270): when a detached RTL sub-menu didn't fit to the left of its opener and flipped to the right, it wasn't checked against the right viewport edge afterwards (only the pre-existing left-edge clamp applied, which guards the wrong side once you've flipped rightward). Added a right-edge clamp for that flipped case, mirroring the left-edge clamp already used for the equivalent LTR flip-to-left case.

Verified with npm run test-unit (34/34) and npx playwright test (15/15) after the fix.

bbrala added 2 commits July 28, 2026 16:35
Resolves conflicts in src/jquery.contextMenu.js between this branch's
RTL submenu-open-side flip and #798's overflow detach/cap-and-scroll
logic (also touching positionSubmenu()). Combined so that:

- the isRtl check picks which side (left/right) a sub-menu opens on
  and which side it flips back to if it doesn't fit there,
- the overflow-detection/detach/cap-and-scroll logic (and its
  preciseOuterHeight()-based measurements) run independently of that
  side choice, since a sub-menu can be too tall regardless of which
  side it opens on.

Both PRs' test coverage (test/unit/direction-rtl.test.js and
test/specs/overflow-submenu-only.js) is preserved.
Covers the combination of direction: 'rtl' (#742) and a sub-menu taller
than the viewport (#752), since both features touch positionSubmenu()
and the merge that combined them deserves its own test rather than
relying on each feature's separate test suite.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Menu item text direction (or alignment)?

1 participant