diff --git a/app/components/Footer.tsx b/app/components/Footer.tsx
index 86c3299..2b516ce 100644
--- a/app/components/Footer.tsx
+++ b/app/components/Footer.tsx
@@ -1,5 +1,4 @@
import Link from '~/components/Link';
-import Tooltip from '~/components/Tooltip';
import cn from '~/utils/cn';
declare global {
diff --git a/app/components/Popover.tsx b/app/components/Popover.tsx
index 9e7ee40..351a2ee 100644
--- a/app/components/Popover.tsx
+++ b/app/components/Popover.tsx
@@ -34,7 +34,7 @@ export default function Popover(props: PopoverProps) {
{...popoverProps}
ref={ref}
className={cn(
- 'z-10 shadow-sm rounded-xl overflow-hidden',
+ 'z-10 shadow-sm rounded-xl',
'bg-white dark:bg-headplane-900',
'border border-headplane-200 dark:border-headplane-800',
className,
diff --git a/app/components/Tooltip.tsx b/app/components/Tooltip.tsx
index 2fc202b..bf39193 100644
--- a/app/components/Tooltip.tsx
+++ b/app/components/Tooltip.tsx
@@ -1,37 +1,80 @@
-import type { ReactNode } from 'react';
+import React, { cloneElement, useRef } from 'react';
import {
- Button as AriaButton,
- Tooltip as AriaTooltip,
- TooltipTrigger,
-} from 'react-aria-components';
+ AriaTooltipProps,
+ mergeProps,
+ useTooltip,
+ useTooltipTrigger,
+} from 'react-aria';
+import { TooltipTriggerState, useTooltipTriggerState } from 'react-stately';
import cn from '~/utils/cn';
-interface Props {
- children: ReactNode;
- className?: string;
+export interface TooltipProps extends AriaTooltipProps {
+ children: [React.ReactElement, React.ReactElement];
}
-function Tooltip({ children }: Props) {
- return {children};
-}
+function Tooltip(props: TooltipProps) {
+ const state = useTooltipTriggerState({
+ ...props,
+ delay: 0,
+ closeDelay: 0,
+ });
-function Button(props: Parameters[0]) {
- return ;
-}
+ const ref = useRef(null);
+ const { triggerProps, tooltipProps } = useTooltipTrigger(
+ {
+ ...props,
+ delay: 0,
+ closeDelay: 0,
+ },
+ state,
+ ref,
+ );
-function Body({ children, className }: Props) {
+ const [component, body] = props.children;
return (
-
- {children}
-
+
+
+ {state.isOpen &&
+ cloneElement(body, {
+ ...tooltipProps,
+ state,
+ })}
+
);
}
-export default Object.assign(Tooltip, { Button, Body });
+interface TooltipBodyProps extends AriaTooltipProps {
+ children: React.ReactNode;
+ state?: TooltipTriggerState;
+ className?: string;
+}
+
+function Body({ state, className, ...props }: TooltipBodyProps) {
+ const { tooltipProps } = useTooltip(props, state);
+ return (
+
+ {props.children}
+
+ );
+}
+
+export default Object.assign(Tooltip, {
+ Body,
+});
diff --git a/app/routes/dns/dialogs/nameserver.tsx b/app/routes/dns/dialogs/nameserver.tsx
index c12dcdd..ff2e198 100644
--- a/app/routes/dns/dialogs/nameserver.tsx
+++ b/app/routes/dns/dialogs/nameserver.tsx
@@ -1,6 +1,7 @@
import { RepoForkedIcon } from '@primer/octicons-react';
import { useState } from 'react';
import { useSubmit } from 'react-router';
+import Chip from '~/components/Chip';
import Dialog from '~/components/Dialog';
import Input from '~/components/Input';
@@ -82,16 +83,11 @@ export default function AddNameserver({ nameservers }: Props) {
Restrict to domain
-
-
- Split DNS
-
+ }
+ className={cn('inline-flex items-center')}
+ />
Only clients that support split DNS (Tailscale v1.8 or later
for most platforms) will use this nameserver. Older clients
diff --git a/app/routes/machines/machine.tsx b/app/routes/machines/machine.tsx
index a01f707..d927e77 100644
--- a/app/routes/machines/machine.tsx
+++ b/app/routes/machines/machine.tsx
@@ -150,9 +150,7 @@ export default function Page() {
Managed by
-
-
-
+
By default, a machine’s permissions match its creator’s.
@@ -209,9 +207,7 @@ export default function Page() {
Approved
-
-
-
+
Traffic to these routes are being routed through this machine.
@@ -242,9 +238,7 @@ export default function Page() {
Awaiting Approval
-
-
-
+
This machine is advertising these routes, but they must be
approved before traffic will be routed to them.
@@ -276,9 +270,7 @@ export default function Page() {
Exit Node
-
-
-
+
Whether this machine can act as an exit node for your tailnet.
diff --git a/app/routes/machines/overview.tsx b/app/routes/machines/overview.tsx
index 063d26c..3c799d5 100644
--- a/app/routes/machines/overview.tsx
+++ b/app/routes/machines/overview.tsx
@@ -1,5 +1,4 @@
import { InfoIcon } from '@primer/octicons-react';
-import { Button, Tooltip, TooltipTrigger } from 'react-aria-components';
import type { ActionFunctionArgs, LoaderFunctionArgs } from 'react-router';
import { useLoaderData } from 'react-router';
@@ -15,6 +14,7 @@ import { getSession } from '~/utils/sessions.server';
import { useLiveData } from '~/utils/useLiveData';
import { initAgentSocket, queryAgent } from '~/utils/ws-agent';
+import Tooltip from '~/components/Tooltip';
import { menuAction } from './action';
import MachineRow from './components/machine';
import NewMachine from './dialogs/new';
@@ -81,31 +81,23 @@ export default function Page() {
-
+
Name
- Addresses
+
Addresses
{data.magic ? (
-
-
-
+
+
+
Since MagicDNS is enabled, you can access devices based on
their name and also at{' '}
[name].
{data.magic}
-
-
+
+
) : undefined}