mirror of
https://github.com/netbirdio/docs.git
synced 2026-04-18 08:26:35 +00:00
fix mobile view
This commit is contained in:
@@ -4,9 +4,7 @@ import { useRouter } from 'next/router'
|
|||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
|
|
||||||
import { Logo, Logomark } from '@/components/Logo'
|
import { Logo, Logomark } from '@/components/Logo'
|
||||||
import { MobileNavigation } from '@/components/MobileNavigation'
|
|
||||||
import { Prose } from '@/components/Prose'
|
import { Prose } from '@/components/Prose'
|
||||||
import { Search } from '@/components/Search'
|
|
||||||
import {HeroPattern} from "@/components/HeroPattern";
|
import {HeroPattern} from "@/components/HeroPattern";
|
||||||
import {NavigationDocs} from "@/components/NavigationDocs";
|
import {NavigationDocs} from "@/components/NavigationDocs";
|
||||||
import {Header} from "@/components/Header";
|
import {Header} from "@/components/Header";
|
||||||
@@ -160,8 +158,8 @@ export function Layout({ children, title, tableOfContents }) {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<Header />
|
<Header />
|
||||||
{router.route.startsWith("/ipa") ? <NavigationAPI tableOfContents={tableOfContents} className="hidden lg:mt-10 lg:block" /> :
|
{router.route.startsWith("/ipa") && <NavigationAPI tableOfContents={tableOfContents} className="hidden lg:mt-10 lg:block" />}
|
||||||
<NavigationDocs className="hidden lg:mt-10 lg:block" />}
|
{router.route.startsWith("/docs") &&<NavigationDocs className="hidden lg:mt-10 lg:block" />}
|
||||||
</div>
|
</div>
|
||||||
</motion.header>
|
</motion.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-16">
|
<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-16">
|
||||||
@@ -174,12 +172,12 @@ export function Layout({ children, title, tableOfContents }) {
|
|||||||
<nav aria-labelledby="on-this-page-title" className="w-56">
|
<nav aria-labelledby="on-this-page-title" className="w-56">
|
||||||
{tableOfContents.length > 0 && (
|
{tableOfContents.length > 0 && (
|
||||||
<>
|
<>
|
||||||
{/*<h2*/}
|
<h2
|
||||||
{/* id="on-this-page-title"*/}
|
id="on-this-page-title"
|
||||||
{/* className="font-display text-sm font-medium text-slate-900 dark:text-white"*/}
|
className="font-display text-sm font-medium text-slate-900 dark:text-white"
|
||||||
{/*>*/}
|
>
|
||||||
{/* On this page*/}
|
On this page
|
||||||
{/*</h2>*/}
|
</h2>
|
||||||
<ol role="list" className="mt-4 space-y-3 text-sm">
|
<ol role="list" className="mt-4 space-y-3 text-sm">
|
||||||
{tableOfContents.map((section) => (
|
{tableOfContents.map((section) => (
|
||||||
<li key={section.id}>
|
<li key={section.id}>
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import { create } from 'zustand'
|
|||||||
|
|
||||||
import { Header } from '@/components/Header'
|
import { Header } from '@/components/Header'
|
||||||
import { NavigationAPI } from '@/components/NavigationAPI'
|
import { NavigationAPI } from '@/components/NavigationAPI'
|
||||||
|
import {NavigationDocs} from "@/components/NavigationDocs";
|
||||||
|
import {useRouter} from "next/router";
|
||||||
|
|
||||||
function MenuIcon(props) {
|
function MenuIcon(props) {
|
||||||
return (
|
return (
|
||||||
@@ -52,6 +54,8 @@ export function MobileNavigation() {
|
|||||||
let { isOpen, toggle, close } = useMobileNavigationStore()
|
let { isOpen, toggle, close } = useMobileNavigationStore()
|
||||||
let ToggleIcon = isOpen ? XIcon : MenuIcon
|
let ToggleIcon = isOpen ? XIcon : MenuIcon
|
||||||
|
|
||||||
|
let router = useRouter()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IsInsideMobileNavigationContext.Provider value={true}>
|
<IsInsideMobileNavigationContext.Provider value={true}>
|
||||||
<button
|
<button
|
||||||
@@ -103,7 +107,8 @@ export function MobileNavigation() {
|
|||||||
layoutScroll
|
layoutScroll
|
||||||
className="fixed bottom-0 left-0 top-14 w-full overflow-y-auto bg-white px-4 pb-4 pt-6 shadow-lg shadow-zinc-900/10 ring-1 ring-zinc-900/7.5 dark:bg-zinc-900 dark:ring-zinc-800 min-[416px]:max-w-sm sm:px-6 sm:pb-10"
|
className="fixed bottom-0 left-0 top-14 w-full overflow-y-auto bg-white px-4 pb-4 pt-6 shadow-lg shadow-zinc-900/10 ring-1 ring-zinc-900/7.5 dark:bg-zinc-900 dark:ring-zinc-800 min-[416px]:max-w-sm sm:px-6 sm:pb-10"
|
||||||
>
|
>
|
||||||
<NavigationAPI />
|
{router.route.startsWith("/ipa") ? <NavigationAPI tableOfContents={[]} /> :
|
||||||
|
<NavigationDocs />}
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</Transition.Child>
|
</Transition.Child>
|
||||||
</Dialog.Panel>
|
</Dialog.Panel>
|
||||||
|
|||||||
@@ -1,20 +1,67 @@
|
|||||||
import {useEffect, useRef, useState} from 'react'
|
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import { AnimatePresence, motion, useIsPresent } from 'framer-motion'
|
import { AnimatePresence, motion, useIsPresent } from 'framer-motion'
|
||||||
|
|
||||||
import { Button } from '@/components/Button'
|
import { Button } from '@/components/Button'
|
||||||
import { useIsInsideMobileNavigation } from '@/components/MobileNavigation'
|
|
||||||
import { useSectionStore } from '@/components/SectionProvider'
|
|
||||||
import { Tag } from '@/components/Tag'
|
import { Tag } from '@/components/Tag'
|
||||||
import { remToPx } from '@/lib/remToPx'
|
import { remToPx } from '@/lib/remToPx'
|
||||||
|
import {useIsInsideMobileNavigation} from "@/components/MobileNavigation";
|
||||||
|
|
||||||
function useInitialValue(value, condition = true) {
|
export const apiNavigation = [
|
||||||
let initialValue = useRef(value).current
|
{
|
||||||
return condition ? initialValue : value
|
title: 'Guides',
|
||||||
|
links: [
|
||||||
|
{ title: 'Quickstart', href: '/ipa/guides/quickstart' },
|
||||||
|
{ title: 'Authentication', href: '/ipa/guides/authentication' },
|
||||||
|
{ title: 'Errors', href: '/ipa/guides/errors' },
|
||||||
|
// { title: 'Events', href: '/accounts' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Resources',
|
||||||
|
links: [
|
||||||
|
{ title: 'Accounts', href: '/ipa/resources/accounts' },
|
||||||
|
{ title: 'Users', href: '/ipa/resources/users' },
|
||||||
|
{ title: 'Tokens', href: '/ipa/resources/tokens' },
|
||||||
|
{ title: 'Peers', href: '/ipa/resources/peers' },
|
||||||
|
{ title: 'Setup Keys', href: '/ipa/resources/setup-keys' },
|
||||||
|
{ title: 'Groups', href: '/ipa/resources/groups' },
|
||||||
|
{ title: 'Rules', href: '/ipa/resources/rules' },
|
||||||
|
{ title: 'Policies', href: '/ipa/resources/policies' },
|
||||||
|
{ title: 'Routes', href: '/ipa/resources/routes' },
|
||||||
|
{ title: 'DNS', href: '/ipa/resources/dns' },
|
||||||
|
{ title: 'Events', href: '/ipa/resources/events' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export function NavigationAPI(props) {
|
||||||
|
return (
|
||||||
|
<nav {...props}>
|
||||||
|
<ul role="list">
|
||||||
|
<TopLevelNavItem href="https://netbird.io/">Home</TopLevelNavItem>
|
||||||
|
<TopLevelNavItem href="/docs/introductions">Docs</TopLevelNavItem>
|
||||||
|
<TopLevelNavItem href="/ipa/introductions">API</TopLevelNavItem>
|
||||||
|
<TopLevelNavItem href="https://netbird.io/blog/">Blog</TopLevelNavItem>
|
||||||
|
<TopLevelNavItem href="https://github.com/netbirdio/netbird">Github</TopLevelNavItem>
|
||||||
|
<TopLevelNavItem href="https://join.slack.com/t/netbirdio/shared_invite/zt-vrahf41g-ik1v7fV8du6t0RwxSrJ96A">Support</TopLevelNavItem>
|
||||||
|
{apiNavigation.map((group, groupIndex) => (
|
||||||
|
<NavigationGroup
|
||||||
|
key={group.title}
|
||||||
|
group={group}
|
||||||
|
tableOfContents={props.tableOfContents}
|
||||||
|
className={groupIndex === 0 && 'md:mt-0'}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
<li className="sticky bottom-0 z-10 mt-6 min-[416px]:hidden">
|
||||||
|
<Button href="https://app.netbird.io/" variant="filled" className="w-full">
|
||||||
|
Sign in
|
||||||
|
</Button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TopLevelNavItem({ href, children }) {
|
export function TopLevelNavItem({ href, children }) {
|
||||||
return (
|
return (
|
||||||
<li className="md:hidden">
|
<li className="md:hidden">
|
||||||
@@ -88,15 +135,7 @@ export function ActivePageMarker({ group, pathname }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function NavigationGroup({ group, className, tableOfContents }) {
|
function NavigationGroup({ group, className, tableOfContents }) {
|
||||||
// If this is the mobile navigation then we always render the initial
|
|
||||||
// state, so that the state does not change during the close animation.
|
|
||||||
// The state will still update when we re-open (re-render) the navigation.
|
|
||||||
// let isInsideMobileNavigation = useIsInsideMobileNavigation()
|
|
||||||
let router = useRouter()
|
let router = useRouter()
|
||||||
// let [router, sections] = useInitialValue(
|
|
||||||
// [useRouter(), useSectionStore((s) => s.sections)],
|
|
||||||
// isInsideMobileNavigation
|
|
||||||
// )
|
|
||||||
|
|
||||||
let isActiveGroup =
|
let isActiveGroup =
|
||||||
group.links.findIndex((link) => link.href === router.pathname) !== -1
|
group.links.findIndex((link) => link.href === router.pathname) !== -1
|
||||||
@@ -111,10 +150,10 @@ function NavigationGroup({ group, className, tableOfContents }) {
|
|||||||
</motion.h2>
|
</motion.h2>
|
||||||
<div className="relative mt-3 pl-2">
|
<div className="relative mt-3 pl-2">
|
||||||
<AnimatePresence >
|
<AnimatePresence >
|
||||||
{isActiveGroup && (
|
{isActiveGroup && (
|
||||||
<VisibleSectionHighlight group={group} pathname={router.pathname} />
|
<VisibleSectionHighlight group={group} pathname={router.pathname} />
|
||||||
)}
|
)}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
<motion.div
|
<motion.div
|
||||||
layout
|
layout
|
||||||
className="absolute inset-y-0 left-2 w-px bg-zinc-900/10 dark:bg-white/5"
|
className="absolute inset-y-0 left-2 w-px bg-zinc-900/10 dark:bg-white/5"
|
||||||
@@ -144,7 +183,7 @@ function NavigationGroup({ group, className, tableOfContents }) {
|
|||||||
transition: { duration: 0.15 },
|
transition: { duration: 0.15 },
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{router.route.startsWith("/ipa/resources") && tableOfContents.tableOfContents.map((section) => (
|
{router.route.startsWith("/ipa/resources") && tableOfContents.tableOfContents?.map((section) => (
|
||||||
<li key={section.id}>
|
<li key={section.id}>
|
||||||
<NavLink
|
<NavLink
|
||||||
href={`${link.href}#${section.id}`}
|
href={`${link.href}#${section.id}`}
|
||||||
@@ -166,60 +205,5 @@ function NavigationGroup({ group, className, tableOfContents }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const apiNavigation = [
|
|
||||||
{
|
|
||||||
title: 'Guides',
|
|
||||||
links: [
|
|
||||||
{ title: 'Quickstart', href: '/ipa/guides/quickstart' },
|
|
||||||
{ title: 'Authentication', href: '/ipa/guides/authentication' },
|
|
||||||
{ title: 'Errors', href: '/ipa/guides/errors' },
|
|
||||||
// { title: 'Events', href: '/accounts' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Resources',
|
|
||||||
links: [
|
|
||||||
{ title: 'Accounts', href: '/ipa/resources/accounts' },
|
|
||||||
{ title: 'Users', href: '/ipa/resources/users' },
|
|
||||||
{ title: 'Tokens', href: '/ipa/resources/tokens' },
|
|
||||||
{ title: 'Peers', href: '/ipa/resources/peers' },
|
|
||||||
{ title: 'Setup Keys', href: '/ipa/resources/setup-keys' },
|
|
||||||
{ title: 'Groups', href: '/ipa/resources/groups' },
|
|
||||||
{ title: 'Rules', href: '/ipa/resources/rules' },
|
|
||||||
{ title: 'Policies', href: '/ipa/resources/policies' },
|
|
||||||
{ title: 'Routes', href: '/ipa/resources/routes' },
|
|
||||||
{ title: 'DNS', href: '/ipa/resources/dns' },
|
|
||||||
{ title: 'Events', href: '/ipa/resources/events' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
export function NavigationAPI(tableOfContents, props) {
|
|
||||||
return (
|
|
||||||
<nav {...props}>
|
|
||||||
<ul role="list">
|
|
||||||
<TopLevelNavItem href="https://netbird.io/">Home</TopLevelNavItem>
|
|
||||||
<TopLevelNavItem href="/docs/introductions">Docs</TopLevelNavItem>
|
|
||||||
<TopLevelNavItem href="/ipa/introductions">API</TopLevelNavItem>
|
|
||||||
<TopLevelNavItem href="https://netbird.io/blog/">Blog</TopLevelNavItem>
|
|
||||||
<TopLevelNavItem href="https://github.com/netbirdio/netbird">Github</TopLevelNavItem>
|
|
||||||
<TopLevelNavItem href="https://join.slack.com/t/netbirdio/shared_invite/zt-vrahf41g-ik1v7fV8du6t0RwxSrJ96A">Support</TopLevelNavItem>
|
|
||||||
{
|
|
||||||
apiNavigation.map((group, groupIndex) => (
|
|
||||||
<NavigationGroup
|
|
||||||
key={group.title}
|
|
||||||
group={group}
|
|
||||||
tableOfContents={tableOfContents}
|
|
||||||
className={groupIndex === 0 && 'md:mt-0'}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
<li className="sticky bottom-0 z-10 mt-6 min-[416px]:hidden">
|
|
||||||
<Button href="https://app.netbird.io/" variant="filled" className="w-full">
|
|
||||||
Sign in
|
|
||||||
</Button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { useRouter } from 'next/router'
|
|||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import {ActivePageMarker, NavLink, TopLevelNavItem, VisibleSectionHighlight} from "@/components/NavigationAPI";
|
import {ActivePageMarker, NavLink, TopLevelNavItem, VisibleSectionHighlight} from "@/components/NavigationAPI";
|
||||||
import {AnimatePresence, motion} from "framer-motion";
|
import {AnimatePresence, motion} from "framer-motion";
|
||||||
|
import {Button} from "@/components/mdx";
|
||||||
|
|
||||||
export const docsNavigation = [
|
export const docsNavigation = [
|
||||||
{
|
{
|
||||||
@@ -18,10 +19,10 @@ export const docsNavigation = [
|
|||||||
title: 'How-to',
|
title: 'How-to',
|
||||||
links: [
|
links: [
|
||||||
{ title: 'Getting Started', href: '/docs/how-to/getting-started' },
|
{ title: 'Getting Started', href: '/docs/how-to/getting-started' },
|
||||||
{ title: 'Setup Keys', href: '/docs/how-to/setup-keys' },
|
{ title: 'Register peers using setup keys', href: '/docs/how-to/register-peers-using-setup-keys' },
|
||||||
{ title: 'Access Control', href: '/docs/how-to/access-control' },
|
{ title: 'Restrict access to peers', href: '/docs/how-to/restrict-access-to-peers' },
|
||||||
{ title: 'Users', href: '/docs/how-to/users' },
|
{ title: 'Add Users to your network', href: '/docs/how-to/add-users-to-you-network' },
|
||||||
{ title: 'Add users to your network', href: '/docs/how-to/add-users-to-you-network' },
|
{ title: 'Use service users with access token', href: '/docs/how-to/use-service-users-with-access-token' },
|
||||||
{ title: 'Configure periodic user authentication', href: '/docs/how-to/configure-periodic-user-authentication' },
|
{ title: 'Configure periodic user authentication', href: '/docs/how-to/configure-periodic-user-authentication' },
|
||||||
{ title: 'Monitor system and network activity', href: '/docs/how-to/monitor-system-and-network-activity' },
|
{ title: 'Monitor system and network activity', href: '/docs/how-to/monitor-system-and-network-activity' },
|
||||||
{ title: 'Routing traffic to private networks', href: '/docs/how-to/routing-traffic-to-private-networks' },
|
{ title: 'Routing traffic to private networks', href: '/docs/how-to/routing-traffic-to-private-networks' },
|
||||||
@@ -56,21 +57,22 @@ export function NavigationDocs(props) {
|
|||||||
className={groupIndex === 0 && 'md:mt-0'}
|
className={groupIndex === 0 && 'md:mt-0'}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
<li className="sticky bottom-0 z-10 mt-6 min-[416px]:hidden">
|
||||||
|
<Button href="https://app.netbird.io/" variant="filled" className="w-full">
|
||||||
|
Sign in
|
||||||
|
</Button>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function NavigationGroup({ group, className }) {
|
function NavigationGroup({ group, className }) {
|
||||||
// If this is the mobile navigation then we always render the initial
|
|
||||||
// state, so that the state does not change during the close animation.
|
|
||||||
// The state will still update when we re-open (re-render) the navigation.
|
|
||||||
let router = useRouter()
|
let router = useRouter()
|
||||||
|
|
||||||
let isActiveGroup =
|
let isActiveGroup =
|
||||||
group.links.findIndex((link) => link.href === router.pathname) !== -1
|
group.links.findIndex((link) => link.href === router.pathname) !== -1
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className={clsx('relative mt-6', className)}>
|
<li className={clsx('relative mt-6', className)}>
|
||||||
<motion.h2
|
<motion.h2
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
# Setup Keys
|
# Register Peers using Setup Keys
|
||||||
|
|
||||||
Setup key is a pre-authentication key that allows to register new machines in your network.
|
Setup key is a pre-authentication key that allows to register new machines in your network.
|
||||||
It simply associates a machine with an account on a first run.
|
It simply associates a machine with an account on a first run.
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
# Access Control
|
# Restrict Access to Peers
|
||||||
NetBird allows administrators to restrict access to resources (peers) by creating access rules and
|
NetBird allows administrators to restrict access to resources (peers) by creating access rules and
|
||||||
defining what peer groups are permitted to establish connections with one another.
|
defining what peer groups are permitted to establish connections with one another.
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
# Users
|
# Use Service Users with Access Token
|
||||||
|
|
||||||
## Service Users
|
## Service Users
|
||||||
|
|
||||||
Reference in New Issue
Block a user