Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/web/src/components/chat/ChatComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ import {
} from "../../lib/attachmentUploadState";
import { isCommandPaletteOpen } from "../../commandPaletteBus";
import { getTerminalFocusOwner } from "../../lib/terminalFocus";
import { resolveShortcutCommand } from "../../keybindings";
import { resolveShortcutCommand, shortcutLabelForCommand } from "../../keybindings";
import {
type TerminalContextDraft,
type TerminalContextSelection,
Expand Down Expand Up @@ -3193,6 +3193,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
<ComposerCommandMenuLayer anchor={composerMenuAnchor}>
<ComposerStashMenu
entries={stashQueue}
stashShortcutLabel={shortcutLabelForCommand(keybindings, "composer.stash")}
onRestore={restoreStashEntry}
onDelete={deleteStashEntry}
onClose={() => setIsStashMenuOpen(false)}
Expand Down
18 changes: 18 additions & 0 deletions apps/web/src/components/chat/ComposerStashMenu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ describe("ComposerStashMenu", () => {
const markup = renderToStaticMarkup(
<ComposerStashMenu
entries={[]}
stashShortcutLabel="Ctrl+S"
onRestore={() => {}}
onDelete={() => {}}
onClose={() => {}}
Expand All @@ -20,6 +21,22 @@ describe("ComposerStashMenu", () => {
expect(markup).toContain('aria-label="Close stash"');
expect(markup).not.toContain("dropdown-glass");
expect(markup).not.toContain("Stashed prompts");
expect(markup).toContain("Press Ctrl+S with a prompt in the composer to stash it.");
});

it("does not advertise a shortcut when stash is unbound", () => {
const markup = renderToStaticMarkup(
<ComposerStashMenu
entries={[]}
stashShortcutLabel={null}
onRestore={() => {}}
onDelete={() => {}}
onClose={() => {}}
/>,
);

expect(markup).toContain("Nothing stashed yet.");
expect(markup).not.toContain("Press");
});

it("shows saved image thumbnails and incomplete image states", () => {
Expand Down Expand Up @@ -53,6 +70,7 @@ describe("ComposerStashMenu", () => {
pendingImageCount: 1,
},
]}
stashShortcutLabel="Ctrl+S"
onRestore={() => {}}
onDelete={() => {}}
onClose={() => {}}
Expand Down
8 changes: 6 additions & 2 deletions apps/web/src/components/chat/ComposerStashMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ function stashEntrySnippet(entry: PromptStashEntry): string {
*/
export const ComposerStashMenu = memo(function ComposerStashMenu(props: {
entries: ReadonlyArray<PromptStashEntry>;
stashShortcutLabel: string | null;
onRestore: (entry: PromptStashEntry) => void;
onDelete: (entry: PromptStashEntry) => void;
onClose: () => void;
}) {
const { entries, onRestore, onDelete, onClose } = props;
const { entries, stashShortcutLabel, onRestore, onDelete, onClose } = props;
const drawerRef = useRef<HTMLDivElement>(null);
const [highlightedId, setHighlightedId] = useState<string | null>(entries[0]?.id ?? null);

Expand Down Expand Up @@ -128,7 +129,10 @@ export const ComposerStashMenu = memo(function ComposerStashMenu(props: {
<CommandGroup>
{entries.length === 0 ? (
<p className="px-3 py-1.5 text-secondary-label text-xs">
Nothing stashed yet. Press ⌘S with a prompt in the composer to stash it.
Nothing stashed yet.
{stashShortcutLabel
? ` Press ${stashShortcutLabel} with a prompt in the composer to stash it.`
: null}
</p>
) : (
entries.map((entry) => (
Expand Down
Loading