Make core portal layout responsive with mobile drawer menu

This commit is contained in:
Andrew Kingston 2021-09-13 15:38:06 +01:00
parent 87aa4b18b1
commit 0c0e656b34
6 changed files with 160 additions and 1712 deletions

View File

@ -13,6 +13,7 @@
class="spectrum-SideNav-item" class="spectrum-SideNav-item"
class:is-selected={selected} class:is-selected={selected}
class:is-disabled={disabled} class:is-disabled={disabled}
on:click
> >
{#if heading} {#if heading}
<h2 class="spectrum-SideNav-heading" id="nav-heading-{heading}"> <h2 class="spectrum-SideNav-heading" id="nav-heading-{heading}">

View File

@ -134,7 +134,7 @@
</script> </script>
<ModalContent <ModalContent
title={template ? "Import app" : "Create new app"} title={template ? "Import app" : "Create app"}
confirmText={template ? "Import app" : "Create app"} confirmText={template ? "Import app" : "Create app"}
onConfirm={createNewApp} onConfirm={createNewApp}
disabled={!valid} disabled={!valid}

View File

@ -20,6 +20,7 @@
let loaded = false let loaded = false
let userInfoModal let userInfoModal
let changePasswordModal let changePasswordModal
let mobileMenuVisible = false
$: menu = buildMenu($auth.isAdmin) $: menu = buildMenu($auth.isAdmin)
@ -60,6 +61,9 @@
return menu return menu
} }
const showMobileMenu = () => (mobileMenuVisible = true)
const hideMobileMenu = () => (mobileMenuVisible = false)
onMount(async () => { onMount(async () => {
// Prevent non-builders from accessing the portal // Prevent non-builders from accessing the portal
if ($auth.user) { if ($auth.user) {
@ -75,7 +79,7 @@
{#if $auth.user && loaded} {#if $auth.user && loaded}
<div class="container"> <div class="container">
<div class="nav"> <div class="nav" class:visible={mobileMenuVisible}>
<Layout paddingX="L" paddingY="L"> <Layout paddingX="L" paddingY="L">
<div class="branding"> <div class="branding">
<div class="name" on:click={() => $goto("./apps")}> <div class="name" on:click={() => $goto("./apps")}>
@ -89,7 +93,12 @@
<div class="menu"> <div class="menu">
<Navigation> <Navigation>
{#each menu as { title, href, heading }} {#each menu as { title, href, heading }}
<Item selected={$isActive(href)} {href} {heading}>{title}</Item> <Item
on:click={hideMobileMenu}
selected={$isActive(href)}
{href}
{heading}>{title}</Item
>
{/each} {/each}
</Navigation> </Navigation>
</div> </div>
@ -97,35 +106,50 @@
</div> </div>
<div class="main"> <div class="main">
<div class="toolbar"> <div class="toolbar">
<div /> <div class="mobile-toggle">
<ActionMenu align="right"> <Icon hoverable name="ShowMenu" on:click={showMobileMenu} />
<div slot="control" class="avatar"> </div>
<Avatar <div class="mobile-logo">
size="M" <img
initials={$auth.initials} src={$organisation?.logoUrl || Logo}
url={$auth.user.pictureUrl} alt={$organisation?.company || "Budibase"}
/> />
<Icon size="XL" name="ChevronDown" /> </div>
</div> <div class="user-dropdown">
<MenuItem icon="UserEdit" on:click={() => userInfoModal.show()}> <ActionMenu align="right">
Update user information <div slot="control" class="avatar">
</MenuItem> <Avatar
<MenuItem size="M"
icon="LockClosed" initials={$auth.initials}
on:click={() => changePasswordModal.show()} url={$auth.user.pictureUrl}
> />
Update password <Icon size="XL" name="ChevronDown" />
</MenuItem> </div>
<MenuItem icon="UserDeveloper" on:click={() => $goto("../apps")}> <MenuItem icon="UserEdit" on:click={() => userInfoModal.show()}>
Close developer mode Update user information
</MenuItem> </MenuItem>
<MenuItem icon="LogOut" on:click={auth.logout}>Log out</MenuItem> <MenuItem
</ActionMenu> icon="LockClosed"
on:click={() => changePasswordModal.show()}
>
Update password
</MenuItem>
<MenuItem icon="UserDeveloper" on:click={() => $goto("../apps")}>
Close developer mode
</MenuItem>
<MenuItem icon="LogOut" on:click={auth.logout}>Log out</MenuItem>
</ActionMenu>
</div>
</div> </div>
<div class="content"> <div class="content">
<slot /> <slot />
</div> </div>
</div> </div>
<div
class="mobile-click-handler"
class:visible={mobileMenuVisible}
on:click={hideMobileMenu}
/>
</div> </div>
<Modal bind:this={userInfoModal}> <Modal bind:this={userInfoModal}>
<UpdateUserInfoModal /> <UpdateUserInfoModal />
@ -138,16 +162,20 @@
<style> <style>
.container { .container {
height: 100%; height: 100%;
display: grid; display: flex;
grid-template-columns: 250px 1fr; flex-direction: row;
justify-content: flex-start;
align-items: stretch; align-items: stretch;
} }
.nav { .nav {
background: var(--background); background: var(--background);
border-right: var(--border-light); border-right: var(--border-light);
overflow: auto; overflow: auto;
flex: 0 0 auto;
width: 250px;
} }
.main { .main {
flex: 1 1 auto;
display: grid; display: grid;
grid-template-rows: auto 1fr; grid-template-rows: auto 1fr;
overflow: hidden; overflow: hidden;
@ -181,11 +209,21 @@
.toolbar { .toolbar {
background: var(--background); background: var(--background);
border-bottom: var(--border-light); border-bottom: var(--border-light);
display: grid; display: flex;
grid-template-columns: 250px auto; flex-direction: row;
justify-content: space-between; justify-content: space-between;
padding: var(--spacing-m) calc(var(--spacing-xl) * 2);
align-items: center; align-items: center;
padding: var(--spacing-m) calc(var(--spacing-xl) * 2);
}
.mobile-toggle,
.mobile-logo {
display: none;
}
.user-dropdown {
flex: 1 1 auto;
display: flex;
flex-direction: row;
justify-content: flex-end;
} }
img { img {
width: 28px; width: 28px;
@ -199,4 +237,41 @@
.content { .content {
overflow: auto; overflow: auto;
} }
.mobile-click-handler {
display: none;
}
@media (max-width: 640px) {
.nav {
position: absolute;
left: -250px;
height: 100%;
transition: left ease-in-out 230ms;
z-index: 2;
}
.nav.visible {
left: 0;
box-shadow: 0 0 80px 20px rgba(0, 0, 0, 0.3);
}
.mobile-toggle,
.mobile-logo {
display: block;
}
.mobile-toggle,
.user-dropdown {
flex: 1 1 0;
}
.mobile-click-handler.visible {
position: absolute;
display: block;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
}
</style> </style>

View File

@ -201,7 +201,7 @@
<Heading>Apps</Heading> <Heading>Apps</Heading>
<ButtonGroup> <ButtonGroup>
<Button secondary on:click={initiateAppImport}>Import app</Button> <Button secondary on:click={initiateAppImport}>Import app</Button>
<Button cta on:click={initiateAppCreation}>Create new app</Button> <Button cta on:click={initiateAppCreation}>Create app</Button>
</ButtonGroup> </ButtonGroup>
</div> </div>
<div class="filter"> <div class="filter">

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff