Skip to content

Commit f39ae91

Browse files
author
Maks Wolkowinski
committed
feat(UI): Overflow menu (Switch from scroll button to dropdown)
Signed-off-by: Maks Wolkowinski <[email protected]> Change-Id: I80c76c9511ceec9d3e46a261ce8ffefc1d5aa477
1 parent caec390 commit f39ae91

File tree

5 files changed

+269
-7
lines changed

5 files changed

+269
-7
lines changed

browser/css/jsdialogs.css

-4
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,6 @@ div#autoFillPreviewTooltip .lokdialog.ui-dialog-content.ui-widget-content {
161161
vertical-align: middle;
162162
}
163163

164-
.jsdialog.vertical:not(.sidebar):not(.ui-separator) {
165-
width: 100%;
166-
}
167-
168164
th.jsdialog:not(:first-child) {
169165
padding-inline-end: 24px;
170166
}

browser/css/toolbar.css

+16
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,22 @@
6060
margin: 0px;
6161
}
6262

63+
/* overflow menu */
64+
.menu-overflow-wrapper {
65+
position: absolute;
66+
height: var(--header-height);
67+
top: var(--header-height);
68+
display: flex;
69+
background-color: var(--color-background-lighter);
70+
border: 1px solid var(--color-toolbar-border);
71+
align-items: center;
72+
border-radius: 4px;
73+
padding: 0 4px;
74+
box-shadow: 0 2px 6px 2px rgba(60, 64, 67, .15);
75+
opacity: 0;
76+
pointer-events: none;
77+
}
78+
6379
/* status bar / mobile bottom bar */
6480

6581
#toolbar-down .ui-badge {
+70
Loading

browser/images/lc_menuoverflow.svg

+70
Loading

browser/src/control/Control.TopToolbar.js

+113-3
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ class TopToolbar extends JSDialog.Toolbar {
190190
{type: 'customtoolitem', id: 'insertannotation', text: _UNO('.uno:InsertAnnotation', '', true), visible: false, lockUno: '.uno:InsertAnnotation'},
191191
{type: 'customtoolitem', id: 'inserthyperlink', command: 'inserthyperlink', text: _UNO('.uno:HyperlinkDialog', '', true), lockUno: '.uno:HyperlinkDialog'},
192192
{type: 'toolitem', id: 'insertsymbol', text: _UNO('.uno:InsertSymbol', '', true), command: '.uno:InsertSymbol'},
193+
{type: 'customtoolitem', id: 'menuoverflow', text: _('More'), desktop: true, mobile: false, visible: true},
193194
{type: 'spacer', id: 'topspacer'},
194195
{type: 'separator', orientation: 'vertical', id: 'breaksidebar', visible: false},
195196
{type: 'toolitem', id: 'sidebar', text: _UNO('.uno:Sidebar', '', true), command: '.uno:SidebarDeck.PropertyDeck', visible: false},
@@ -228,14 +229,123 @@ class TopToolbar extends JSDialog.Toolbar {
228229
}
229230
}
230231

232+
createOverflowMenu() {
233+
const topBarMenu = this.parentContainer.querySelector(
234+
'.root-container .vertical',
235+
);
236+
237+
const overflowMenu = L.DomUtil.create(
238+
'div',
239+
'menu-overflow-wrapper',
240+
this.parentContainer,
241+
);
242+
243+
const overflowMenuButton =
244+
this.parentContainer.querySelector('#menuoverflow');
245+
246+
const showOverflowMenu = () => {
247+
overflowMenu.style.opacity = 1;
248+
overflowMenu.style.pointerEvents = 'revert';
249+
L.DomUtil.addClass(overflowMenuButton, 'selected');
250+
};
251+
252+
const hideOverflowMenu = () => {
253+
overflowMenu.style.opacity = 0;
254+
overflowMenu.style.pointerEvents = 'none';
255+
L.DomUtil.removeClass(overflowMenuButton, 'selected');
256+
};
257+
258+
overflowMenuButton.addEventListener('click', () => {
259+
if (
260+
overflowMenu.style.opacity === '0' ||
261+
overflowMenu.style.opacity === ''
262+
) {
263+
showOverflowMenu();
264+
} else {
265+
hideOverflowMenu();
266+
}
267+
});
268+
269+
const breakSidebar = this.parentContainer.querySelector('#breaksidebar');
270+
const foldButton = this.parentContainer.querySelector('#fold');
271+
272+
const getMenuWidth = () => {
273+
const splitPosition =
274+
foldButton.offsetLeft +
275+
foldButton.offsetWidth * 2 -
276+
breakSidebar.offsetLeft;
277+
return window.innerWidth - splitPosition;
278+
};
279+
280+
let overflowMenuDebounced = 0;
281+
const originalTopbar = topBarMenu.querySelectorAll('.jsdialog');
282+
283+
const overflowMenuHandler = () => {
284+
overflowMenuDebounced && clearTimeout(overflowMenuDebounced);
285+
286+
hideOverflowMenu();
287+
288+
overflowMenuDebounced = setTimeout(() => {
289+
topBarMenu.replaceChildren(...originalTopbar);
290+
291+
const topBarButtons = topBarMenu.querySelectorAll('.jsdialog:not(.hidden)');
292+
const menuWidth = getMenuWidth();
293+
294+
const overflowMenuOffscreen = document.createElement('div');
295+
overflowMenuOffscreen.className = 'menu-overfow-vertical';
296+
297+
let section = [];
298+
let overflow = false;
299+
300+
const appendSection = () => {
301+
for (const element of section) {
302+
overflowMenuOffscreen.appendChild(element);
303+
}
304+
section.length = 0;
305+
};
306+
307+
for (const button of topBarButtons) {
308+
if (button.id === 'topspacer' || button.id === 'menuoverflow') {
309+
break;
310+
}
311+
312+
if (button.offsetLeft > menuWidth || overflow) {
313+
overflow = true;
314+
appendSection();
315+
overflowMenuOffscreen.appendChild(button);
316+
} else if (button.className.includes('vertical')) {
317+
section = [button];
318+
} else {
319+
section.push(button);
320+
}
321+
}
322+
323+
overflowMenu.replaceChildren(overflowMenuOffscreen);
324+
325+
if (overflowMenuOffscreen.children.length <= 0) {
326+
overflowMenuButton.style.display = 'none';
327+
} else {
328+
overflowMenuButton.style.display = 'revert';
329+
}
330+
331+
overflowMenu.style.left =
332+
overflowMenuButton.offsetLeft -
333+
overflowMenu.clientWidth +
334+
overflowMenuButton.offsetWidth +
335+
'px';
336+
}, 250);
337+
};
338+
339+
window.addEventListener('resize', overflowMenuHandler);
340+
}
341+
231342
create() {
232343
this.reset();
233344

234345
var items = this.getToolItems();
235346
this.builder.build(this.parentContainer, items);
236347

237-
JSDialog.MakeScrollable(this.parentContainer, this.parentContainer.querySelector('div'));
238-
JSDialog.RefreshScrollables();
348+
this.createOverflowMenu();
239349

240350
if (this.map.isRestrictedUser()) {
241351
for (var i = 0; i < items.length; i++) {
@@ -260,7 +370,7 @@ class TopToolbar extends JSDialog.Toolbar {
260370
this.onDocLayerInit();
261371

262372
// if app opens direct in compact mode then we need to set the saveState first
263-
this.map.saveState = new app.definitions.saveState(this.map);
373+
this.map.saveState = new app.definitions.saveState(this.map);
264374
}
265375

266376
onDocLayerInit() {

0 commit comments

Comments
 (0)