
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, default10): Sets the resting distance between surfaces. Values are clamped from-60to10.debug(Boolean): Displays path outlines, corner circles, coupling circles, and the waist guide.provider(String, defaultNotion): Sets the main provider label.eyebrow(String, defaultMCP Connector): Sets the smaller label above the provider name.placeholder(String, defaultAsk anything...): Sets the prompt placeholder.connect-label(String, defaultConnect): Sets the visible Connect button text.skip-label(String, defaultSkip): Sets the visible Skip button text.prompt-label(String, defaultPrompt): Sets the textarea accessibility label.send-label(String, defaultSend prompt): Sets the send button accessibility label.stage-label(String, defaultLiquid connector prompt): Sets the SVG stage accessibility label.emit-frames(Boolean): Activates the high-frequencyliquid-framediagnostic 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:
- SVG Gooey Toast Notification Library – Physics Toast
- Create Realistic iOS Liquid Glass Effects with SVG Filters
- Lightweight & Versatile JavaScript Animation Engine – Anime.js
- SVG Path Animation with Pure JavaScript – Segment.js
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.







