Skip to content

Commit 5f07f31

Browse files
committed
Lexical: Added mobile toolbar support
Adds dynamic and fixed (out of DOM order) positioning with location adjustment depending on space. Also adds smarter hiding to prevent disappearing when mouse leaves but within the same space as the toggle.
1 parent a71aa24 commit 5f07f31

File tree

6 files changed

+62
-7
lines changed

6 files changed

+62
-7
lines changed

resources/js/wysiwyg/ui/framework/blocks/button-with-menu.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export class EditorButtonWithMenu extends EditorContainerUiElement {
1616
button: {label: 'Menu', icon: caretDownIcon},
1717
showOnHover: false,
1818
direction: 'vertical',
19+
showAside: false,
1920
}, menuItems);
2021
this.addChildren(this.dropdownButton);
2122
}

resources/js/wysiwyg/ui/framework/blocks/dropdown-button.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import {EditorMenuButton} from "./menu-button";
77
export type EditorDropdownButtonOptions = {
88
showOnHover?: boolean;
99
direction?: 'vertical'|'horizontal';
10+
showAside?: boolean;
1011
button: EditorBasicButtonDefinition|EditorButton;
1112
};
1213

1314
const defaultOptions: EditorDropdownButtonOptions = {
1415
showOnHover: false,
1516
direction: 'horizontal',
17+
showAside: undefined,
1618
button: {label: 'Menu'},
1719
}
1820

@@ -65,6 +67,7 @@ export class EditorDropdownButton extends EditorContainerUiElement {
6567

6668
handleDropdown({toggle: button, menu : menu,
6769
showOnHover: this.options.showOnHover,
70+
showAside: typeof this.options.showAside === 'boolean' ? this.options.showAside : (this.options.direction === 'vertical'),
6871
onOpen : () => {
6972
this.open = true;
7073
this.getContext().manager.triggerStateUpdateForElement(this.button);

resources/js/wysiwyg/ui/framework/helpers/dropdowns.ts

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,48 @@
1-
2-
3-
41
interface HandleDropdownParams {
52
toggle: HTMLElement;
63
menu: HTMLElement;
74
showOnHover?: boolean,
85
onOpen?: Function | undefined;
96
onClose?: Function | undefined;
7+
showAside?: boolean;
8+
}
9+
10+
function positionMenu(menu: HTMLElement, toggle: HTMLElement, showAside: boolean) {
11+
const toggleRect = toggle.getBoundingClientRect();
12+
const menuBounds = menu.getBoundingClientRect();
13+
14+
menu.style.position = 'fixed';
15+
16+
if (showAside) {
17+
let targetLeft = toggleRect.right;
18+
const isRightOOB = toggleRect.right + menuBounds.width > window.innerWidth;
19+
if (isRightOOB) {
20+
targetLeft = Math.max(toggleRect.left - menuBounds.width, 0);
21+
}
22+
23+
menu.style.top = toggleRect.top + 'px';
24+
menu.style.left = targetLeft + 'px';
25+
} else {
26+
const isRightOOB = toggleRect.left + menuBounds.width > window.innerWidth;
27+
let targetLeft = toggleRect.left;
28+
if (isRightOOB) {
29+
targetLeft = Math.max(toggleRect.right - menuBounds.width, 0);
30+
}
31+
32+
menu.style.top = toggleRect.bottom + 'px';
33+
menu.style.left = targetLeft + 'px';
34+
}
1035
}
1136

1237
export function handleDropdown(options: HandleDropdownParams) {
13-
const {menu, toggle, onClose, onOpen, showOnHover} = options;
38+
const {menu, toggle, onClose, onOpen, showOnHover, showAside} = options;
1439
let clickListener: Function|null = null;
1540

1641
const hide = () => {
1742
menu.hidden = true;
43+
menu.style.removeProperty('position');
44+
menu.style.removeProperty('left');
45+
menu.style.removeProperty('top');
1846
if (clickListener) {
1947
window.removeEventListener('click', clickListener as EventListener);
2048
}
@@ -25,6 +53,7 @@ export function handleDropdown(options: HandleDropdownParams) {
2553

2654
const show = () => {
2755
menu.hidden = false
56+
positionMenu(menu, toggle, Boolean(showAside));
2857
clickListener = (event: MouseEvent) => {
2958
if (!toggle.contains(event.target as HTMLElement) && !menu.contains(event.target as HTMLElement)) {
3059
hide();
@@ -44,5 +73,18 @@ export function handleDropdown(options: HandleDropdownParams) {
4473
toggle.addEventListener('mouseenter', toggleShowing);
4574
}
4675

47-
menu.parentElement?.addEventListener('mouseleave', hide);
76+
menu.parentElement?.addEventListener('mouseleave', (event: MouseEvent) => {
77+
78+
// Prevent mouseleave hiding if withing the same bounds of the toggle.
79+
// Avoids hiding in the event the mouse is interrupted by a high z-index
80+
// item like a browser scrollbar.
81+
const toggleBounds = toggle.getBoundingClientRect();
82+
const withinX = event.clientX <= toggleBounds.right && event.clientX >= toggleBounds.left;
83+
const withinY = event.clientY <= toggleBounds.bottom && event.clientY >= toggleBounds.top;
84+
const withinToggle = withinX && withinY;
85+
86+
if (!withinToggle) {
87+
hide();
88+
}
89+
});
4890
}

resources/js/wysiwyg/ui/toolbars.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,8 @@ export function getMainEditorFullToolbar(context: EditorUiContext): EditorContai
149149
new EditorOverflowContainer(4, [
150150
new EditorButton(link),
151151

152-
new EditorDropdownButton({button: table, direction: 'vertical'}, [
153-
new EditorDropdownButton({button: {label: 'Insert', format: 'long'}, showOnHover: true}, [
152+
new EditorDropdownButton({button: table, direction: 'vertical', showAside: false}, [
153+
new EditorDropdownButton({button: {label: 'Insert', format: 'long'}, showOnHover: true, showAside: true}, [
154154
new EditorTableCreator(),
155155
]),
156156
new EditorSeparator(),

resources/sass/_editor.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@
2424
@include mixins.lightDark(border-color, #DDD, #000);
2525
}
2626

27+
@include mixins.smaller-than(vars.$bp-xl) {
28+
.editor-toolbar-main {
29+
overflow-x: scroll;
30+
flex-wrap: nowrap;
31+
justify-content: start;
32+
}
33+
}
34+
2735
body.editor-is-fullscreen {
2836
overflow: hidden;
2937
.edit-area {

resources/sass/_pages.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
width: 100%;
2727
border-radius: 8px;
2828
box-shadow: vars.$bs-card;
29+
min-width: 300px;
2930
@include mixins.lightDark(background-color, #FFF, #333)
3031
}
3132

0 commit comments

Comments
 (0)