feat(about): add hotkeys list (#4165)

This commit is contained in:
Meier Lukas
2025-10-02 19:54:30 +02:00
committed by GitHub
parent b76003de9b
commit f82f343631
8 changed files with 79 additions and 4 deletions

View File

@@ -23,6 +23,7 @@ import { useRequiredBoard } from "@homarr/boards/context";
import { useEditMode } from "@homarr/boards/edit-mode";
import { revalidatePathActionAsync } from "@homarr/common/client";
import { env } from "@homarr/common/env";
import { hotkeys } from "@homarr/definitions";
import { useConfirmModal, useModalAction } from "@homarr/modals";
import { AppSelectModal } from "@homarr/modals-collection";
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
@@ -165,7 +166,7 @@ const EditModeMenu = () => {
open();
}, [board, isEditMode, saveBoard, open]);
useHotkeys([["mod+e", toggle]]);
useHotkeys([[hotkeys.toggleBoardEdit, toggle]]);
usePreventLeaveWithDirty(isEditMode);
return (

View File

@@ -11,14 +11,23 @@ import {
Center,
Flex,
Group,
Kbd,
List,
ListItem,
Stack,
Table,
TableTbody,
TableTd,
TableTh,
TableThead,
TableTr,
Text,
Title,
} from "@mantine/core";
import { IconLanguage, IconLibrary, IconUsers } from "@tabler/icons-react";
import { IconKeyboard, IconLanguage, IconLibrary, IconUsers } from "@tabler/icons-react";
import { capitalize, objectEntries } from "@homarr/common";
import { hotkeys } from "@homarr/definitions";
import { getScopedI18n } from "@homarr/translation/server";
import { homarrLogoPath } from "~/components/layout/logo/homarr-logo";
@@ -149,6 +158,45 @@ export default async function AboutPage() {
</List>
</AccordionPanel>
</AccordionItem>
<AccordionItem value="hotkeys">
<AccordionControl icon={<IconKeyboard size="1rem" />}>
<Stack gap={0}>
<Text>{t("accordion.hotkeys.title")}</Text>
<Text size="sm" c="dimmed">
{t("accordion.hotkeys.subtitle")}
</Text>
</Stack>
</AccordionControl>
<AccordionPanel>
<Table>
<TableThead>
<TableTr>
<TableTh>{t("accordion.hotkeys.field.shortcut")}</TableTh>
<TableTh>{t("accordion.hotkeys.field.action")}</TableTh>
</TableTr>
</TableThead>
<TableTbody>
{objectEntries(hotkeys).map(([key, shortcut]) => (
<TableTr key={key}>
<TableTd>
<Kbd size="md">
{shortcut
.split("+")
.map((key) => capitalize(key.trim()))
.join(" + ")}
</Kbd>
</TableTd>
<TableTd>{t(`accordion.hotkeys.action.${key}`)}</TableTd>
</TableTr>
))}
</TableTbody>
</Table>
<Text size="sm" c="dimmed">
{t("accordion.hotkeys.note")}
</Text>
</AccordionPanel>
</AccordionItem>
</Accordion>
</div>
);

View File

@@ -19,6 +19,7 @@ import {
import type { RouterOutputs } from "@homarr/api";
import { signOut, useSession } from "@homarr/auth/client";
import { hotkeys } from "@homarr/definitions";
import { createModal, useModalAction } from "@homarr/modals";
import { useScopedI18n } from "@homarr/translation/client";
@@ -34,7 +35,7 @@ interface UserAvatarMenuProps {
export const UserAvatarMenu = ({ children, availableUpdatesPromise }: UserAvatarMenuProps) => {
const t = useScopedI18n("common.userAvatar.menu");
const { colorScheme, toggleColorScheme } = useMantineColorScheme();
useHotkeys([["mod+J", toggleColorScheme]]);
useHotkeys([[hotkeys.toggleColorScheme, toggleColorScheme]]);
const ColorSchemeIcon = colorScheme === "dark" ? IconSun : IconMoon;

View File

@@ -0,0 +1,6 @@
export const hotkeys = {
toggleBoardEdit: "mod+e",
toggleColorScheme: "mod+j",
saveNotebook: "mod+s",
openSpotlight: "mod+k",
};

View File

@@ -13,3 +13,4 @@ export * from "./cookie";
export * from "./search-engine";
export * from "./onboarding";
export * from "./emptysuperjson";
export * from "./hotkeys";

View File

@@ -6,6 +6,7 @@ import { ActionIcon, Center, Group, Kbd } from "@mantine/core";
import { Spotlight as MantineSpotlight } from "@mantine/spotlight";
import { IconQuestionMark, IconSearch, IconX } from "@tabler/icons-react";
import { hotkeys } from "@homarr/definitions";
import type { TranslationObject } from "@homarr/translation";
import { useI18n } from "@homarr/translation/client";
@@ -49,6 +50,7 @@ const SpotlightWithActiveMode = ({ modeState, activeMode }: SpotlightWithActiveM
return (
<MantineSpotlight.Root
shortcut={hotkeys.openSpotlight}
yOffset={8}
onSpotlightClose={() => {
setMode(defaultMode);

View File

@@ -3446,6 +3446,21 @@
"libraries": {
"title": "Libraries",
"subtitle": "{count} used in the Code of Homarr"
},
"hotkeys": {
"title": "Hotkeys",
"subtitle": "Keyboard shortcuts to enhance your workflow",
"field": {
"shortcut": "Shortcut",
"action": "Action"
},
"action": {
"toggleBoardEdit": "Toggle board edit mode",
"toggleColorScheme": "Toggle light/dark mode",
"saveNotebook": "Save notebook (only inside notebook widget)",
"openSpotlight": "Open search"
},
"note": "Tip: Mod refers to both Ctrl key and ⌘ key on macOS"
}
}
}

View File

@@ -72,6 +72,7 @@ import "./notebook.css";
import { useSession } from "@homarr/auth/client";
import { constructBoardPermissions } from "@homarr/auth/shared";
import { useRequiredBoard } from "@homarr/boards/context";
import { hotkeys } from "@homarr/definitions";
import { useConfirmModal } from "@homarr/modals";
const iconProps = {
@@ -266,7 +267,7 @@ export function Notebook({ options, setOptions, isEditMode, boardId, itemId }: W
p={0}
mt={0}
h="100%"
onKeyDown={isEditing ? getHotkeyHandler([["mod+s", handleEditToggle]]) : undefined}
onKeyDown={isEditing ? getHotkeyHandler([[hotkeys.saveNotebook, handleEditToggle]]) : undefined}
editor={editor}
styles={(theme) => ({
root: {