feat: demo gallery prompt collection#68
Conversation
Restore and simplify the demo gallery components. Cards are now compact clickable prompts in a single-column list instead of a grid with large preview areas. Clicking a card sends its prompt to the chat.
Replace deprecated appendMessage/useCopilotChat with sendMessage/useCopilotChatInternal to fix "isResultMessage is not a function" error when clicking demo cards.
GeneralJerel
left a comment
There was a problem hiding this comment.
PR #68 Review: Demo Gallery Prompt Collection
Issues
1. useCopilotChatInternal is an internal/private API — High severity
The import in page.tsx uses useCopilotChatInternal from @copilotkit/react-core (the v1 module). This is clearly an internal hook — the name says so, and it's not part of the documented public API. The commit message mentions this was a workaround for an isResultMessage is not a function error with the public useCopilotChat API.
The safer approach would be to use useCopilotChat (the public v1 hook) and call its sendMessage, or use the useCopilotChatHeadless_c hook which documents sendMessage with the exact { id, role, content } shape this PR uses. Either way, relying on an Internal hook means this could break silently on any CopilotKit update.
2. Mixing v1 and v2 APIs — Medium severity
page.tsx imports CopilotChat from @copilotkit/react-core/v2 but useCopilotChatInternal from @copilotkit/react-core (v1). Mixing API versions is fragile — if v2 evolves its message format or context providers, the v1 internal hook may not see the right context.
3. Keyboard accessibility: no Escape-to-close on drawer — Low severity
The drawer in index.tsx closes via backdrop click but has no keyboard handler for Escape. Also, when the drawer opens, focus isn't trapped — a keyboard user can tab behind the backdrop.
4. SVG icon duplication — Nit
The 4-square grid icon SVG is duplicated verbatim in page.tsx (Demos button) and index.tsx (drawer header). Could extract to a small component or constant.
Things done well
- Clean separation:
demo-data.tsfor content,demo-card.tsx/category-filter.tsx/index.tsxfor UI — easy to extend. - Category filter with the gradient active state matches the existing design system nicely.
- The
DemoCardis a<button>(not a<div>with an onClick), which is correct for accessibility. - Drawer width is capped at
90vwfor mobile responsiveness.
Recommendation
The useCopilotChatInternal usage is the main blocker. If useCopilotChat genuinely throws isResultMessage is not a function, that's likely a CopilotKit bug worth reporting upstream — but the fix shouldn't be to reach into internals. Try useCopilotChatHeadless_c or investigate the root cause of the error. Everything else looks solid.
Replace internal useCopilotChatInternal hook with public useAgent + useCopilotKit from @copilotkit/react-core/v2. Add Escape key handler to close the demo gallery drawer. Extract duplicated grid SVG into a shared GridIcon component.
Summary
sendMessageAPITest plan
🤖 Generated with Claude Code