Skip to content
Merged
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
6 changes: 6 additions & 0 deletions .server-changes/span-accessory-text-guard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
area: webapp
type: fix
---

Prevent dashboard crash (React error #31) when span accessory item text is not a string. Filters out malformed accessory items in SpanCodePathAccessory instead of passing objects to React as children.
42 changes: 24 additions & 18 deletions apps/webapp/app/components/runs/v3/SpanTitle.tsx
Comment thread
ericallam marked this conversation as resolved.
Comment thread
ericallam marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,24 @@ function SpanAccessory({
case "pills": {
return (
<span className="flex items-center gap-1">
{accessory.items.map((item, index) => (
<SpanPill key={index} text={item.text} icon={item.icon} />
))}
{accessory.items
.filter((item) => typeof item.text === "string")
.map((item, index) => (
<SpanPill key={index} text={item.text} icon={item.icon} />
))}
</span>
);
}
default: {
return (
<span className={cn("flex gap-1")}>
{accessory.items.map((item, index) => (
<span key={index} className={cn("inline-flex items-center gap-1")}>
{item.text}
</span>
))}
{accessory.items
.filter((item) => typeof item.text === "string")
.map((item, index) => (
<span key={index} className={cn("inline-flex items-center gap-1")}>
{item.text}
</span>
))}
</span>
);
}
Expand Down Expand Up @@ -104,16 +108,18 @@ export function SpanCodePathAccessory({
className
)}
>
{accessory.items.map((item, index) => (
<Fragment key={index}>
<span className={cn("truncate", "text-text-dimmed")}>{item.text}</span>
{index < accessory.items.length - 1 && (
<span className="text-text-dimmed">
<ChevronRightIcon className="size-4" />
</span>
)}
</Fragment>
))}
{accessory.items
.filter((item) => typeof item.text === "string")
.map((item, index, filtered) => (
<Fragment key={index}>
<span className={cn("truncate", "text-text-dimmed")}>{item.text}</span>
{index < filtered.length - 1 && (
<span className="text-text-dimmed">
<ChevronRightIcon className="size-4" />
</span>
)}
</Fragment>
))}
</code>
);
}
Expand Down
Loading