Skip to content

Commit 0e6a726

Browse files
committed
Better support for RTL environment
See also: piroor/treestyletab#3689
1 parent 4416e66 commit 0e6a726

File tree

1 file changed

+84
-16
lines changed

1 file changed

+84
-16
lines changed

MenuUI.js

Lines changed: 84 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
license: The MIT License, Copyright (c) 2018-2023 YUKI "Piro" Hiroshi
2+
license: The MIT License, Copyright (c) 2018-2025 YUKI "Piro" Hiroshi
33
original:
44
https://github.com/piroor/webextensions-lib-menu-ui
55
*/
@@ -53,6 +53,23 @@
5353
return array;
5454
}
5555

56+
RTL_LANGUAGES = new Set([
57+
'ar',
58+
'he',
59+
'fa',
60+
'ur',
61+
]);
62+
63+
get isRTL() {
64+
const lang = (
65+
navigator.language ||
66+
navigator.userLanguage ||
67+
//(new Intl.DateTimeFormat()).resolvedOptions().locale ||
68+
''
69+
).split('-')[0];
70+
return this.RTL_LANGUAGES.has(lang);
71+
}
72+
5673
constructor(params = {}) {
5774
this.$lastHoverItem = null;
5875
this.$lastFocusedItem = null;
@@ -79,6 +96,8 @@
7996
this.$onTransitionEnd = this.$onTransitionEnd.bind(this);
8097
this.$onContextMenu = this.$onContextMenu.bind(this);
8198

99+
this.root.classList.toggle('rtl', this.isRTL);
100+
82101
if (!this.root.id)
83102
this.root.id = `MenuUI-root-${this.$uniqueKey}-${parseInt(Math.random() * Math.pow(2, 16))}`;
84103

@@ -303,13 +322,31 @@
303322
this.$marker.style.top = `calc(${top}px + ${menuRect.height}px - 0.6em)`;
304323
}
305324

306-
if (containerRect.right - anchorRect.left >= menuRect.width) {
307-
left = anchorRect.left;
308-
this.$marker.style.left = `calc(${left}px + 0.5em)`;
309-
}
310-
else if (anchorRect.left - containerRect.left >= menuRect.width) {
311-
left = Math.max(0, anchorRect.right - menuRect.width);
312-
this.$marker.style.left = `calc(${left}px + ${menuRect.width}px - 1.5em)`;
325+
const canPlaceAtRight = containerRect.right - anchorRect.left >= menuRect.width;
326+
const canPlaceAtLeft = anchorRect.left - containerRect.left >= menuRect.width;
327+
328+
if (canPlaceAtRight || canPlaceAtLeft) {
329+
if (this.isRTL) {
330+
if (canPlaceAtLeft) {
331+
left = Math.max(0, anchorRect.right - menuRect.width);
332+
this.$marker.style.left = `calc(${left}px + ${menuRect.width}px - 1.5em)`;
333+
}
334+
else {
335+
left = anchorRect.left;
336+
this.$marker.style.left = `calc(${left}px + 0.5em)`;
337+
}
338+
}
339+
else {
340+
if (canPlaceAtRight) {
341+
left = anchorRect.left;
342+
this.$marker.style.left = `calc(${left}px + 0.5em)`;
343+
}
344+
else {
345+
left = Math.max(0, anchorRect.right - menuRect.width);
346+
this.$marker.style.left = `calc(${left}px + ${menuRect.width}px - 1.5em)`;
347+
}
348+
}
349+
313350
}
314351
else {
315352
left = Math.max(0, containerRect.left - menuRect.width);
@@ -320,12 +357,15 @@
320357
let parentRect;
321358
if (menu.parentNode.localName == 'li') {
322359
parentRect = menu.parentNode.getBoundingClientRect();
323-
left = parentRect.right;
360+
left = this.isRTL ? parentRect.left - menuRect.width : parentRect.right;
324361
top = parentRect.top;
325362
}
326363

327364
if (left === undefined)
328365
left = Math.max(0, (containerRect.width - menuRect.width) / 2);
366+
else if (this.isRTL)
367+
left -= menuRect.width;
368+
329369
if (top === undefined)
330370
top = Math.max(0, (containerRect.height - menuRect.height) / 2);
331371

@@ -601,13 +641,19 @@
601641
case 'ArrowRight':
602642
event.stopPropagation();
603643
event.preventDefault();
604-
this.$digIn();
644+
if (this.isRTL)
645+
this.$digOut();
646+
else
647+
this.$digIn();
605648
break;
606649

607650
case 'ArrowLeft':
608651
event.stopPropagation();
609652
event.preventDefault();
610-
this.$digOut();
653+
if (this.isRTL)
654+
this.$digIn();
655+
else
656+
this.$digOut();
611657
break;
612658

613659
case 'Home':
@@ -858,6 +904,9 @@
858904
position: fixed;
859905
z-index: 999999;
860906
}
907+
${common}.menu-ui.rtl {
908+
direction: rtl;
909+
}
861910
862911
${common}.menu-ui.open,
863912
${common}.menu-ui.open li.open > ul {
@@ -902,9 +951,14 @@
902951
${common}.menu-ui li.has-submenu::after {
903952
content: "❯";
904953
position: absolute;
905-
right: 0.25em;
906954
transform: scale(0.75);
907955
}
956+
${common}.menu-ui:not(.rtl) li.has-submenu::after {
957+
right: 0.25em;
958+
}
959+
${common}.menu-ui.rtl li.has-submenu::after {
960+
left: 0.25em;
961+
}
908962
909963
${common}.menu-ui .accesskey {
910964
text-decoration: underline;
@@ -967,10 +1021,19 @@
9671021
${common}.menu-ui.menu li[data-icon],
9681022
${common}.menu-ui.panel li[data-icon] {
9691023
--icon-size: 16px;
970-
background-position: left center;
9711024
background-repeat: no-repeat;
9721025
background-size: var(--icon-size);
973-
padding-left: calc(var(--icon-size) + 0.7em);
1026+
padding-inline-start: calc(var(--icon-size) + 0.7em);
1027+
}
1028+
${common}.menu-ui:not(.rtl) li[data-icon],
1029+
${common}.menu-ui:not(.rtl).menu li[data-icon],
1030+
${common}.menu-ui:not(.rtl).panel li[data-icon] {
1031+
background-position: left center;
1032+
}
1033+
${common}.menu-ui.rtl li[data-icon],
1034+
${common}.menu-ui.rtl.menu li[data-icon],
1035+
${common}.menu-ui.rtl.panel li[data-icon] {
1036+
background-position: right center;
9741037
}
9751038
9761039
${common}.menu-ui li.checkbox,
@@ -979,7 +1042,7 @@
9791042
${common}.menu-ui.panel li.checkbox,
9801043
${common}.menu-ui.menu li.radio,
9811044
${common}.menu-ui.panel li.radio {
982-
padding-left: 1.7em;
1045+
padding-inline-start: 1.7em;
9831046
}
9841047
9851048
/* panel-like appearance */
@@ -1049,12 +1112,17 @@
10491112
${common}.menu-ui li[data-icon][data-icon-color] .icon {
10501113
display: inline-block;
10511114
height: var(--icon-size);
1052-
left: 0.5em;
10531115
max-height: var(--icon-size);
10541116
max-width: var(--icon-size);
10551117
position: absolute;
10561118
width: var(--icon-size);
10571119
}
1120+
${common}.menu-ui:not(.rtl) li[data-icon][data-icon-color] .icon {
1121+
left: 0.5em;
1122+
}
1123+
${common}.menu-ui.rtl li[data-icon][data-icon-color] .icon {
1124+
right: 0.5em;
1125+
}
10581126
`;
10591127
document.head.appendChild(this.style);
10601128
}

0 commit comments

Comments
 (0)