Commit Graph

48 Commits

Author SHA1 Message Date
tylerslaton 4394f9c81d chore: release monorepo v1.62.3 2026-07-08 16:17:36 +00:00
Benjamin Taylor 0b4f6ca392 fix(threads-drawer): clear stale fetch-more error, trap Escape while confirming, shield rows behind open menu (ENT-1051)
Addresses PR #5823 review (MikeRyanDev + marthakelly):

- core/threads.ts: a full-list refetch (filter-change / retry) now clears
  fetchMoreError on both listRequested and listSucceeded, so the inline
  'couldn't load more - retry' banner no longer survives onto a fresh list.
- web-components: Escape while the confirm-delete <dialog> is open is now
  consumed by a confirm guard in the host keydown handler; previously the
  bubbled keydown fell through to the mobile branch and closed the whole drawer
  along with the confirmation.
- web-components: an open kebab popover now shields the rest of the list -
  .list.menu-open .row:not(.menu-open) gets pointer-events:none so other rows
  no longer reveal their kebab or paint a host ::part(row):hover background
  around/behind the menu. Click-away dismissal is preserved via the existing
  document pointerdown handler.
- README: drop the removed --cpk-drawer-rail-width from the documented tokens.

Tests: core clears-fetchMoreError-on-refetch; web-components Escape-while-
confirming, confirm-dialog backdrop-click, menu-open row shield; Angular
scoped-chat-input focus (ancestor copilot-chat-view over the global fallback).
Menu-shield verified live in the langgraph-js example (:3002).
2026-07-07 14:01:12 -05:00
Benjamin Taylor a1c97501c9 style(web-components): drop the redundant New Conversation top margin now the header shows [ENT-1051]
The collapse toggle keeps the header bar visible on desktop, so the row's 12px
top margin doubled up with the header's padding (extra gap vs mobile). Make the
top margin conditional on the header being HIDDEN (collapsible=false + no header
slot) via .header[hidden] + .new-conversation; otherwise the header supplies the
top spacing on both breakpoints.
2026-07-07 12:54:23 -05:00
Benjamin Taylor 068f097627 style(web-components): designer nits — 24px cluster gutter, no selected-row border, cap radius at 4px [ENT-1051]
- Floating cluster/launcher default gutter → 24px on both top and left (was 12px).
- Selected row: drop the border-color; the background change alone marks it
  (base row keeps its 1px transparent border for layout stability).
- Cap --_radius at 4px via min(theme, 4px) and lower the hardcoded 6px button
  radii to 4px, so no bordered element exceeds a 4px corner radius.
2026-07-07 10:59:29 -05:00
Benjamin Taylor 38a94ad1eb fix(web-components): center delete modal over the drawer's VISIBLE box [ENT-1051]
Intersect the .root rect with the viewport before centering the confirm dialog.
A host grid that doesn't bound the drawer's row lets .root grow to content
height, so centering over the raw rect dropped the modal far down the page (seen
in the langgraph-js example, whose grid has no row bound). Clamping to the
on-screen band keeps it centered in the visible drawer regardless of host sizing.
2026-07-07 09:28:17 -05:00
Benjamin Taylor 8ab9b9613a fix(web-components): right-align the desktop collapse toggle in the header [ENT-1051]
Move the collapse toggle after the header slot so it right-aligns (the slot has
flex:1 and pushes it over), matching the mobile close button — it was reading as
left-aligned above New Conversation, which the designer flagged.
2026-07-07 09:17:25 -05:00
Benjamin Taylor 8bfd245305 feat(web-components,react,vue,angular): restore collapse + drawer-centered modal [ENT-1051]
Design iteration (Ben's designer):

- RESTORE desktop collapse. Re-add collapsed/collapsible + collapse-change
  (element + all three wrappers, lockstep), the desktop header collapse toggle,
  and the CollapseChangeDetail type/re-export. Default is EXPANDED.
- UNIFY the closed affordance into one floating cluster (Figma 'closed' mockup):
  a sidebar-glyph toggle + a New Conversation (+) icon button, shown in BOTH the
  mobile-closed state (adds New Conversation to the old single launcher) and the
  desktop-collapsed state. Parts: launcher-cluster, launcher, launcher-new-thread.
- COLUMN RECLAIM (no empty reserved gap): on desktop-collapse the element sets
  --cpk-drawer-reserved-width: 0px on the document root (reaches the grid past
  the wrapper host via :root inheritance); hosts read it in grid-template-columns.
  Default expanded never sets it, so no hydration flicker.
- DELETE MODAL centered over the DRAWER PANEL, not the viewport: keeps the
  top-layer showModal() robustness (never clipped) but drives --confirm-cx/cy
  from the visible .root rect and caps width to the drawer band.
- Vue fix: default collapsible to true in the wrapper. Vue coerces an omitted
  Boolean prop to false, which was silently forcing collapsible=false (collapse
  toggle vanished) — React/Angular pass undefined and keep the element default.

Validated live in the Nuxt (Vue) and Angular demos against managed Intelligence:
collapse/expand, cluster + New Conversation, column reclaim, drawer-centered
top-layer modal, mobile cluster. Tests: web-components 89, react-core 1419,
vue 32, angular 34 — all green.
2026-07-07 08:35:22 -05:00
Benjamin Taylor b989d92bb1 style(web-components): drop New Conversation top margin on mobile (header bar supplies it) [ENT-1051]
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 15:43:50 -05:00
Benjamin Taylor d3e03fae36 fix(web-components): use the Figma sidebar glyph for the drawer toggle (launcher + mobile close) [ENT-1051]
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 15:37:51 -05:00
Benjamin Taylor e19e96ba0a feat(web-components): add mobile off-canvas close button to the drawer header [ENT-1051]
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 15:30:05 -05:00
Benjamin Taylor 3a229b78d0 fix(web-components): render delete-confirm as a top-layer <dialog> (never under other UI) [ENT-1051]
The confirm-delete overlay was a CSS-positioned div trapped in the drawer
host's stacking context, so it could paint under other UI (e.g. the chat's
welcome view). Render it as a native <dialog> opened with showModal(), which
lives in the browser top layer and can never be occluded. The <dialog> is
always present so updated() can drive showModal()/close() from
_confirmingDeleteId; jsdom implements neither method, so a feature-detect falls
back to toggling the `open` attribute (which HTMLDialogElement.open reflects)
to keep unit tests observing open/closed state. Native Escape is handled via
the dialog's `cancel` event (the manual confirm-Escape branch in _onKeyDown is
removed); backdrop clicks dismiss via a target===currentTarget check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 14:54:29 -05:00
Benjamin Taylor 78c4fd772e fix(web-components): center delete-confirm in viewport (fixed), not in the tall .root [ENT-1051]
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 14:40:05 -05:00
Benjamin Taylor e5d1937248 style(web-components): align New Conversation icon + heading to thread-name edge; add top space [ENT-1051]
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 14:28:37 -05:00
Benjamin Taylor 01d5850ae8 refactor(web-components,react,vue,angular): drop desktop collapse from threads drawer [ENT-1051]
The thread panel is a persistent always-visible sidebar on desktop; the Figma
"closed" mockup is the MOBILE state, already covered by off-canvas behavior.

- web-components: remove the `collapsed`/`collapsible` properties,
  `_toggleCollapsed`, the header collapse-toggle button, and the
  collapsed-cluster render branch; render() always paints the full panel body.
  Gate the now control-less header on a `_hasHeader` slotchange flag so no empty
  bar renders. Drop the unused `iconSidebar`, the `CollapseChangeDetail` type +
  `collapse-change` event-map entry, the index re-export, and the
  `.root.collapsed`/`.collapsed-cluster` styles.
- react: drop the `collapsible` prop + property assignment, the
  `onCollapseChange` prop + `collapse-change` listener/handler, and the local
  `CollapseChangeDetail` type.
- vue: drop the `collapsible` prop + element binding, the `collapse-change`
  emit + `@collapse-change` handler, and the local `CollapseChangeDetail` type.
- angular: drop the `collapsible` input + property push, the `collapseChange`
  @Output + event wiring (and now-unused EventEmitter/Output imports), and the
  local `CollapseChangeDetail` type.
- tests: remove all collapse tests across the four packages; add an element
  header-gating test. Mobile off-canvas (open-driven) behavior is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 14:15:58 -05:00
Benjamin Taylor ef6224908d feat(web-components): remove client-side search from threads drawer [ENT-1051]
Element-only; downstream wrappers' search removal lands in the paired commit.
Verified in isolation: @copilotkit/web-components test (86) + build green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 13:44:20 -05:00
Benjamin Taylor 078e8bcf11 feat(web-components): drawer search-expand/auto-collapse, remove name tooltips, collapsible + collapse-change [ENT-1051]
- Search: the magnifier now expands an inline search input in the header icon
  row and focuses it; it auto-collapses back to the icon on blur when the query
  is empty/whitespace, but stays open while a non-empty query is active.
  Toggle-click and Escape still close + clear + emit search{query:''}.
- Remove all clipped-name tooltip machinery (data-tooltip attr,
  _syncNameClipping + its updated() call, name-clipped toggling, the tooltip
  ::after/::before CSS, and the name-clipped:hover z-index lift). Ellipsis
  truncation is kept.
- Add reactive collapsible property (default true, mirrors licensed): when
  false the header omits the collapse toggle and the collapsed cluster never
  renders (drawer stays expanded). Mobile off-canvas is unaffected.
- Add collapse-change event + CollapseChangeDetail (types + index re-export);
  the collapse toggle and cluster-expand route through _toggleCollapsed(), which
  flips collapsed and emits collapse-change with the new value (user-driven only).
2026-07-06 13:13:55 -05:00
Benjamin Taylor ddcb4764ca fix(web-components,react,vue,angular): CR round 2 — open=false default + dead-CSS/comment/test cleanup [ENT-1051]
Bucket A — mobile open-flash:
- Default the drawer element's `open` property to `false`. On a mobile viewport
  the previous `open = true` default made the first render satisfy
  _isMobileModalOpen(), painting the modal + body scroll-lock + focus steal for
  one frame before any wrapper effect could close it. Desktop is unaffected
  (only .root.mobile.open / _isMobileModalOpen() consume `open`).
- Element tests: added an `open` option to setup(); updated the 6 mobile/desktop
  tests that relied on the old open=true default to opt in explicitly; added a
  regression test asserting a fresh mobile element defaults open=false and paints
  no backdrop / applies no scroll-lock until opened.

Bucket B — dead CSS + inert `confirming` machinery:
- styles.ts: removed the `.row-action[data-tooltip]` hover/focus tooltip rules
  and the `.root.confirming .row-action[data-tooltip]…` suppression rules — no
  rendered .row-action carries data-tooltip anymore (row actions moved into the
  kebab menu as labeled .row-menu-items). Kept the .row-action base rules (still
  used by the confirm-dialog Cancel button + fetch-more retry).
- element: removed the now-inert `confirming` root class (it gated only the
  dead CSS above) and its stale comment; deleted the test asserting the no-op
  tooltip suppression. Refreshed two comments that referenced the removed
  row-action tooltip lineage.

Bucket B — comment/test hygiene:
- react-core CopilotThreadsDrawer.tsx: reworded the imprecise event-rebind
  comment to describe the actual [mounted] deps.
- angular spec: added a beforeEach resetting the module-level threadsState
  signals + clearing mock fns to remove order-coupling (parity with react/vue).
- vue use-threads.test.ts: aligned MockThreadStore.unarchiveThread + its
  assertion to the real core contract (PATCH /threads/{id} { archived:false },
  not POST /threads/{id}/unarchive).

Verified: web-components (89), vue (1068), angular (176), react-core suites all
green; web-components + react-core builds green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 11:40:52 -05:00
Benjamin Taylor 59cb365e5e fix(web-components): threads-drawer CR round 1 fixes [ENT-1051]
- Search toggle-close clears the query and emits search{query:""} via a shared
  _closeSearch() helper, so it no longer leaves a stale, invisible list filter.
- Escape-close routes through _closeSearch() too, so a consumer's onSearch is
  never left holding a stale query.
- Composed document pointerdown listener (bound/removed in connected/
  disconnectedCallback) dismisses the funnel popover and row kebab menu on
  outside clicks; selecting a thread row also closes an open menu.
- Kebab popover no longer clipped by the list overflow for bottom rows:
  lower-half rows open the menu upward (menu-up -> bottom-anchored popover).
- Locked/unlicensed view no longer renders the search toggle, search input, or
  "New Conversation" row — only the Upgrade panel (collapse toggle kept).
- Row-action aria-labels use the shared hasName?name:"New thread" fallback so an
  empty-string name never announces a trailing blank.
- Hardened CSS-contract tests: archived-italic and :host height:100% match
  selector+declaration as a unit; muted-not-struck checks color + no line-through.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 11:12:28 -05:00
Benjamin Taylor a3ec73e134 feat(web-components): filter-applied indicator dot on the funnel toggle [ENT-1051]
Adds the 'a filter is applied' dot (part=filter-indicator, --cpk-drawer-indicator,
default #5b94e4) shown on the funnel when the active filter is not the default,
matching the Figma archived view.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 10:27:56 -05:00
Benjamin Taylor abb8e9333f fix(web-components): use funnel-simple (decreasing bars) filter icon per Figma [ENT-1051]
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 10:20:25 -05:00
Benjamin Taylor a68deca31c feat(react-core): CopilotThreadsDrawer recentLabel + onSearch passthrough [ENT-1051]
Also re-exports SearchDetail from @copilotkit/web-components/threads-drawer
so the React wrapper's type import resolves.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 09:54:40 -05:00
Benjamin Taylor 438ec4952e test(web-components): repair drawer suite for redesigned structure [ENT-1051]
Add the optional header projection slot back to the redesigned icon-row
header (flex:1 so empty keeps icons right-aligned, filled fills the left),
keep `label` driving the region + listbox accessible names only, drop the
retired visible-title expectations from the two label tests, and remove the
orphaned --_rail-width token and .row-action.danger rule.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 09:46:57 -05:00
Benjamin Taylor 3a2537035e feat(web-components): italic archived rows + collapsed floating cluster [ENT-1051] 2026-07-06 09:41:48 -05:00
Benjamin Taylor 53d6ccb4ed feat(web-components): per-row kebab actions menu [ENT-1051] 2026-07-06 09:37:03 -05:00
Benjamin Taylor 3131c1a2db feat(web-components): client-side thread search [ENT-1051] 2026-07-06 09:30:24 -05:00
Benjamin Taylor f521671129 feat(web-components): Recent Conversations heading + funnel filter popover [ENT-1051]
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 09:27:17 -05:00
Benjamin Taylor e628d8abcf feat(web-components): drawer New Conversation row [ENT-1051] 2026-07-06 09:23:13 -05:00
Benjamin Taylor c0f0bb7ffd feat(web-components): drawer header icon row (search + collapse toggle) [ENT-1051] 2026-07-06 09:19:49 -05:00
BenTaylorDev a2cabd9455 chore: release monorepo v1.62.2 2026-07-02 22:23:11 +00:00
Benjamin Taylor edd5dc1915 fix(threads-drawer): keep confirm dialog above chat input; fix stuck "Loading threads…" on cold load
Two related bugs in the React <CopilotThreadsDrawer> surface.

Bug 1 (web-components): the delete-confirm dialog's backdrop is
`position:absolute; inset:0; z-index:10`, but `.root` was not a positioning
context, so on desktop it resolved against the viewport and its low z-index
lost to the chat composer (`position:relative; z-index:20`), painting the
dialog UNDER the input. Anchor `.root` with `position:relative` to confine the
modal to the drawer column. Framework-agnostic (Angular wraps the same element).

Bug 2 (react-core): the provider's immediate runtime-info catch-up read grabbed
`a2uiEnabled` but omitted `licenseStatus`. The core starts its `/info` fetch
during construction, so on a cold first load (incognito/hard refresh) the
`Connected` event can fire before the passive subscribe effect runs; the event
is missed and license status stays null forever, pinning the drawer to
"Loading threads…". Read all three values immediately, mirroring the subscriber.
Angular/Vue already read licenseStatus in their catch-up, so they are unaffected.

Adds a deterministic regression test for the provider race (red before, green after).

ENT-1046

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 17:00:37 -05:00
tylerslaton 617e88a069 chore: release monorepo v1.62.1 2026-07-01 17:07:44 +00:00
Tyler Slaton 9ed48a9dc3 fix(web-components): keep generated tokens formatted 2026-07-01 09:44:46 -07:00
Tyler Slaton 3e8e409f1f chore(release): add web-components release scope 2026-07-01 09:43:04 -07:00
Benjamin Taylor 74b8a1981f feat(drawer): default Upgrade CTA URL + Angular license gate
Add a `licenseUrl` property to the shared element (default
https://docs.copilotkit.ai/intelligence). The locked view's Upgrade CTA now
dispatches a cancelable `licensed` event carrying the url and, unless the
host calls preventDefault(), opens it in a new tab; a blank url suppresses
navigation. React and Angular wrappers expose an optional `licenseUrl` prop.

License-gate the Angular drawer like React: surface `licenseStatus` as a
signal on the CopilotKit service and gate the wrapper on
status valid|expiring && checkFeature("threads"), skipping the thread fetch
while unlicensed and showing the loading state (not the locked view) until
the status resolves. Reverses the earlier always-licensed Angular call.

Closes ENT-1027.
2026-06-30 17:34:39 -05:00
Benjamin Taylor f53a70c691 refactor(drawer): rename to CopilotThreadsDrawer / copilotkit-threads-drawer
Final naming decision. Renames the public component + element across the
board: React/Angular CopilotDrawer -> CopilotThreadsDrawer, the Lit element
copilotkit-drawer -> copilotkit-threads-drawer (tag, CopilotKitThreadsDrawer
class, COPILOTKIT_THREADS_DRAWER_TAG, defineCopilotKitThreadsDrawer), the
@copilotkit/web-components/drawer subpath -> /threads-drawer (+ src dir),
the CopilotThreadsDrawerRow directive / copilotThreadsDrawerRow input, and
all prose/test references. Generic types (DrawerThread, DrawerFilter),
--cpk-drawer-* tokens, and ::part names are unchanged. Behavior unchanged.
2026-06-30 17:34:39 -05:00
Benjamin Taylor eb3c20e865 refactor(drawer): rename unlicensed -> licensed across the public surface
Per review, settle the locked-view affordance on a neutral 'license'
name. Renames the event (unlicensed -> licensed), React prop
(onUnlicensed -> onLicensed), slot/part/class (licensed, licensed-cta),
LicensedDetail type, data-testid, render method, and identifier-referencing
comments/test names. The existing 'licensed' boolean gate is unchanged;
prose describing the not-licensed state still reads 'unlicensed'/'locked
view'. Behavior unchanged; Angular unaffected.
2026-06-30 17:34:39 -05:00
Benjamin Taylor d7cb0fded1 refactor(drawer): rename upsell -> unlicensed across the public surface
Per review, drop the 'upsell' monetization jargon. Renames the event
(upsell -> unlicensed), the React prop (onUpsell -> onUnlicensed), the
slot/part/class (upsell -> unlicensed, upsell-cta -> unlicensed-cta),
the UnlicensedDetail type, the data-testid, and all comments/test names.
Behavior unchanged. Angular is unaffected (always-licensed, no gate).
2026-06-30 17:34:39 -05:00
Benjamin Taylor cf4f00ecc1 feat(drawer): activate thread pagination (Load more + limit prop)
Wires up the previously-dormant pagination plumbing (ENT-1016):

- Element: render a 'Load more' button at the list bottom when hasMore
  (and not fetching / not errored), emitting a new load-more event
  (LoadMoreDetail). Distinct from retry{scope:'fetch-more'} (error
  recovery); both advance pagination.
- React CopilotDrawer: add a limit prop (forwarded to useThreads) and
  route load-more to fetchMoreThreads.
- Angular CopilotDrawer: add a limit input (forwarded to injectThreads)
  and route load-more to fetchMoreThreads.

Tests: element load-more render + emit + precedence; React limit
forwarding + load-more routing; Angular load-more routing.
2026-06-30 17:34:38 -05:00
Benjamin Taylor 0183a30369 fix(web-components): scroll the drawer thread list when it overflows (:host height + .list min-height:0) 2026-06-30 17:34:38 -05:00
Benjamin Taylor 787b9ad382 feat(web-components): make the drawer label/aria-label configurable (label property, defaults to Threads) 2026-06-30 17:34:37 -05:00
Benjamin Taylor 9223fc476a fix(web-components): stamp name-clipped on the row so the tooltip z-lift 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.
2026-06-26 17:11:25 -05:00
Benjamin Taylor 31f31eeebd fix(web-components): tooltip for clipped CopilotDrawer thread names
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).
2026-06-26 16:54:55 -05:00
Benjamin Taylor 4fbb5d1f65 fix(web-components): match CopilotDrawer row-action tooltips to the standard 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.
2026-06-26 16:54:55 -05:00
Benjamin Taylor 2664df54a9 feat(web-components): CopilotDrawer host-theme inheritance, action icons, 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).
2026-06-26 16:54:55 -05:00
Benjamin Taylor 225a3fc646 fix(web-components): contain mobile-modal focus including the backdrop
The mobile drawer is a modal dialog, but the Tab trap was bound to .root only,
while the backdrop button renders as a sibling OUTSIDE .root — so Tab from the
backdrop (or any out-of-root node) could escape the modal. Move the trap to the
host keydown listener (keydown is composed, so it catches the backdrop too) and
include the backdrop in the focusable cycle; keep initial focus on the first
real control. Adds a regression test for backdrop/outside-root Tab containment.
2026-06-25 11:28:32 -05:00
Benjamin Taylor d07888c611 fix(web-components): make the UMD lit-inlining CI-safe
The UMD bundle inlines lit for a self-contained CDN <script>; inlining lit also
pulls in its runtime deps (@lit/reactive-element, lit-html, lit-element,
@lit-labs/ssr-dom-shim). tsdown flags that transitive bundling as 'unintended'
and promotes the warning to a fatal error under CI, breaking
@copilotkit/web-components:build (and every dependent). Declare all lit packages
in noExternal and set inlineOnly: false to mark the bundling intentional.
2026-06-25 11:28:32 -05:00
github-actions[bot] ba85b2f0a6 style: auto-fix formatting 2026-06-25 15:45:46 +00:00
Benjamin Taylor a7a6aa0c29 feat(web-components): add @copilotkit/web-components with the <copilotkit-drawer> element
Shadow-DOM Lit element that renders the threads drawer: self-contained styles
with build-time token sync from react-core's theme, slot projection for custom
rows, license/upsell gating, filtering, and a mobile modal. View-state lives on
the element; domain state stays with the host. Multi-format build (ESM/CJS
externalize lit as a peer dep; UMD inlines lit so the CDN <script> path is
self-contained).
2026-06-25 10:42:46 -05:00