{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "blob-animation", "type": "registry:block", "title": "Blob Animation", "description": "Blob Animation is a React component for a morphing blob in pure CSS, the kind of blob animation used in hero sections, behind avatars and as page decoration. The shape is a box whose eight-value border radius moves between four keyframes, so the browser interpolates an organic outline with no SVG path morphing and no JavaScript per frame. Opposite edges of every radius add up to the full side, which keeps the outline closed and smooth instead of pinching into corners. The four shapes come from a seed, so a seed always gives the same blob on the server and the client, and wobble sets how far the outline strays from a circle. Four looks: solid is a gradient blob with a soft highlight and an inner shade, soft blurs the gradient into a glow, outline draws a gradient ring that morphs with the shape, and image masks a photo with the blob while keeping it upright as the outline turns. A slow rotation hides the four-keyframe rhythm. Reduced motion holds the first shape still. The stylesheet is injected once, with no global CSS or dependencies.", "author": "Wensity ", "dependencies": [ "clsx", "tailwind-merge" ], "registryDependencies": [], "files": [ { "path": "registry/wensity/lib/utils.ts", "type": "registry:lib", "target": "@lib/utils.ts", "content": "import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n" }, { "path": "registry/wensity/blob-animation.tsx", "type": "registry:component", "target": "@components/wensity/blob-animation.tsx", "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Blob Animation\n *\n * A morphing blob in pure CSS. The shape is a box whose eight-value\n * border-radius changes between four keyframes, so the browser interpolates\n * an organic outline with no SVG path morphing and no JavaScript per frame.\n * The four radii live in custom properties, so every blob runs the same\n * shared keyframes with its own shape, generated from a `seed`.\n *\n * Variants:\n * - solid: a gradient blob with a soft highlight and an inner shade, so it\n * reads as a lit, rounded object rather than a flat sticker.\n * - soft: the same gradient blurred into a glow, for backgrounds.\n * - outline: a gradient ring that morphs with the shape.\n * - image: a photo masked by the blob, which stays upright while the\n * outline turns, for portfolio heroes and avatars.\n *\n * `wobble` sets how far the outline strays from a circle. `rotate` turns the\n * whole shape slowly, which hides the four-keyframe rhythm. Reduced motion\n * holds the first shape still. The stylesheet renders with the component,\n * so server-rendered pages are styled before hydration, and React keeps one\n * copy in however many blobs are on the page. No global CSS or\n * dependencies.\n */\n\nexport type BlobAnimationVariant = \"solid\" | \"soft\" | \"outline\" | \"image\";\n\nexport interface BlobAnimationProps extends Omit, \"color\"> {\n /** Look of the blob. Default solid, or image when `src` is set. */\n variant?: BlobAnimationVariant;\n /** Gradient colors, two or more CSS colors. */\n colors?: string[];\n /** Width and height in pixels, or any CSS length. Default 320. */\n size?: number | string;\n /** Seconds for one full morph cycle. Default 10. */\n duration?: number;\n /** How far the outline strays from a circle, from 0 to 1. Default 0.6. */\n wobble?: number;\n /** Turns the shape slowly while it morphs. Default true. */\n rotate?: boolean;\n /** Picks a different shape. Same seed, same blob. Default 1. */\n seed?: number;\n /** Ring thickness in pixels for the outline variant. Default 2. */\n thickness?: number;\n /** Image for the image variant. */\n src?: string;\n /** Alt text for the image. Leave empty for a decorative image. */\n alt?: string;\n children?: React.ReactNode;\n}\n\nconst STYLE_ID = \"wensity-blob-animation\";\nconst DEFAULT_COLORS = [\"#ff1100\", \"#f97316\", \"#fbbf24\"];\n\nconst CSS = `\n@keyframes wba-morph {\n 0%, 100% { border-radius: var(--wba-r0); }\n 25% { border-radius: var(--wba-r1); }\n 50% { border-radius: var(--wba-r2); }\n 75% { border-radius: var(--wba-r3); }\n}\n@keyframes wba-turn { to { transform: rotate(360deg); } }\n@keyframes wba-unturn { to { transform: rotate(-360deg); } }\n.wba {\n position: relative;\n display: grid;\n place-items: center;\n flex-shrink: 0;\n width: var(--wba-size);\n height: var(--wba-size);\n}\n.wba-turn {\n position: absolute;\n inset: 0;\n}\n.wba[data-rotate=\"true\"] .wba-turn { animation: wba-turn calc(var(--wba-d) * 3) linear infinite; }\n.wba-shape {\n position: absolute;\n inset: 0;\n overflow: hidden;\n border-radius: var(--wba-r0);\n animation: wba-morph var(--wba-d) ease-in-out infinite;\n}\n.wba[data-variant=\"solid\"] .wba-shape {\n background: linear-gradient(135deg, var(--wba-c1), var(--wba-c2), var(--wba-c3));\n box-shadow:\n inset -18px -26px 48px rgba(0, 0, 0, 0.22),\n inset 14px 18px 36px rgba(255, 255, 255, 0.18);\n}\n.wba[data-variant=\"solid\"] .wba-shape::after {\n content: \"\";\n position: absolute;\n inset: 0;\n background: radial-gradient(60% 45% at 32% 24%, rgba(255, 255, 255, 0.38), transparent 70%);\n mix-blend-mode: soft-light;\n}\n.wba[data-variant=\"soft\"] .wba-shape {\n background: linear-gradient(135deg, var(--wba-c1), var(--wba-c2), var(--wba-c3));\n filter: blur(calc(var(--wba-size) * 0.09));\n opacity: 0.85;\n overflow: visible;\n}\n.wba[data-variant=\"outline\"] .wba-shape {\n padding: var(--wba-w);\n background: linear-gradient(135deg, var(--wba-c1), var(--wba-c2), var(--wba-c3));\n -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);\n -webkit-mask-composite: xor;\n mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);\n}\n.wba[data-variant=\"image\"] .wba-shape {\n background: linear-gradient(135deg, var(--wba-c1), var(--wba-c2), var(--wba-c3));\n}\n.wba-img {\n position: absolute;\n inset: -12%;\n width: 124%;\n height: 124%;\n max-width: none;\n object-fit: cover;\n}\n.wba[data-rotate=\"true\"] .wba-img { animation: wba-unturn calc(var(--wba-d) * 3) linear infinite; }\n.wba-content {\n position: relative;\n z-index: 1;\n}\n@media (prefers-reduced-motion: reduce) {\n .wba .wba-turn,\n .wba .wba-shape,\n .wba .wba-img { animation: none !important; }\n}\n`;\n\n/** Small seeded random, so a seed always gives the same blob on server and client. */\nfunction seeded(seed: number) {\n let t = Math.floor(seed * 9973) >>> 0;\n return () => {\n t = (t + 0x6d2b79f5) >>> 0;\n let r = Math.imul(t ^ (t >>> 15), 1 | t);\n r ^= r + Math.imul(r ^ (r >>> 7), 61 | r);\n return ((r ^ (r >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/**\n * Four border-radius shapes. Each corner gets a horizontal and a vertical\n * radius, and opposite edges add up to 100%, so the outline stays closed and\n * smooth instead of pinching into corners.\n */\nfunction blobShapes(seed: number, wobble: number) {\n const random = seeded(seed);\n const spread = 32 * Math.min(1, Math.max(0, wobble));\n const pick = () => Math.round(50 + (random() * 2 - 1) * spread);\n return Array.from({ length: 4 }, () => {\n const top = pick();\n const bottom = pick();\n const left = pick();\n const right = pick();\n return `${top}% ${100 - top}% ${100 - bottom}% ${bottom}% / ${left}% ${right}% ${100 - right}% ${100 - left}%`;\n });\n}\n\nexport function BlobAnimation({\n variant,\n colors = DEFAULT_COLORS,\n size = 320,\n duration = 10,\n wobble = 0.6,\n rotate = true,\n seed = 1,\n thickness = 2,\n src,\n alt = \"\",\n className,\n style,\n children,\n ...props\n}: BlobAnimationProps) {\n const look: BlobAnimationVariant = variant ?? (src ? \"image\" : \"solid\");\n const palette = colors.length > 0 ? colors : DEFAULT_COLORS;\n const [c1, c2 = c1, c3 = c2] = palette;\n const shapes = React.useMemo(() => blobShapes(seed, wobble), [seed, wobble]);\n\n const vars = {\n \"--wba-c1\": c1,\n \"--wba-c2\": c2,\n \"--wba-c3\": c3,\n \"--wba-size\": typeof size === \"number\" ? `${size}px` : size,\n \"--wba-d\": `${Math.max(1, duration)}s`,\n \"--wba-w\": `${thickness}px`,\n \"--wba-r0\": shapes[0],\n \"--wba-r1\": shapes[1],\n \"--wba-r2\": shapes[2],\n \"--wba-r3\": shapes[3],\n } as React.CSSProperties;\n\n return (\n \n {/* Rendered with the markup, so server-rendered pages are styled before\n hydration. React hoists it into and emits it once per page. */}\n \n
\n
\n {look === \"image\" && src ? (\n // eslint-disable-next-line @next/next/no-img-element\n {alt}\n ) : null}\n
\n
\n {children ?
{children}
: null}\n \n );\n}\n" } ], "cssVars": { "theme": { "font-sans": "var(--font-satoshi, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif)", "font-display": "var(--font-satoshi, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif)", "font-heading": "var(--font-cabinet, ui-sans-serif, system-ui, sans-serif)", "color-background": "var(--background)", "color-foreground": "var(--foreground)", "color-surface": "var(--surface)", "color-surface-muted": "var(--surface-muted)", "color-border": "var(--border)", "color-border-strong": "var(--border-strong)", "color-muted": "var(--muted)", "color-muted-foreground": "var(--muted-foreground)", "color-ring": "var(--ring)", "color-chili-50": "#fff1ee", "color-chili-100": "#ffe2db", "color-chili-200": "#ffa896", "color-chili-300": "#ff8a73", "color-chili-400": "#f15a45", "color-chili-500": "#cd1c18", "color-chili-600": "#b31614", "color-chili-700": "#9b1313", "color-chili-800": "#6a0d0e", "color-chili-900": "#38000a", "color-chili-950": "#1f0006", "color-primitive-surface-elevated": "var(--primitive-surface-elevated)", "color-primitive-surface-overlay": "var(--primitive-surface-overlay)", "color-primitive-surface-hover": "var(--primitive-surface-hover)", "color-primitive-surface-active": "var(--primitive-surface-active)", "color-primitive-surface-selected": "var(--primitive-surface-selected)", "color-primitive-border-subtle": "var(--primitive-border-subtle)", "color-primitive-ring": "var(--primitive-ring)", "color-primitive-text-secondary": "var(--primitive-text-secondary)", "color-primitive-text-placeholder": "var(--primitive-text-placeholder)", "color-primitive-text-inverse": "var(--primitive-text-inverse)", "color-primitive-destructive": "var(--primitive-destructive)", "color-primitive-destructive-hover": "var(--primitive-destructive-hover)", "color-primitive-destructive-active": "var(--primitive-destructive-active)", "color-primitive-destructive-foreground": "var(--primitive-destructive-foreground)", "color-primitive-destructive-surface": "var(--primitive-destructive-surface)", "color-primitive-destructive-border": "var(--primitive-destructive-border)", "color-primitive-success": "var(--primitive-success)", "color-primitive-warning": "var(--primitive-warning)", "color-primitive-info": "var(--primitive-info)", "color-primitive-control-solid": "var(--primitive-control-solid)", "color-primitive-control-solid-hover": "var(--primitive-control-solid-hover)", "color-primitive-control-solid-active": "var(--primitive-control-solid-active)", "color-primitive-control-solid-foreground": "var(--primitive-control-solid-foreground)", "color-primitive-chart-1": "var(--primitive-chart-1)", "color-primitive-chart-2": "var(--primitive-chart-2)", "color-primitive-chart-3": "var(--primitive-chart-3)", "color-primitive-chart-4": "var(--primitive-chart-4)", "color-primitive-chart-5": "var(--primitive-chart-5)", "color-primitive-chart-6": "var(--primitive-chart-6)", "radius-primitive": "var(--primitive-radius)", "radius-primitive-control": "var(--primitive-radius-control)", "radius-primitive-control-sm": "var(--primitive-radius-control-sm)", "radius-primitive-surface": "var(--primitive-radius-surface)", "radius-primitive-popup": "var(--primitive-radius-popup)", "radius-primitive-item": "var(--primitive-radius-item)", "font-primitive-sans": "var(--primitive-font-sans)", "font-primitive-display": "var(--primitive-font-display)", "font-primitive-mono": "var(--primitive-font-mono)", "spacing-primitive-control-height-sm": "var(--primitive-control-height-sm)", "spacing-primitive-control-height-md": "var(--primitive-control-height-md)", "spacing-primitive-control-height-lg": "var(--primitive-control-height-lg)" }, "light": { "background": "#fafafa", "foreground": "#0a0a0a", "surface": "#ffffff", "surface-muted": "#f4f4f5", "border": "rgba(10, 10, 10, 0.08)", "border-strong": "rgba(10, 10, 10, 0.16)", "muted": "#f4f4f5", "muted-foreground": "#52525b", "ring": "#cd1c18", "pattern-fg": "rgba(10, 10, 10, 0.07)", "llb-primary": "#18181b", "llb-primary-fg": "#ffffff", "llb-success": "#1f883d", "llb-error": "#cf222e", "primitive-surface-elevated": "#ffffff", "primitive-surface-overlay": "#ffffff", "primitive-surface-hover": "color-mix(in srgb, var(--foreground) 4%, transparent)", "primitive-surface-active": "color-mix(in srgb, var(--foreground) 7%, transparent)", "primitive-surface-selected": "color-mix(in srgb, var(--foreground) 6%, transparent)", "primitive-border-subtle": "color-mix(in srgb, var(--border) 60%, transparent)", "primitive-ring": "color-mix(in srgb, var(--foreground) 45%, transparent)", "primitive-text-secondary": "color-mix(in srgb, var(--foreground) 72%, transparent)", "primitive-text-placeholder": "color-mix(in srgb, var(--muted-foreground) 85%, transparent)", "primitive-radius": "0.75rem", "primitive-font-sans": "var(--font-sans)", "primitive-font-display": "var(--font-display)", "primitive-font-mono": "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace", "primitive-control-solid": "#24292d", "primitive-control-solid-hover": "#2c3237", "primitive-control-solid-active": "#1e2326", "primitive-control-solid-foreground": "#ffffff", "primitive-chart-1": "#2a78d6", "primitive-chart-2": "#1baf7a", "primitive-chart-3": "#eda100", "primitive-chart-4": "#008300", "primitive-chart-5": "#4a3aa7", "primitive-chart-6": "#e34948", "primitive-text-inverse": "#ffffff", "primitive-text-hint": "0.6875rem", "primitive-destructive": "#dc2626", "primitive-destructive-hover": "#b91c1c", "primitive-destructive-active": "#991b1b", "primitive-destructive-foreground": "#ffffff", "primitive-destructive-surface": "rgba(220, 38, 38, 0.10)", "primitive-destructive-border": "rgba(220, 38, 38, 0.45)", "primitive-success": "#047857", "primitive-success-surface": "rgba(4, 120, 87, 0.10)", "primitive-success-border": "rgba(4, 120, 87, 0.45)", "primitive-warning": "#b45309", "primitive-warning-surface": "rgba(180, 83, 9, 0.10)", "primitive-warning-border": "rgba(180, 83, 9, 0.45)", "primitive-info": "#0369a1", "primitive-info-surface": "rgba(3, 105, 161, 0.10)", "primitive-info-border": "rgba(3, 105, 161, 0.45)", "primitive-radius-control": "var(--primitive-radius)", "primitive-radius-control-sm": "min(calc(var(--primitive-radius) * 0.8), 12px)", "primitive-radius-surface": "calc(var(--primitive-radius) * 1.4)", "primitive-radius-popup": "var(--primitive-radius)", "primitive-radius-item": "calc(var(--primitive-radius) * 0.8)", "primitive-control-height-sm": "2rem", "primitive-control-height-md": "2.25rem", "primitive-control-height-lg": "2.5rem", "primitive-shadow-raised": "0 1px 1px -0.5px rgba(10, 10, 10, 0.08), 0 2px 6px -2px rgba(10, 10, 10, 0.08)", "primitive-shadow-overlay": "0 2px 4px -1px rgba(10, 10, 10, 0.06), 0 8px 16px -4px rgba(10, 10, 10, 0.08), 0 16px 32px -8px rgba(10, 10, 10, 0.14)", "primitive-shadow-modal": "0 4px 8px -2px rgba(10, 10, 10, 0.06), 0 16px 32px -8px rgba(10, 10, 10, 0.12), 0 32px 64px -16px rgba(10, 10, 10, 0.2)", "primitive-edge": "rgba(10, 10, 10, 0.1)", "primitive-catchlight": "rgba(10, 10, 10, 0.06)", "primitive-groove-shadow": "rgba(10, 10, 10, 0.08)", "primitive-groove-highlight": "rgba(255, 255, 255, 0.85)", "primitive-shadow-drop": "0 1px 1px -0.5px rgba(10, 10, 10, 0.1), 0 2px 4px -1px rgba(10, 10, 10, 0.06)", "primitive-shadow-recess": "inset 0 2px 3px -1px rgba(10, 10, 10, 0.1)", "primitive-control-face": "var(--primitive-surface-elevated)", "primitive-field-face": "var(--primitive-surface-elevated)", "primitive-well": "rgba(10, 10, 10, 0.045)", "primitive-shadow-well": "inset 0 1px 2px 0 rgba(10, 10, 10, 0.06)", "primitive-tint-hover": "rgba(10, 10, 10, 0.045)", "primitive-tint-press": "rgba(10, 10, 10, 0.06)", "primitive-footer": "color-mix(in srgb, var(--primitive-surface-elevated) 97%, black)", "primitive-overlay-face": "var(--primitive-surface-overlay)", "primitive-frame-face": "color-mix(in srgb, var(--primitive-surface-elevated) 97%, black)", "primitive-z-overlay": "100", "primitive-z-popover": "130", "primitive-z-toast": "140", "primitive-backdrop": "rgba(0, 0, 0, 0.6)", "primitive-motion-fast": "80ms", "primitive-motion-fast-exit": "60ms", "primitive-motion-moderate": "160ms", "primitive-motion-moderate-exit": "120ms", "primitive-motion-slow": "240ms", "primitive-motion-slow-exit": "160ms", "primitive-ease": "cubic-bezier(0.23, 1, 0.32, 1)" }, "dark": { "background": "#0a0a0b", "foreground": "#f5f5f6", "surface": "#111113", "surface-muted": "#18181b", "border": "rgba(255, 255, 255, 0.08)", "border-strong": "rgba(255, 255, 255, 0.14)", "muted": "#1c1c1f", "muted-foreground": "#a1a1aa", "ring": "#cd1c18", "pattern-fg": "rgba(255, 255, 255, 0.06)", "llb-primary": "#f5f5f6", "llb-primary-fg": "#0a0a0b", "llb-success": "#2da44e", "llb-error": "#f85149", "primitive-surface-elevated": "#0f0f10", "primitive-surface-overlay": "#141415", "primitive-surface-hover": "color-mix(in srgb, var(--foreground) 5%, transparent)", "primitive-surface-active": "color-mix(in srgb, var(--foreground) 10%, transparent)", "primitive-surface-selected": "color-mix(in srgb, var(--foreground) 8%, transparent)", "primitive-border-subtle": "color-mix(in srgb, var(--border) 60%, transparent)", "primitive-ring": "color-mix(in srgb, var(--foreground) 45%, transparent)", "primitive-text-secondary": "color-mix(in srgb, var(--foreground) 72%, transparent)", "primitive-text-placeholder": "color-mix(in srgb, var(--muted-foreground) 85%, transparent)", "primitive-radius": "0.75rem", "primitive-font-sans": "var(--font-sans)", "primitive-font-display": "var(--font-display)", "primitive-font-mono": "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace", "primitive-control-solid": "#f5f3ee", "primitive-control-solid-hover": "#ffffff", "primitive-control-solid-active": "#e8e4da", "primitive-control-solid-foreground": "#151719", "primitive-chart-1": "#3987e5", "primitive-chart-2": "#199e70", "primitive-chart-3": "#c98500", "primitive-chart-4": "#008300", "primitive-chart-5": "#9085e9", "primitive-chart-6": "#e66767", "primitive-text-inverse": "#151719", "primitive-text-hint": "0.6875rem", "primitive-destructive": "#e11d2e", "primitive-destructive-hover": "#c1121f", "primitive-destructive-active": "#a4161a", "primitive-destructive-foreground": "#ffffff", "primitive-destructive-surface": "rgba(225, 29, 46, 0.12)", "primitive-destructive-border": "rgba(225, 29, 46, 0.52)", "primitive-success": "#34d399", "primitive-success-surface": "rgba(52, 211, 153, 0.12)", "primitive-success-border": "rgba(52, 211, 153, 0.45)", "primitive-warning": "#fbbf24", "primitive-warning-surface": "rgba(251, 191, 36, 0.12)", "primitive-warning-border": "rgba(251, 191, 36, 0.45)", "primitive-info": "#38bdf8", "primitive-info-surface": "rgba(56, 189, 248, 0.12)", "primitive-info-border": "rgba(56, 189, 248, 0.45)", "primitive-radius-control": "var(--primitive-radius)", "primitive-radius-control-sm": "min(calc(var(--primitive-radius) * 0.8), 12px)", "primitive-radius-surface": "calc(var(--primitive-radius) * 1.4)", "primitive-radius-popup": "var(--primitive-radius)", "primitive-radius-item": "calc(var(--primitive-radius) * 0.8)", "primitive-control-height-sm": "2rem", "primitive-control-height-md": "2.25rem", "primitive-control-height-lg": "2.5rem", "primitive-shadow-raised": "inset 0 1px 0 0 rgba(255, 255, 255, 0.05), 0 1px 2px -1px rgba(0, 0, 0, 0.6), 0 2px 6px -2px rgba(0, 0, 0, 0.5)", "primitive-shadow-overlay": "inset 0 1px 0 0 rgba(255, 255, 255, 0.06), 0 2px 4px -1px rgba(0, 0, 0, 0.4), 0 8px 16px -4px rgba(0, 0, 0, 0.45), 0 16px 32px -8px rgba(0, 0, 0, 0.65)", "primitive-shadow-modal": "inset 0 1px 0 0 rgba(255, 255, 255, 0.06), 0 4px 8px -2px rgba(0, 0, 0, 0.4), 0 16px 32px -8px rgba(0, 0, 0, 0.55), 0 32px 64px -16px rgba(0, 0, 0, 0.75)", "primitive-edge": "rgba(255, 255, 255, 0.09)", "primitive-catchlight": "rgba(255, 255, 255, 0.16)", "primitive-groove-shadow": "rgba(0, 0, 0, 0.55)", "primitive-groove-highlight": "rgba(255, 255, 255, 0.05)", "primitive-shadow-drop": "0 1px 1px -0.5px rgba(0, 0, 0, 0.6), 0 2px 4px -1px rgba(0, 0, 0, 0.4)", "primitive-shadow-recess": "inset 0 2px 3px -1px rgba(0, 0, 0, 0.5)", "primitive-control-face": "var(--primitive-frame-face)", "primitive-field-face": "var(--primitive-frame-face)", "primitive-well": "rgba(0, 0, 0, 0.35)", "primitive-shadow-well": "inset 0 1px 2px 0 rgba(0, 0, 0, 0.45)", "primitive-tint-hover": "rgba(255, 255, 255, 0.06)", "primitive-tint-press": "rgba(0, 0, 0, 0.2)", "primitive-footer": "color-mix(in srgb, var(--primitive-surface-elevated) 97%, white)", "primitive-overlay-face": "color-mix(in srgb, var(--primitive-surface-overlay) 94%, white)", "primitive-frame-face": "color-mix(in srgb, var(--primitive-surface-elevated) 97%, white)", "primitive-z-overlay": "100", "primitive-z-popover": "130", "primitive-z-toast": "140", "primitive-backdrop": "rgba(0, 0, 0, 0.6)", "primitive-motion-fast": "80ms", "primitive-motion-fast-exit": "60ms", "primitive-motion-moderate": "160ms", "primitive-motion-moderate-exit": "120ms", "primitive-motion-slow": "240ms", "primitive-motion-slow-exit": "160ms", "primitive-ease": "cubic-bezier(0.23, 1, 0.32, 1)" } }, "css": { "@layer components": { "[data-surface]": { "--surface-tint": "transparent", "border-width": "1px", "border-style": "solid", "border-color": "var(--surface-rim)", "border-top-color": "var(--surface-rim-top)", "background-color": "var(--surface-face)", "background-image": "linear-gradient(var(--surface-tint), var(--surface-tint))", "--tw-shadow": "var(--surface-depth)", "box-shadow": "var(--tw-inset-shadow, 0 0 #0000), var(--tw-inset-ring-shadow, 0 0 #0000), var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)" }, "[data-surface=\"control\"]": { "--surface-face": "var(--primitive-control-face)", "--surface-rim": "var(--primitive-edge)", "--surface-rim-top": "var(--primitive-catchlight)", "--surface-depth": "var(--primitive-shadow-drop)" }, "[data-surface=\"field\"]": { "--surface-face": "var(--primitive-field-face)", "--surface-rim": "var(--primitive-edge)", "--surface-rim-top": "var(--primitive-catchlight)", "--surface-depth": "var(--primitive-shadow-drop)" }, "[data-surface=\"fill\"]": { "--surface-face": "var(--primitive-control-solid)", "--surface-rim": "color-mix(in srgb, var(--surface-face) 88%, black)", "--surface-rim-top": "color-mix(in srgb, var(--surface-face) 80%, white)", "--surface-depth": "var(--primitive-shadow-drop)" }, "[data-surface=\"flat\"], [data-surface=\"toggle\"], [data-surface=\"toggle-fill\"]": { "--surface-face": "transparent", "--surface-rim": "transparent", "--surface-rim-top": "transparent", "--surface-depth": "0 0 #0000" }, "[data-surface=\"toggle\"]:is([data-pressed]:not([data-pressed=\"false\"]), [aria-pressed=\"true\"])": { "--surface-face": "var(--primitive-control-face)", "--surface-rim": "var(--primitive-edge)", "--surface-rim-top": "var(--primitive-catchlight)", "--surface-depth": "var(--primitive-shadow-drop)" }, "[data-surface=\"toggle-fill\"]:is([data-pressed]:not([data-pressed=\"false\"]), [aria-pressed=\"true\"])": { "--surface-face": "var(--primitive-control-solid)", "--surface-rim": "color-mix(in srgb, var(--surface-face) 88%, black)", "--surface-rim-top": "color-mix(in srgb, var(--surface-face) 80%, white)", "--surface-depth": "var(--primitive-shadow-drop)" }, "[data-surface=\"well\"]": { "--surface-face": "var(--primitive-well)", "--surface-rim": "transparent", "--surface-rim-top": "transparent", "--surface-depth": "var(--primitive-shadow-well)" }, "[data-surface=\"frame\"]": { "--surface-face": "var(--primitive-frame-face)", "--surface-rim": "var(--primitive-edge)", "--surface-rim-top": "var(--primitive-catchlight)", "--surface-depth": "0 0 #0000" }, "[data-surface=\"panel\"]": { "--surface-face": "var(--primitive-surface-elevated)", "--surface-rim": "var(--primitive-edge)", "--surface-rim-top": "var(--primitive-edge)", "--surface-depth": "var(--primitive-shadow-raised)" }, "[data-surface=\"overlay\"]": { "--surface-face": "var(--primitive-overlay-face)", "--surface-rim": "var(--primitive-edge)", "--surface-rim-top": "var(--primitive-edge)", "--surface-depth": "var(--primitive-shadow-overlay)" }, "[data-surface=\"modal\"]": { "--surface-face": "var(--primitive-surface-elevated)", "--surface-rim": "var(--primitive-edge)", "--surface-rim-top": "var(--primitive-edge)", "--surface-depth": "var(--primitive-shadow-modal)" }, "[data-surface=\"footer\"]": { "--surface-face": "var(--primitive-footer)", "--surface-rim": "transparent", "--surface-rim-top": "transparent", "--surface-depth": "0 0 #0000", "border-width": "0", "background-image": "linear-gradient(to bottom, var(--primitive-groove-shadow) 0 1px, var(--primitive-groove-highlight) 1px 2px)", "background-size": "100% 2px", "background-repeat": "no-repeat", "background-position": "top" }, "@media (hover: hover)": { "[data-surface]:where(button, a[href], summary, label, [role=\"button\"], [role=\"tab\"], [role=\"combobox\"], [role=\"option\"], [role=\"menuitem\"]):where(:not(:disabled, [data-disabled], [aria-disabled=\"true\"])):hover": { "--surface-tint": "var(--primitive-tint-hover)" }, ":is([data-surface=\"control\"], [data-surface=\"field\"]):is([data-pressed]:not([data-pressed=\"false\"]), [aria-pressed=\"true\"]):where(:not(:disabled, [data-disabled], [aria-disabled=\"true\"])):hover": { "--surface-tint": "var(--primitive-tint-hover)" } }, ":is([data-surface=\"control\"], [data-surface=\"field\"]):is([data-pressed]:not([data-pressed=\"false\"]), [aria-pressed=\"true\"])": { "--surface-tint": "var(--primitive-tint-press)", "--surface-rim-top": "var(--surface-rim)", "--surface-depth": "var(--primitive-shadow-recess)" }, ":is([data-surface=\"control\"], [data-surface=\"field\"], [data-surface=\"fill\"], [data-surface=\"toggle\"], [data-surface=\"toggle-fill\"]):is([aria-expanded=\"true\"], [data-popup-open]):not(input, textarea)": { "--surface-tint": "var(--primitive-tint-press)", "--surface-rim-top": "var(--surface-rim)", "--surface-depth": "var(--primitive-shadow-recess)" }, ":is([data-surface=\"control\"], [data-surface=\"field\"], [data-surface=\"fill\"], [data-surface=\"toggle\"], [data-surface=\"toggle-fill\"]):where(button, a[href], summary, [role=\"button\"], [role=\"tab\"]):where(:not(:disabled, [data-disabled], [aria-disabled=\"true\"])):active": { "--surface-tint": "var(--primitive-tint-press)", "--surface-rim-top": "var(--surface-rim)", "--surface-depth": "var(--primitive-shadow-recess)" }, "[data-surface=\"flat\"]:where(button, a[href], summary, [role=\"button\"], [role=\"tab\"]):where(:not(:disabled, [data-disabled], [aria-disabled=\"true\"])):active": { "--surface-tint": "var(--primitive-tint-press)" }, "[data-surface]:is([aria-invalid=\"true\"], :has(> :is(input, textarea)[aria-invalid=\"true\"]))": { "--surface-rim": "var(--primitive-destructive-border)", "--surface-rim-top": "var(--primitive-destructive-border)" }, "[data-surface][data-surface]:is(:disabled, [data-disabled], [aria-disabled=\"true\"])": { "--surface-tint": "transparent", "--surface-rim-top": "var(--surface-rim)", "--surface-depth": "0 0 #0000" }, "[data-groove]": { "flex-shrink": "0", "border-width": "0", "background-image": "linear-gradient(var(--groove-direction, to bottom), var(--primitive-groove-shadow) 0 1px, var(--primitive-groove-highlight) 1px 2px)" }, "[data-groove=\"horizontal\"]": { "height": "2px" }, "[data-groove=\"vertical\"]": { "--groove-direction": "to right", "width": "2px", "align-self": "stretch" }, "[data-carve]": { "background-image": "linear-gradient(to bottom, var(--primitive-groove-shadow) 0 1px, var(--primitive-groove-highlight) 1px 2px)", "background-repeat": "no-repeat", "background-size": "100% 2px" }, "[data-carve=\"top\"]": { "background-position": "top" }, "[data-carve=\"bottom\"]": { "background-position": "bottom" } }, "@layer base": { ":where([data-wensity-primitive])": { "font-family": "var(--primitive-font-sans)" } }, "@utility scrollbar-hidden": { "scrollbar-width": "none", "-ms-overflow-style": "none", "&::-webkit-scrollbar": { "display": "none" } }, "@keyframes wensity-marquee-x": { "from": { "transform": "translate3d(0, 0, 0)" }, "to": { "transform": "translate3d(-50%, 0, 0)" } }, "@keyframes wensity-marquee-x-reverse": { "from": { "transform": "translate3d(-50%, 0, 0)" }, "to": { "transform": "translate3d(0, 0, 0)" } }, "@keyframes wensity-morph-rot-cw": { "from": { "transform": "rotate(0deg)" }, "to": { "transform": "rotate(360deg)" } }, "@keyframes wensity-morph-rot-ccw": { "from": { "transform": "rotate(0deg)" }, "to": { "transform": "rotate(-360deg)" } } }, "docs": "Free Wensity component. Installs to @components/wensity/blob-animation.tsx. For Pro components and updates, use pnpm dlx wensity@latest add blob-animation.", "categories": [ "Cinematic Interactions", "wensity", "free" ], "meta": { "wensity": { "slug": "blob-animation", "access": "free", "category": "Cinematic Interactions", "kind": "component", "componentUrl": "https://ui.wensity.com/components/blob-animation", "shadcnUrl": "https://ui.wensity.com/r/blob-animation", "cliInstall": "pnpm dlx wensity@latest add blob-animation" } } }