
Next.jsでCtrl(Command)キと数字キークリックでページ遷移する処理
2024/05/12
2024/05/12
Next.jsでCtrlキー(or Commandキー)を押下している時だけ数字を表示し、数字キーをクリックすると、ページ遷移する処理を実装したいときのサンプルソースです。
以下画像のように、サイドバーにCtrlキー(or Commandキー)を押下時のみ数字が表示され、数字を押下するとその画面に遷移する処理です。
オブジェクト配列定義
オブジェクト配列を用意します。
keyはCtrl(Command)キーと一緒に押したいキー、hrefは遷移先のパスを定義しています。
以下はdata/sidebar.tsxというファイルを用意する想定です。
export const SIDEBAR_OPTIONS = [
{
key: '1',
href: '/house',
label: '住居',
icon: <FaHome />,
},
{
key: '2',
href: '/shopping',
label: '買物',
icon: <FaCartShopping />,
},
{
key: '3',
href: '/cooking',
label: '料理',
icon: <GiCookingPot />,
},
{
key: '4',
href: '/childcare',
label: '育児',
icon: <MdChildCare />,
},
{
key: '5',
href: '/money',
label: 'お金',
icon: <FaMoneyCheckAlt />,
},
{
key: '6',
href: '/gift',
label: 'ギフト',
icon: <FaGift />,
},
];数字キー押下時の共通処理
キー押下時に画面遷移する、共通処理を作成します。
以下はhooks/use-keydown.tsxというファイルを作成する想定です。
event.metaKeyでMacのCommandキーを指定しています。
event.preventDefault();部分でブラウザが持っているショートカットキーのイベントをキャンセルしています。
import { useEffect } from 'react';
import { SIDEBAR_OPTIONS } from '@/data/sidebar';
const useKeydown = () => {
useEffect(() => {
/**
* キーボードのキーが押されたときの処理
* @param event
*/
const handleKeyDown = (event: KeyboardEvent) => {
// CtrlキーまたはCmdキーが押されているとき
if (event.ctrlKey || event.metaKey) {
// 押されたキーの番号に対応するページを取得
const page = SIDEBAR_OPTIONS.find((option) => option.key === event.key)?.href;
if (page) {
// デフォルトのイベントをキャンセル
event.preventDefault();
// ページ遷移
const pageLink: HTMLElement | null = document.querySelector(
`a[href="${page}"]`
);
if (pageLink) {
pageLink.click();
}
}
}
};
// イベントリスナーを追加
window.addEventListener('keydown', handleKeyDown);
return () => {
window.removeEventListener('keydown', handleKeyDown);
};
}, []);
};
export default useKeydown;Ctrlキー(Commandキー)押下時の処理
キーが押下されているときだけ数字が表示される実装をします。
components/sidebar.tsxというファイルを作成する想定です。
useKeydown();が前述の手順で作成した共通処理を使用している部分です。
'use client';
import Link from 'next/link';
import { useEffect, useState } from 'react';
import { SIDEBAR_OPTIONS } from '@/data/sidebar';
import useKeydown from '@/hooks/use-keydown';
import { useSidebar } from '@/hooks/use-sidebar';
const Sidebar = () => {
const { sidebarOption } = useSidebar();
// キーボードのキーが押されたときの共通処理
useKeydown();
// CtrlキーまたはCmdキーが押されているかどうかの状態
const [isCtrlOrCmdPressed, setIsCtrlOrCmdPressed] = useState(false);
useEffect(() => {
/**
* キーボードのキーが押されたときの処理
* @param event
*/
const handleKeyDown = (event: KeyboardEvent) => {
if (event.ctrlKey || event.metaKey) {
setIsCtrlOrCmdPressed(true);
}
};
/**
* キーボードのキーが離されたときの処理
* @param event
*/
const handleKeyUp = (event: KeyboardEvent) => {
if (!event.ctrlKey || !event.metaKey) {
setIsCtrlOrCmdPressed(false);
}
};
// イベントリスナーを追加
window.addEventListener('keydown', handleKeyDown);
window.addEventListener('keyup', handleKeyUp);
return () => {
window.removeEventListener('keydown', handleKeyDown);
window.removeEventListener('keyup', handleKeyUp);
};
}, []);
return (
<aside className="relative hidden w-48 bg-sidebar py-4 sm:block">
<h3 className="mb-5 px-4 py-1">
<Link href="/">LifeHub Links</Link>
</h3>
{SIDEBAR_OPTIONS.map((option) => (
<Link
key={option.href}
href={option.href}
className={`block w-full px-4 py-2 duration-200 hover:bg-gray-600 ${
sidebarOption === option ? 'bg-gray-600' : ''
}`}
>
<div className="flex justify-between">
<div className="flex items-center gap-1">
{option.icon}
<p>{option.label}</p>
</div>
{isCtrlOrCmdPressed && <div>{option.key}</div>}
</div>
</Link>
))}
<small className="absolute bottom-2 left-4">© tukky 2024</small>
</aside>
);
};
export default Sidebar;参考資料
以下の自作サイトで実装しています。
LifeHubLlinks