Add FlowIconText component for UI v2 migration#9
Conversation
Create a new FlowIconText component that displays a flow's icon and name as a clickable link, fetching flow data by ID. This component follows the existing Suspense pattern used in similar link components like FlowLink and DeploymentLink. Files added: - flow-icon-text.tsx: Main component with Suspense wrapper - flow-icon-text.stories.tsx: Storybook stories - flow-icon-text.test.tsx: Unit tests - index.ts: Export file Co-Authored-By: alex.s@prefect.io <ajstreed1@gmail.com>
Add RouterProvider decorator to the Storybook story so the component renders correctly in Storybook. The Link component from TanStack Router requires a router context to function properly. Co-Authored-By: alex.s@prefect.io <ajstreed1@gmail.com>
📝 WalkthroughWalkthroughA new FlowIconText component has been added that fetches and displays flow details. The component uses React Query for data fetching with Suspense boundaries and renders a clickable link with an icon. Accompanying Storybook story and barrel export files have been created. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@ui-v2/src/components/flows/flow-icon-text/flow-icon-text.stories.tsx`:
- Around line 12-18: The story uses two different QueryClient instances (the
module-level QueryClient and a second inline QueryClient passed to the router
context), causing cache inconsistencies and state leakage between stories;
update the decorator to create a fresh QueryClient per invocation and reuse that
same instance for both the QueryClientProvider and any router/test providers so
all hooks share one client and each story gets an isolated client (refer to
QueryClient, new QueryClient(...), and QueryClientProvider in the file).
In `@ui-v2/src/components/flows/flow-icon-text/flow-icon-text.tsx`:
- Line 6: The Suspense boundary in flow-icon-text.tsx is missing a fallback and
the imported Skeleton is unused; update the <Suspense> wrapping the async
content (look for the Suspense component in FlowIconText or
FlowIconTextSuspense) to pass a fallback prop that renders the imported Skeleton
component for loading state, and if you decide not to use Skeleton remove its
import to avoid the unused import warning; ensure the fallback matches the
component's size/props so the Skeleton visually fits the icon/text area.
| const queryClient = new QueryClient({ | ||
| defaultOptions: { | ||
| queries: { | ||
| retry: false, | ||
| }, | ||
| }, | ||
| }); |
There was a problem hiding this comment.
Inconsistent QueryClient instances.
Two different QueryClient instances are used: one at module level (Line 12) passed to QueryClientProvider, and another created inline (Line 32) passed to the router context. This mismatch could cause cache inconsistencies if components or hooks expect data from the same client.
Additionally, the module-level QueryClient persists across story renders, potentially causing state pollution between stories.
Proposed fix: use consistent QueryClient
const createTestRouter = (flowId: string) => {
const rootRoute = createRootRoute({
component: () => (
<Suspense fallback={<div>Loading...</div>}>
<FlowIconText flowId={flowId} />
</Suspense>
),
});
return createRouter({
routeTree: rootRoute,
history: createMemoryHistory({ initialEntries: ["/"] }),
- context: { queryClient: new QueryClient() },
+ context: { queryClient },
});
};Alternatively, create a fresh QueryClient per decorator invocation to isolate story state.
Also applies to: 29-33
🤖 Prompt for AI Agents
In `@ui-v2/src/components/flows/flow-icon-text/flow-icon-text.stories.tsx` around
lines 12 - 18, The story uses two different QueryClient instances (the
module-level QueryClient and a second inline QueryClient passed to the router
context), causing cache inconsistencies and state leakage between stories;
update the decorator to create a fresh QueryClient per invocation and reuse that
same instance for both the QueryClientProvider and any router/test providers so
all hooks share one client and each story gets an isolated client (refer to
QueryClient, new QueryClient(...), and QueryClientProvider in the file).
| import { Suspense } from "react"; | ||
| import { buildFLowDetailsQuery } from "@/api/flows"; | ||
| import { Icon } from "@/components/ui/icons"; | ||
| import { Skeleton } from "@/components/ui/skeleton"; |
There was a problem hiding this comment.
Skeleton imported but unused; Suspense missing fallback.
The Skeleton component is imported but never used. The <Suspense> boundary has no fallback prop, so nothing renders while the query is pending. Consider using the imported Skeleton as the fallback for better loading UX.
Proposed fix
export const FlowIconText = ({ flowId }: FlowIconTextProps) => {
return (
- <Suspense>
+ <Suspense fallback={<Skeleton className="h-4 w-24" />}>
<FlowIconTextImplementation flowId={flowId} />
</Suspense>
);
};Also applies to: 14-14
🤖 Prompt for AI Agents
In `@ui-v2/src/components/flows/flow-icon-text/flow-icon-text.tsx` at line 6, The
Suspense boundary in flow-icon-text.tsx is missing a fallback and the imported
Skeleton is unused; update the <Suspense> wrapping the async content (look for
the Suspense component in FlowIconText or FlowIconTextSuspense) to pass a
fallback prop that renders the imported Skeleton component for loading state,
and if you decide not to use Skeleton remove its import to avoid the unused
import warning; ensure the fallback matches the component's size/props so the
Skeleton visually fits the icon/text area.
Benchmark PR from agentic-review-benchmarks#9
Summary by CodeRabbit