Suggest modals will often have instructions for different ways of selecting a suggestion (e.g. Enter does one thing, Shift+Enter does another, etc.). However, in my very basic implementation of a SuggestModal, holding down a key like Cmd, Shift, etc. while hitting Enter actually never fires either selectSuggestion
nor chooseSuggestion
. Is this expected behavior?
Here’s the implementation for those interested:
import { App, Notice } from "obsidian";
import { SuggestModal } from "./SuggestModal";
import { MyPlugin } from "~/plugin";
type SubtitledItem = {
title: string;
subtitle: string;
};
type SubtitledSelectorModalOptions = {
initialValue?: string;
suggestionsGetter: (query: string) => SubtitledItem[];
actions?: Array<{
id: string;
command: string;
purpose: string;
}>;
placeholder?: string;
};
export class SubtitledSelectorModal extends SuggestModal<SubtitledItem> {
options: SubtitledItem[];
initialValue: NonNullable<SubtitledSelectorModalOptions["initialValue"]>;
suggestionsGetter: SubtitledSelectorModalOptions["suggestionsGetter"];
constructor(
app: App,
plugin: MyPlugin,
{
initialValue = "",
suggestionsGetter,
placeholder = "",
actions = [],
}: SubtitledSelectorModalOptions
) {
super(app, plugin);
this.initialValue = initialValue;
this.setPlaceholder(placeholder);
this.setInstructions(actions);
this.options = [];
this.suggestionsGetter = suggestionsGetter;
}
onOpen() {
super.onOpen();
if (this.initialValue) {
this.inputEl.value = this.initialValue;
this.inputEl.focus();
this.inputEl.dispatchEvent(new InputEvent("input"));
}
}
// Render each suggestion item with title and subtitle
renderSuggestion(item: SubtitledItem, el: HTMLElement) {
const titleEl = el.createEl("div", {
text: item.title,
cls: "suggestion-title",
});
const subtitleEl = el.createEl("small", {
text: item.subtitle,
cls: "suggestion-subtitle",
});
// Optional: Add styling for better visibility
titleEl.style.fontWeight = "bold";
subtitleEl.style.color = "var(--color-base-40)";
}
// Return filtered options based on query
getSuggestions(query: string): SubtitledItem[] {
return this.suggestionsGetter(query);
}
onChooseSuggestion(item: SubtitledItem) {
// ! this will never fire if you're holding down a modifier key
console.log("onChooseSuggestion", item);
}
}
Yes, it’s expected. You need to register keymap event handlers to the modal’s scope.
For example, the quick swticher modal has something like this in its constructor (you can see it in app.js):
this.setInstructions([{
command: "↑↓",
purpose: h1.instructionNavigate()
}, {
command: "↵",
purpose: h1.instructionOpen()
}, {
command: Platform.isMacOS ? "⌘ ↵" : "ctrl ↵",
purpose: h1.instructionOpenInNewTab()
}, {
command: Platform.isMacOS ? "⌘ ⌥ ↵" : "ctrl alt ↵",
purpose: h1.instructionOpenToTheRight()
}, {
command: "shift ↵",
purpose: h1.instructionCreate()
}, {
command: "esc",
purpose: h1.instructionDismiss()
}]);
return this.scope.register(["Shift"], "Enter", (function (e) {
this.selectSuggestion(null, e);
return false;
}
));
this.scope.register(["Mod", "Shift"], "Enter", (function (e) {
this.selectSuggestion(null, e)
return false;
}
));
this.scope.register(null, "Enter", (function (e) {
this.selectActiveSuggestion(e)
return false;
}
))
1 Like
What is app.js? Where do I find it? The code you sent looks chopped up, I suppose app.js is where I find the full version, but where is it
Open Developer tool > Source tab > app.js
1 Like