mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-13 07:04:53 +09:00
In-app navigation was done with JS onClick -> navigate() handlers instead of real <a href> anchors, so the browser's right-click "Open in new tab" (and middle-click / ctrl-click) was unavailable. (closes #929) - Sidebar nav items and the account "user" entry now render their label as the existing Link component (a real anchor via react-router useHref), keeping the Menu onClick for plain left-clicks; stopPropagation avoids double navigation. - The "back to instances" alert action becomes a Link. - Table rows (Hosts, Roles, Plugins, Instances, Users, the user instance-stats table, Mod Packs): the name cell becomes a real Link (color inherit, so it looks unchanged) which carries the right-click context menu, and a new useRowNavigation hook handles the whole row — left-click navigates in place, middle-click / ctrl-click open the target in a new tab. The hook ignores clicks landing on a real link inside the row so the anchor handles those. Genuine actions (download/delete/modify/logout), post-create navigation and external links are left as-is. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
53 lines
1.7 KiB
TypeScript
53 lines
1.7 KiB
TypeScript
import type React from "react";
|
|
import { useNavigate } from "react-router-dom";
|
|
|
|
/** Resolve an in-app path to a full path including the router basename. */
|
|
function resolvePath(to: string): string {
|
|
const base = webRoot.replace(/\/$/, "");
|
|
return base + to;
|
|
}
|
|
|
|
function isInsideLink(target: EventTarget | null): boolean {
|
|
return target instanceof HTMLElement && target.closest("a") !== null;
|
|
}
|
|
|
|
/**
|
|
* Navigation handlers for a whole table row that also support "open in new
|
|
* tab": left-click navigates in place, middle-click or ctrl/cmd-click opens the
|
|
* target in a new tab. Spread the result into the object returned from antd's
|
|
* `onRow`, e.g. `onRow={record => rowNav(`/hosts/${record.id}/view`)}`. Clicks
|
|
* that land on a real link inside the row are ignored so the anchor handles
|
|
* them (and shows the native context menu / new-tab affordances itself).
|
|
*/
|
|
export default function useRowNavigation() {
|
|
const navigate = useNavigate();
|
|
return function rowNavigation(to: string): React.HTMLAttributes<HTMLElement> {
|
|
return {
|
|
style: { cursor: "pointer" },
|
|
onClick: (event) => {
|
|
if (event.defaultPrevented || isInsideLink(event.target)) {
|
|
return;
|
|
}
|
|
if (event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
window.open(resolvePath(to), "_blank", "noopener");
|
|
} else {
|
|
navigate(to);
|
|
}
|
|
},
|
|
onAuxClick: (event) => {
|
|
// Middle click opens the row in a new tab.
|
|
if (event.button === 1 && !isInsideLink(event.target)) {
|
|
event.preventDefault();
|
|
window.open(resolvePath(to), "_blank", "noopener");
|
|
}
|
|
},
|
|
onMouseDown: (event) => {
|
|
// Suppress the middle-click autoscroll cursor.
|
|
if (event.button === 1) {
|
|
event.preventDefault();
|
|
}
|
|
},
|
|
};
|
|
};
|
|
}
|