T
TyphonJS•17mo ago
Gerark

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
TyphonJS (Michael)
TyphonJS (Michael)•17mo ago
There is a menu / context menu components and buttons in svelte-standard
Gerark
GerarkOP•17mo ago
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
Gerark
GerarkOP•17mo ago
No description
Gerark
GerarkOP•17mo ago
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? 😅
TyphonJS (Michael)
TyphonJS (Michael)•17mo ago
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.
Gerark
GerarkOP•17mo ago
yup exactly those are "groups/folders"
TyphonJS (Michael)
TyphonJS (Michael)•17mo ago
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.
Gerark
GerarkOP•17mo ago
Should I go for using a SvelteApplication as a "host" for the context menu anyway?
TyphonJS (Michael)
TyphonJS (Michael)•17mo ago
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
Gerark
GerarkOP•17mo ago
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?
TyphonJS (Michael)
TyphonJS (Michael)•17mo ago
AA uses TJSMenu / non-context menu. Item Piles might use a context menu, but also uses various TJSMenu instances.
Gerark
GerarkOP•17mo ago
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 )
TyphonJS (Michael)
TyphonJS (Michael)•17mo ago
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.
Gerark
GerarkOP•17mo ago
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?
TyphonJS (Michael)
TyphonJS (Michael)•17mo ago
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:
Hooks.on('renderJournalPage', (html, etc, etc) =>
{
const myMenuEl = html.querySelector('.my-context-menu');
if (myMenuEl)
{
myMenuEl.addEventListener('click', (event) =>
{
TJSContextMenu,create({
event,
items: [
{ class: MyContextMenuImpl } // Your Svelte component
}
});
});
}
});
Hooks.on('renderJournalPage', (html, etc, etc) =>
{
const myMenuEl = html.querySelector('.my-context-menu');
if (myMenuEl)
{
myMenuEl.addEventListener('click', (event) =>
{
TJSContextMenu,create({
event,
items: [
{ class: MyContextMenuImpl } // Your Svelte component
}
});
});
}
});
Gerark
GerarkOP•17mo ago
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.
TyphonJS (Michael)
TyphonJS (Michael)•17mo ago
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.
Gerark
GerarkOP•17mo ago
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 🙂
TyphonJS (Michael)
TyphonJS (Michael)•17mo ago
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.
Gerark
GerarkOP•17mo ago
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.
TyphonJS (Michael)
TyphonJS (Michael)•17mo ago
You can do whatever you want with your own components or 3rd party ones, but should give things in TRL a try first.
Gerark
GerarkOP•17mo ago
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.
TyphonJS (Michael)
TyphonJS (Michael)•17mo ago
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.
Gerark
GerarkOP•17mo ago
I see. Thank you! 🙂
TyphonJS (Michael)
TyphonJS (Michael)•16mo ago
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
Want results from more Discord servers?
Add your server