Background
V2's resource_link content rendering is currently a placeholder. In clients/web/src/components/elements/ContentViewer/ContentViewer.tsx the resource_link case just renders the name/uri as plain blue text:
case "resource_link":
return (
<Stack gap="xs">
<Text size="sm" c="blue">
{block.name ?? block.uri}
</Text>
</Stack>
);
V1 has a much richer treatment in client/src/components/ResourceLinkView.tsx (rendered from ToolResults.tsx). We should bring that experience to V2 (Mantine-native, following V2 conventions).
What V1 does (the target behavior)
ResourceLinkView renders each resource_link as an interactive, expandable card showing:
- The URI (monospace, link-styled).
- Optional name (emphasized).
- Optional description.
- A mimeType badge when present.
- An expand/collapse affordance (▶ / ▼, with a loading spinner) that, on click/Enter/Space, calls
onReadResource(uri) to fetch the linked resource and inline its content below the card.
- Accessible:
role="button", aria-expanded, aria-label, keyboard handlers, focus ring.
Scope (V2)
- Replace the placeholder
resource_link branch in ContentViewer with a proper presentation showing uri / name / description / mimeType.
- Make it expandable with a read-on-demand action that fetches the resource and renders its content inline (reuse the existing V2 resource content rendering, e.g.
ContentViewer/resource content components, rather than V1's JsonView).
- Wire the read-resource callback through the relevant props so the host (tool result panel, etc.) can supply the read handler — follow the V2 "dumb component + callbacks as props" pattern.
- Use Mantine components, theme variants, and
--inspector-* tokens per the project conventions (no raw hex, no inline styles, no Tailwind classes carried over from V1).
- Add an element/story under
src/components/elements/ if it warrants its own documented component (e.g. ResourceLink), with Storybook coverage.
Acceptance criteria
- A
resource_link in tool results (and anywhere ContentViewer renders) shows uri, name, description, and mimeType (when present).
- The link is expandable and reads the resource on demand, rendering its content inline; collapse hides it again.
- Keyboard accessible and consistent with V2 styling conventions.
- Unit tests cover the collapsed/expanded states and the read-on-demand callback;
npm run validate, test:integration, and test:storybook pass.
References
- V1:
client/src/components/ResourceLinkView.tsx, client/src/components/ToolResults.tsx
- V2:
clients/web/src/components/elements/ContentViewer/ContentViewer.tsx
Background
V2's
resource_linkcontent rendering is currently a placeholder. Inclients/web/src/components/elements/ContentViewer/ContentViewer.tsxtheresource_linkcase just renders the name/uri as plain blue text:V1 has a much richer treatment in
client/src/components/ResourceLinkView.tsx(rendered fromToolResults.tsx). We should bring that experience to V2 (Mantine-native, following V2 conventions).What V1 does (the target behavior)
ResourceLinkViewrenders eachresource_linkas an interactive, expandable card showing:onReadResource(uri)to fetch the linked resource and inline its content below the card.role="button",aria-expanded,aria-label, keyboard handlers, focus ring.Scope (V2)
resource_linkbranch inContentViewerwith a proper presentation showing uri / name / description / mimeType.ContentViewer/resource content components, rather than V1'sJsonView).--inspector-*tokens per the project conventions (no raw hex, no inline styles, no Tailwind classes carried over from V1).src/components/elements/if it warrants its own documented component (e.g.ResourceLink), with Storybook coverage.Acceptance criteria
resource_linkin tool results (and anywhereContentViewerrenders) shows uri, name, description, and mimeType (when present).npm run validate,test:integration, andtest:storybookpass.References
client/src/components/ResourceLinkView.tsx,client/src/components/ToolResults.tsxclients/web/src/components/elements/ContentViewer/ContentViewer.tsx