Skip to content

feat: add keyboard shortcut hints to toolbar #774

Open
Junaid-Kn wants to merge 4 commits intoOpenCut-app:mainfrom
Junaid-Kn:main
Open

feat: add keyboard shortcut hints to toolbar #774
Junaid-Kn wants to merge 4 commits intoOpenCut-app:mainfrom
Junaid-Kn:main

Conversation

@Junaid-Kn
Copy link
Copy Markdown

@Junaid-Kn Junaid-Kn commented Apr 19, 2026

Summary

This PR implements #732.

It adds keyboard shortcut indicators to tooltips across the relevant UI components using <kbd /> tags for better accessibility and discoverability.

Changes Made

  • Added shortcut key display inside tooltips using <kbd /> components
  • Updated tooltip UI to visually reflect available keyboard shortcuts
  • Ensured consistent styling for shortcut key badges across the app

Why this change?

This improves usability by making keyboard shortcuts more visible and easier to learn, especially for power users.

Related Issue

Closes #732

Notes

No breaking changes. UI-only improvement.

Summary by CodeRabbit

  • New Features
    • Editor toolbar buttons now display keyboard shortcuts in interactive tooltips when users hover over them
    • Play/pause control and timeline toolbar buttons show their associated keyboard shortcuts for quick reference during editing
    • Additional toolbar actions throughout the timeline editor now display keyboard shortcuts for improved discoverability
    • Enhanced editor usability with integrated shortcut information visible across the interface

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 19, 2026

@Junaid-Kn is attempting to deploy a commit to the OpenCut OSS Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 19, 2026

📝 Walkthrough

Walkthrough

This PR adds visual keyboard shortcut hints to toolbar buttons by introducing a new Kbd component, integrating the useKeyboardShortcutsHelp hook to fetch shortcut metadata, and displaying shortcut descriptions with key combinations in tooltips across the preview and timeline toolbars.

Changes

Cohort / File(s) Summary
Keyboard shortcut UI component
apps/web/src/components/ui/kbd.tsx
New client-side React component that renders styled <kbd> elements for displaying keyboard keys with fixed utility classes (rounded, bg-muted, padding, text-xs, font-mono, border).
Toolbar shortcut tooltips
apps/web/src/components/editor/panels/preview/toolbar.tsx, apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx
Enhanced toolbar buttons with keyboard shortcut metadata via useKeyboardShortcutsHelp, wrapping buttons in Tooltip components to display shortcut descriptions and keys. Timeline toolbar refactored from hardcoded button instances to a configuration-driven loop approach. Extended ToolbarButton tooltip prop type from string to React.ReactNode | string to support JSX tooltips.
Dependencies
package.json
Added opencut-wasm dependency (^0.2.5) to root package.json.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • #433: Modifies keyboard-shortcuts UI/hooks that this PR depends on for shortcut metadata retrieval
  • #342: Both PRs modify keyboard shortcut display/handling and introduce/use the Kbd component and keyboard-shortcuts-help utilities
  • #284: Introduces the keyboard-shortcuts system that this PR extends with UI integration in toolbar components

Suggested reviewers

  • mazeincoding

Poem

🐰 With whiskers twitched and keys displayed,
The shortcuts dance in tooltip shade,
Where Kbd frames each secret call,
And toolbar hints reveal them all! ⌨️

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes an out-of-scope change: adding the opencut-wasm dependency to package.json is unrelated to the keyboard shortcut hints feature described in issue #732. Remove the opencut-wasm dependency addition from package.json or clarify its necessity and open a separate issue if it's required for keyboard shortcuts functionality.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description provides a clear summary, changes made, rationale, and notes no breaking changes; however, it doesn't follow the repository's template structure which requires feature discussion via issues first. The description content is complete but may conflict with the repository policy stated in the template. Verify that issue #732 was discussed and approved before proceeding.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add keyboard shortcut hints to toolbar' directly describes the main change—adding keyboard shortcut indicators to tooltips across toolbar components.
Linked Issues check ✅ Passed The PR successfully implements issue #732 by adding keyboard shortcut indicators to toolbar buttons via components in tooltips, matching the expected behavior of displaying shortcut hints on hover.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx (1)

99-104: Memoize shortcutMap and prefer typed lookup.

shortcutMap is rebuilt with Object.fromEntries on every render, and typing is lost (Record<string, KeyboardShortcut> at best). Consider useMemo keyed on shortcuts, and use a Map<TActionWithOptionalArgs, KeyboardShortcut> so lookups are action-typed. Also the trailing tab + blank lines on 102-104 appear to be stray whitespace.

-	const { shortcuts } = useKeyboardShortcutsHelp();
-	const shortcutMap = Object.fromEntries(
-	shortcuts.map(s => [s.action, s])
-	);	
-
-
+	const { shortcuts } = useKeyboardShortcutsHelp();
+	const shortcutMap = useMemo(
+		() => new Map(shortcuts.map((s) => [s.action, s] as const)),
+		[shortcuts],
+	);

Then callers become shortcutMap.get("split")?.keys?.[0], etc.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx` around
lines 99 - 104, The current code recreates shortcutMap on every render and loses
typing; wrap the conversion in useMemo keyed on shortcuts and change the
structure from a plain object to a typed Map so lookups are action-typed (e.g.
Map<TActionWithOptionalArgs, KeyboardShortcut>); update all callers to use
shortcutMap.get("split")?.keys?.[0] (or the appropriate action literal) and
remove the stray trailing tab/blank lines after the shortcutMap declaration in
timeline-toolbar.tsx; keep the source of shortcuts via
useKeyboardShortcutsHelp() unchanged.
apps/web/src/components/ui/kbd.tsx (1)

1-19: Minor: unnecessary "use client" and stray whitespace.

Kbd is a purely presentational component with no hooks or interactivity, so the "use client" directive isn't required and pulls it into the client bundle needlessly. Also export const Kbd = ( (line 8) has a double space, and the empty line inside the destructure (line 12) looks unintentional.

♻️ Proposed tidy-up
-"use client"
 import * as React from "react";
 import { cn } from "@/utils/ui";
 type KbdProps = {
-    children: React.ReactNode;
-    className?: string;
-}
-export const Kbd =  (
-    { 
-        children,
-        className
-
-    }: KbdProps) => {
+    children: React.ReactNode;
+    className?: string;
+};
+export const Kbd = ({ children, className }: KbdProps) => {
   return (
     <kbd className={cn("rounded bg-muted px-1.5 py-0.5 text-xs font-mono border", className)}>
       {children}
     </kbd>
   );
-}
+};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/components/ui/kbd.tsx` around lines 1 - 19, Remove the
unnecessary "use client" directive and tidy up whitespace in the Kbd component:
delete the top-line "use client", collapse the extra space in the export
declaration for export const Kbd, and remove the empty line inside the
destructured props. Locate the Kbd component and its type KbdProps (and the cn
import) to make these edits so the presentational component remains server-safe
and formatting is consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/components/editor/panels/preview/toolbar.tsx`:
- Around line 144-166: Replace the incorrect prop name on TooltipProvider:
change the prop currently named duration to delayDuration and set it to 500
(i.e., TooltipProvider delayDuration={500}) so Radix's hover delay is applied;
additionally, prevent rendering an empty keyboard badge by conditionally
rendering the <Kbd> element only when togglePlay?.keys exists and has length
(e.g., check togglePlay?.keys?.length > 0) inside the TooltipContent where
togglePlay?.description and keys are shown—this touches the TooltipProvider,
TooltipContent and Kbd usages around invokeAction("toggle-play") and the
togglePlay references.

In `@apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx`:
- Around line 255-262: The list rendered from Object.values(ToolTipShortcuts) is
missing a stable React key; update the mapping to iterate with
Object.entries(ToolTipShortcuts) (or retain values but obtain the unique action
key) and pass a key prop to each ToolbarButton using the unique action
identifier (e.g., the ToolTipShortcuts entry key or action name) so that
ToolbarButton receives key={uniqueKey} along with the existing props (icon,
disabled, tooltip, onClick).

In `@package.json`:
- Around line 30-32: The root package.json currently declares "opencut-wasm":
"^0.2.5" which conflicts with the apps/web/package.json version "^0.2.6" and
will shadow the app's version in a Bun monorepo; remove the "opencut-wasm" entry
from the root package.json so the app-level dependency in apps/web/package.json
(used by files like toolbar.tsx and various timeline managers/hooks) is the
single source of truth, or if the root truly needs it, update both package.json
files to the same version (^0.2.6) and add a short comment in the root
explaining why root requires the dependency; after changing package.json, run
your install to update the lockfile.

---

Nitpick comments:
In `@apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx`:
- Around line 99-104: The current code recreates shortcutMap on every render and
loses typing; wrap the conversion in useMemo keyed on shortcuts and change the
structure from a plain object to a typed Map so lookups are action-typed (e.g.
Map<TActionWithOptionalArgs, KeyboardShortcut>); update all callers to use
shortcutMap.get("split")?.keys?.[0] (or the appropriate action literal) and
remove the stray trailing tab/blank lines after the shortcutMap declaration in
timeline-toolbar.tsx; keep the source of shortcuts via
useKeyboardShortcutsHelp() unchanged.

In `@apps/web/src/components/ui/kbd.tsx`:
- Around line 1-19: Remove the unnecessary "use client" directive and tidy up
whitespace in the Kbd component: delete the top-line "use client", collapse the
extra space in the export declaration for export const Kbd, and remove the empty
line inside the destructured props. Locate the Kbd component and its type
KbdProps (and the cn import) to make these edits so the presentational component
remains server-safe and formatting is consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4fe5a024-aa6f-413d-90c9-790ccba5ac5d

📥 Commits

Reviewing files that changed from the base of the PR and between 8bdc894 and 8d81b78.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • apps/web/src/components/editor/panels/preview/toolbar.tsx
  • apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx
  • apps/web/src/components/ui/kbd.tsx
  • package.json

Comment on lines 144 to +166
return (
<Button
variant="text"
size="icon"
onClick={() => invokeAction("toggle-play")}
>
<HugeiconsIcon icon={isPlaying ? PauseIcon : PlayIcon} />
</Button>
<TooltipProvider duration={500}>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="text"
size="icon"
onClick={() => invokeAction("toggle-play")}
>
<HugeiconsIcon icon={isPlaying ? PauseIcon : PlayIcon} />
</Button>
</TooltipTrigger>

<TooltipContent className="flex items-center gap-2">
<span> {togglePlay?.description} </span>
<div className="flex gap-1">
<Kbd>
{togglePlay?.keys?.join(" / ")}
</Kbd>
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

What is the correct prop name for configuring the hover delay on Radix UI TooltipProvider?

💡 Result:

The correct prop name for configuring the hover delay on Radix UI TooltipProvider is delayDuration. It controls the duration (in milliseconds) from when the mouse enters a tooltip trigger until the tooltip opens, with a default value of 700ms. This is confirmed in the official Radix Primitives documentation, which lists delayDuration under TooltipProvider props. Examples show usage like <Tooltip.Provider delayDuration={200}>. The same prop is available on Tooltip.Root for per-tooltip overrides, and skipDelayDuration (default 300ms) handles delays when moving between triggers.

Citations:


🏁 Script executed:

# First, locate the toolbar.tsx file
find . -name "toolbar.tsx" -path "*/preview/*" 2>/dev/null

Repository: OpenCut-app/OpenCut

Length of output: 122


🏁 Script executed:

# Read the specific lines from toolbar.tsx to confirm the code
if [ -f "apps/web/src/components/editor/panels/preview/toolbar.tsx" ]; then
  sed -n '144,166p' "apps/web/src/components/editor/panels/preview/toolbar.tsx" | cat -n
fi

Repository: OpenCut-app/OpenCut

Length of output: 831


🏁 Script executed:

# Check timeline-toolbar.tsx for the delayDuration usage references
if [ -f "apps/web/src/components/editor/panels/timeline-toolbar.tsx" ]; then
  sed -n '250,260p' "apps/web/src/components/editor/panels/timeline-toolbar.tsx" | cat -n
  echo "---"
  sed -n '345,355p' "apps/web/src/components/editor/panels/timeline-toolbar.tsx" | cat -n
fi

Repository: OpenCut-app/OpenCut

Length of output: 45


🏁 Script executed:

# Search for togglePlay definition in toolbar.tsx to understand its type
if [ -f "apps/web/src/components/editor/panels/preview/toolbar.tsx" ]; then
  head -150 "apps/web/src/components/editor/panels/preview/toolbar.tsx" | grep -n "togglePlay" | head -10
fi

Repository: OpenCut-app/OpenCut

Length of output: 102


🏁 Script executed:

# Get more context around togglePlay definition
if [ -f "apps/web/src/components/editor/panels/preview/toolbar.tsx" ]; then
  sed -n '135,150p' "apps/web/src/components/editor/panels/preview/toolbar.tsx" | cat -n
fi

Repository: OpenCut-app/OpenCut

Length of output: 565


🏁 Script executed:

# Search for timeline-toolbar.tsx in the editor panels directory
find . -name "timeline-toolbar.tsx" 2>/dev/null | head -5

Repository: OpenCut-app/OpenCut

Length of output: 132


🏁 Script executed:

# Check the imports at the top of toolbar.tsx to verify TooltipProvider source
if [ -f "apps/web/src/components/editor/panels/preview/toolbar.tsx" ]; then
  head -30 "apps/web/src/components/editor/panels/preview/toolbar.tsx" | cat -n
fi

Repository: OpenCut-app/OpenCut

Length of output: 1356


🏁 Script executed:

# Check the actual usage in timeline-toolbar.tsx at lines 254 and 348
if [ -f "apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx" ]; then
  sed -n '250,260p' "apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx" | cat -n
  echo "---"
  sed -n '344,354p' "apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx" | cat -n
fi

Repository: OpenCut-app/OpenCut

Length of output: 850


🏁 Script executed:

# Search for all TooltipProvider usages in the codebase to see the pattern
rg "TooltipProvider" -A 2 -B 1 apps/web/src/components/

Repository: OpenCut-app/OpenCut

Length of output: 6671


Change duration to delayDuration on TooltipProvider.

Radix UI's TooltipProvider accepts delayDuration, not duration. The prop is silently ignored, so the intended 500ms hover delay has no effect. This file is the only one using the incorrect prop name; all other usages in the codebase (timeline-toolbar.tsx, properties/index.tsx) correctly use delayDuration={500}.

Also, guard the <Kbd> element with a conditional to avoid rendering empty badges when togglePlay?.keys is undefined or empty:

Proposed fix
-		<TooltipProvider duration={500}>
+		<TooltipProvider delayDuration={500}>
 			<Tooltip>
-        <TooltipTrigger asChild>
-          <Button
-            variant="text"
-            size="icon"
-            onClick={() => invokeAction("toggle-play")}
-          >
-            <HugeiconsIcon icon={isPlaying ? PauseIcon : PlayIcon} />
-          </Button>
-        </TooltipTrigger>
-
-        <TooltipContent className="flex items-center gap-2">
-			<span> {togglePlay?.description} </span>
-			<div className="flex gap-1">
-				<Kbd>
-					{togglePlay?.keys?.join(" / ")}
-				</Kbd>
-			</div>
-		</TooltipContent>
-      </Tooltip>
+				<TooltipTrigger asChild>
+					<Button
+						variant="text"
+						size="icon"
+						onClick={() => invokeAction("toggle-play")}
+					>
+						<HugeiconsIcon icon={isPlaying ? PauseIcon : PlayIcon} />
+					</Button>
+				</TooltipTrigger>
+				<TooltipContent className="flex items-center gap-2">
+					<span>{togglePlay?.description}</span>
+					{togglePlay?.keys?.length ? (
+						<Kbd>{togglePlay.keys.join(" / ")}</Kbd>
+					) : null}
+				</TooltipContent>
+			</Tooltip>
 		</TooltipProvider>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return (
<Button
variant="text"
size="icon"
onClick={() => invokeAction("toggle-play")}
>
<HugeiconsIcon icon={isPlaying ? PauseIcon : PlayIcon} />
</Button>
<TooltipProvider duration={500}>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="text"
size="icon"
onClick={() => invokeAction("toggle-play")}
>
<HugeiconsIcon icon={isPlaying ? PauseIcon : PlayIcon} />
</Button>
</TooltipTrigger>
<TooltipContent className="flex items-center gap-2">
<span> {togglePlay?.description} </span>
<div className="flex gap-1">
<Kbd>
{togglePlay?.keys?.join(" / ")}
</Kbd>
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
return (
<TooltipProvider delayDuration={500}>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="text"
size="icon"
onClick={() => invokeAction("toggle-play")}
>
<HugeiconsIcon icon={isPlaying ? PauseIcon : PlayIcon} />
</Button>
</TooltipTrigger>
<TooltipContent className="flex items-center gap-2">
<span>{togglePlay?.description}</span>
{togglePlay?.keys?.length ? (
<Kbd>{togglePlay.keys.join(" / ")}</Kbd>
) : null}
</TooltipContent>
</Tooltip>
</TooltipProvider>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/components/editor/panels/preview/toolbar.tsx` around lines 144 -
166, Replace the incorrect prop name on TooltipProvider: change the prop
currently named duration to delayDuration and set it to 500 (i.e.,
TooltipProvider delayDuration={500}) so Radix's hover delay is applied;
additionally, prevent rendering an empty keyboard badge by conditionally
rendering the <Kbd> element only when togglePlay?.keys exists and has length
(e.g., check togglePlay?.keys?.length > 0) inside the TooltipContent where
togglePlay?.description and keys are shown—this touches the TooltipProvider,
TooltipContent and Kbd usages around invokeAction("toggle-play") and the
togglePlay references.

Comment on lines +255 to +262
{Object.values(ToolTipShortcuts).map((item)=> (
<ToolbarButton
icon={item.icon}
disabled={item.disabled}
tooltip={item.tooltip}
onClick={item.onClick}
/>
}
tooltip={sourceAudioLabel}
disabled={!canToggleSelectedSourceAudio}
onClick={({ event }) =>
handleAction({ action: "toggle-source-audio", event })
}
/>

<ToolbarButton
icon={<HugeiconsIcon icon={Copy01Icon} />}
tooltip="Duplicate element"
onClick={({ event }) =>
handleAction({ action: "duplicate-selected", event })
}
/>

<ToolbarButton
icon={<HugeiconsIcon icon={SnowIcon} />}
tooltip="Freeze frame (coming soon)"
disabled={true}
onClick={({ event: _event }) => {}}
/>

<ToolbarButton
icon={<HugeiconsIcon icon={Delete02Icon} />}
tooltip="Delete element"
onClick={({ event }) =>
handleAction({ action: "delete-selected", event })
}
/>
))}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing key prop in iterable.

Biome flags this correctly: React requires a stable key when rendering a list from .map(). Since each entry in ToolTipShortcuts has a unique action key, iterate with Object.entries and use the key.

🔑 Proposed fix
-				{Object.values(ToolTipShortcuts).map((item)=> (
-					<ToolbarButton
-						icon={item.icon}
-						disabled={item.disabled}
-						tooltip={item.tooltip}
-						onClick={item.onClick}
-						/>
-				))}
+				{Object.entries(ToolTipShortcuts).map(([key, item]) => (
+					<ToolbarButton
+						key={key}
+						icon={item.icon}
+						disabled={item.disabled}
+						tooltip={item.tooltip}
+						onClick={item.onClick}
+					/>
+				))}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{Object.values(ToolTipShortcuts).map((item)=> (
<ToolbarButton
icon={item.icon}
disabled={item.disabled}
tooltip={item.tooltip}
onClick={item.onClick}
/>
}
tooltip={sourceAudioLabel}
disabled={!canToggleSelectedSourceAudio}
onClick={({ event }) =>
handleAction({ action: "toggle-source-audio", event })
}
/>
<ToolbarButton
icon={<HugeiconsIcon icon={Copy01Icon} />}
tooltip="Duplicate element"
onClick={({ event }) =>
handleAction({ action: "duplicate-selected", event })
}
/>
<ToolbarButton
icon={<HugeiconsIcon icon={SnowIcon} />}
tooltip="Freeze frame (coming soon)"
disabled={true}
onClick={({ event: _event }) => {}}
/>
<ToolbarButton
icon={<HugeiconsIcon icon={Delete02Icon} />}
tooltip="Delete element"
onClick={({ event }) =>
handleAction({ action: "delete-selected", event })
}
/>
))}
{Object.entries(ToolTipShortcuts).map(([key, item]) => (
<ToolbarButton
key={key}
icon={item.icon}
disabled={item.disabled}
tooltip={item.tooltip}
onClick={item.onClick}
/>
))}
🧰 Tools
🪛 Biome (2.4.11)

[error] 256-261: Missing key property for this element in iterable.

(lint/correctness/useJsxKeyInIterable)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx` around
lines 255 - 262, The list rendered from Object.values(ToolTipShortcuts) is
missing a stable React key; update the mapping to iterate with
Object.entries(ToolTipShortcuts) (or retain values but obtain the unique action
key) and pass a key prop to each ToolbarButton using the unique action
identifier (e.g., the ToolTipShortcuts entry key or action name) so that
ToolbarButton receives key={uniqueKey} along with the existing props (icon,
disabled, tooltip, onClick).

Comment thread package.json
Comment on lines +30 to 32
"next": "^16.1.3",
"opencut-wasm": "^0.2.5"
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm where opencut-wasm is actually consumed and whether apps/web already declares it.
rg -nP "from ['\"]opencut-wasm['\"]" --type=ts --type=tsx
fd -t f package.json | xargs -I{} sh -c 'echo "=== {} ==="; jq ".dependencies[\"opencut-wasm\"] // empty" {}'

Repository: OpenCut-app/OpenCut

Length of output: 176


🏁 Script executed:

# Search for any import/require of opencut-wasm with broader patterns
rg -i "opencut-wasm" --type=js --type=ts
# Also check if the specific file exists
find . -path "*preview/toolbar*" -type f
# Check the workspace configuration
fd -t f "package.json|yarn.lock|bun.lock|pnpm-workspace.yaml" | head -5

Repository: OpenCut-app/OpenCut

Length of output: 3505


🏁 Script executed:

# Check bun workspace configuration
cat package.json | jq '.workspaces'
# Check if root has direct dependencies that would need opencut-wasm
rg "opencut-wasm" package.json apps/package.json 2>/dev/null | head -20
# Look at bun.lock to see how versions are resolved
head -100 bun.lock | grep -A5 -B5 "opencut-wasm" || echo "Pattern not in first 100 lines; searching entire lock file..."
rg "opencut-wasm" bun.lock | head -20

Repository: OpenCut-app/OpenCut

Length of output: 1004


Version conflict — opencut-wasm appears in both root and app package.json with different versions.

This PR is scoped to keyboard-shortcut tooltip hints, but it adds opencut-wasm to the root package.json with version ^0.2.5. However, opencut-wasm is already declared in apps/web/package.json with version ^0.2.6, and all 30+ imports are confined to apps/web (e.g., formatTimecode in toolbar.tsx, timeline managers, hooks, etc.). In a Bun monorepo, the root version will shadow the higher app-level version, causing the lower version (0.2.5) to resolve instead of 0.2.6.

Remove this dependency from the root package.json, or if there's a legitimate reason for it there, align both declarations to the same version and document why root needs it.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` around lines 30 - 32, The root package.json currently declares
"opencut-wasm": "^0.2.5" which conflicts with the apps/web/package.json version
"^0.2.6" and will shadow the app's version in a Bun monorepo; remove the
"opencut-wasm" entry from the root package.json so the app-level dependency in
apps/web/package.json (used by files like toolbar.tsx and various timeline
managers/hooks) is the single source of truth, or if the root truly needs it,
update both package.json files to the same version (^0.2.6) and add a short
comment in the root explaining why root requires the dependency; after changing
package.json, run your install to update the lockfile.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[UX] Add keyboard shortcut hints to toolbar buttons

1 participant