techniq / svelte-ux

Collection of Svelte components, actions, stores, and utilities to build highly interactive applications.
https://svelte-ux.techniq.dev/
MIT License
741 stars 39 forks source link

Access AppLayout.showDrawer externally #279

Open erlenddahl opened 6 months ago

erlenddahl commented 6 months ago

In some cases, for example on a landing page, it is useful to be able to start the side with the drawer hidden, but still allow the user to open it.

Therefore, it would be very useful to make showDrawer in AppLayout a bindable attribute, or accessible from the outside in some other way, so that it is possible to programmatically show or hide the drawer.

(And very sorry if this is actually possible already, I couldn't see anything about it in the documentation, and I can't seem to find any available fields in the source code either.)

techniq commented 6 months ago

Hi @erlenddahl, thanks for checking out Svelte UX. That's an interesting use case with AppLayout, and something we want to support.

Right now (as you've seen) showDrawer is a store within AppLayout module, so thus a singleton. We could export showDrawer which would allow...

<script>
  import { showDrawer } from 'svelte-ux';
</script>

and give you control externally, much like AppBar and NavItem do, although this will likely cause a quick flash of the drawer since the default value is based on the browser windows/breakpoint. Trying to think of a way to define this default, but also allow it to be per-page.

One thought I'm having is showDrawer should be moved to settings() (context), which is where we store the theme and locale. The more I think about it, this seems like the better location (showDrawer precedes the existence of settings()).

settings({
  navDrawer: {
    default: $page.url.pagename === '/' ? false : window.innerWidth >= breakpoints.md
})

The tricky thing will be initially navigating to a sub page (ex. /about) and then back to / since this value will already be set. Worst case you should still be able to automatically hide it when navigating back home, although you will likely see it transition out.

const { showDrawer } = getSettings();
$showDrawer = false;

Let me think on this a little, but I think moving this to settings is the way to go, at least as an initial step. I need to think how this will support per-page default and such..

erlenddahl commented 6 months ago

Great! And yes, I've been checking out Svelte UX, and I am now happily using multiple of the components. Very nice library! I realize that I can create my own

plutonium-239 commented 2 months ago

Thanks for the amazing library! Hi, I would be interested in this too, is there any update?

techniq commented 2 months ago

Hey @plutonium-239 👋 thanks for the kind words.

I did move the showDrawer store to the settings context, which you can access and programmatically control using...

import { getSettings } from 'svelte-ux';
const { showDrawer } = getSettings();

$showDrawer = true; // show
$showDrawer = false; // hide

You could probably hide the drawer within onMount(() => ...) for a specific page, but you would see it transition away.

As of right now the store is initialized based on the window width, but exposing this initialization as a callback should provide the added flexibility, although if you were to revisit you would either want to also use the onMount() approach, or add a separate settings() context so it would be re-initialized on each visit. Not sure when I'll get to this change, but it's on my radar :)