feat: integrate keyboard shortcuts into Root layout and account menu

- Mount useKeyboardShortcuts and KeyboardShortcutsDialog in Root.tsx
  via a KeyboardShortcutsProvider wrapper (only renders post-auth)
- Add 'Keyboard Shortcuts' menu item with Keyboard icon to the
  account settings popover for discoverability
This commit is contained in:
Marco Beretta 2026-03-26 23:47:11 +01:00
parent 08a54273fa
commit 1d0827ff79
No known key found for this signature in database
GPG key ID: D918033D8E74CC11
2 changed files with 17 additions and 1 deletions

View file

@ -1,12 +1,14 @@
import { useState, memo, useRef } from 'react';
import * as Menu from '@ariakit/react/menu';
import { FileText, LogOut } from 'lucide-react';
import { useSetRecoilState } from 'recoil';
import { FileText, LogOut, Keyboard } from 'lucide-react';
import { LinkIcon, GearIcon, DropdownMenuSeparator, Avatar } from '@librechat/client';
import { MyFilesModal } from '~/components/Chat/Input/Files/MyFilesModal';
import { useGetStartupConfig, useGetUserBalance } from '~/data-provider';
import { useAuthContext } from '~/hooks/AuthContext';
import { useLocalize } from '~/hooks';
import Settings from './Settings';
import store from '~/store';
function AccountSettings({ collapsed = false }: { collapsed?: boolean }) {
const localize = useLocalize();
@ -17,6 +19,7 @@ function AccountSettings({ collapsed = false }: { collapsed?: boolean }) {
});
const [showSettings, setShowSettings] = useState(false);
const [showFiles, setShowFiles] = useState(false);
const setShowShortcutsDialog = useSetRecoilState(store.showShortcutsDialog);
const accountSettingsButtonRef = useRef<HTMLButtonElement>(null);
return (
@ -82,6 +85,10 @@ function AccountSettings({ collapsed = false }: { collapsed?: boolean }) {
{localize('com_nav_help_faq')}
</Menu.MenuItem>
)}
<Menu.MenuItem onClick={() => setShowShortcutsDialog(true)} className="select-item text-sm">
<Keyboard className="icon-md" aria-hidden="true" />
{localize('com_shortcut_keyboard_shortcuts')}
</Menu.MenuItem>
<Menu.MenuItem onClick={() => setShowSettings(true)} className="select-item text-sm">
<GearIcon className="icon-md" aria-hidden="true" />
{localize('com_nav_settings')}

View file

@ -18,10 +18,18 @@ import {
FileMapContext,
} from '~/Providers';
import { useUserTermsQuery, useGetStartupConfig } from '~/data-provider';
import KeyboardShortcutsDialog from '~/components/Nav/KeyboardShortcutsDialog';
import { UnifiedSidebar } from '~/components/UnifiedSidebar';
import { TermsAndConditionsModal } from '~/components/ui';
import { useHealthCheck } from '~/data-provider';
import { Banner } from '~/components/Banners';
import useKeyboardShortcuts from '~/hooks/useKeyboardShortcuts';
/** Isolates keyboard shortcut listeners so they only mount after auth. */
function KeyboardShortcutsProvider() {
useKeyboardShortcuts();
return <KeyboardShortcutsDialog />;
}
export default function Root() {
const [showTerms, setShowTerms] = useState(false);
@ -98,6 +106,7 @@ export default function Root() {
modalContent={config.interface.termsOfService.modalContent}
/>
)}
<KeyboardShortcutsProvider />
</AssistantsMapContext.Provider>
</FileMapContext.Provider>
</SetConvoProvider>