frontend: animate sidebar on small viewports
This commit is contained in:
parent
1c87fa9758
commit
24fb9feead
6 changed files with 46 additions and 17 deletions
|
@ -13,7 +13,7 @@
|
|||
|
||||
<div class="top-bar">
|
||||
{#if !$showSidebar}
|
||||
<button class="icon-button menu-button" on:click="{ () => selectedChannel.set({ id: -1, name: "none", creator_id: -1 }) }">
|
||||
<button class="icon-button menu-button" on:click="{ () => showSidebar.set(true) }">
|
||||
<MenuIcon />
|
||||
</button>
|
||||
{/if}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<script>
|
||||
import { showChannelView } from "../stores";
|
||||
import ChannelTopBar from "./ChannelTopBar.svelte";
|
||||
import MessageInput from "./MessageInput.svelte";
|
||||
import Messages from "./Messages.svelte";
|
||||
|
@ -15,9 +16,13 @@
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="main-container">
|
||||
<div class="main-container" class:hidden={ !$showChannelView }>
|
||||
<ChannelTopBar channel={ channel } />
|
||||
<Messages channelId="{ channel.id }" />
|
||||
<MessageInput channel={ channel } />
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { CloudIcon } from "svelte-feather-icons";
|
||||
import { gatewayStatus, showSidebar, selectedChannel } from "../stores";
|
||||
import { gatewayStatus, showSidebar, selectedChannel, smallViewport, showChannelView } from "../stores";
|
||||
import ChannelView from "./ChannelView.svelte";
|
||||
import OverlayProvider from "./overlays/OverlayProvider.svelte";
|
||||
import Sidebar from "./Sidebar.svelte";
|
||||
|
@ -26,17 +26,10 @@
|
|||
{/if}
|
||||
|
||||
<div class="flex-container">
|
||||
{#if $selectedChannel.id === -1}
|
||||
<Sidebar />
|
||||
{#if $showSidebar}
|
||||
<div class="fullscreen-message">
|
||||
no channel selected.
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
{#if $showSidebar}
|
||||
<Sidebar />
|
||||
{/if}
|
||||
{#if !($smallViewport && $showSidebar)}
|
||||
<ChannelView channel={$selectedChannel} />
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
@ -1,14 +1,41 @@
|
|||
<script>
|
||||
import { HashIcon, PlusIcon, MoreVerticalIcon } from "svelte-feather-icons";
|
||||
import { channels, overlayStore, selectedChannel } from "../stores";
|
||||
import { quadInOut } from "svelte/easing";
|
||||
import { fly } from "svelte/transition";
|
||||
import { channels, overlayStore, selectedChannel, showChannelView, showSidebar, smallViewport } from "../stores";
|
||||
import UserTopBar from "./UserTopBar.svelte";
|
||||
|
||||
let pendingSelectChannel = null;
|
||||
|
||||
const selectChannel = (channel) => $selectedChannel = channel;
|
||||
|
||||
// janky code to hide the channel view during animation
|
||||
// this will make a smooth sidebar animation on smaller viewports (such as a phone, where you switch between sidebar being active)
|
||||
|
||||
const scheduleSelectChannel = (channel) => {
|
||||
if ($smallViewport) {
|
||||
$showChannelView = false;
|
||||
pendingSelectChannel = channel;
|
||||
$showSidebar = false;
|
||||
} else {
|
||||
selectChannel(channel);
|
||||
}
|
||||
};
|
||||
|
||||
const outroEnd = () => {
|
||||
if (pendingSelectChannel) {
|
||||
selectChannel(pendingSelectChannel);
|
||||
pendingSelectChannel = null;
|
||||
$showChannelView = true;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="sidebar-container">
|
||||
<div class="sidebar-container" transition:fly="{{ duration: 200, easing: quadInOut, x: -10 }}" on:outroend="{ outroEnd }">
|
||||
<UserTopBar />
|
||||
<div class="sidebar">
|
||||
{#each $channels as channel (channel.id)}
|
||||
<button on:click="{ () => $selectedChannel = channel }" class="sidebar-button" class:selected={ channel.id === $selectedChannel.id }>
|
||||
<button on:click="{ scheduleSelectChannel(channel) }" class="sidebar-button" class:selected={ channel.id === $selectedChannel.id }>
|
||||
<div>
|
||||
<HashIcon />
|
||||
</div>
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { showSidebar } from "./stores";
|
||||
import { showSidebar, smallViewport } from "./stores";
|
||||
|
||||
export function initResponsiveHandlers() {
|
||||
const mediaQuery = window.matchMedia('(min-width: 768px)');
|
||||
|
||||
const update = ({ matches }) => {
|
||||
showSidebar.set(matches);
|
||||
smallViewport.set(!matches);
|
||||
};
|
||||
|
||||
mediaQuery.addEventListener("change", update);
|
||||
|
|
|
@ -36,6 +36,7 @@ class ChannelsStore extends Store {
|
|||
|
||||
gateway.subscribe(GatewayEventType.Ready, ({ channels }) => {
|
||||
this.value = channels;
|
||||
selectedChannel.set(channels.length ? channels[0] : null);
|
||||
this.updated();
|
||||
});
|
||||
gateway.subscribe(GatewayEventType.ChannelCreate, (channel) => {
|
||||
|
@ -265,3 +266,5 @@ export const userInfoStore = new UserInfoStore();
|
|||
export const overlayStore = new OverlayStore();
|
||||
export const selectedChannel = writable({ id: -1, name: "none", creator_id: -1 });
|
||||
export const showSidebar = writable(false);
|
||||
export const showChannelView = writable(true);
|
||||
export const smallViewport = writable(false);
|
||||
|
|
Loading…
Reference in a new issue