Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export function DeploymentNetworkView({

return (
<InfiniteCanvas
locked
defaultZoom={1}
overlay={
<>
Expand All @@ -69,7 +70,7 @@ export function DeploymentNetworkView({
>
<TreeLayout
data={currentTree}
nodeSpacing={{ x: 10, y: 100 }}
nodeSpacing={{ x: 75, y: 100 }}
onNodeClick={isShowingSkeleton ? undefined : (node) => setSelectedNode(node)}
renderNode={(node, parent) => renderDeploymentNode(node, parent, deploymentId ?? undefined)}
renderConnection={(path, parent, child) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ export const CanvasBoundary = ({ children }: PropsWithChildren) => {
return (
<ErrorBoundary
fallback={(error, reset) => (
<TreeElementNode id="error-state" position={{ x: 0, y: 250 }}>
<TreeElementNode
id="error-state"
position={{ x: 0, y: 250 }}
size={{ width: 0, height: 0 }}
>
<div className="w-[400px]">
{/* Background card with glow */}
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type InfiniteCanvasProps = {
dotRadius?: number;
dotClassName?: string;
showGrid?: boolean;
locked?: boolean;
children: React.ReactNode;
overlay?: React.ReactNode;
};
Expand All @@ -42,6 +43,7 @@ export function InfiniteCanvas({
dotRadius = DEFAULT_DOT_RADIUS,
dotClassName = DEFAULT_DOT_CLASS,
showGrid = true,
locked = false,
children,
overlay,
}: InfiniteCanvasProps) {
Expand Down Expand Up @@ -69,7 +71,8 @@ export function InfiniteCanvas({
const rect = svg.getBoundingClientRect();
setCanvas((prev) => ({
...prev,
offset: { x: rect.width / 2, y: rect.height / 6 },
// Anchor the origin toward the top of the element; increase the divisor to move it higher.
offset: { x: rect.width / 2, y: rect.height / 12 },
}));
}, []);

Expand Down Expand Up @@ -210,6 +213,10 @@ export function InfiniteCanvas({

// Prevent browser's default scroll behavior
useEffect(() => {
if (locked) {
return;
}

const svg = svgRef.current;
if (!svg) {
return;
Expand All @@ -221,18 +228,18 @@ export function InfiniteCanvas({

svg.addEventListener("wheel", handleWheelNative, { passive: false });
return () => svg.removeEventListener("wheel", handleWheelNative);
}, []);
}, [locked]);

return (
<div className="relative w-full h-full">
<svg
ref={svgRef}
className="w-full h-full cursor-grab active:cursor-grabbing dark:bg-black bg-gray-1"
onMouseDown={handleMouseDown}
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}
onMouseLeave={handleMouseUp}
onWheel={handleWheel}
className={`w-full h-full dark:bg-black bg-gray-1 ${locked ? "cursor-default" : "cursor-grab active:cursor-grabbing"}`}
onMouseDown={locked ? undefined : handleMouseDown}
onMouseMove={locked ? undefined : handleMouseMove}
onMouseUp={locked ? undefined : handleMouseUp}
onMouseLeave={locked ? undefined : handleMouseUp}
onWheel={locked ? undefined : handleWheel}
>
<g transform={transform}>
{showGrid && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function HealthBanner({ healthStatus }: HealthBannerProps) {
const Icon = config.icon;

return (
<div className={`z-10 mx-auto w-[${DEFAULT_NODE_WIDTH}px] -m-[20px]`}>
<div className={`mx-auto w-[${DEFAULT_NODE_WIDTH}px] -m-[20px]`}>
<div
className={cn(
"h-12 border rounded-t-[14px]",
Expand All @@ -33,28 +33,19 @@ export function HealthBanner({ healthStatus }: HealthBannerProps) {
<span className={cn("text-xs font-medium mr-4", config.colors.textColor)}>
{config.label}
</span>
<div className="flex-1 overflow-hidden relative max-w-[200px]">
<div className="flex-1 overflow-hidden max-w-[200px] grid">
<div
className={cn(
"text-xs",
"[grid-area:1/1] text-xs animate-marquee whitespace-nowrap",
config.colors.textColor,
"animate-marquee whitespace-nowrap",
)}
>
{config.message}
</div>
<div
className={cn(
"absolute left-0 top-0 bottom-0 w-6 pointer-events-none",
config.colors.gradientFromLeft,
)}
/>
<div
className={cn(
"absolute right-0 top-0 bottom-0 w-6 pointer-events-none",
config.colors.gradientFromRight,
)}
/>
<div className="[grid-area:1/1] flex justify-between pointer-events-none">
<div className={cn("w-6 h-full", config.colors.gradientFromLeft)} />
<div className={cn("w-6 h-full ml-auto", config.colors.gradientFromRight)} />
</div>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ export function NodeWrapper({ health, children }: NodeWrapperProps) {
return (
<div
className={cn(
"relative w-[282px] rounded-[14px]",
"w-[282px] rounded-[14px]",
isDisabled
? "grayscale opacity-90 cursor-not-allowed"
: cn(
"hover:scale-[1.001] transition-all duration-200 ease-out cursor-pointer",
"transition-shadow duration-200 ease-out cursor-pointer",
"hover:ring-2 hover:ring-offset-0",
ring,
glow,
Expand All @@ -30,7 +30,7 @@ export function NodeWrapper({ health, children }: NodeWrapperProps) {
<HealthBanner healthStatus={health} />
<div
className={cn(
"relative z-20 w-[282px] h-[100px] border border-grayA-4 rounded-[14px] flex flex-col bg-white dark:bg-black shadow-[0_2px_8px_-2px_rgba(0,0,0,0.1)]",
"w-[282px] h-[100px] border border-grayA-4 rounded-[14px] flex flex-col bg-white dark:bg-black shadow-[0_2px_8px_-2px_rgba(0,0,0,0.1)]",
)}
>
{children}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,29 +40,6 @@ export const SKELETON_TREE: DeploymentNode = {
label: "s-skeleton-2",
metadata: { type: "skeleton" },
},
{
id: "eu-central-1-s-3-skeleton",
label: "s-skeleton-3",
metadata: { type: "skeleton" },
},
],
},
{
id: "ap-southeast-2-skeleton",
label: "ap-southeast-2",
direction: "vertical",
metadata: { type: "skeleton" },
children: [
{
id: "ap-southeast-2-s-1-skeleton",
label: "s-skeleton-1",
metadata: { type: "skeleton" },
},
{
id: "ap-southeast-2-s-2-skeleton",
label: "s-skeleton-2",
metadata: { type: "skeleton" },
},
],
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const SkeletonNode = () => {

{/* Status indicators skeleton */}
<div className="flex gap-2 items-center ml-auto">
<div className="w-[30px] h-[40px] rounded-lg bg-grayA-3 animate-pulse" />
<div className="w-[30px]" />
<div className="w-[30px] h-[40px] rounded-lg bg-grayA-3 animate-pulse" />
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,32 @@ import { type HealthStatus, STATUS_CONFIG } from "./status-config";

type StatusDotProps = {
healthStatus: HealthStatus;
variant?: "absolute" | "relative";
};

export function StatusDot({ healthStatus, variant = "absolute" }: StatusDotProps) {
export function StatusDot({ healthStatus }: StatusDotProps) {
const { colors } = STATUS_CONFIG[healthStatus];

const wrapperClass =
variant === "absolute" ? "absolute top-1.5 right-1.5 size-[7px]" : "relative size-[7px]";

return (
<>
<div className={wrapperClass}>
<div className="size-[7px] grid">
{/* Ring 1 */}
<div
className="absolute inset-0 rounded-full"
className="[grid-area:1/1] rounded-full breathe-ring"
style={{
animation: "breathe-ring 2s ease-in-out infinite",
boxShadow: `0 0 0 1.5px ${colors.dotRing}`,
}}
/>
{/* Ring 2 */}
<div
className="absolute inset-0 rounded-full"
className="[grid-area:1/1] rounded-full breathe-ring"
style={{
animation: "breathe-ring 2s ease-in-out infinite 1s",
boxShadow: `0 0 0 1.5px ${colors.dotRing}`,
}}
/>
{/* Solid dot */}
<div className={cn("absolute inset-0 rounded-full", colors.dotBg)} />
<div className={cn("[grid-area:1/1] rounded-full", colors.dotBg)} />
</div>
<style>{`
@keyframes breathe-ring {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ export function StatusIndicator({
position={{ align: "center", side: "top", sideOffset: 5 }}
>
<div
className="border bg-gray-1 border-grayA-3 h-[22px] w-14 rounded-full flex transition-all hover:ring-1 hover:ring-gray-7 duration-200 ease-out hover:scale-105 cursor-pointer overflow-hidden flex-row-reverse"
className="border bg-gray-1 border-grayA-3 h-[22px] w-14 rounded-full flex transition-shadow hover:ring-1 hover:ring-gray-7 duration-200 ease-out cursor-pointer overflow-hidden flex-row-reverse"
style={{
boxShadow: glowBoxShadow,
}}
>
<div className="w-1/2 border-r border-grayA-3 relative flex items-center justify-center flex-shrink-0">
<div className="w-1/2 border-r border-grayA-3 flex justify-end items-start pt-1.5 pr-1.5 flex-shrink-0">
<StatusDot healthStatus={healthStatus} />
</div>
<div className="w-1/2 bg-grayA-2 flex items-center justify-center flex-shrink-0">
Expand All @@ -59,12 +59,12 @@ export function StatusIndicator({
position={{ align: "center", side: "top", sideOffset: 5 }}
>
<div
className="border bg-gray-1 border-grayA-3 h-full rounded-lg w-8 transition-all hover:ring-1 hover:ring-gray-7 duration-200 ease-out hover:scale-105 cursor-pointer overflow-hidden"
className="border bg-gray-1 border-grayA-3 h-full rounded-lg w-8 transition-shadow hover:ring-1 hover:ring-gray-7 duration-200 ease-out cursor-pointer overflow-hidden"
style={{
boxShadow: glowBoxShadow,
}}
>
<div className="h-6 border-b border-grayA-3 relative">
<div className="h-6 border-b border-grayA-3 flex justify-end items-start pt-1.5 pr-1.5">
<StatusDot healthStatus={healthStatus} />
</div>
<div className="h-5 bg-grayA-2 pl-1 pt-[3px]">{icon}</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const LiveIndicator = () => {
position={{ align: "center", side: "top", sideOffset: 5 }}
>
<div className="bg-base-12 flex items-center justify-between gap-2 cursor-pointer">
<StatusDot healthStatus="health_syncing" variant="relative" />
<StatusDot healthStatus="health_syncing" />
<span className="text-accent-12 font-medium text-[13px]">Live</span>
</div>
</InfoTooltip>
Expand Down
Loading