Repository: motion-canvas/motion-canvas
File: packages/ui/src/contexts/shortcuts.tsx (TypeScript)

Code before:
import {ComponentChildren, createContext} from 'preact';
import {useContext, useState} from 'preact/hooks';

export type Shortcut = {
  key: string;
  action: string;
  isGlobal?: boolean;
};

export type ShortcutModules = 'global' | 'timeline' | 'none';
type ShortcutsByModule = Record<ShortcutModules, Shortcut[]>;
type ShortcutsState = {
  currentModule: ShortcutModules;
  shortcuts: ShortcutsByModule;
  setCurrentModule?: (module: ShortcutModules) => void;
};

const initialshortcuts: ShortcutsByModule = {
  global: [
    {key: 'Space', action: 'Toggle playback', isGlobal: true},
    {key: '←', action: 'Previous frame', isGlobal: true},
    {key: '→', action: 'Next frame', isGlobal: true},
    {key: 'Shift + ←', action: 'Reset to first frame', isGlobal: true},
    {key: 'Shift + →', action: 'Seek to last frame', isGlobal: true},
    {key: 'm', action: 'Toggle audio', isGlobal: true},
    {key: 'l', action: 'Toggle loop', isGlobal: true},
  ],
  timeline: [{key: 'f', action: 'Focus Playhead'}],
  none: [],
};

const ShortcutsContext = createContext<ShortcutsState>({
  currentModule: 'none',
  shortcuts: initialshortcuts,
});

export function ShortcutsProvider({children}: {children: ComponentChildren}) {
  const [currentModule, setCurrentModule] = useState<ShortcutModules>('none');

  return (
    <ShortcutsContext.Provider
      value={{currentModule, setCurrentModule, shortcuts: initialshortcuts}}
    >
      {children}
    </ShortcutsContext.Provider>
  );

Review comment (suggestion):
We should use ligatures since the editor font supports them:
```suggestion
    {key: '<-', action: 'Previous frame', isGlobal: true},
```
This will make sure that the arrow width matches the rest of the font.

Code after:
import {ComponentChildren, createContext} from 'preact';
import {useContext, useState} from 'preact/hooks';

export type Shortcut = {
  key: string;
  action: string;
};

export type ShortcutModules = 'global' | 'timeline' | 'viewport' | 'none';
type ShortcutsByModule = Record<ShortcutModules, Shortcut[]>;
type ShortcutsState = {
  currentModule: ShortcutModules;
  shortcuts: ShortcutsByModule;
  setCurrentModule?: (module: ShortcutModules) => void;
};

const InitialShortcuts: ShortcutsByModule = {
  global: [
    {key: 'Space', action: 'Toggle playback'},
    {key: '<-', action: 'Previous frame'},
    {key: '->', action: 'Next frame'},
    {key: 'Shift + <-', action: 'Reset to first frame'},
    {key: 'Shift + ->', action: 'Seek to last frame'},
    {key: 'M', action: 'Toggle audio'},
    {key: 'L', action: 'Toggle loop'},
  ],
  viewport: [
    {key: '0', action: 'Reset zoom'},
    {key: '=', action: 'Zoom in'},
    {key: '-', action: 'Zoom out'},
    {key: "'", action: 'Toggle grid'},
  ],
  timeline: [{key: 'F', action: 'Focus playhead'}],
  none: [],
};

const ShortcutsContext = createContext<ShortcutsState>({
  currentModule: 'none',
  shortcuts: InitialShortcuts,
});

export function ShortcutsProvider({children}: {children: ComponentChildren}) {
  const [currentModule, setCurrentModule] = useState<ShortcutModules>('none');

  return (
    <ShortcutsContext.Provider