Make the brand CTA visible and fix two more v3 variable classes
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UytviPMJbXzD8P84nLvXcq
This commit is contained in:
@@ -131,7 +131,7 @@ function SuggestInput({
|
|||||||
</PopoverAnchor>
|
</PopoverAnchor>
|
||||||
<PopoverContent
|
<PopoverContent
|
||||||
align="start"
|
align="start"
|
||||||
className="w-[--radix-popover-trigger-width] p-0"
|
className="w-[var(--radix-popover-trigger-width)] p-0"
|
||||||
onOpenAutoFocus={(event) => event.preventDefault()}
|
onOpenAutoFocus={(event) => event.preventDefault()}
|
||||||
>
|
>
|
||||||
<Command shouldFilter={false}>
|
<Command shouldFilter={false}>
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export function ValuePreview({
|
|||||||
>
|
>
|
||||||
<ChevronRight
|
<ChevronRight
|
||||||
className={cn(
|
className={cn(
|
||||||
"size-3 shrink-0 transition-transform duration-[--duration-fast]",
|
"size-3 shrink-0 transition-transform duration-[var(--duration-fast)]",
|
||||||
open && "rotate-90",
|
open && "rotate-90",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -205,7 +205,8 @@ export function RemoteAccess() {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
className="rounded-full bg-[--brand-secondary] text-white hover:opacity-90"
|
variant="brand"
|
||||||
|
className="rounded-full"
|
||||||
disabled={!code.trim() || !portalUrl.trim() || connect.isPending}
|
disabled={!code.trim() || !portalUrl.trim() || connect.isPending}
|
||||||
onClick={() => connect.mutate()}
|
onClick={() => connect.mutate()}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import { useMutation, useQuery } from "@tanstack/react-query"
|
import { useMutation, useQuery } from "@tanstack/react-query"
|
||||||
import { createFileRoute } from "@tanstack/react-router"
|
import { createFileRoute } from "@tanstack/react-router"
|
||||||
|
import { Check, Copy } from "lucide-react"
|
||||||
import { useEffect } from "react"
|
import { useEffect } from "react"
|
||||||
|
|
||||||
import { ApiError, PanelsService } from "@/client"
|
import { ApiError, PanelsService } from "@/client"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { useCopyToClipboard } from "@/hooks/useCopyToClipboard"
|
||||||
import { appPath, isPortal, openPortalSession } from "@/lib/portal"
|
import { appPath, isPortal, openPortalSession } from "@/lib/portal"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,6 +30,8 @@ export const Route = createFileRoute("/panel/")({
|
|||||||
})
|
})
|
||||||
|
|
||||||
function PairPanel() {
|
function PairPanel() {
|
||||||
|
const [copied, copy] = useCopyToClipboard()
|
||||||
|
|
||||||
// A code lives ten minutes. Asking for one is the mount, and asking again is
|
// A code lives ten minutes. Asking for one is the mount, and asking again is
|
||||||
// what happens when this one is no longer recognised.
|
// what happens when this one is no longer recognised.
|
||||||
const start = useMutation({
|
const start = useMutation({
|
||||||
@@ -98,16 +103,32 @@ function PairPanel() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="font-mono text-6xl font-medium tracking-[0.2em]">
|
<div className="flex items-center justify-center gap-4">
|
||||||
<span data-testid="pairing-code" aria-hidden="true">
|
<p className="font-mono text-6xl font-medium tracking-[0.2em]">
|
||||||
{started?.code ?? "······"}
|
<span data-testid="pairing-code" aria-hidden="true">
|
||||||
</span>
|
{started?.code ?? "······"}
|
||||||
{/* Spelled out, so a reader says the characters rather than trying
|
</span>
|
||||||
to pronounce them as a word. */}
|
{/* Spelled out, so a reader says the characters rather than trying
|
||||||
<span className="sr-only">
|
to pronounce them as a word. */}
|
||||||
{(started?.code ?? "").split("").join(" ")}
|
<span className="sr-only">
|
||||||
</span>
|
{(started?.code ?? "").split("").join(" ")}
|
||||||
</p>
|
</span>
|
||||||
|
</p>
|
||||||
|
{/* Only where it would work: a panel served over plain http on the
|
||||||
|
LAN has no clipboard, and a button that silently does nothing is
|
||||||
|
worse than none. */}
|
||||||
|
{started?.code && navigator.clipboard ? (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="size-11 shrink-0 text-muted-foreground md:size-8"
|
||||||
|
aria-label="Copy the code"
|
||||||
|
onClick={() => copy(started.code)}
|
||||||
|
>
|
||||||
|
{copied === started.code ? <Check /> : <Copy />}
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
The code lasts ten minutes; this screen replaces it when it runs out.
|
The code lasts ten minutes; this screen replaces it when it runs out.
|
||||||
|
|||||||
Reference in New Issue
Block a user