mirror of
https://github.com/netbirdio/docs.git
synced 2026-10-09 15:19:04 +02:00
Fix mobile rendering issues (#1022)
This commit is contained in:
+1
-1
@@ -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 ' },
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user