T
TyphonJS•2y ago
Faey

Sidebar Tab Application

I have, after diving deep into the Foundry Code, figured out how to actually add new Sidebar tabs. it's a two step process of sorts. You need to add the actual button to reveal the Sidebar Tab, as well as actually provide the SidebarTab Application. Only ways to add the Button is either wrap the getData() method on Sidebar, if you already use libWrapper this is the cleaner method. Alternatively you can just sort of inject the HTML for the button with jQuery. The Tab itself is actually the easier part. Because the canonical way is already just
ui.sidebar.tabs[this.tabName] = this;
ui.sidebar.tabs[this.tabName] = this;
at the end of the SidebarTab constructor. And then the Sidebar takes care of rendering and stuff. However, the SidebarTab has a very specific api that the Sidebar Application expects to exist. As such, the Application templates in TRL are currently insufficient to just make new SidebarTabs on their own
37 Replies
Faey
FaeyOP•2y ago
As long as you add your SidebarTab class to CONFIG.ui at literally any point before the setup hook is called, it will get treated like any other SidebarTab, except for the missing button
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
There isn't too much logic in SidebarTab, so you can implement what is necessary as a child class to SvelteApplication. There is no ETA currently when I might provide a ready-made solution. Perhaps any effort on your side could turn into said ready-made solution. 😄 There is a mechanism to switch the element root in SvelteApplication. This would come in handy when implementing the docked vs popout modes. You can use ApplicationShell when in popout mode and a docked component otherwise. An example of this is in my unreleased "Better Macro Directory" demo module. It switches between ApplicationShell / TJSApplicationShell for testing this mechanism though I haven't finished the ApplicationShell / light mode styles. This is done for a dark mode / native app look and feel test. https://github.com/typhonjs-fvtt/better-macros-directory/blob/main/src/view/BMDAppShell.svelte#L20 https://github.com/typhonjs-fvtt/better-macros-directory/blob/main/src/view/BMDAppShell.svelte#L30-L34 https://github.com/typhonjs-fvtt/better-macros-directory/blob/main/src/view/BMDAppShell.svelte#L53-L55 Quite likely though you don't need the above and just have to launch another SvelteApplication w/ ApplicationShell wrapping your sidebar content component when the sidebar tab is right clicked. Store the reference to the popped out app in the sidebar instance and if tab right clicked again call bringToTop instead of creating a new pop out.
Faey
FaeyOP•2y ago
Oh yeah, i just have to figure out which of these methods actually matter and reimplement them. I can't just copy the foundry code because that would violate the license
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
Not sure if that is the case if your code is only being run on Foundry. I believe there is some leniency for small utility aspects, but a lot of it can be rewritten. You can always ask / contact them directly or in the developer channels on the mothership.
Faey
FaeyOP•2y ago
@mleahy Okay so I've finally had some time to sit down and do this. Wierdly, I can't get the application to render docked. It always appears popped out
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
You need to use your own component beside ApplicationShell for the docked sidebar. Essentially duplicating similar layout to one of the classes that extends the SidebarTab class w/ a template like (SidebarDirectory): templates/sidebar/document-directory.html. The JS implementation of your SidebarTab class should be able to hold an instance of the SvelteApplication that uses ApplicationShell to wrap whatever content is in the tab.
Faey
FaeyOP•2y ago
is there a way to make use of getData with SvelteApplication?
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
For what purpose? In the App v1 API that is used to gather data to hand to the HBS template.
Faey
FaeyOP•2y ago
I'm trying to write the base class as a SvelteApplication version of SidebarTab As such I want to keep the variability SidebarTab has 4 variables that are passed to the template cssId, cssClass and tabName are the ones that immediately matter it also passes game.user but that matters less with svelte
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
Yeah... You have access to the external application that the css ID / classes assigned in defaultOptions with const { application } = getContext('#external'); You could store an additional parameter for tabName in the options. You can actually access game directly in Svelte templates as there is a special store to do so: import { gameState } from '@typhonjs-fvtt/runtime/store'; Then in the template use $gameState.user. That last bit probably wouldn't be obvious, but just a handy utility store to access game in a template. You can always access game in the <script> section. Check out how ApplicationShell uses the options from the external app options to set CSS ID / classes: https://github.com/typhonjs-fvtt-lib/svelte/blob/main/src/component/core/application/ApplicationShell.svelte#L374-L375
Faey
FaeyOP•2y ago
I'm still having the issue of actually getting the svelte component to render at the correct position It just renders to document root
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
Creating a standardized SidebarTab implementation is something useful to come up w/ an official wrapped / basic implementation that can be reused in the future. Kind of like providing a standardized TRL / Svelte ActorSheet.
Faey
FaeyOP•2y ago
Not the document-fragment created in the tab
Faey
FaeyOP•2y ago
it should show up up there, but it just kind of gets appended If I give it the same ID as my chat tab, it just refuses to render in the first place
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
You need to change the target parameter to #sidebar instead of document.body or provide the specific element. ---- I can actually look into things this weekend as setting up the sidebar Svelte wrapper doesn't require more work per se like the actor sheet will. It does look like you'll need to override the Foundry Sidebar class to provide additional info on the new tabs to add in getData.
Faey
FaeyOP•2y ago
I also honestly have NO idea how those templates get filled, I#ve been trying to analyse it, but its just, boom, different You shouldn't override it It's a better idea to monkeypatch the function specifically libWrapper is excellent for that exact purpose Also, you've got to get the app rendered too, the best way to do so is to stick it into CONFIG.ui Then Sidebar will just call _render during its own _render call
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
libWrapper should be avoided if at all possible. Just need to replace the getData aspect returning a more complete list of tabs. I'll look into things this weekend though, so I'm just kind of spitballing right now.
Faey
FaeyOP•2y ago
It's much more unsafe and prone for conflict to tear out the entire sidebar and replace the class than it is to use libWrapper to patch the function call
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
There can be no dependency in TRL / svelte-standard on libWrapper.
Faey
FaeyOP•2y ago
That said, you can also forgo this entire workaround and just plug the tab in yourself
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
I'll see if I can come up with a solution. The Sidebar class only renders once so that most likely is possible.
Faey
FaeyOP•2y ago
as long as the <nav> element contains the button and the parent sidebar div contains the section with the corresponding data-tab property, it will work So you could feasibly just write two svelte components that render a button and a section with the required contents and just target the corresponding elements on the page The only downside is that you loose all the SidebarTab specific API
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
I'm mostly concerned about providing a simple API to do so for module / system developers that handles what is necessary to inject the data into the Sidebar class and Foundry rendered template. The SidebarTab specific API needs to be duplicated. As mentioned I'll take a look this weekend.
Faey
FaeyOP•2y ago
Yea yea, no worries, I'm just sharing what I have found about how the sidebar works to hopefully give you a headstart
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
It shouldn't be too bad and will likely work out only because Sidebar is only rendered once.
Faey
FaeyOP•2y ago
Yeah I wouldn't replace the Sidebar application itself though, as that might cause issues with modules that do use libWrapper to modify it
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
Yep, not mentioning replacing the Sidebar application.
Faey
FaeyOP•2y ago
Okay then I misunderstood
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
Just some initial spitballing.
Faey
FaeyOP•2y ago
I should mention, the only reason I am using libWrapper is to get the tab button rendered because the buttons are hardcoded, the applications themselves interestingly aren't The way those get added to the sidebar is actually in the constructor of the SidebarTab class Literally like this: ui.sidebar.tabs[this.tabName] = this So if you were to just mount the button and rendered tab manually, you can avoid modifying getData() altogether
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
Yep.. It will involve manipulating ui.sidebar.tabs. No modifying of getData.
Faey
FaeyOP•2y ago
The assignment of ui.sidebar.tabs also has to happen by the time the renderSidebar hook is called. I simply decided to stick my application class into CONFIG.ui in the init hook, which will automatically call the constructor before rendering the sidebar
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
Well I'll definitely keep you informed on what I come up with.
Faey
FaeyOP•2y ago
I'm looking forward to it. For now, I'll simply develop the popout version of my component and take care of the sidebar once you've had time to figure it out That said, this foray into TRL has taught me a lot though and the library has grown on me, I might migrate my other module over to TRL when I have the time
TyphonJS (Michael)
TyphonJS (Michael)•2y ago
Modules for sure are open game for TRL presently w/ no limitations really. Getting the system specific helper APIs worked out is the stuff that will develop over a bit more time. Heh heh.. Glad to know that things are growing on you / making sense. Making good progress... Initial engineering test / analysis efforts indicate that I should get this finished over the weekend.
Faey
FaeyOP•2y ago
Awesome!
Want results from more Discord servers?
Add your server