A Web Component for Card-to-Prompt Peel Effects – Liquid Connector

Category: Animation , Javascript | July 21, 2026
Authorzanwei
Last UpdateJuly 21, 2026
LicenseMIT
Tags
Views31 views
A Web Component for Card-to-Prompt Peel Effects – Liquid Connector

Liquid Connector is a Web Component that turns a small card-to-prompt transition into a single continuous SVG surface.

A provider card sits above a prompt field, and when a user connects or skips, the two shapes merge, stretch, peel apart, or snap back together as if they were one sheet of liquid material.

The effect looks like a blur filter or a metaball trick. The component builds it from a solver: corner tangencies, coupling circles, and a waist width that shrink and expand as a resting gap value changes.

An AI assistant that lets users connect a third-party account, such as a Notion or Slack workspace, can use Liquid Connector to show the provider identity card first and morph it into the prompt input the moment the connection succeeds.

Features:

  • Real SVG path geometry for merge, peel, and separation states.
  • Fixed provider-card dimensions throughout the transition.
  • Direction-aware motion for opening, closing, and gap changes.
  • Independent strain effects across prompt content and the send control.
  • Native textarea and button controls with keyboard support.
  • Shadow DOM styles with CSS custom properties and exposed parts.
  • Deterministic frame stepping and an optional geometry debugger.
  • Reduced-motion handling and no runtime dependencies.

See it in Action:

How to use it:

1. Download the web component and load the liquid-path.js before liquid-connector.js.

<script src="./liquid-path.js"></script>
<script src="./liquid-connector.js"></script>

2. Add the custom element after both browser scripts. The open attribute displays the provider card, while the label attributes replace the built-in text. All possible HTML attributes:

  • open (Boolean): Displays the provider card and starts the opening state when present.
  • gap (Number, default 10): Sets the resting distance between surfaces. Values are clamped from -60 to 10.
  • debug (Boolean): Displays path outlines, corner circles, coupling circles, and the waist guide.
  • provider (String, default Notion): Sets the main provider label.
  • eyebrow (String, default MCP Connector): Sets the smaller label above the provider name.
  • placeholder (String, default Ask anything...): Sets the prompt placeholder.
  • connect-label (String, default Connect): Sets the visible Connect button text.
  • skip-label (String, default Skip): Sets the visible Skip button text.
  • prompt-label (String, default Prompt): Sets the textarea accessibility label.
  • send-label (String, default Send prompt): Sets the send button accessibility label.
  • stage-label (String, default Liquid connector prompt): Sets the SVG stage accessibility label.
  • emit-frames (Boolean): Activates the high-frequency liquid-frame diagnostic event.
<liquid-connector
  open
  gap="8"
  provider="Project Hub"
  eyebrow="Workspace Connector"
  placeholder="Ask about this workspace..."
  connect-label="Connect"
  skip-label="Skip"
  prompt-label="Workspace question"
  send-label="Send question"
  stage-label="Workspace connector prompt"
></liquid-connector>

3. These 4 JavaScript properties provide direct state access:

  • open (Boolean): Reads or changes the open state.
  • gap (Number): Reads or changes the resting gap.
  • value (String): Reads or replaces the prompt value.
  • peelParameters (Object): Returns normalized peel values or applies a partial update.
const connector = document.querySelector("liquid-connector");
connector.open = true;
connector.gap = 6;
connector.value = "Summarize the selected workspace";
connector.peelParameters = {
  detachGap: 5.5,
  couplingRadius: 4.75,
};

4. API methods:

const connector = document.querySelector("liquid-connector");
// Toggle the current open state.
connector.toggle();
// Force the component open or closed.
connector.toggle(true);
connector.toggle(false);
// Change the resting gap.
// Passing immediate skips the animated transition.
connector.setGap(6, { immediate: true });
// Apply a partial set of normalized peel parameters.
connector.setPeelParameters({
  detachGap: 6,
  transition: 6.5,
  couplingRadius: 5,
  pull: 2.5,
});
// Restore the default peel parameters.
connector.resetPeelParameters();
// Pause scheduled playback and advance one deterministic frame.
const frame = connector.step(1000 / 60);
console.log(frame);

5. Every component event bubbles and crosses the Shadow DOM boundary.

const connector = document.querySelector("liquid-connector");
// Fires when the Connect button is activated.
connector.addEventListener("connect", () => {
  console.log("Connection requested");
});
// Fires when Skip is activated.
// The component starts closing before this event is dispatched.
connector.addEventListener("skip", () => {
  console.log("Connector skipped");
});
// Fires from the send button or Enter without Shift.
// event.detail.value contains the prompt text.
connector.addEventListener("submit", (event) => {
  console.log(event.detail.value);
});
// Fires after the open state changes.
connector.addEventListener("liquid-toggle", (event) => {
  console.log("Open:", event.detail.open);
});
// Fires for rendered diagnostic frames when debug or emit-frames is present.
connector.addEventListener("liquid-frame", (event) => {
  console.log(event.detail.mode, event.detail.waistWidth);
});

6. Customize the web component with CSS:

liquid-connector {
  --liquid-surface: #fffdf8;
  --liquid-ink: #202124;
  --liquid-muted: #6c7077;
  --liquid-blue: #6b4eff;
  width: min(520px, 100%);
}

Alternatives:

FAQs:

Q: Can Liquid Connector run during server-side rendering?
A: No. Import it from client-side code because module evaluation requires browser DOM APIs, globalThis, Custom Elements, and Shadow DOM.

Q: How do I replace the Notion icon?
A: The public attributes change the provider text but do not replace the embedded icon. Hide the icon part through CSS or edit the component template to insert another SVG.

Q: Why does the liquid animation jump directly to its final state?
A: Check the user’s reduced-motion preference first. Also confirm that liquid-path.js loads before liquid-connector.js and that the element changes between distinct open or gap states.

Q: What accessibility behavior is included?
A: The component uses native buttons and a native textarea, preserves visible focus states, supports Enter and Shift+Enter, moves focus before the output card becomes inert, and honors reduced motion.

You Might Be Interested In:


Leave a Reply