UI / theme improvements (#7036)

This commit is contained in:
Adorian Doran 2025-09-20 04:11:40 +03:00 committed by GitHub
commit 188319d2d9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 136 additions and 59 deletions

View File

@ -2,6 +2,7 @@ import { KeyboardActionNames } from "@triliumnext/commons";
import keyboardActionService, { getActionSync } from "../services/keyboard_actions.js"; import keyboardActionService, { getActionSync } from "../services/keyboard_actions.js";
import note_tooltip from "../services/note_tooltip.js"; import note_tooltip from "../services/note_tooltip.js";
import utils from "../services/utils.js"; import utils from "../services/utils.js";
import { should } from "vitest";
export interface ContextMenuOptions<T> { export interface ContextMenuOptions<T> {
x: number; x: number;
@ -14,8 +15,13 @@ export interface ContextMenuOptions<T> {
onHide?: () => void; onHide?: () => void;
} }
interface MenuSeparatorItem { export interface MenuSeparatorItem {
title: "----"; kind: "separator";
}
export interface MenuHeader {
title: string;
kind: "header";
} }
export interface MenuItemBadge { export interface MenuItemBadge {
@ -45,7 +51,7 @@ export interface MenuCommandItem<T> {
columns?: number; columns?: number;
} }
export type MenuItem<T> = MenuCommandItem<T> | MenuSeparatorItem; export type MenuItem<T> = MenuCommandItem<T> | MenuSeparatorItem | MenuHeader;
export type MenuHandler<T> = (item: MenuCommandItem<T>, e: JQuery.MouseDownEvent<HTMLElement, undefined, HTMLElement, HTMLElement>) => void; export type MenuHandler<T> = (item: MenuCommandItem<T>, e: JQuery.MouseDownEvent<HTMLElement, undefined, HTMLElement, HTMLElement>) => void;
export type ContextMenuEvent = PointerEvent | MouseEvent | JQuery.ContextMenuEvent; export type ContextMenuEvent = PointerEvent | MouseEvent | JQuery.ContextMenuEvent;
@ -150,14 +156,51 @@ class ContextMenu {
.addClass("show"); .addClass("show");
} }
addItems($parent: JQuery<HTMLElement>, items: MenuItem<any>[]) { addItems($parent: JQuery<HTMLElement>, items: MenuItem<any>[], multicolumn = false) {
for (const item of items) { let $group = $parent; // The current group or parent element to which items are being appended
let shouldStartNewGroup = false; // If true, the next item will start a new group
let shouldResetGroup = false; // If true, the next item will be the last one from the group
for (let index = 0; index < items.length; index++) {
const item = items[index];
if (!item) { if (!item) {
continue; continue;
} }
if (item.title === "----") { // If the current item is a header, start a new group. This group will contain the
$parent.append($("<div>").addClass("dropdown-divider")); // header and the next item that follows the header.
if ("kind" in item && item.kind === "header") {
if (multicolumn && !shouldResetGroup) {
shouldStartNewGroup = true;
}
}
// If the next item is a separator, start a new group. This group will contain the
// current item, the separator, and the next item after the separator.
const nextItem = (index < items.length - 1) ? items[index + 1] : null;
if (multicolumn && nextItem && "kind" in nextItem && nextItem.kind === "separator") {
if (!shouldResetGroup) {
shouldStartNewGroup = true;
} else {
shouldResetGroup = true; // Continue the current group
}
}
// Create a new group to avoid column breaks before and after the seaparator / header.
// This is a workaround for Firefox not supporting break-before / break-after: avoid
// for columns.
if (shouldStartNewGroup) {
$group = $("<div class='dropdown-no-break'>");
$parent.append($group);
shouldStartNewGroup = false;
}
if ("kind" in item && item.kind === "separator") {
$group.append($("<div>").addClass("dropdown-divider"));
shouldResetGroup = true; // End the group after the next item
} else if ("kind" in item && item.kind === "header") {
$group.append($("<h6>").addClass("dropdown-header").text(item.title));
shouldResetGroup = true;
} else { } else {
const $icon = $("<span>"); const $icon = $("<span>");
@ -259,16 +302,24 @@ class ContextMenu {
$link.addClass("dropdown-toggle"); $link.addClass("dropdown-toggle");
const $subMenu = $("<ul>").addClass("dropdown-menu"); const $subMenu = $("<ul>").addClass("dropdown-menu");
if (!this.isMobile && item.columns) { const hasColumns = !!item.columns && item.columns > 1;
$subMenu.css("column-count", item.columns); if (!this.isMobile && hasColumns) {
$subMenu.css("column-count", item.columns!);
} }
this.addItems($subMenu, item.items); this.addItems($subMenu, item.items, hasColumns);
$item.append($subMenu); $item.append($subMenu);
} }
$parent.append($item); $group.append($item);
// After adding a menu item, if the previous item was a separator or header,
// reset the group so that the next item will be appended directly to the parent.
if (shouldResetGroup) {
$group = $parent;
shouldResetGroup = false;
};
} }
} }
} }

View File

@ -112,7 +112,7 @@ function setupContextMenu() {
// Replace the placeholder with the real search keyword. // Replace the placeholder with the real search keyword.
let searchUrl = searchEngineUrl.replace("{keyword}", encodeURIComponent(params.selectionText)); let searchUrl = searchEngineUrl.replace("{keyword}", encodeURIComponent(params.selectionText));
items.push({ title: "----" }); items.push({ kind: "separator" });
items.push({ items.push({
title: t("electron_context_menu.search_online", { term: shortenedSelection, searchEngine: searchEngineName }), title: t("electron_context_menu.search_online", { term: shortenedSelection, searchEngine: searchEngineName }),

View File

@ -45,16 +45,16 @@ export default class LauncherContextMenu implements SelectMenuItemEventListener<
isVisibleRoot || isAvailableRoot ? { title: t("launcher_context_menu.add-script-launcher"), command: "addScriptLauncher", uiIcon: "bx bx-code-curly" } : null, isVisibleRoot || isAvailableRoot ? { title: t("launcher_context_menu.add-script-launcher"), command: "addScriptLauncher", uiIcon: "bx bx-code-curly" } : null,
isVisibleRoot || isAvailableRoot ? { title: t("launcher_context_menu.add-custom-widget"), command: "addWidgetLauncher", uiIcon: "bx bx-customize" } : null, isVisibleRoot || isAvailableRoot ? { title: t("launcher_context_menu.add-custom-widget"), command: "addWidgetLauncher", uiIcon: "bx bx-customize" } : null,
isVisibleRoot || isAvailableRoot ? { title: t("launcher_context_menu.add-spacer"), command: "addSpacerLauncher", uiIcon: "bx bx-dots-horizontal" } : null, isVisibleRoot || isAvailableRoot ? { title: t("launcher_context_menu.add-spacer"), command: "addSpacerLauncher", uiIcon: "bx bx-dots-horizontal" } : null,
isVisibleRoot || isAvailableRoot ? { title: "----" } : null, isVisibleRoot || isAvailableRoot ? { kind: "separator" } : null,
isAvailableItem ? { title: t("launcher_context_menu.move-to-visible-launchers"), command: "moveLauncherToVisible", uiIcon: "bx bx-show", enabled: true } : null, isAvailableItem ? { title: t("launcher_context_menu.move-to-visible-launchers"), command: "moveLauncherToVisible", uiIcon: "bx bx-show", enabled: true } : null,
isVisibleItem ? { title: t("launcher_context_menu.move-to-available-launchers"), command: "moveLauncherToAvailable", uiIcon: "bx bx-hide", enabled: true } : null, isVisibleItem ? { title: t("launcher_context_menu.move-to-available-launchers"), command: "moveLauncherToAvailable", uiIcon: "bx bx-hide", enabled: true } : null,
isVisibleItem || isAvailableItem ? { title: "----" } : null, isVisibleItem || isAvailableItem ? { kind: "separator" } : null,
{ title: `${t("launcher_context_menu.duplicate-launcher")}`, command: "duplicateSubtree", uiIcon: "bx bx-outline", enabled: isItem }, { title: `${t("launcher_context_menu.duplicate-launcher")}`, command: "duplicateSubtree", uiIcon: "bx bx-outline", enabled: isItem },
{ title: `${t("launcher_context_menu.delete")}`, command: "deleteNotes", uiIcon: "bx bx-trash destructive-action-icon", enabled: canBeDeleted }, { title: `${t("launcher_context_menu.delete")}`, command: "deleteNotes", uiIcon: "bx bx-trash destructive-action-icon", enabled: canBeDeleted },
{ title: "----" }, { kind: "separator" },
{ title: t("launcher_context_menu.reset"), command: "resetLauncher", uiIcon: "bx bx-reset destructive-action-icon", enabled: canBeReset } { title: t("launcher_context_menu.reset"), command: "resetLauncher", uiIcon: "bx bx-reset destructive-action-icon", enabled: canBeReset }
]; ];

View File

@ -93,7 +93,7 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
? null ? null
: { title: t("tree-context-menu.unhoist-note"), command: "toggleNoteHoisting", keyboardShortcut: "toggleNoteHoisting", uiIcon: "bx bx-door-open" }, : { title: t("tree-context-menu.unhoist-note"), command: "toggleNoteHoisting", keyboardShortcut: "toggleNoteHoisting", uiIcon: "bx bx-door-open" },
{ title: "----" }, { kind: "separator" },
{ {
title: t("tree-context-menu.insert-note-after"), title: t("tree-context-menu.insert-note-after"),
@ -115,13 +115,13 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
columns: 2 columns: 2
}, },
{ title: "----" }, { kind: "separator" },
{ title: t("tree-context-menu.protect-subtree"), command: "protectSubtree", uiIcon: "bx bx-check-shield", enabled: noSelectedNotes }, { title: t("tree-context-menu.protect-subtree"), command: "protectSubtree", uiIcon: "bx bx-check-shield", enabled: noSelectedNotes },
{ title: t("tree-context-menu.unprotect-subtree"), command: "unprotectSubtree", uiIcon: "bx bx-shield", enabled: noSelectedNotes }, { title: t("tree-context-menu.unprotect-subtree"), command: "unprotectSubtree", uiIcon: "bx bx-shield", enabled: noSelectedNotes },
{ title: "----" }, { kind: "separator" },
{ {
title: t("tree-context-menu.advanced"), title: t("tree-context-menu.advanced"),
@ -130,7 +130,7 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
items: [ items: [
{ title: t("tree-context-menu.apply-bulk-actions"), command: "openBulkActionsDialog", uiIcon: "bx bx-list-plus", enabled: true }, { title: t("tree-context-menu.apply-bulk-actions"), command: "openBulkActionsDialog", uiIcon: "bx bx-list-plus", enabled: true },
{ title: "----" }, { kind: "separator" },
{ {
title: t("tree-context-menu.edit-branch-prefix"), title: t("tree-context-menu.edit-branch-prefix"),
@ -141,7 +141,7 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
}, },
{ title: t("tree-context-menu.convert-to-attachment"), command: "convertNoteToAttachment", uiIcon: "bx bx-paperclip", enabled: isNotRoot && !isHoisted && notOptionsOrHelp }, { title: t("tree-context-menu.convert-to-attachment"), command: "convertNoteToAttachment", uiIcon: "bx bx-paperclip", enabled: isNotRoot && !isHoisted && notOptionsOrHelp },
{ title: "----" }, { kind: "separator" },
{ title: t("tree-context-menu.expand-subtree"), command: "expandSubtree", keyboardShortcut: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes }, { title: t("tree-context-menu.expand-subtree"), command: "expandSubtree", keyboardShortcut: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
{ title: t("tree-context-menu.collapse-subtree"), command: "collapseSubtree", keyboardShortcut: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes }, { title: t("tree-context-menu.collapse-subtree"), command: "collapseSubtree", keyboardShortcut: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
@ -153,14 +153,14 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
enabled: noSelectedNotes && notSearch enabled: noSelectedNotes && notSearch
}, },
{ title: "----" }, { kind: "separator" },
{ title: t("tree-context-menu.copy-note-path-to-clipboard"), command: "copyNotePathToClipboard", uiIcon: "bx bx-directions", enabled: true }, { title: t("tree-context-menu.copy-note-path-to-clipboard"), command: "copyNotePathToClipboard", uiIcon: "bx bx-directions", enabled: true },
{ title: t("tree-context-menu.recent-changes-in-subtree"), command: "recentChangesInSubtree", uiIcon: "bx bx-history", enabled: noSelectedNotes && notOptionsOrHelp } { title: t("tree-context-menu.recent-changes-in-subtree"), command: "recentChangesInSubtree", uiIcon: "bx bx-history", enabled: noSelectedNotes && notOptionsOrHelp }
] ]
}, },
{ title: "----" }, { kind: "separator" },
{ {
title: t("tree-context-menu.cut"), title: t("tree-context-menu.cut"),
@ -241,13 +241,13 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
enabled: isNotRoot && !isHoisted && parentNotSearch && notOptionsOrHelp enabled: isNotRoot && !isHoisted && parentNotSearch && notOptionsOrHelp
}, },
{ title: "----" }, { kind: "separator" },
{ title: t("tree-context-menu.import-into-note"), command: "importIntoNote", uiIcon: "bx bx-import", enabled: notSearch && noSelectedNotes && notOptionsOrHelp }, { title: t("tree-context-menu.import-into-note"), command: "importIntoNote", uiIcon: "bx bx-import", enabled: notSearch && noSelectedNotes && notOptionsOrHelp },
{ title: t("tree-context-menu.export"), command: "exportNote", uiIcon: "bx bx-export", enabled: notSearch && noSelectedNotes && notOptionsOrHelp }, { title: t("tree-context-menu.export"), command: "exportNote", uiIcon: "bx bx-export", enabled: notSearch && noSelectedNotes && notOptionsOrHelp },
{ title: "----" }, { kind: "separator" },
{ {
title: t("tree-context-menu.search-in-subtree"), title: t("tree-context-menu.search-in-subtree"),

View File

@ -1,7 +1,7 @@
import { t } from "./i18n.js"; import { t } from "./i18n.js";
import froca from "./froca.js"; import froca from "./froca.js";
import server from "./server.js"; import server from "./server.js";
import type { MenuCommandItem, MenuItem, MenuItemBadge } from "../menus/context_menu.js"; import type { MenuCommandItem, MenuItem, MenuItemBadge, MenuSeparatorItem } from "../menus/context_menu.js";
import type { NoteType } from "../entities/fnote.js"; import type { NoteType } from "../entities/fnote.js";
import type { TreeCommandNames } from "../menus/tree_context_menu.js"; import type { TreeCommandNames } from "../menus/tree_context_menu.js";
@ -73,7 +73,7 @@ const BETA_BADGE = {
title: t("note_types.beta-feature") title: t("note_types.beta-feature")
}; };
const SEPARATOR = { title: "----" }; const SEPARATOR: MenuSeparatorItem = { kind: "separator" };
const creationDateCache = new Map<string, Date>(); const creationDateCache = new Map<string, Date>();
let rootCreationDate: Date | undefined; let rootCreationDate: Date | undefined;
@ -81,8 +81,8 @@ let rootCreationDate: Date | undefined;
async function getNoteTypeItems(command?: TreeCommandNames) { async function getNoteTypeItems(command?: TreeCommandNames) {
const items: MenuItem<TreeCommandNames>[] = [ const items: MenuItem<TreeCommandNames>[] = [
...getBlankNoteTypes(command), ...getBlankNoteTypes(command),
...await getBuiltInTemplates(t("note_types.collections"), command, true),
...await getBuiltInTemplates(null, command, false), ...await getBuiltInTemplates(null, command, false),
...await getBuiltInTemplates(t("note_types.collections"), command, true),
...await getUserTemplates(command) ...await getUserTemplates(command)
]; ];
@ -121,7 +121,10 @@ async function getUserTemplates(command?: TreeCommandNames) {
} }
const items: MenuItem<TreeCommandNames>[] = [ const items: MenuItem<TreeCommandNames>[] = [
SEPARATOR {
title: t("note_type_chooser.templates"),
kind: "header"
}
]; ];
for (const templateNote of templateNotes) { for (const templateNote of templateNotes) {
@ -158,8 +161,7 @@ async function getBuiltInTemplates(title: string | null, command: TreeCommandNam
if (title) { if (title) {
items.push({ items.push({
title: title, title: title,
enabled: false, kind: "header"
uiIcon: "bx bx-empty"
}); });
} else { } else {
items.push(SEPARATOR); items.push(SEPARATOR);

View File

@ -370,14 +370,10 @@ button kbd {
--bs-dropdown-link-active-bg: var(--active-item-background-color) !important; --bs-dropdown-link-active-bg: var(--active-item-background-color) !important;
} }
.dropdown-menu .dropdown-divider {
break-before: avoid;
break-after: avoid;
}
body.desktop .dropdown-menu, body.desktop .dropdown-menu,
body.desktop .tabulator-popup-container { body.desktop .tabulator-popup-container {
border: 1px solid var(--dropdown-border-color); border: 1px solid var(--dropdown-border-color);
column-rule: 1px solid var(--dropdown-border-color);
box-shadow: 0px 10px 20px rgba(0, 0, 0, var(--dropdown-shadow-opacity)); box-shadow: 0px 10px 20px rgba(0, 0, 0, var(--dropdown-shadow-opacity));
animation: dropdown-menu-opening 100ms ease-in; animation: dropdown-menu-opening 100ms ease-in;
} }
@ -444,9 +440,11 @@ body #context-menu-container .dropdown-item > span {
align-items: center; align-items: center;
} }
.dropdown-item span.keyboard-shortcut { .dropdown-item span.keyboard-shortcut,
.dropdown-item *:not(.keyboard-shortcut) > kbd {
flex-grow: 1; flex-grow: 1;
text-align: right; text-align: right;
padding-inline-start: 12px;
} }
.dropdown-menu kbd { .dropdown-menu kbd {
@ -456,8 +454,6 @@ body #context-menu-container .dropdown-item > span {
box-shadow: none; box-shadow: none;
padding-bottom: 0; padding-bottom: 0;
padding: 0; padding: 0;
flex-grow: 1;
text-align: right;
} }
.dropdown-item, .dropdown-item,
@ -466,6 +462,12 @@ body #context-menu-container .dropdown-item > span {
border: 1px solid transparent !important; border: 1px solid transparent !important;
} }
/* This is a workaround for Firefox not supporting break-before / break-after: avoid on columns.
* It usually wraps a menu item followed by a separator / header and another menu item. */
.dropdown-no-break {
break-inside: avoid;
}
.dropdown-item.disabled, .dropdown-item.disabled,
.dropdown-item.disabled kbd { .dropdown-item.disabled kbd {
color: #aaa !important; color: #aaa !important;

View File

@ -154,7 +154,7 @@ body.desktop .dropdown-submenu .dropdown-menu {
.dropdown-item, .dropdown-item,
body.mobile .dropdown-submenu .dropdown-toggle { body.mobile .dropdown-submenu .dropdown-toggle {
padding: 2px 2px 2px 8px !important; padding: 2px 2px 2px 8px !important;
padding-inline-end: 16px !important; padding-inline-end: 22px !important;
/* Note: the right padding should also accommodate the submenu arrow. */ /* Note: the right padding should also accommodate the submenu arrow. */
border-radius: 6px; border-radius: 6px;
cursor: default !important; cursor: default !important;

View File

@ -84,7 +84,7 @@ button.btn.btn-success kbd {
*/ */
:root .icon-action:not(.global-menu-button), :root .icon-action:not(.global-menu-button),
:root .btn.tn-tool-button, :root .tn-tool-button,
:root .btn-group .tn-tool-button:not(:last-child), :root .btn-group .tn-tool-button:not(:last-child),
:root .btn-group .tn-tool-button:last-child { :root .btn-group .tn-tool-button:last-child {
width: var(--icon-button-size); width: var(--icon-button-size);

View File

@ -348,6 +348,21 @@ body.layout-horizontal > .horizontal {
--select-arrow-svg: initial; /* Disable the dropdown arrow */ --select-arrow-svg: initial; /* Disable the dropdown arrow */
} }
/* Week number column */
.calendar-dropdown-widget .calendar-week-number {
transform: rotate(270deg);
justify-content: center;
padding: 0;
opacity: 0.5;
font-size: 1em;
font-weight: 700;
letter-spacing: .5pt;
}
.calendar-dropdown-widget .calendar-week-number::after {
display: none;
}
@media (max-width: 992px) { @media (max-width: 992px) {
.calendar-dropdown-widget .calendar-header button { .calendar-dropdown-widget .calendar-header button {
margin: 0 !important; margin: 0 !important;

View File

@ -41,7 +41,7 @@ export function openNoteContextMenu(api: Api, event: ContextMenuEvent, note: FNo
y: event.pageY, y: event.pageY,
items: [ items: [
...link_context_menu.getItems(), ...link_context_menu.getItems(),
{ title: "----" }, { kind: "separator" },
{ {
title: t("board_view.move-to"), title: t("board_view.move-to"),
uiIcon: "bx bx-transfer", uiIcon: "bx bx-transfer",
@ -52,7 +52,7 @@ export function openNoteContextMenu(api: Api, event: ContextMenuEvent, note: FNo
})), })),
}, },
getArchiveMenuItem(note), getArchiveMenuItem(note),
{ title: "----" }, { kind: "separator" },
{ {
title: t("board_view.insert-above"), title: t("board_view.insert-above"),
uiIcon: "bx bx-list-plus", uiIcon: "bx bx-list-plus",
@ -63,7 +63,7 @@ export function openNoteContextMenu(api: Api, event: ContextMenuEvent, note: FNo
uiIcon: "bx bx-empty", uiIcon: "bx bx-empty",
handler: () => api.insertRowAtPosition(column, branchId, "after") handler: () => api.insertRowAtPosition(column, branchId, "after")
}, },
{ title: "----" }, { kind: "separator" },
{ {
title: t("board_view.remove-from-board"), title: t("board_view.remove-from-board"),
uiIcon: "bx bx-task-x", uiIcon: "bx bx-task-x",

View File

@ -10,14 +10,14 @@ import link from "../../../services/link.js";
export default function openContextMenu(noteId: string, e: LeafletMouseEvent, isEditable: boolean) { export default function openContextMenu(noteId: string, e: LeafletMouseEvent, isEditable: boolean) {
let items: MenuItem<keyof CommandMappings>[] = [ let items: MenuItem<keyof CommandMappings>[] = [
...buildGeoLocationItem(e), ...buildGeoLocationItem(e),
{ title: "----" }, { kind: "separator" },
...linkContextMenu.getItems(), ...linkContextMenu.getItems(),
]; ];
if (isEditable) { if (isEditable) {
items = [ items = [
...items, ...items,
{ title: "----" }, { kind: "separator" },
{ title: t("geo-map-context.remove-from-map"), command: "deleteFromMap", uiIcon: "bx bx-trash" } { title: t("geo-map-context.remove-from-map"), command: "deleteFromMap", uiIcon: "bx bx-trash" }
]; ];
} }
@ -46,7 +46,7 @@ export function openMapContextMenu(noteId: string, e: LeafletMouseEvent, isEdita
if (isEditable) { if (isEditable) {
items = [ items = [
...items, ...items,
{ title: "----" }, { kind: "separator" },
{ {
title: t("geo-map-context.add-note"), title: t("geo-map-context.add-note"),
handler: () => createNewNote(noteId, e), handler: () => createNewNote(noteId, e),

View File

@ -74,7 +74,7 @@ function showColumnContextMenu(parentComponent: Component, e: MouseEvent, column
handler: () => tabulator.clearSort() handler: () => tabulator.clearSort()
}, },
{ {
title: "----" kind: "separator"
}, },
{ {
title: t("table_view.hide-column", { title }), title: t("table_view.hide-column", { title }),
@ -86,7 +86,7 @@ function showColumnContextMenu(parentComponent: Component, e: MouseEvent, column
uiIcon: "bx bx-columns", uiIcon: "bx bx-columns",
items: buildColumnItems(tabulator) items: buildColumnItems(tabulator)
}, },
{ title: "----" }, { kind: "separator" },
{ {
title: t("table_view.add-column-to-the-left"), title: t("table_view.add-column-to-the-left"),
uiIcon: "bx bx-horizontal-left", uiIcon: "bx bx-horizontal-left",
@ -105,7 +105,7 @@ function showColumnContextMenu(parentComponent: Component, e: MouseEvent, column
direction: "after" direction: "after"
}) })
}, },
{ title: "----" }, { kind: "separator" },
{ {
title: t("table_view.edit-column"), title: t("table_view.edit-column"),
uiIcon: "bx bxs-edit-alt", uiIcon: "bx bxs-edit-alt",
@ -143,7 +143,7 @@ function showHeaderContextMenu(parentComponent: Component, e: MouseEvent, tabula
uiIcon: "bx bx-columns", uiIcon: "bx bx-columns",
items: buildColumnItems(tabulator) items: buildColumnItems(tabulator)
}, },
{ title: "----" }, { kind: "separator" },
{ {
title: t("table_view.new-column"), title: t("table_view.new-column"),
uiIcon: "bx bx-empty", uiIcon: "bx bx-empty",
@ -174,7 +174,7 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
contextMenu.show({ contextMenu.show({
items: [ items: [
...link_context_menu.getItems(), ...link_context_menu.getItems(),
{ title: "----" }, { kind: "separator" },
{ {
title: t("table_view.row-insert-above"), title: t("table_view.row-insert-above"),
uiIcon: "bx bx-horizontal-left bx-rotate-90", uiIcon: "bx bx-horizontal-left bx-rotate-90",
@ -214,7 +214,7 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
} }
}) })
}, },
{ title: "----" }, { kind: "separator" },
{ {
title: t("table_context_menu.delete_row"), title: t("table_context_menu.delete_row"),
uiIcon: "bx bx-trash", uiIcon: "bx bx-trash",

View File

@ -17,8 +17,15 @@
} }
.bulk-actions-dialog .bulk-existing-action-list .button-column { .bulk-actions-dialog .bulk-existing-action-list .button-column {
/* minimal width so that table remains static sized and most space remains for middle column with settings */
width: 50px; width: 50px;
white-space: nowrap; white-space: nowrap;
text-align: right; text-align: right;
}
.bulk-actions-dialog .bulk-existing-action-list .button-column > * {
vertical-align: middle;
}
.bulk-actions-dialog .bulk-existing-action-list .button-column .help-dropdown {
display: inline-block !important;
} }

View File

@ -41,7 +41,7 @@ export default function NoteTypeChooserDialogComponent() {
let index = -1; let index = -1;
setNoteTypes((noteTypes ?? []).map((item) => { setNoteTypes((noteTypes ?? []).map((item) => {
if (item.title === "----") { if ("kind" in item && item.kind === "separator") {
index++; index++;
return { return {
title: SEPARATOR_TITLE_REPLACEMENTS[index], title: SEPARATOR_TITLE_REPLACEMENTS[index],
@ -95,7 +95,7 @@ export default function NoteTypeChooserDialogComponent() {
<FormGroup name="note-type" label={t("note_type_chooser.modal_body")}> <FormGroup name="note-type" label={t("note_type_chooser.modal_body")}>
<FormList onSelect={onNoteTypeSelected}> <FormList onSelect={onNoteTypeSelected}>
{noteTypes.map((_item) => { {noteTypes.map((_item) => {
if (_item.title === "----") { if ("kind" in _item && _item.kind === "separator") {
return; return;
} }

View File

@ -24,7 +24,7 @@ export default function MobileDetailMenu() {
items: [ items: [
{ title: t("mobile_detail_menu.insert_child_note"), command: "insertChildNote", uiIcon: "bx bx-plus", enabled: note?.type !== "search" }, { title: t("mobile_detail_menu.insert_child_note"), command: "insertChildNote", uiIcon: "bx bx-plus", enabled: note?.type !== "search" },
{ title: t("mobile_detail_menu.delete_this_note"), command: "delete", uiIcon: "bx bx-trash", enabled: note?.noteId !== "root" }, { title: t("mobile_detail_menu.delete_this_note"), command: "delete", uiIcon: "bx bx-trash", enabled: note?.noteId !== "root" },
{ title: "----" }, { kind: "separator" },
{ title: "Note revisions", command: "showRevisions", uiIcon: "bx bx-history" } { title: "Note revisions", command: "showRevisions", uiIcon: "bx bx-history" }
], ],
selectMenuItemHandler: async ({ command }) => { selectMenuItemHandler: async ({ command }) => {

View File

@ -387,7 +387,7 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI
items: [ items: [
{ title: t("attribute_editor.add_new_label"), command: "addNewLabel", uiIcon: "bx bx-hash" }, { title: t("attribute_editor.add_new_label"), command: "addNewLabel", uiIcon: "bx bx-hash" },
{ title: t("attribute_editor.add_new_relation"), command: "addNewRelation", uiIcon: "bx bx-transfer" }, { title: t("attribute_editor.add_new_relation"), command: "addNewRelation", uiIcon: "bx bx-transfer" },
{ title: "----" }, { kind: "separator" },
{ title: t("attribute_editor.add_new_label_definition"), command: "addNewLabelDefinition", uiIcon: "bx bx-empty" }, { title: t("attribute_editor.add_new_label_definition"), command: "addNewLabelDefinition", uiIcon: "bx bx-empty" },
{ title: t("attribute_editor.add_new_relation_definition"), command: "addNewRelationDefinition", uiIcon: "bx bx-empty" } { title: t("attribute_editor.add_new_relation_definition"), command: "addNewRelationDefinition", uiIcon: "bx bx-empty" }
], ],

View File

@ -356,11 +356,11 @@ export default class TabRowWidget extends BasicWidget {
{ title: t("tab_row.close_right_tabs"), command: "closeRightTabs", uiIcon: "bx bx-empty", enabled: appContext.tabManager.noteContexts?.at(-1)?.ntxId !== ntxId }, { title: t("tab_row.close_right_tabs"), command: "closeRightTabs", uiIcon: "bx bx-empty", enabled: appContext.tabManager.noteContexts?.at(-1)?.ntxId !== ntxId },
{ title: t("tab_row.close_all_tabs"), command: "closeAllTabs", uiIcon: "bx bx-empty" }, { title: t("tab_row.close_all_tabs"), command: "closeAllTabs", uiIcon: "bx bx-empty" },
{ title: "----" }, { kind: "separator" },
{ title: t("tab_row.reopen_last_tab"), command: "reopenLastTab", uiIcon: "bx bx-undo", enabled: appContext.tabManager.recentlyClosedTabs.length !== 0 }, { title: t("tab_row.reopen_last_tab"), command: "reopenLastTab", uiIcon: "bx bx-undo", enabled: appContext.tabManager.recentlyClosedTabs.length !== 0 },
{ title: "----" }, { kind: "separator" },
{ title: t("tab_row.move_tab_to_new_window"), command: "moveTabToNewWindow", uiIcon: "bx bx-window-open" }, { title: t("tab_row.move_tab_to_new_window"), command: "moveTabToNewWindow", uiIcon: "bx bx-window-open" },
{ title: t("tab_row.copy_tab_to_new_window"), command: "copyTabToNewWindow", uiIcon: "bx bx-empty" } { title: t("tab_row.copy_tab_to_new_window"), command: "copyTabToNewWindow", uiIcon: "bx bx-empty" }