Skip to content

feat(drawer): CopilotDrawer host theming, mobile launcher, action icons + thread-management/tooltip fixes - #5707

Merged
BenTaylorDev merged 6 commits into
mainfrom
feat/copilot-drawer-ux-polish
Jun 28, 2026
Merged

BenTaylorDev merged 6 commits into
mainfrom
feat/copilot-drawer-ux-polish

Conversation

@BenTaylorDev

@BenTaylorDev BenTaylorDev commented Jun 25, 2026 •

Copy link
Copy Markdown
Contributor

CopilotDrawer — SDK polish + thread-management fixes

Polish and fixes on top of the shipped <copilotkit-drawer> (#5701), surfaced by real de-fork pilots run against a locally-built SDK + the hosted Intelligence runtime: langgraph-js (rich canvas / inline CopilotChat / dark theme) and mastra (the proverbs CoAgents demo / CopilotSidebar / light theme / controlled→uncontrolled provider). Spans @copilotkit/web-components and @copilotkit/react-core — no example/de-fork changes here (those wait on a release that publishes web-components + a react-core bump that includes CopilotDrawer). Captured as Phase-5 acceptance requirements in the design doc.

react-core — thread management

  • Thread switching works under <CopilotKit>. CopilotChatConfigurationProvider treated any threadId prop as controlled, so the auto-minted, non-explicit threadId that <CopilotKit>'s v1 bridge seeds blocked the drawer's imperative setActiveThreadId / startNewThread — thread switching and "+ New" were dead in every app wrapped in <CopilotKit>. A non-explicit (hasExplicitThreadId={false}) threadId is now overridable; a genuine caller-supplied threadId stays controlled.
  • "+ New" resets the chat. CopilotChat clears messages when switching to a fresh non-explicit thread so the welcome screen shows instead of the prior thread's messages — including when a still-loading /connect is superseded by the switch (the aborted connect's stale snapshot is dropped instead of repopulating the view).
  • No upsell flash/stick. CopilotDrawer treats a pending (null) license status as loading, not unlicensed, so the upgrade upsell no longer flashes (or sticks) before the runtime reports the license.
  • In-header drawer launcher is mobile-only. CopilotModalHeader.DrawerLauncher toggles drawerOpen, which only drives the off-canvas mobile drawer; on desktop the drawer is a persistent in-flow panel that ignores open, so the launcher was a dead no-op there. It now renders only at ≤767px. On desktop the chat's own open/close (the toggle FAB + the header close, both lucide X) is the consistent pair.

web-components — theming, launcher, icons, tooltips

  • Host-theme inheritance (incl. dark mode). Each token now resolves --cpk-drawer-* override → host theme var (--background/--card/--foreground/--border/…) → built-in light default. The drawer follows the host app's light/dark theme by inheritance, instead of baking light-only values (it showed a light drawer on a dark app). Custom properties aren't reset by the :host { all: initial } guard, so the standalone fallback still holds.
  • Row actions are icon buttons with instant, on-brand tooltips. Archive / Unarchive / Delete render inline lucide-style SVGs (currentColor). Native title is replaced by an instant CSS tooltip (matches the React components' Radix delayDuration: 0; title's show-delay is browser-fixed at ~1.5s), styled to match the standard CopilotKit tooltip — a primary-colored bubble with an arrow, not a surface/bordered box — and positioned to the side so the list's scroll-overflow never clips it. The tooltip is suppressed while the delete-confirm dialog is open (the clicked trash button keeps :focus-visible otherwise, leaving its "Delete" tooltip floating over the dialog).
  • Clipped thread names get a tooltip. A truncated name exposes its full text via the same instant primary-bubble tooltip as the row actions (not the native title), shown only when actually clipped. The name text moved to an inner span (so the outer can host the un-clipped bubble) and the hovered row is z-lifted (each row is its own stacking context from the entry-animation transform, which otherwise painted the bubble under later rows).
  • Archived rows are muted, no longer struck through.
  • Refetch preserves the list. A refetch (e.g. Active↔All toggle) keeps the known threads visible; the full loading state only renders on the initial empty fetch.
  • Empty footer region hides (it rendered as a stray bordered box at the bottom). Driven by a slotchange listener, mirroring the memories region.
  • Self-owned mobile launcher. When the drawer is a closed off-canvas mobile modal it renders its own floating "open threads" launcher, so it's always openable without the host wiring a header button. The icon is swappable via a launcher-icon slot, position is themeable via --cpk-drawer-launcher-top / --cpk-drawer-launcher-left (so a host can center it on its own header controls), and it exposes part="launcher". The richer in-header CopilotModalHeader.DrawerLauncher remains an optional integration.

Tests

  • react-core: thread-control + non-explicit-override cases on CopilotChatConfigurationProvider, the "+ New" message reset on CopilotChat, license-pending gating on CopilotDrawer, and the mobile-only / desktop-hidden launcher on CopilotModalHeader. New regression tests verified red-green; chat + provider suites green, tsc --noEmit clean, build green. (The superseded-connect race guard is covered by live verification + its synchronous sibling test — an async-timing unit test would be flaky, which the repo treats as a bug.)
  • web-components: element tests for the icon tooltips + confirm-dialog suppression, the clipped-name tooltip (data-tooltip + placeholder), archived styling, refetch-preserves-list, footer hide-when-empty, and mobile launcher render/open + desktop-absent. Drawer suite green, tsc --noEmit clean, build + es-check green under CI=true. (Truncation detection + tooltip stacking are layout/CSS — verified live, not in jsdom.)

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

📣 Social Copy Generator

Generate social media copies (Twitter/X, LinkedIn, Blog Post) for this PR using Claude.

  • Generate social media copies

@pkg-pr-new

pkg-pr-new Bot commented Jun 25, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@copilotkit/a2ui-renderer

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/a2ui-renderer@5707

@copilotkit/agentcore-runner

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/agentcore-runner@5707

@copilotkit/angular

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/angular@5707

@copilotkit/bot

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/bot@5707

@copilotkit/bot-discord

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/bot-discord@5707

@copilotkit/bot-slack

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/bot-slack@5707

@copilotkit/bot-store-postgres

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/bot-store-postgres@5707

@copilotkit/bot-store-redis

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/bot-store-redis@5707

@copilotkit/bot-teams

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/bot-teams@5707

@copilotkit/bot-telegram

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/bot-telegram@5707

@copilotkit/bot-ui

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/bot-ui@5707

@copilotkit/bot-whatsapp

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/bot-whatsapp@5707

@copilotkit/core

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/core@5707

@copilotkit/react-core

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/react-core@5707

@copilotkit/react-native

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/react-native@5707

@copilotkit/react-textarea

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/react-textarea@5707

@copilotkit/react-ui

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/react-ui@5707

@copilotkit/runtime

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/runtime@5707

@copilotkit/runtime-client-gql

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/runtime-client-gql@5707

@copilotkit/sdk-js

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/sdk-js@5707

@copilotkit/shared

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/shared@5707

@copilotkit/sqlite-runner

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/sqlite-runner@5707

@copilotkit/voice

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/voice@5707

@copilotkit/vue

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/vue@5707

@copilotkit/web-components

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/web-components@5707

@copilotkit/web-inspector

pnpm add https://pkg.pr.new/CopilotKit/CopilotKit/@copilotkit/web-inspector@5707

commit: 9223fc4

@github-actions

github-actions Bot commented Jun 25, 2026 •

Copy link
Copy Markdown
Contributor

Size Change: +1.44 kB (+0.13%)

Total Size: 1.1 MB

📦 View Changed
Filename Size Change
packages/react-core/dist/copilotkit-8cZqc9mL.cjs 103 kB +103 kB (new file) 🆕
packages/react-core/dist/copilotkit-Dzrz8zaa.mjs 0 B -101 kB (removed) 🏆
packages/react-core/dist/copilotkit-G9XgUKGG.cjs 0 B -103 kB (removed) 🏆
packages/react-core/dist/copilotkit-IOLu2tC4.mjs 102 kB +102 kB (new file) 🆕
packages/react-core/dist/index.umd.js 65.6 kB +34 B (+0.05%)
packages/react-core/dist/v2/headless.cjs 12.6 kB +32 B (+0.25%)
packages/react-core/dist/v2/headless.mjs 12 kB +34 B (+0.28%)
packages/react-core/dist/v2/index.cjs 1.17 kB +1 B (+0.09%)
packages/react-core/dist/v2/index.umd.js 103 kB +495 B (+0.48%)
ℹ️ View Unchanged
Filename Size
packages/a2ui-renderer/dist/_virtual/_rolldown/runtime.cjs 516 B
packages/a2ui-renderer/dist/a2ui-types.cjs 172 B
packages/a2ui-renderer/dist/a2ui-types.mjs 171 B
packages/a2ui-renderer/dist/index.cjs 842 B
packages/a2ui-renderer/dist/index.mjs 563 B
packages/a2ui-renderer/dist/index.umd.js 12.2 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/A2uiSurface.cjs 1.49 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/A2uiSurface.mjs 1.43 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/adapter.cjs 1.07 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/adapter.mjs 1.01 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/AudioPlayer.cjs 904 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/AudioPlayer.mjs 492 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Button.cjs 1 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Button.mjs 596 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Card.cjs 829 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Card.mjs 419 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/CheckBox.cjs 1.1 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/CheckBox.mjs 1.02 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/ChildList.cjs 799 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/ChildList.mjs 737 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/ChoicePicker.cjs 1.63 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/ChoicePicker.mjs 1.57 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Column.cjs 856 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Column.mjs 802 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/DateTimeInput.cjs 1.12 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/DateTimeInput.mjs 1.05 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Divider.cjs 842 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Divider.mjs 432 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Icon.cjs 877 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Icon.mjs 469 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Image.cjs 995 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Image.mjs 587 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/List.cjs 920 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/List.mjs 508 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Modal.cjs 1.19 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Modal.mjs 1.13 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Row.cjs 855 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Row.mjs 801 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Slider.cjs 1.06 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Slider.mjs 984 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Tabs.cjs 1.1 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Tabs.mjs 1.04 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Text.cjs 903 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Text.mjs 489 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/TextField.cjs 1.21 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/TextField.mjs 1.14 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Video.cjs 788 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/components/Video.mjs 378 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/index.cjs 928 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/index.mjs 855 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/utils.cjs 579 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/basic/utils.mjs 556 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Button.cjs 982 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Button.mjs 580 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/ChildList.cjs 800 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/ChildList.mjs 735 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Column.cjs 1.08 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Column.mjs 1.02 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Row.cjs 1.07 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Row.mjs 1.01 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Text.cjs 894 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/Text.mjs 839 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/TextField.cjs 1.21 kB
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/components/TextField.mjs 802 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/index.cjs 849 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/catalog/minimal/index.mjs 804 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/index.cjs 310 B
packages/a2ui-renderer/dist/react-renderer/a2ui-react/index.mjs 325 B
packages/a2ui-renderer/dist/react-renderer/catalog-utils.cjs 1.59 kB
packages/a2ui-renderer/dist/react-renderer/catalog-utils.mjs 1.52 kB
packages/a2ui-renderer/dist/react-renderer/core/A2UIProvider.cjs 1.5 kB
packages/a2ui-renderer/dist/react-renderer/core/A2UIProvider.mjs 1.42 kB
packages/a2ui-renderer/dist/react-renderer/core/A2UIRenderer.cjs 728 B
packages/a2ui-renderer/dist/react-renderer/core/A2UIRenderer.mjs 671 B
packages/a2ui-renderer/dist/react-renderer/create-catalog.cjs 1.35 kB
packages/a2ui-renderer/dist/react-renderer/create-catalog.mjs 1.28 kB
packages/a2ui-renderer/dist/react-renderer/hooks/useA2UI.cjs 316 B
packages/a2ui-renderer/dist/react-renderer/hooks/useA2UI.mjs 309 B
packages/a2ui-renderer/dist/react-renderer/index.cjs 399 B
packages/a2ui-renderer/dist/react-renderer/index.mjs 515 B
packages/a2ui-renderer/dist/react-renderer/lib/utils.cjs 236 B
packages/a2ui-renderer/dist/react-renderer/lib/utils.mjs 188 B
packages/a2ui-renderer/dist/react-renderer/styles/index.cjs 239 B
packages/a2ui-renderer/dist/react-renderer/styles/index.mjs 231 B
packages/a2ui-renderer/dist/react-renderer/theme/ThemeContext.cjs 436 B
packages/a2ui-renderer/dist/react-renderer/theme/ThemeContext.mjs 381 B
packages/a2ui-renderer/dist/web-components/_virtual/_rolldown/runtime.cjs 260 B
packages/a2ui-renderer/dist/web-components/_virtual/_rolldown/runtime.mjs 258 B
packages/a2ui-renderer/dist/web-components/adapter.cjs 346 B
packages/a2ui-renderer/dist/web-components/adapter.mjs 335 B
packages/a2ui-renderer/dist/web-components/bound-component.cjs 670 B
packages/a2ui-renderer/dist/web-components/bound-component.mjs 662 B
packages/a2ui-renderer/dist/web-components/catalog/basic/audio-player.cjs 536 B
packages/a2ui-renderer/dist/web-components/catalog/basic/audio-player.mjs 492 B
packages/a2ui-renderer/dist/web-components/catalog/basic/button.cjs 647 B
packages/a2ui-renderer/dist/web-components/catalog/basic/button.mjs 604 B
packages/a2ui-renderer/dist/web-components/catalog/basic/card.cjs 448 B
packages/a2ui-renderer/dist/web-components/catalog/basic/card.mjs 402 B
packages/a2ui-renderer/dist/web-components/catalog/basic/check-box.cjs 743 B
packages/a2ui-renderer/dist/web-components/catalog/basic/check-box.mjs 695 B
packages/a2ui-renderer/dist/web-components/catalog/basic/choice-picker.cjs 1.27 kB
packages/a2ui-renderer/dist/web-components/catalog/basic/choice-picker.mjs 1.24 kB
packages/a2ui-renderer/dist/web-components/catalog/basic/column.cjs 474 B
packages/a2ui-renderer/dist/web-components/catalog/basic/column.mjs 431 B
packages/a2ui-renderer/dist/web-components/catalog/basic/components.cjs 482 B
packages/a2ui-renderer/dist/web-components/catalog/basic/components.mjs 424 B
packages/a2ui-renderer/dist/web-components/catalog/basic/date-time-input.cjs 756 B
packages/a2ui-renderer/dist/web-components/catalog/basic/date-time-input.mjs 714 B
packages/a2ui-renderer/dist/web-components/catalog/basic/divider.cjs 450 B
packages/a2ui-renderer/dist/web-components/catalog/basic/divider.mjs 404 B
packages/a2ui-renderer/dist/web-components/catalog/basic/icon.cjs 504 B
packages/a2ui-renderer/dist/web-components/catalog/basic/icon.mjs 455 B
packages/a2ui-renderer/dist/web-components/catalog/basic/ids.cjs 192 B
packages/a2ui-renderer/dist/web-components/catalog/basic/ids.mjs 190 B
packages/a2ui-renderer/dist/web-components/catalog/basic/image.cjs 624 B
packages/a2ui-renderer/dist/web-components/catalog/basic/image.mjs 578 B
packages/a2ui-renderer/dist/web-components/catalog/basic/index.cjs 465 B
packages/a2ui-renderer/dist/web-components/catalog/basic/index.mjs 526 B
packages/a2ui-renderer/dist/web-components/catalog/basic/list.cjs 534 B
packages/a2ui-renderer/dist/web-components/catalog/basic/list.mjs 483 B
packages/a2ui-renderer/dist/web-components/catalog/basic/modal.cjs 842 B
packages/a2ui-renderer/dist/web-components/catalog/basic/modal.mjs 800 B
packages/a2ui-renderer/dist/web-components/catalog/basic/row.cjs 471 B
packages/a2ui-renderer/dist/web-components/catalog/basic/row.mjs 427 B
packages/a2ui-renderer/dist/web-components/catalog/basic/slider.cjs 701 B
packages/a2ui-renderer/dist/web-components/catalog/basic/slider.mjs 653 B
packages/a2ui-renderer/dist/web-components/catalog/basic/tabs.cjs 780 B
packages/a2ui-renderer/dist/web-components/catalog/basic/tabs.mjs 730 B
packages/a2ui-renderer/dist/web-components/catalog/basic/text-field.cjs 857 B
packages/a2ui-renderer/dist/web-components/catalog/basic/text-field.mjs 814 B
packages/a2ui-renderer/dist/web-components/catalog/basic/text.cjs 553 B
packages/a2ui-renderer/dist/web-components/catalog/basic/text.mjs 501 B
packages/a2ui-renderer/dist/web-components/catalog/basic/utils.cjs 484 B
packages/a2ui-renderer/dist/web-components/catalog/basic/utils.mjs 462 B
packages/a2ui-renderer/dist/web-components/catalog/basic/video.cjs 400 B
packages/a2ui-renderer/dist/web-components/catalog/basic/video.mjs 352 B
packages/a2ui-renderer/dist/web-components/catalog/children.cjs 302 B
packages/a2ui-renderer/dist/web-components/catalog/children.mjs 300 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/button.cjs 629 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/button.mjs 584 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/column.cjs 609 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/column.mjs 559 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/components.cjs 245 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/components.mjs 263 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/index.cjs 724 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/index.mjs 654 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/row.cjs 593 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/row.mjs 544 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/text-field.cjs 874 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/text-field.mjs 822 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/text.cjs 509 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/text.mjs 477 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/utils.cjs 291 B
packages/a2ui-renderer/dist/web-components/catalog/minimal/utils.mjs 287 B
packages/a2ui-renderer/dist/web-components/create-catalog.cjs 1.89 kB
packages/a2ui-renderer/dist/web-components/create-catalog.mjs 1.83 kB
packages/a2ui-renderer/dist/web-components/define.cjs 440 B
packages/a2ui-renderer/dist/web-components/define.mjs 341 B
packages/a2ui-renderer/dist/web-components/index.cjs 960 B
packages/a2ui-renderer/dist/web-components/index.mjs 655 B
packages/a2ui-renderer/dist/web-components/node.cjs 1.05 kB
packages/a2ui-renderer/dist/web-components/node.mjs 1.04 kB
packages/a2ui-renderer/dist/web-components/surface.cjs 2.83 kB
packages/a2ui-renderer/dist/web-components/surface.mjs 2.81 kB
packages/core/dist/index.cjs 35.8 kB
packages/core/dist/index.mjs 35.5 kB
packages/core/dist/index.umd.js 38.4 kB
packages/react-core/dist/index.cjs 16.9 kB
packages/react-core/dist/index.mjs 16.8 kB
packages/react-core/dist/v2/context.cjs 1.55 kB
packages/react-core/dist/v2/context.mjs 1.47 kB
packages/react-core/dist/v2/index.mjs 1.01 kB
packages/react-textarea/dist/index.cjs 18.1 kB
packages/react-textarea/dist/index.mjs 17.4 kB
packages/react-textarea/dist/index.umd.js 18.8 kB
packages/react-ui/dist/index.cjs 24.6 kB
packages/react-ui/dist/index.mjs 23.9 kB
packages/react-ui/dist/index.umd.js 25.8 kB
packages/runtime-client-gql/dist/_virtual/_rolldown/runtime.cjs 516 B
packages/runtime-client-gql/dist/client/conversion.cjs 1.52 kB
packages/runtime-client-gql/dist/client/conversion.mjs 1.45 kB
packages/runtime-client-gql/dist/client/CopilotRuntimeClient.cjs 1.48 kB
packages/runtime-client-gql/dist/client/CopilotRuntimeClient.mjs 1.44 kB
packages/runtime-client-gql/dist/client/types.cjs 701 B
packages/runtime-client-gql/dist/client/types.mjs 642 B
packages/runtime-client-gql/dist/graphql/@generated/gql.cjs 850 B
packages/runtime-client-gql/dist/graphql/@generated/gql.mjs 850 B
packages/runtime-client-gql/dist/graphql/@generated/graphql.cjs 2.4 kB
packages/runtime-client-gql/dist/graphql/@generated/graphql.mjs 2.36 kB
packages/runtime-client-gql/dist/graphql/definitions/mutations.cjs 740 B
packages/runtime-client-gql/dist/graphql/definitions/mutations.mjs 732 B
packages/runtime-client-gql/dist/graphql/definitions/queries.cjs 316 B
packages/runtime-client-gql/dist/graphql/definitions/queries.mjs 304 B
packages/runtime-client-gql/dist/index.cjs 679 B
packages/runtime-client-gql/dist/index.mjs 495 B
packages/runtime-client-gql/dist/index.umd.js 9.49 kB
packages/runtime-client-gql/dist/message-conversion/agui-to-gql.cjs 1.72 kB
packages/runtime-client-gql/dist/message-conversion/agui-to-gql.mjs 1.7 kB
packages/runtime-client-gql/dist/message-conversion/gql-to-agui.cjs 1.56 kB
packages/runtime-client-gql/dist/message-conversion/gql-to-agui.mjs 1.53 kB
packages/runtime-client-gql/dist/package.cjs 181 B
packages/runtime-client-gql/dist/package.mjs 116 B
packages/shared/dist/_virtual/_rolldown/runtime.cjs 516 B
packages/shared/dist/a2ui-prompts.cjs 2.85 kB
packages/shared/dist/a2ui-prompts.mjs 2.85 kB
packages/shared/dist/attachments/utils.cjs 1.74 kB
packages/shared/dist/attachments/utils.mjs 1.7 kB
packages/shared/dist/constants/index.cjs 362 B
packages/shared/dist/constants/index.mjs 345 B
packages/shared/dist/debug.cjs 454 B
packages/shared/dist/debug.mjs 452 B
packages/shared/dist/finalize-events.cjs 1.09 kB
packages/shared/dist/finalize-events.mjs 1.05 kB
packages/shared/dist/index.cjs 1.99 kB
packages/shared/dist/index.mjs 1.66 kB
packages/shared/dist/index.umd.js 20.3 kB
packages/shared/dist/logger.cjs 112 B
packages/shared/dist/logger.mjs 112 B
packages/shared/dist/package.cjs 181 B
packages/shared/dist/package.mjs 116 B
packages/shared/dist/standard-schema.cjs 740 B
packages/shared/dist/standard-schema.mjs 737 B
packages/shared/dist/telemetry/lambda-client.cjs 1.14 kB
packages/shared/dist/telemetry/lambda-client.mjs 1.13 kB
packages/shared/dist/telemetry/telemetry-client.cjs 1.33 kB
packages/shared/dist/telemetry/telemetry-client.mjs 1.27 kB
packages/shared/dist/telemetry/utils.cjs 321 B
packages/shared/dist/telemetry/utils.mjs 277 B
packages/shared/dist/transcription-errors.cjs 951 B
packages/shared/dist/transcription-errors.mjs 944 B
packages/shared/dist/utils/clipboard.cjs 407 B
packages/shared/dist/utils/clipboard.mjs 405 B
packages/shared/dist/utils/conditions.cjs 540 B
packages/shared/dist/utils/conditions.mjs 536 B
packages/shared/dist/utils/console-styling.cjs 1.24 kB
packages/shared/dist/utils/console-styling.mjs 1.22 kB
packages/shared/dist/utils/errors.cjs 4.51 kB
packages/shared/dist/utils/errors.mjs 4.41 kB
packages/shared/dist/utils/index.cjs 1.39 kB
packages/shared/dist/utils/index.mjs 1.65 kB
packages/shared/dist/utils/json-schema.cjs 1.97 kB
packages/shared/dist/utils/json-schema.mjs 1.91 kB
packages/shared/dist/utils/random-id.cjs 618 B
packages/shared/dist/utils/random-id.mjs 559 B
packages/shared/dist/utils/requests.cjs 706 B
packages/shared/dist/utils/requests.mjs 704 B
packages/shared/dist/utils/types.cjs 161 B
packages/shared/dist/utils/types.mjs 160 B
packages/voice/dist/_virtual/_rolldown/runtime.cjs 516 B
packages/voice/dist/index.cjs 175 B
packages/voice/dist/index.mjs 95 B
packages/voice/dist/index.umd.js 1.5 kB
packages/voice/dist/transcription/transcription-service-openai.cjs 495 B
packages/voice/dist/transcription/transcription-service-openai.mjs 434 B
packages/web-inspector/dist/assets/inspector-logo-icon.cjs 499 B
packages/web-inspector/dist/assets/inspector-logo-icon.mjs 434 B
packages/web-inspector/dist/assets/inspector-logo.cjs 4.32 kB
packages/web-inspector/dist/assets/inspector-logo.mjs 4.23 kB
packages/web-inspector/dist/index.cjs 46.4 kB
packages/web-inspector/dist/index.mjs 46.4 kB
packages/web-inspector/dist/index.umd.js 63.4 kB
packages/web-inspector/dist/lib/context-helpers.cjs 862 B
packages/web-inspector/dist/lib/context-helpers.mjs 830 B
packages/web-inspector/dist/lib/persistence.cjs 1.2 kB
packages/web-inspector/dist/lib/persistence.mjs 1.16 kB
packages/web-inspector/dist/lib/telemetry.cjs 2.26 kB
packages/web-inspector/dist/lib/telemetry.mjs 2.2 kB
packages/web-inspector/dist/package.cjs 181 B
packages/web-inspector/dist/package.mjs 116 B
packages/web-inspector/dist/styles/generated.cjs 6.41 kB
packages/web-inspector/dist/styles/generated.mjs 6.35 kB

compressed-size-action

@BenTaylorDev BenTaylorDev changed the title feat(web-components): CopilotDrawer host-theme inheritance, action icons, self-owned mobile launcher, and UX fixes feat(drawer): CopilotDrawer host theming, mobile launcher, action icons + thread-management/tooltip fixes Jun 26, 2026
@BenTaylorDev
BenTaylorDev marked this pull request as draft June 26, 2026 16:40
@BenTaylorDev
BenTaylorDev marked this pull request as ready for review June 26, 2026 21:30

@MikeRyanDev MikeRyanDev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found one blocking issue in the clipped-name tooltip change.

In packages/web-components/src/drawer/styles.ts, the stacking fix is written as .row.name-clipped:hover { z-index: 2; }, but _syncNameClipping() toggles name-clipped on the .row-name element, not on the surrounding li.row. That selector never matches, so the intended z-lift does not run. Because each row has its own transform-created stacking context, clipped-name tooltips can still paint under later rows, which is the exact visual issue this PR says it fixes.

Please apply the clipped state to the row (or otherwise make the z-index rule target the actual row stacking context) and add coverage/assertion for that class/selector contract.

…ons, self-owned mobile launcher, and UX fixes

Polish on top of the shipped <copilotkit-drawer> (#5701), surfaced by the first
real de-fork pilot (langgraph-js):

- Theming follows the host app's light/dark theme: each token resolves
  override -> host theme var (--background/--card/...) -> built-in light default,
  instead of baking light-only values (drawer was light on a dark app).
- Row actions are icon buttons (inline lucide-style SVG, currentColor) with
  instant tooltips. Native title is replaced by a CSS tooltip (matches the
  react components' delayDuration:0; title's show-delay is browser-fixed) and is
  positioned to the side so the list's scroll-overflow never clips it.
- Archived rows are muted, no longer struck through.
- A refetch (e.g. Active<->All filter toggle) keeps the known list visible;
  the full loading state shows only on the initial empty fetch.
- The reserved footer region hides when nothing is slotted into it (it rendered
  as an empty box at the bottom); mirrors the memories region.
- Mobile gets a self-owned floating launcher so the drawer is always openable
  with no host header wiring. Its icon is swappable via a launcher-icon slot and
  its position via --cpk-drawer-launcher-top/left (host can center it on its own
  header controls); exposes part="launcher".

Adds element tests for icons+tooltips, archived styling, refetch-preserves-list,
footer hide-when-empty, and the mobile launcher (render + open + desktop-absent).
…lotKit>

CopilotChatConfigurationProvider treated any `threadId` prop as controlled, so
the auto-minted non-explicit threadId that <CopilotKit>'s v1 bridge seeds
blocked the drawer's imperative setActiveThreadId/startNewThread — thread
switching and "+ New" were dead in every app wrapped in <CopilotKit>. A
non-explicit (`hasExplicitThreadId={false}`) threadId is now overridable; a
genuine caller-supplied threadId stays controlled.

Also, surfaced during the langgraph-js de-fork validation:
- CopilotChat clears messages when switching to a fresh non-explicit thread
  ("+ New") so the welcome screen shows instead of the prior thread — including
  when a still-loading /connect is superseded by the switch.
- CopilotDrawer treats a pending (null) license status as loading, not
  unlicensed, so the upgrade upsell no longer flashes or sticks before the
  runtime reports the license.
…tandard CPK tooltip

Row-action tooltips used a surface background + border, which read as a button.
Restyle to the standard CopilotKit tooltip: primary bubble, primary-foreground
text, an arrow, no border. Also suppress the tooltip while the delete-confirm
dialog is open — the clicked trash button keeps :focus-visible, which otherwise
left its "Delete" tooltip floating over the dialog.
…n mobile

The in-header thread-drawer launcher toggles `drawerOpen`, which only drives the
off-canvas MOBILE drawer; on desktop the drawer is a persistent in-flow panel
that ignores `open`, so the launcher was a dead no-op there (it appeared to do
nothing on click). Gate it on a reactive mobile viewport check so it renders
only at ≤767px. On desktop the chat's own open/close — the toggle FAB + the
header close (both lucide X) — is the consistent pair; nothing masquerades as a
chat control.
A long thread name is clipped with an ellipsis; expose the full text via the
same instant primary-bubble tooltip as the row actions (not the native `title`),
shown only when the name is actually truncated. The name text moved to an inner
span so the outer `.row-name` can host the un-clipped bubble, and the hovered
row is z-lifted so the bubble isn't painted under later rows (each row is its
own stacking context from the entry-animation transform).
@BenTaylorDev
BenTaylorDev force-pushed the feat/copilot-drawer-ux-polish branch from 4100e69 to 31f31ee Compare June 26, 2026 21:54
@BenTaylorDev

Copy link
Copy Markdown
Contributor Author

Fixed in edbf98034 — thanks @MikeRyanDev, good catch.

_syncNameClipping() was toggling name-clipped on .row-name, while the stacking rule in styles.ts is .row.name-clipped:hover { z-index: 2 } — a different element, so it never matched and the clipped-name tooltip stayed trapped under later rows (each .row is its own transform stacking context).

Fix: also stamp the flag on the owning .row via name.closest('.row'), so the z-lift rule matches. The tooltip bubble itself stays scoped to .row-name.name-clipped:hover so hovering a row-action never surfaces it.

Added a red-green contract test (a clipped name marks BOTH the row-name and the owning row…) that simulates a truncated text node and asserts name-clipped lands on both .row-name (tooltip) and .row (z-index) — and clears on both when the name fits. Verified it fails on the row assertion with the fix reverted, passes with it. Full web-components suite 57/57 green.

…ift fires

_syncNameClipping toggled name-clipped on .row-name, but the stacking fix in
styles.ts targets .row.name-clipped:hover — a different element — so the z-index
lift never matched and clipped-name tooltips still painted under later rows
(each row is its own transform stacking context). Stamp the flag on the owning
.row too; the tooltip bubble stays scoped to .row-name:hover so a row-action
hover never surfaces it. Adds a red-green contract test asserting the class
lands on both the row-name and the row.

Addresses MikeRyanDev review on #5707.
@BenTaylorDev

Copy link
Copy Markdown
Contributor Author

(Note: the branch was force-rebased onto latest main between my comment and push, so the fix landed as 9223fc476 rather than edbf98034 — same change, cherry-picked onto the updated tip.)

@MikeRyanDev MikeRyanDev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed after the clipped-name tooltip fix. The previous blocker is addressed: name-clipped is now stamped on both .row-name and the owning .row, and the contract test covers set/clear behavior.

Verified locally with:

  • pnpm exec nx run @copilotkit/web-components:test (57 tests passed)
  • pnpm exec nx run @copilotkit/react-core:test (107 files / 1375 Vitest tests passed, plus 2 node test script tests passed)

@BenTaylorDev
BenTaylorDev merged commit ca28191 into main Jun 28, 2026
35 checks passed
@BenTaylorDev
BenTaylorDev deleted the feat/copilot-drawer-ux-polish branch June 28, 2026 13:44
MikeRyanDev added a commit that referenced this pull request Jun 30, 2026
## What

The **Angular `<CopilotDrawer>` feature** for the CopilotKit SDK — a
ready, usable threads drawer for Angular apps, plus the active-thread
foundation it sits on. (This PR merges the originally-staged PR1+PR2 so
it ships a working feature, not just plumbing.)

**Foundation — active-thread coordination (no new store):**
1. **`CopilotChatConfiguration`** — an injectable, signal-based service
mirroring React's `CopilotChatConfigurationProvider`: owns
`agentId`/`threadId` resolution (controlled prop → override → minted
fallback) + the `hasExplicitThreadId` welcome flag; `setActiveThreadId`
/ `startNewThread` setters that no-op when host-controlled;
single-instance via `useExisting`.
2. **`connectActiveThread`** (internal connector) — reactively pins the
resolved thread onto `agent.threadId` and owns the connect lifecycle
(per-run `AbortController` on `HttpAgent`s, a single caught connect
chain, a staleness-guarded loading cursor, abort+`detachActiveRun()`
teardown), mirroring the standalone `connectToAgent` path. Clears
messages only on a genuine new-thread transition (never on
mount/agent-swap).
3. **`CopilotChat`** consumes the ambient config when present
(input-first precedence: `[agentId]`/`[threadId]` win), seeds the config
from a set `[threadId]`; standalone `[threadId]` usage unchanged when no
provider is present.

**The drawer — `<copilot-drawer>`:**
4. A standalone `OnPush` wrapper around the framework-agnostic
`copilotkit-drawer` Lit element (`@copilotkit/web-components`). Events
bind declaratively; element properties are set imperatively via
`viewChild`+`effect` (the `a2ui-activity-renderer` precedent). Routes
the element's events
(`thread-selected`/`new-thread`/`archive`/`unarchive`/`delete`/`filter-change`/`retry`)
to the config + `injectThreads` mutations (delete-of-active resets to a
fresh thread).
5. **`CopilotDrawerRow`** directive for per-row custom content
(`slot="row:{id}"`), `onThreadSelect`/`onNewThread` host escape-hatch
callbacks, and `<ng-content>` slot passthrough
(`launcher-icon`/`memories`).
6. **`listError`** added to `injectThreads` — a filtered error (genuine
list/mutation errors only, excluding developer/config errors like
"Runtime URL is not configured") so the drawer's error panel never shows
dev strings to end users. Mirrors react-core's `useThreads`.

**Always-licensed:** Angular SDK licensing is no longer a thing, so the
wrapper does not wire the element's `licensed`/`upsell` — no upsell
path. **Inline-chat-only:** no Layer-2 open-state coordination (the
element self-provides its mobile launcher).

## Why

Angular had no active-thread provider (only `injectThreads`) and no
drawer component. This lands both so Angular apps get thread switching +
a usable threads drawer at parity with the React vertical, reinterpreted
for Angular's inline-chat-only surface.

## Testing

`@copilotkit/angular`: tsc clean, `oxlint` 0 errors, `ng-packagr` build
green, **152 tests pass** (full package suite). New coverage: config
precedence/controlled-vs-uncontrolled + single-instance identity;
connector connect-on-switch / clear-only-on-real-transition / cursor
staleness / no-unhandled-rejection / abort+detach teardown (verified
against a real `HttpAgent`); drawer prop binding, all 7 event routings
(incl. delete-active reset), escape-hatch overrides, `renderRow`
projection, `<ng-content>` slot passthrough, and the `listError`
dev-error-exclusion.

Hardened through a full `cr-loop` (foundation: 5 rounds; wrapper: 2
rounds) — the wrapper CR caught + fixed a real bug (the error panel was
leaking dev/config errors; fixed via the filtered `listError`).

## Dependency / release gate

Depends on `@copilotkit/web-components` (the `copilotkit-drawer`
element) being published — the same release gate as the React drawer
work (#5707). `packages/angular` publishes alongside.

## Follow-ups (out of scope, tracked)

- A demo `routes/threads` in `examples/v2/angular/demo` (kept separate
to keep this a clean SDK-only change).
- Pre-existing OSS packaging: `zod` is in `devDependencies` but imported
by production source — should move to `dependencies`/`peerDependencies`.
- `packages/angular/src/lib/threads.spec.ts` uses `describe/it` vs the
flat-`test` convention of sibling specs (pre-existing).
- Minor polish backlog from CR (renderRow multi-row tests, a docblock
tidy) — non-blocking.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
BenTaylorDev added a commit that referenced this pull request Jul 1, 2026
…K CopilotDrawer

Replace the hand-rolled threads-drawer fork in every threads-enabled
integration example with the SDK <CopilotDrawer> (uncontrolled
CopilotChatConfigurationProvider + reserved-column layout + theme no-flash
where applicable). 16 examples; all browser/build-validated locally.

DRAFT — depends on #5707 and the subsequent npm release; not mergeable until
the SDK publishes @copilotkit/web-components and react-core bumps. Pre-merge
TODOs in the PR description.
BenTaylorDev added a commit that referenced this pull request Jul 1, 2026
…K CopilotDrawer

Replace the hand-rolled threads-drawer fork in every threads-enabled
integration example with the SDK <CopilotDrawer> (uncontrolled
CopilotChatConfigurationProvider + reserved-column layout + theme no-flash
where applicable). 16 examples; all browser/build-validated locally.

DRAFT — depends on #5707 and the subsequent npm release; not mergeable until
the SDK publishes @copilotkit/web-components and react-core bumps. Pre-merge
TODOs in the PR description.
BenTaylorDev added a commit that referenced this pull request Jul 1, 2026
…K CopilotDrawer

Replace the hand-rolled threads-drawer fork in every threads-enabled
integration example with the SDK <CopilotDrawer> (uncontrolled
CopilotChatConfigurationProvider + reserved-column layout + theme no-flash
where applicable). 16 examples; all browser/build-validated locally.

DRAFT — depends on #5707 and the subsequent npm release; not mergeable until
the SDK publishes @copilotkit/web-components and react-core bumps. Pre-merge
TODOs in the PR description.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants