diff --git a/app/components/Attribute.tsx b/app/components/Attribute.tsx index fad9457..9e2c7dd 100644 --- a/app/components/Attribute.tsx +++ b/app/components/Attribute.tsx @@ -1,23 +1,37 @@ -import { Check, Copy } from 'lucide-react'; +import { Check, Copy, Info } from 'lucide-react'; import cn from '~/utils/cn'; import toast from '~/utils/toast'; +import Tooltip from './Tooltip'; export interface AttributeProps { name: string; value: string; + tooltip?: string; isCopyable?: boolean; } -export default function Attribute({ name, value, isCopyable }: AttributeProps) { +export default function Attribute({ + name, + value, + tooltip, + isCopyable, +}: AttributeProps) { return (
{name} + {tooltip ? ( + + + {tooltip} + + ) : undefined}
(); + const { node, magic, users, agent, stats } = useLoaderData(); const [showRouting, setShowRouting] = useState(false); const uiTags = useMemo(() => { @@ -120,8 +123,8 @@ export default function Page() { -

Subnets & Routing

+

Subnets & Routing

Subnets let you expose physical network routes onto Tailscale.{' '} @@ -240,40 +243,156 @@ export default function Page() {

-

Machine Details

- - - - - - - - - - {magic ? ( +

Machine Details

+

+ Information about this machine’s network. Used to debug connection + issues. +

+ +
+ + + + {stats ? ( + <> + + + + ) : undefined} + - ) : undefined} + + + + {magic ? ( + + ) : undefined} +
+
+

+ Addresses +

+ + + + {magic ? ( + + ) : undefined} + {stats ? ( + <> +

+ Client Connectivity +

+ + + + + + + + + ) : undefined} +
); } + +function getIpv4Address(addresses: string[]) { + for (const address of addresses) { + if (address.startsWith('100.')) { + // Return the first CGNAT address + return address; + } + } + + return '—'; +} + +function getIpv6Address(addresses: string[]) { + for (const address of addresses) { + if (address.startsWith('fd')) { + // Return the first IPv6 address + return address; + } + } + + return '—'; +}