/* Copyright 2026 Marimo. All rights reserved. */
import { useAtomValue } from "jotai";
import { hotkeysAtom } from "@/core/config/config";
import { type HotkeyAction, NOT_SET } from "@/core/hotkeys/hotkeys";
import { isPlatformMac } from "@/core/hotkeys/shortcuts";
import { cn } from "@/utils/cn";
import { DropdownMenuShortcut } from "../ui/dropdown-menu";
import { Kbd } from "../ui/kbd";
import { Tooltip } from "../ui/tooltip";
export function renderShortcut(shortcut: HotkeyAction, includeName = true) {
return ;
}
const Shortcut: React.FC<{ shortcut: HotkeyAction; includeName?: boolean }> = ({
shortcut,
includeName = true,
}) => {
const hotkeys = useAtomValue(hotkeysAtom);
const hotkey = hotkeys.getHotkey(shortcut);
return (
{includeName && {hotkey.name}}
);
};
export const KeyboardHotkeys: React.FC<{
className?: string;
shortcut: string | typeof NOT_SET;
}> = ({ shortcut, className }) => {
if (shortcut === NOT_SET || shortcut === "") {
return ;
}
const keys = shortcut.split("-");
return (
{keys.map(prettyPrintHotkey).map(([label, symbol]) => {
if (symbol) {
return (
{symbol}
);
}
return {capitalize(label)};
})}
);
};
export function renderMinimalShortcut(shortcut: HotkeyAction) {
return ;
}
export const MinimalShortcut: React.FC<{
className?: string;
shortcut: HotkeyAction;
}> = ({ className, shortcut }) => {
const hotkeys = useAtomValue(hotkeysAtom);
const hotkey = hotkeys.getHotkey(shortcut);
return ;
};
export const MinimalHotkeys: React.FC<{
className?: string;
shortcut: string | typeof NOT_SET;
}> = ({ shortcut, className }) => {
if (shortcut === NOT_SET || shortcut === "") {
return ;
}
const keys = shortcut.split("-");
return (
{keys.map(prettyPrintHotkey).map(([label, symbol]) => {
if (symbol) {
return (
{symbol}
);
}
return {capitalize(label)};
})}
);
};
export function prettyPrintHotkey(
key: string,
): [label: string, symbol?: string] {
const platform = isPlatformMac() ? "mac" : "default";
const lowerKey = key.toLowerCase();
const keyData = KEY_MAPPINGS[key.toLowerCase()];
if (keyData) {
const symbol = keyData.symbols[platform] || keyData.symbols.default;
return [keyData.label, symbol];
}
return [lowerKey];
}
interface KeyData {
symbols: {
mac?: string;
windows?: string;
default: string;
};
label: string;
}
const KEY_MAPPINGS: Record = {
ctrl: {
symbols: { mac: "⌃", default: "Ctrl" },
label: "Control",
},
control: {
symbols: { mac: "⌃", default: "Ctrl" },
label: "Control",
},
shift: {
symbols: { mac: "⇧", default: "Shift" },
label: "Shift",
},
alt: {
symbols: { mac: "⌥", default: "Alt" },
label: "Alt/Option",
},
escape: {
symbols: { mac: "⎋", default: "Esc" },
label: "Escape",
},
arrowup: {
symbols: { default: "↑" },
label: "Arrow Up",
},
arrowdown: {
symbols: { default: "↓" },
label: "Arrow Down",
},
arrowleft: {
symbols: { default: "←" },
label: "Arrow Left",
},
arrowright: {
symbols: { default: "→" },
label: "Arrow Right",
},
backspace: {
symbols: { mac: "⌫", default: "⟵" },
label: "Backspace",
},
tab: {
symbols: { mac: "⇥", default: "⭾" },
label: "Tab",
},
capslock: {
symbols: { default: "⇪" },
label: "Caps Lock",
},
fn: {
symbols: { default: "Fn" },
label: "Fn",
},
cmd: {
symbols: { mac: "⌘", windows: "⊞ Win", default: "Command" },
label: "Command",
},
insert: {
symbols: { default: "Ins" },
label: "Insert",
},
delete: {
symbols: { mac: "⌦", default: "Del" },
label: "Delete",
},
home: {
symbols: { mac: "↖", default: "Home" },
label: "Home",
},
end: {
symbols: { mac: "↘", default: "End" },
label: "End",
},
mod: {
symbols: { mac: "⌘", windows: "⊞ Win", default: "Ctrl" },
label: "Control",
},
};
function capitalize(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1);
}