Embed a DropDown/MenuList made with Svelte
Hello again! 😄
I've been pondering creating a second module for Foundry and a few questions popped up. The idea is to display a Menu/MenuItem using Svelte/TyphonJS when the user clicks on a specific element within a Journal. Now, since the journal is an integral part of Foundry, I'm a bit uncertain about the feasibility of this. Any advice?
My initial idea was to trigger the creation of a SvelteApplication ( EmptyApplicationShell ) with an invisible bkg which opens a MenuList. As soon as the MenuItem is selected it will close the app. By doing so I can work in isolation.
25 Replies
There is a menu / context menu components and buttons in
svelte-standard
what If a want this menu/context menu to be a bit more custom? My idea is to simulate something similar to the one in the Unreal Blueprints
And since I'm explaining this I'm starting to feel more like this is just a normal window/application than a Context menu after all...
is this a rubber duck moment? 😅
There also is a folder component similar to what I suppose the triangle icon in the pict in
svelte-standard
You can add your own custom component to the menu provided in svelte-standard
.yup exactly those are "groups/folders"
Using a dynamic array reducer for all of the menu items / search capability is possible as well.
It'll still be a bit of custom coding to piece this all together, but should be possible with the tooling available. A good project for a custom component.
Should I go for using a SvelteApplication as a "host" for the context menu anyway?
Probably not especially if it's a context menu. SvelteApplication and the application shells are for windowed GUI construction.
I do believe Item Piles and Auto Animations uses the various menus, but probably not for providing a custom component.
Here are the docs for TJSContextMenu... It's data driven and so should be your custom component. A fair amount of the standard components are data driven.
https://typhonjs-fvtt-lib.github.io/api-docs/classes/_standard_application.TJSContextMenu.html
Auto Animations is a windowed gui tho.
or maybe I'm not aware of some context menu. THis is actually a lack of base knowledge from my side. If I create a custom component in svelte can I use it inside a non-svelte application?
AA uses TJSMenu / non-context menu. Item Piles might use a context menu, but also uses various TJSMenu instances.
Would then be possible to trigger a TJSMenu from, let's say, anywhere. It doesn't matter to what the Context Menu is "parented" ( if anything like this is even a concept )
You'll want to use TJSContextMenu for a menu triggered from anywhere. TJSMenu is "parented".
Are you wanting this context menu to be able to be displayed from anywhere in the browser window or a specific app / component?
Here are some examples for TJSContextMenu from an unreleased module I use for testing:
https://github.com/typhonjs-fvtt/better-macros-directory/blob/main/src/view/dir/Folder.svelte
https://github.com/typhonjs-fvtt/better-macros-directory/blob/main/src/view/dir/FolderContent.svelte
It is a replacement for the core macro directory to improve it, but also isn't 100% finished. As mentioned I've been using it for testing TRL features for focus management / keyboard navigation; TJSContextMenu is keyboard / focus navigation aware.
I see that in this case the TJSContextMenu is accepting a focusEl and it's a Constants.appId.
What if I want to show the TJSContextMenu from a journal in Foundry? Let's say I have a specific class named "MyClass" assigned to a <span> element and I use jquery to retrieve all the "MyClass" elements and register to a click event.
Can I pass an htmlElement to the TJSContextMenu focusEl property?
I see that in this case the TJSContextMenu is accepting a focusEl and it's a Constants.appId.In this case it's forwarding through the original focus source. When the context menu closes or an item is selected the original folder is focused again for potential keyboard navigation continuation. This is not something you'd particularly be concerned with in an adhoc GUI you're potentially creating. Foundry in general is not built or takes keyboard accessibility into concern, but I'm baking that into the TRL standard components. All you'd need to do is add a click event and pass the event for the
event
data. Perhaps you can setup a custom TextEditor substitution so you can just input @my-context-menu
into a journal and it will add the necessary HTML to then hookup on the renderJournalPage
or equivalent hook / whatever it is. I suggest using straight DOM API instead of JQuery... Something like:
Psuedocode:
Perhaps you can setup a custom TextEditor substitution so you can just input @my-context-menu into a journal and it will add the necessary HTML to then hookup on the renderJournalPage or equivalent hook / whatever it is. I suggest using straight DOM API instead of JQuery... Something like:Exactly. That's what I'm already doing so I want to show the context menu. I'm not sure if I can use the TJSContextMenu to simulate what I sent in the picture above ( With a search textbox and hierarchical treeview ) but I'll take a look at it no matter what as It can be handy for other case.
TJSContextMenu to simulate what I sent in the picture above ( With a search textbox and hierarchical treeview ) but I'll take a look at it no matter what as It can be handy for other case.That is
MyContextMenuImpl
You can provide your own Svelte component that implements the GUI you desire... Of which a lot of other TRL API can help you implement it.I should look more into what the TRL API provides already when it comes to components. With the first module I mainly did all by myself cause I wanted to learn on creating custom components. Now it's probably time to reuse something already available 🙂
Yeah.. There is some good stuff in there particular around stores and then a lot of the components are data driven so can be externally configured..
Indeed many more potential examples to add to
essential-svelte-esm
and such.. The Better Macros Directory
module does use a derived array reducer populated from Foundry document data and provides a search box to filter / macro results along w/ choosing the user to filter by that is similar to what you are going for in some respect, but also uses the TRL plugin manager, so might not be the easiest to follow without further explanations.
It shows how to recursively use Svelte to render a folder structure w/ items inside. Might be worth installing to play around with the code.
I see that I accidentally left in the local dev setup I use for that repo though so it may work with a few mods. I can clean it up today and make sure it works against the latest TRL when I get it out. Just working on some more type declarations / better API docs presently.Maybe I didn't understand correctly what you meant by a
MyContextMenuImpl
. I see that the TJSContextMenu
is using already an Impl. So I'm not sure if I should stick to it or I should just take inspiration and create my own version.You can do whatever you want with your own components or 3rd party ones, but should give things in TRL a try first.
What I meant was mostly if there was a way to inject a custom impl inside the existing TJSContextMenu in case the customization of each item won't be enough. Seems like I can customize each item so I can have a MenuItem for the Search box, another one for some title, a separator and then the TreeViewItems, probably.
You could do that, but it won't be as effective. You can indeed inject any number of custom components per menu item, but the search index and the dynamic nature of the data being displayed and filtered is better suited to a single component that has full control of the data being displayed.
I see. Thank you! 🙂
I updated the "Better Macros Directory" unreleased module for the latest TRL. It should be installable now. It may be instructive on how to configure a component for using a dynamic reducer that can filter data and have a dynamic display. While the main component is in an application shell instead you could provide it to TJSMenu instead, etc. This is not going to be a 1:1 demo code for your purpose, but a general repo to review on how to do something similar w/ Svelte. Particularly the use of the
<svelte:self>
directive if there are nested folders.
https://github.com/typhonjs-fvtt/better-macros-directory