tailwindcss-safe-area icon indicating copy to clipboard operation
tailwindcss-safe-area copied to clipboard

Need help setting up p-safe class strategy for a Next.js pwa app with a fixed top and bottom navbar

Open monecchi opened this issue 1 year ago • 0 comments

Hi there. Thanks for the plugin. I'm trying to perform an optmized UX for my pwa app (Next.js 12 / Tailwindcss / Shadcn ui) when installed on iOS fullscreen / standalone mode.

The issue is I can't find the right "recipe" when applying p-safe classes to my app's layout structure, as it is shown bellow...

The top and bottom navbars are working as expected with the safe padding apllied properly when in fullscreen / standalone mode. However, I'm still having issues with the body that ends up getting a huge extra top padding when the app is opened on iOS standalone mode, it also seems to block interactivity until it is touched or scrolled, which is when it kind of falls back to a normal acceptable padding.

Even if I remove the safe padding from the body and then try to apply a top and bottom padding to the main layout, something is just not right in fullscreen mode. I'd really appreciate any guidance regarding the layout. Thanks in advance!

global.css

  html {
    display: flex;
    flex-direction: column;
  }

  html,
  body {
    height: -webkit-fill-available;
  }

  body {
    flex-grow: 1;
    /* PWA enhancements */
    -webkit-overflow-scrolling: touch;
    -webkit-tap-highlight-color: transparent;
    -webkit-touch-callout: none;
    overflow-x: hidden;
    @apply flex flex-col bg-background text-foreground antialiased select-none pt-safe pb-safe;
  }

top-navbar.tsx

interface TopNavProps {
  title?: string
}

export const TopNav = ({ title }: TopNavProps) => {
  return (
    <header className='site-header fixed left-0 top-0 z-40 w-full border-b border-border bg-secondary px-safe pt-safe'>
      <div className='mx-auto flex h-16 w-full max-w-screen-lg items-center justify-between px-6'>
        ...
      </div>
    </header>
  )
}

bottom-nav.tsx

export const BottomNav = () => {
    return (
        <nav className='bottom-nav fixed bottom-0 left-0 z-40 w-full border-t border-border bg-secondary pb-safe'>
            <div className='mx-auto flex h-16 max-w-md items-center justify-around px-6'>
                ...
            </div>
        </nav>
    )
}

layout.tsx

import Head from 'next/head'
import { Appbar } from '@/components/nav-top'
import { BottomNav } from '@/components/nav-bottom'
import { cn } from '@/lib/utils'

interface PageLayoutProps {
  title?: string
  className?: string
  children: React.ReactNode
}

export const PageLayout = ({ title, className, children }: PageLayoutProps): JSX.Element => (
  <>
    {title ? (
      <Head>
        <title>{title} - Mio Vino</title>
      </Head>
    ) : null}

    <Appbar title={title} />

    <main
      /**
       * Padding top = `appbar` height
       * Padding bottom = `bottom-nav` height
       */
      className={cn('mx-auto max-w-screen-lg px-safe pt-16 pb-20', className)}
    >
      <div className='px-6 py-4'>{children}</div>
    </main>

    <BottomNav />
  </>
)

monecchi avatar May 07 '24 15:05 monecchi