Computed flow layout, and mobile written into the design
The canvas lays itself out: a layered graph, left to right on a desktop and top to bottom on a phone, with room reserved for the value each edge carries. Nodes cannot be dragged and `NodeDef.position` is gone from the document — a graph nobody can arrange is one worth keeping small, which is what keeps flows atomic. Endpoints join the same layout, so their lanes and the localStorage that remembered where they were dragged go too. Mobile, per the new Responsive section of DESIGN-GUIDELINES.md: the dock caps its width and wraps instead of running off the screen, the dashboard stacks into one column rather than shrinking a wall panel to a fifth of its size, and Home stops widening its grid track past the viewport. A Playwright project at a phone's width fails the build when a screen no longer fits. Along the way: publish is the checkmark that was already there rather than a button that appears and disappears, with discard beside it on both the flow and the dashboard; the brain reveals a neuron's name on the first tap; and the port sparklines get room to breathe. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VDSXaRhvqHYNevgDGmNAto
This commit is contained in:
@@ -35,7 +35,7 @@ function Layout() {
|
||||
<header className="sticky top-0 z-10 flex h-16 shrink-0 items-center gap-2 px-4 md:hidden">
|
||||
<SidebarTrigger className="-ml-1 text-muted-foreground" />
|
||||
</header>
|
||||
<main className="flex-1 p-6 md:p-8">
|
||||
<main className="flex-1 p-4 sm:p-6 md:p-8">
|
||||
<div className="mx-auto max-w-7xl">
|
||||
<Outlet />
|
||||
</div>
|
||||
|
||||
@@ -114,7 +114,11 @@ function Dashboard() {
|
||||
const running = flows.filter((flow) => flow.enabled ?? true).length
|
||||
|
||||
return (
|
||||
<div className="grid gap-6">
|
||||
// `[&>*]:min-w-0`: a grid item's automatic minimum is its content, so one
|
||||
// long name or wide table widens the whole column and the page with it.
|
||||
// Every section here is free to shrink instead. See DESIGN-GUIDELINES.md
|
||||
// → Responsive.
|
||||
<div className="grid gap-6 [&>*]:min-w-0">
|
||||
<div>
|
||||
<h1 className="max-w-sm truncate text-2xl">
|
||||
Hi, {currentUser?.full_name || currentUser?.email} 👋
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
import { dashboardQueryOptions } from "@/components/Dashboard/queries"
|
||||
import { useFlowSocket } from "@/components/Flow/useFlowSocket"
|
||||
import { isLoggedIn } from "@/hooks/useAuth"
|
||||
import { useIsMobile } from "@/hooks/useMobile"
|
||||
|
||||
/**
|
||||
* What a wall panel is pointed at.
|
||||
@@ -31,16 +32,27 @@ function PanelView() {
|
||||
const { name } = Route.useParams()
|
||||
useFlowSocket()
|
||||
const { data: dashboard } = useQuery(dashboardQueryOptions(name))
|
||||
// A landscape arrangement scaled onto a phone comes out at about a fifth of
|
||||
// its size, which reads as nothing at all. Stack it instead.
|
||||
const stacked = useIsMobile()
|
||||
|
||||
if (!dashboard) return <main className="h-svh w-full" />
|
||||
|
||||
if (stacked) {
|
||||
return (
|
||||
<main className="h-svh w-full overflow-y-auto p-4">
|
||||
<DashboardView dashboard={dashboard as Dashboard} stacked />
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="h-svh w-full overflow-hidden p-4">
|
||||
{dashboard ? (
|
||||
// The panel's own surface, scaled to whatever screen it landed on. No
|
||||
// dots: nothing is being arranged here.
|
||||
<CanvasSurface dashboard={dashboard as Dashboard}>
|
||||
{() => <DashboardView dashboard={dashboard as Dashboard} />}
|
||||
</CanvasSurface>
|
||||
) : null}
|
||||
{/* The panel's own surface, scaled to whatever screen it landed on. No
|
||||
dots: nothing is being arranged here. */}
|
||||
<CanvasSurface dashboard={dashboard as Dashboard}>
|
||||
{() => <DashboardView dashboard={dashboard as Dashboard} />}
|
||||
</CanvasSurface>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user