Fix mobile rendering issues (#1022)

This commit is contained in:
Brandon Hopkins
2026-10-05 18:12:39 -07:00
committed by GitHub
parent 1ea7881248
commit 084ff2462c
7 changed files with 59 additions and 21 deletions
+1 -1
View File
@@ -54,7 +54,7 @@ function rehypeInsertLastUpdated() {
type: 'element', type: 'element',
tagName: 'p', tagName: 'p',
properties: { properties: {
className: ['not-prose', 'text-sm', 'text-slate-400', 'dark:text-zinc-500', 'mt-0', 'mb-8', 'ml-2.5'], className: ['not-prose', 'text-sm', 'text-slate-400', 'dark:text-zinc-500', 'mt-0', 'mb-8', 'md:ml-2.5'],
}, },
children: [ children: [
{ type: 'text', value: 'Updated ' }, { type: 'text', value: 'Updated ' },
+4 -4
View File
@@ -188,7 +188,7 @@ export function Layout({ children, title, tableOfContents }) {
<AnnouncementBanner /> <AnnouncementBanner />
<HeroPattern/> <HeroPattern/>
<div <div
className="relative mx-auto flex max-w-8xl sm:px-2 lg:px-8 xl:px-12 lg:ml-72 xl:ml-80" className="relative mx-auto flex max-w-8xl md:px-2 lg:px-8 xl:px-12 lg:ml-72 xl:ml-80"
style={{ paddingTop: bannerHeight }} style={{ paddingTop: bannerHeight }}
> >
<header <header
@@ -206,9 +206,9 @@ export function Layout({ children, title, tableOfContents }) {
</div> </div>
<Header /> <Header />
</header> </header>
<div className="min-w-0 max-w-2xl flex-auto px-4 py-16 lg:max-w-none lg:pl-8 lg:pr-0 xl:px-5"> <div className="min-w-0 flex-auto px-4 py-16 md:max-w-2xl lg:max-w-none lg:pl-8 lg:pr-0 xl:px-5">
<main className="py-16"> <main className="py-8 lg:py-16">
<Prose as="article">{children}</Prose> <Prose as="article" className="max-md:max-w-none">{children}</Prose>
</main> </main>
<Footer /> <Footer />
</div> </div>
+8 -2
View File
@@ -7,6 +7,7 @@ import { Header } from '@/components/Header'
import { NavigationAPI } from '@/components/NavigationAPI' import { NavigationAPI } from '@/components/NavigationAPI'
import {NavigationDocs} from "@/components/NavigationDocs"; import {NavigationDocs} from "@/components/NavigationDocs";
import {useRouter} from "next/router"; import {useRouter} from "next/router";
import { useAnnouncements } from '@/components/announcement-banner/AnnouncementBannerProvider'
function MenuIcon(props) { function MenuIcon(props) {
return ( return (
@@ -52,6 +53,7 @@ export const useMobileNavigationStore = create((set) => ({
export function MobileNavigation() { export function MobileNavigation() {
let isInsideMobileNavigation = useIsInsideMobileNavigation() let isInsideMobileNavigation = useIsInsideMobileNavigation()
let { isOpen, toggle, close } = useMobileNavigationStore() let { isOpen, toggle, close } = useMobileNavigationStore()
let { bannerHeight } = useAnnouncements()
let ToggleIcon = isOpen ? XIcon : MenuIcon let ToggleIcon = isOpen ? XIcon : MenuIcon
let router = useRouter() let router = useRouter()
@@ -78,7 +80,10 @@ export function MobileNavigation() {
leaveFrom="opacity-100" leaveFrom="opacity-100"
leaveTo="opacity-0" leaveTo="opacity-0"
> >
<div className="fixed inset-0 top-14 bg-zinc-400/20 backdrop-blur-sm dark:bg-[#181A1D]/40" /> <div
className="fixed inset-0 bg-zinc-400/20 backdrop-blur-sm dark:bg-[#181A1D]/40"
style={{ top: `calc(${bannerHeight}px + 4rem)` }}
/>
</Transition.Child> </Transition.Child>
<Dialog.Panel> <Dialog.Panel>
@@ -105,7 +110,8 @@ export function MobileNavigation() {
> >
<motion.div <motion.div
layoutScroll layoutScroll
className="fixed bottom-0 left-0 top-14 w-full overflow-y-auto bg-white/70 dark:bg-[#181A1D]/95 backdrop-blur-lg px-4 pb-4 pt-6 shadow-lg shadow-zinc-900/10 ring-1 ring-zinc-900/7.5 dark:ring-neutral-500/10 min-[416px]:max-w-sm sm:px-6 sm:pb-10" className="fixed bottom-0 left-0 w-full overflow-y-auto bg-white/70 dark:bg-[#181A1D]/95 backdrop-blur-lg px-4 pb-4 pt-6 shadow-lg shadow-zinc-900/10 ring-1 ring-zinc-900/7.5 dark:ring-neutral-500/10 min-[416px]:max-w-sm sm:px-6 sm:pb-10"
style={{ top: `calc(${bannerHeight}px + 4rem)` }}
> >
{router.route.startsWith("/ipa") ? <NavigationAPI tableOfContents={[]} /> : {router.route.startsWith("/ipa") ? <NavigationAPI tableOfContents={[]} /> :
<NavigationDocs />} <NavigationDocs />}
@@ -1,4 +1,4 @@
import clsx from 'clsx' import { useLayoutEffect, useRef } from 'react'
import Link from 'next/link' import Link from 'next/link'
import { useAnnouncements } from '@/components/announcement-banner/AnnouncementBannerProvider' import { useAnnouncements } from '@/components/announcement-banner/AnnouncementBannerProvider'
@@ -36,19 +36,34 @@ function CloseIcon(props) {
function AnnouncementItem({ announcement, onClose }) { function AnnouncementItem({ announcement, onClose }) {
const announcementLink = useCustomQueryURL(announcement.link || '') const announcementLink = useCustomQueryURL(announcement.link || '')
const bannerRef = useRef(null)
const { setBannerHeight } = useAnnouncements()
useLayoutEffect(() => {
const banner = bannerRef.current
// Text wrapping and viewport changes can make the banner taller on phones.
const updateHeight = () => setBannerHeight(banner.getBoundingClientRect().height)
updateHeight()
const observer = new ResizeObserver(updateHeight)
observer.observe(banner)
return () => {
observer.disconnect()
setBannerHeight(0)
}
}, [setBannerHeight])
return ( return (
<div <div
id="announcement-banner" id="announcement-banner"
className={clsx( ref={bannerRef}
'sticky top-0 z-50 flex w-full items-center justify-center border-b border-zinc-800 bg-netbird/95 px-4 py-1.5 text-[11px] font-medium text-black shadow-sm backdrop-blur' className="fixed inset-x-0 top-0 z-50 flex w-full items-center justify-center border-b border-zinc-800 bg-netbird/95 px-4 py-1.5 text-[11px] font-medium text-black shadow-sm backdrop-blur"
)}
> >
<div className="flex flex-col items-start gap-1 pr-8 leading-snug md:flex-row md:items-center"> <div className="pr-8 leading-relaxed md:flex md:items-center md:gap-1 md:leading-snug">
{announcement.tag ? ( {announcement.tag ? (
<div className="mr-2 inline rounded-md bg-black/70 px-2 py-1 text-[9px] font-semibold uppercase tracking-[0.18em] text-white"> <span className="mr-2 inline-block whitespace-nowrap rounded-md bg-black/70 px-2 py-1 align-middle text-[9px] font-semibold uppercase tracking-[0.18em] text-white">
{announcement.tag} {announcement.tag}
</div> </span>
) : null} ) : null}
<span className="mr-2 text-[12px] md:text-[13px]"> <span className="mr-2 text-[12px] md:text-[13px]">
{announcement.text} {announcement.text}
@@ -101,4 +116,4 @@ export function AnnouncementBanner() {
onClose={closeAnnouncement} onClose={closeAnnouncement}
/> />
) )
} }
@@ -12,10 +12,10 @@ const ANNOUNCEMENTS_URL =
'https://raw.githubusercontent.com/netbirdio/dashboard/main/announcements.json' 'https://raw.githubusercontent.com/netbirdio/dashboard/main/announcements.json'
const STORAGE_KEY = 'netbird-announcements' const STORAGE_KEY = 'netbird-announcements'
const CACHE_DURATION_MS = 30 * 60 * 1000 const CACHE_DURATION_MS = 30 * 60 * 1000
const BANNER_HEIGHT = 33
const AnnouncementContext = createContext({ const AnnouncementContext = createContext({
bannerHeight: 0, bannerHeight: 0,
setBannerHeight: () => {},
announcements: undefined, announcements: undefined,
closeAnnouncement: () => {}, closeAnnouncement: () => {},
}) })
@@ -83,6 +83,7 @@ const saveAnnouncements = (closedAnnouncements) => {
export function AnnouncementBannerProvider({ children }) { export function AnnouncementBannerProvider({ children }) {
const [announcements, setAnnouncements] = useState(undefined) const [announcements, setAnnouncements] = useState(undefined)
const [bannerHeight, setBannerHeight] = useState(0)
const fetchingRef = useRef(false) const fetchingRef = useRef(false)
useEffect(() => { useEffect(() => {
@@ -108,12 +109,11 @@ export function AnnouncementBannerProvider({ children }) {
[announcements] [announcements]
) )
const bannerHeight = announcements?.some((a) => a.isOpen) ? BANNER_HEIGHT : 0
return ( return (
<AnnouncementContext.Provider <AnnouncementContext.Provider
value={{ value={{
bannerHeight, bannerHeight,
setBannerHeight,
announcements, announcements,
closeAnnouncement, closeAnnouncement,
}} }}
@@ -125,4 +125,4 @@ export function AnnouncementBannerProvider({ children }) {
export function useAnnouncements() { export function useAnnouncements() {
return useContext(AnnouncementContext) return useContext(AnnouncementContext)
} }
+13
View File
@@ -11,6 +11,19 @@ export { Badge } from '@/components/Badge'
export { YouTube } export { YouTube }
export { Video } from '@/components/Video' export { Video } from '@/components/Video'
export const table = function Table(props) {
return (
<div
className="my-8 overflow-x-auto [&>table]:my-0"
role="region"
aria-label="Scrollable table"
tabIndex={0}
>
<table {...props} />
</div>
)
}
export const h2 = function H2(props) { export const h2 = function H2(props) {
return <Heading level={2} {...props} /> return <Heading level={2} {...props} />
} }
+6 -2
View File
@@ -48,9 +48,13 @@ module.exports = ({ theme }) => ({
// Layout // Layout
'> *': { '> *': {
maxWidth: theme('maxWidth.2xl'), maxWidth: '100%',
marginLeft: 10, marginLeft: 0,
marginRight: 'auto', marginRight: 'auto',
'@screen md': {
maxWidth: theme('maxWidth.2xl'),
marginLeft: 10,
},
'@screen lg': { '@screen lg': {
maxWidth: theme('maxWidth.3xl'), maxWidth: theme('maxWidth.3xl'),
marginLeft: 10, marginLeft: 10,