Skip to content

feat(sdk): let the interview app own the slider/popup/float close button#62

Merged
LEVI-RIVKIN merged 1 commit into
mainfrom
feat/sdk-app-owned-close-button
Jul 1, 2026
Merged

feat(sdk): let the interview app own the slider/popup/float close button#62
LEVI-RIVKIN merged 1 commit into
mainfrom
feat/sdk-app-owned-close-button

Conversation

@LEVI-RIVKIN

Copy link
Copy Markdown
Contributor

What & why

The Perspective app now renders its own close (X) button for slider, popup, and float embeds and emits perspective:close when clicked (shipped in codebase#4397). This was done because the SDK's own X overlapped the app's top-right UI — the participant avatar on slider/popup, and the header ··· menu on float.

This PR retires the SDK's self-rendered X in favour of letting the app draw it, while keeping a close affordance visible during loading.

How it works

  • The SDK now draws only a temporary X over the loading skeleton and removes it the moment the interview becomes visible (at skeleton-hide). The app then renders its own X in its header.
  • This avoids both a double / overlapping X and a no-X gap: a brief moment with no X reads as "still loading", whereas an SDK X lingering over the app's avatar/menu looks like a bug.
  • The perspective:init handshake now sends renderCloseButton (true unless disableClose) for slider/popup/float. widget/fullpage have no X and omit it.
  • The legacy hasCloseButton init flag is retired — the SDK no longer emits it. It stays on InitMessage as @deprecated because the app may still receive it from older deployed SDK clients.
  • Backdrop-click, Escape, and disableClose behaviour are unchanged. Float's launcher bubble is untouched and still closes the window (perspective:close maps to closeFloat).

Changes

  • iframe.ts — send renderCloseButton in init; drop hasCloseButton from the send path.
  • slider.ts / popup.ts / float.ts — temporary close button removed in hideSkeleton; send renderCloseButton: !disableClose.
  • types.tsrenderCloseButton added; hasCloseButton marked @deprecated.
  • e2e — the persistent X is now app-owned, so the mock iframe renders its own X on renderCloseButton and emits perspective:close; the close-button tests click that (after the loading overlay detaches).
  • Changeset (minor).

Verification

  • Unit: 415 pass · Typecheck: clean · E2E: 39 pass.
  • End-to-end against the production app (getperspective.ai): slider, popup, and float each hand the X off to the app's header with no overlap, across mobile/tablet/desktop. disableClose correctly shows no X on either side.

Rollout note

This relies on the app rendering the X, which is already in production (codebase#4397), so there's no deploy-ordering risk. Versioned as a minor since it adds to the init protocol; backward compatible (the app prefers renderCloseButton and still honours the legacy hasCloseButton path for older SDKs).

🤖 Generated with Claude Code


Generated by Claude Code

@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

📦 Snapshot Release

Published snapshot packages for this PR:

pnpm add @perspective-ai/sdk@1.12.0-pr-62-20260701112728
pnpm add @perspective-ai/sdk-react@1.12.0-pr-62-20260701112728

Or use the npm tag (always points to the latest snapshot from this PR):

pnpm add @perspective-ai/sdk@pr-62
pnpm add @perspective-ai/sdk-react@pr-62

@LEVI-RIVKIN LEVI-RIVKIN requested a review from Copilot July 1, 2026 10:50
@LEVI-RIVKIN

Copy link
Copy Markdown
Contributor Author

@codex review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the SDK/embed handshake and UI behavior so the interview app (inside the iframe) owns the persistent close (X) button for slider / popup / float embeds, while the SDK only shows a temporary close button during the loading skeleton and removes it at skeleton-hide to prevent overlap with the app’s top-right UI.

Changes:

  • Add renderCloseButton to perspective:init (slider/popup/float only) and retire the SDK-emitted hasCloseButton flag (kept as deprecated type for legacy clients).
  • Remove the SDK close button as soon as the loading skeleton hides for slider/popup/float (handoff moment).
  • Update unit tests and e2e fixtures/tests so e2e clicks the app-rendered close button inside the iframe.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/sdk/src/types.ts Deprecates hasCloseButton and adds renderCloseButton to the init protocol type.
packages/sdk/src/iframe.ts Sends renderCloseButton (conditionally) in perspective:init and stops emitting hasCloseButton.
packages/sdk/src/slider.ts Removes the SDK close button at skeleton-hide; sends renderCloseButton in init options.
packages/sdk/src/slider.test.ts Adds a unit test asserting the SDK close button is removed on visual-ready.
packages/sdk/src/popup.ts Removes the SDK close button at skeleton-hide; sends renderCloseButton in init options.
packages/sdk/src/popup.test.ts Updates init-message assertions to renderCloseButton and adds skeleton-hide close-button removal coverage.
packages/sdk/src/float.ts Makes float close button explicitly temporary (including disableClose handling); sends renderCloseButton.
packages/sdk/src/float.test.ts Adds coverage for close-button handoff and renderCloseButton in init.
packages/sdk/e2e/fixtures/mock-iframe.html Adds an app-rendered close button shown when renderCloseButton is requested; emits perspective:close.
packages/sdk/e2e/embed.spec.ts Updates e2e to click the app-rendered close button inside the iframe after the loading overlay detaches.
.changeset/app-owned-close-button.md Documents the protocol/UI change as a minor release.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/sdk/src/popup.ts Outdated
The Perspective app now renders its own close (X) button for slider, popup,
and float embeds and emits perspective:close when clicked (codebase#4397).
This stops the SDK's X from overlapping the app's top-right UI — the
participant avatar on slider/popup, and the header ··· menu on float.

The SDK now only draws a temporary X over the loading skeleton and removes
it the moment the interview becomes visible (at skeleton-hide), so the app's
X takes over with no double or overlapping X, and no no-X gap.

- iframe.ts: the perspective:init handshake sends `renderCloseButton`
  (true unless disableClose) for slider/popup/float; widget/fullpage have no
  X and omit it.
- slider.ts / popup.ts / float.ts: temporary close button removed in
  hideSkeleton; float's launcher bubble is untouched and still closes the
  window (perspective:close maps to closeFloat).
- styles.ts: the temporary X uses a ghost style (transparent background) to
  match the app's X, so the handoff has no visual pop.
- Retire the legacy `hasCloseButton` init flag — the SDK no longer emits it.
  It stays on InitMessage as @deprecated for older deployed SDK clients.
- e2e: the persistent X is now app-owned, so the mock iframe renders its own
  X on renderCloseButton and emits perspective:close; the close-button tests
  click that (after the loading overlay detaches).
- Add a changeset (minor). Backdrop-click/Escape and disableClose unchanged.

Verified end-to-end against the production app (getperspective.ai):
slider/popup/float hand the X to the app header with no overlap. Unit (415)
and e2e (39) tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lk3DUSi41xCaYr5GGC1qh8

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.

Comment thread packages/sdk/src/iframe.ts
@LEVI-RIVKIN LEVI-RIVKIN requested a review from vinaypuppal July 1, 2026 12:11
@LEVI-RIVKIN LEVI-RIVKIN merged commit 70fdf25 into main Jul 1, 2026
6 checks passed
@LEVI-RIVKIN LEVI-RIVKIN deleted the feat/sdk-app-owned-close-button branch July 1, 2026 12:51
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.

3 participants