Files
app/frontend/src/components/Flow/CanvasTitle.tsx
T
stroblmeandClaude Fable 5 0af09eedbe Rework the dashboards onto the flow canvas
One shell for both editors. Flows and dashboards each get a searchable
overview under the padded shell, their editors move to the full-bleed
canvas, and the floating chrome is shared: a title bar that only says
what you are looking at, and a bottom dock carrying everything else —
the flow bar's status, settings and Publish moved down there, the
add-flow button moved to the overview.

Dashboards gain the rest of M4's visualization work:

- widgets are picked by clicking them, with the header as the drag
  handle so a slider still slides and a switch still flips while
  editing; settings moved into the flows' SidePanel
- react-grid-layout for drag and edge-resize, so the stored x/y finally
  mean something; a dashboard nobody arranged is shelf-packed once
- a per-dashboard grid size, so a panel can be matched to its screen
- the chart widget, drawn with uPlot: several messages on one axis, fed
  from the stored history plus the live socket tail, coloured from the
  new --chart-1..5 ramp
- /view/{name}: the URL a wall panel is pointed at — no sidebar, no
  footer, no editing, and no editor code, since routes are split
- a widget wired to a payload type it cannot carry, or wired to nothing
  at all, carries the same red dot a failing node does; the picker
  records the type it bound and WidgetDef refuses a mismatch on save

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7LwYgJfpkbLCTeiAf8U4A
2026-08-16 17:13:10 +02:00

32 lines
1.2 KiB
TypeScript

import { motion } from "motion/react"
import type { ReactNode } from "react"
import { SidebarTrigger } from "@/components/ui/sidebar"
import { slideUp, transitions } from "@/lib/motion"
/**
* What you are looking at, floating top-centre over a full-bleed canvas.
*
* Reference rather than navigation: switching to another flow or dashboard is
* what the overviews are for, so this bar carries the name and nothing that
* takes you away from it. Shared by the flow editor and the dashboards so the
* two shells read as one.
*/
export function CanvasTitle({ children }: { children: ReactNode }) {
return (
<motion.div
variants={slideUp}
initial="hidden"
animate="visible"
exit="exit"
transition={transitions.emphasized}
className="pointer-events-auto absolute left-1/2 top-4 z-10 flex max-w-[calc(100%-2rem)] -translate-x-1/2 items-center gap-1 rounded-full border border-border bg-card/80 px-1.5 py-1 shadow-e2 backdrop-blur-md"
>
{/* The sidebar carries its own collapse control; a phone has no sidebar
on screen to carry it. */}
<SidebarTrigger className="size-8 shrink-0 text-muted-foreground md:hidden" />
{children}
</motion.div>
)
}