ui: card layout for shared components with collapsible kind sections#85
ui: card layout for shared components with collapsible kind sections#85TerrifiedBug merged 1 commit intomainfrom
Conversation
Replace table rows with card grid on the shared components list page to match the visual style used elsewhere in the library. Group the component catalog on the create page into collapsible Source/Transform/Sink sections so the long list is easier to navigate.
Greptile SummaryThis PR refactors two library pages to use a card-grid layout inside collapsible kind sections, replacing the previous table-row layout in
Confidence Score: 4/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[SharedComponentsPage] --> B{selectedEnvironmentId?}
B -- No --> C[Prompt to select environment]
B -- Yes --> D[useQuery sharedComponent.list]
D --> E{filtered.length == 0?}
E -- Yes --> F[Empty state]
E -- No --> G[grouped by KIND_ORDER]
G --> H[KindSection SOURCE]
G --> I[KindSection TRANSFORM]
G --> J[KindSection SINK]
H & I & J --> K[Collapsible header + Card grid]
K --> L[onClick → router.push detail page]
M[NewSharedComponentPage] --> N{step}
N -- select --> O[filteredCatalog via useMemo]
O --> P{filteredCatalog.length == 0?}
P -- Yes --> Q[Empty search state]
P -- No --> R[groupedCatalog via useMemo]
R --> S[CatalogKindSection × 3]
S --> T[onClick → handleSelectComponent]
T --> U[step = configure]
N -- configure --> V[SchemaForm + Details card]
V --> W[createMutation.mutate]
Last reviewed commit: 99df614 |
| {items.map((sc) => ( | ||
| <button | ||
| <Card | ||
| key={sc.id} | ||
| className="cursor-pointer transition-colors hover:bg-accent/50" | ||
| onClick={() => onItemClick(sc.id)} | ||
| className="flex w-full cursor-pointer items-center gap-4 px-4 py-3 text-left transition-colors hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset" | ||
| > | ||
| <Link2 className="h-4 w-4 shrink-0 text-muted-foreground" /> | ||
| <div className="min-w-0 flex-1"> | ||
| <p className="truncate text-sm font-medium">{sc.name}</p> | ||
| <CardHeader className="pb-2"> | ||
| <div className="flex items-start justify-between gap-2"> | ||
| <CardTitle className="text-sm">{sc.name}</CardTitle> | ||
| <Badge variant="outline" className={cn("text-xs", badgeClass)}> | ||
| v{sc.version} | ||
| </Badge> | ||
| </div> | ||
| </CardHeader> | ||
| <CardContent> | ||
| <p className="text-xs text-muted-foreground">{sc.componentType}</p> | ||
| </div> | ||
| <div className="flex items-center gap-3 shrink-0 text-xs text-muted-foreground"> | ||
| <span>{sc.linkedPipelineCount} linked</span> | ||
| <Badge variant="outline" className={cn("text-xs", badgeClass)}> | ||
| v{sc.version} | ||
| </Badge> | ||
| <span className="w-16 text-right">{formatRelativeTime(sc.updatedAt)}</span> | ||
| </div> | ||
| </button> | ||
| <div className="mt-2 flex items-center gap-2 text-xs text-muted-foreground"> | ||
| <Link2 className="h-3 w-3" /> | ||
| <span>{sc.linkedPipelineCount} linked</span> | ||
| <span className="ml-auto">{formatRelativeTime(sc.updatedAt)}</span> | ||
| </div> | ||
| </CardContent> | ||
| </Card> | ||
| ))} |
There was a problem hiding this comment.
Keyboard accessibility regression
The previous implementation used a native <button> element (see the diff), which is natively keyboard-focusable (Tab) and activatable (Enter/Space). The replacement <Card> renders as a <div>, which receives no keyboard focus by default, and the focus-visible:ring styles were removed along with it.
Users who navigate with a keyboard or assistive technology can no longer reach or activate individual component cards. To restore the original behaviour, add tabIndex={0}, role="button", an onKeyDown handler, and the focus-visible ring classes back to the <Card>.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/app/(dashboard)/library/shared-components/page.tsx
Line: 226-249
Comment:
**Keyboard accessibility regression**
The previous implementation used a native `<button>` element (see the diff), which is natively keyboard-focusable (Tab) and activatable (Enter/Space). The replacement `<Card>` renders as a `<div>`, which receives no keyboard focus by default, and the `focus-visible:ring` styles were removed along with it.
Users who navigate with a keyboard or assistive technology can no longer reach or activate individual component cards. To restore the original behaviour, add `tabIndex={0}`, `role="button"`, an `onKeyDown` handler, and the focus-visible ring classes back to the `<Card>`.
How can I resolve this? If you propose a fix, please make it concise.
Summary
Test plan
/library/shared-components— existing components render as cards in a grid within collapsible kind sections/library/shared-components/new— catalog grouped by Sources, Transforms, Sinks with collapsible headers