~ knotless Search/
↑↓ move↵ open⇧↵ all results

grain.social/grain

photography-focused photo sharing platform

grain.social
1 collaborator
0
2
143 lines · 3.7 KB Raw History
<script lang="ts">
  import { profilePath } from '$lib/utils'
  import { Image, Compass, ImagePlus, Bell } from 'lucide-svelte'
  import { goto } from '$app/navigation'
  import { page } from '$app/state'
  import { isAuthenticated, loginModalOpen, viewer } from '$lib/stores'
  import Avatar from '../atoms/Avatar.svelte'
  import Button from '../atoms/Button.svelte'
  import { createQuery } from '@tanstack/svelte-query'
  import { unseenNotificationCountQuery } from '$lib/queries'


  const unseenCount = createQuery(() => ({
    ...unseenNotificationCountQuery($viewer?.did ?? ''),
    enabled: !!$viewer?.did,
  }))
</script>

{#if $isAuthenticated}
  <div class="mobile-bottom">
    <button
      class="mobile-tab"
      class:active={page.url.pathname === '/'}
      onclick={() => goto('/')}
    >
      <Image size={22} />
    </button>
    <button
      class="mobile-tab"
      class:active={page.url.pathname === '/explore'}
      onclick={() => goto('/explore')}
    >
      <Compass size={22} />
    </button>
    <button
      class="mobile-tab"
      class:active={page.url.pathname === '/create'}
      onclick={() => goto('/create')}
    >
      <ImagePlus size={22} />
    </button>
    <button
      class="mobile-tab"
      class:active={page.url.pathname === '/notifications'}
      onclick={() => goto('/notifications')}
    >
      <span class="bell-wrap">
        <Bell size={22} />
        {#if (unseenCount.data ?? 0) > 0}
          <span class="badge">{unseenCount.data! > 99 ? '99+' : unseenCount.data}</span>
        {/if}
      </span>
    </button>
    {#if $viewer}
      <button
        class="mobile-tab"
        class:active={page.url.pathname.startsWith('/profile/')}
        onclick={() => goto(profilePath($viewer))}
      >
        <Avatar did={$viewer.did} src={$viewer.avatar} name={$viewer.displayName || $viewer.handle} size={24} />
      </button>
    {/if}
  </div>
{:else}
  <div class="mobile-bottom mobile-bottom-signed-out">
    <span class="mobile-tagline">Share your photography</span>
    <Button size="sm" onclick={() => ($loginModalOpen = true)}>Sign in</Button>
  </div>
{/if}

<style>
  /* The login wall carries its own Sign in; two at once is noise. */
  :global(body.wall-open) .mobile-bottom { display: none; }
  .mobile-bottom {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background: var(--bg-root);
    border-top: 1px solid var(--border);
    padding: 0 0 env(safe-area-inset-bottom, 0px);
    z-index: 100;
    justify-content: space-around;
    align-items: center;
    height: calc(50px + env(safe-area-inset-bottom, 0px));
  }
  .mobile-tab {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 22px;
    padding: 8px 16px;
    cursor: pointer;
    transition: color 0.12s;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .mobile-tab.active {
    color: var(--grain);
  }
  .bell-wrap {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .badge {
    position: absolute;
    top: -4px;
    right: -6px;
    background: var(--grain);
    color: var(--on-grain);
    font-size: 9px;
    font-weight: 700;
    min-width: 14px;
    height: 14px;
    border-radius: 7px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 3px;
    font-family: var(--font-body);
  }

  .mobile-bottom-signed-out {
    justify-content: space-between;
    padding: 0 16px env(safe-area-inset-bottom, 0px);
  }
  .mobile-tagline {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-secondary);
  }

  @media (max-width: 600px) {
    .mobile-bottom {
      display: flex;
      touch-action: manipulation;
    }
  }
</style>