Getting Started

Install

pnpm add @squircle-js/vue
# or
npm install @squircle-js/vue

Requires Vue 3.3 or later. Nuxt 3 is supported out of the box — the library has no Nuxt-specific configuration.

Basic usage

<script setup>
import { Squircle } from "@squircle-js/vue";
</script>
<template>
<Squircle :corner-radius="24" :corner-smoothing="0.6" class="bg-indigo-500 p-6">
<h2 class="text-white font-semibold text-lg">Hello, squircle</h2>
</Squircle>
</template>

Squircle renders a <div> that auto-measures itself with a ResizeObserver and applies a computed SVG clip-path for the smooth-corner effect.

The directive alternative

Vue's asChild equivalent is a directive — apply the squircle clip-path directly to any element without a wrapper:

<script setup>
import { squircleDirective as vSquircle } from "@squircle-js/vue";
</script>
<template>
<button
v-squircle="{ cornerRadius: 12, cornerSmoothing: 0.6 }"
class="bg-blue-600 px-4 py-2 text-white"
>
Click me
</button>
</template>

See The Directive Pattern for the full story.

Global registration (optional)

For larger apps, register the components and directives globally:

// main.ts
import { createApp } from "vue";
import { SquirclePlugin } from "@squircle-js/vue";
import App from "./App.vue";
createApp(App).use(SquirclePlugin).mount("#app");

After app.use(SquirclePlugin), <Squircle>, <StaticSquircle>, <SquircleNoScript>, v-squircle, and v-static-squircle are available in every template with no imports.

Composable API

For programmatic use — especially when options need to react to other state:

<script setup>
import { ref } from "vue";
import { useSquircle } from "@squircle-js/vue";
const el = ref<HTMLElement | null>(null);
useSquircle(el, { cornerRadius: 16 });
</script>
<template>
<div ref="el" class="bg-emerald-500 p-6">Content</div>
</template>

See The Composable API.

Nuxt SSR

Everything works with Nuxt 3 SSR and static generation. The composable and directive only run on the client, so the initial server-rendered HTML omits the clip-path unless you pass defaultWidth / defaultHeight (or use StaticSquircle for fixed-size elements).

See No-JavaScript Fallback for progressive enhancement details.

Coming from React, Solid, or Svelte?

The component API is nearly identical across frameworks:

  • Squircle, StaticSquircle, SquircleNoScript — same names, same props
  • cornerRadius, cornerSmoothing, width, height, defaultWidth, defaultHeight — same semantics
  • asChild → replaced by v-squircle directive (idiomatic Vue)

The one deviation: Vue uses kebab-case attributes in templates (:corner-radius), and props are passed with the : prefix for reactive bindings.