Conversion Funnel
blockanalyticsHorizontal conversion funnel with count strip above the SmoothFunnel chart and a stage-name + retention-from-previous footer below. Works for hiring (applied → hired), e-commerce (sessions → purchases), onboarding (signed up → activated). 3-6 stages. Theme-aware via OKLCH chart tokens.
Installation
$pnpm dlx shadcn-svelte@latest add https://uipkge.dev/r/svelte/conversion-funnel.json$npx shadcn-svelte@latest add https://uipkge.dev/r/svelte/conversion-funnel.json$yarn dlx shadcn-svelte@latest add https://uipkge.dev/r/svelte/conversion-funnel.json$bunx shadcn-svelte@latest add https://uipkge.dev/r/svelte/conversion-funnel.jsonManifest:
https://uipkge.dev/r/svelte/conversion-funnel.jsonInstalls to:src/lib/components/blocks/conversion-funnel/Variants
Loading interactive previews…
Loading interactive previews…
Includes
Theming
CSS custom properties referenced in this item. Override any of them in your :root or per-element to retheme.
--chart-1--chart-2--chart-3--chart-4--chart-5Files installed (1)
src/lib/components/blocks/conversion-funnel/ConversionFunnel.svelte3.2 kB
<!-- Conversion funnel: SmoothFunnel chart with count strip above and stage-name + retention-from-previous strip below. Works for any drop-off flow with 3-6 stages: hiring (applied -> hired), e-commerce (sessions -> purchases), onboarding (signed up -> activated), etc. Reads as a single horizontal "flow": 72K 38.2K 16.8K 5.6K ╔══════╗╔════════╗╔══════════╗╔══════════╗ ║ 100% ║║ 53% ║║ 23% ║║ 8% ║ ╚══════╝╚════════╝╚══════════╝╚══════════╝ Views Cart Checkout Purchase -> 53% -> 44% -> 33% The middle pill (inside each band) shows the share OF THE TOP stage (100%, 53%, 23%, ...). The bottom retention number shows the stage-to-stage conversion -- usually the more actionable signal. --> <script lang="ts" module> export interface FunnelBlockStage { name: string value: number } export interface ConversionFunnelProps { data: FunnelBlockStage[] /** SmoothFunnel container height. Defaults to 180. */ height?: number | string /** Override colour palette. Defaults to the registry's chart-1..N * OKLCH tokens via CSS variables (so light/dark + theme-customizer * flips ripple through without any JS). Pass a literal hex array to * override. */ colors?: string[] /** Compact number formatter for the count strip (default toLocaleString). */ format?: (n: number) => string /** Hide the retention-from-previous footer on each non-first stage. */ hideRetention?: boolean class?: string } </script> <script lang="ts"> import { cn } from '$lib/utils' import { SmoothFunnel } from '$lib/components/ui/smooth-funnel' const DEFAULT_PALETTE = [ 'var(--chart-1)', 'var(--chart-2)', 'var(--chart-3)', 'var(--chart-4)', 'var(--chart-5)', 'var(--chart-1)', ] let { data, height = 180, colors, format, hideRetention = false, class: className, }: ConversionFunnelProps = $props() const palette = $derived(colors ?? DEFAULT_PALETTE) const fmt = (v: number) => (format ? format(v) : v.toLocaleString()) function retention(i: number) { if (i === 0) return null const prev = data[i - 1]?.value ?? 1 return Math.round(((data[i]?.value ?? 0) / prev) * 100) } </script> <div data-uipkge data-slot="conversion-funnel" class={cn('space-y-2', className)}> <!-- Top: per-stage count --> <div class="grid px-2 text-center" style:grid-template-columns={`repeat(${data.length}, minmax(0, 1fr))`}> {#each data as stage (stage.name)} <div class="text-foreground text-base font-bold tabular-nums"> {fmt(stage.value)} </div> {/each} </div> <!-- Funnel SVG --> <SmoothFunnel {data} {height} colors={palette} /> <!-- Bottom: stage name + retention from previous --> <div class="grid px-2 text-center" style:grid-template-columns={`repeat(${data.length}, minmax(0, 1fr))`}> {#each data as stage, i (stage.name)} <div class="space-y-0.5"> <p class="text-muted-foreground text-xs">{stage.name}</p> {#if !hideRetention && retention(i) !== null} <p class="text-info text-xs font-semibold tabular-nums"> → {retention(i)}% retained </p> {/if} </div> {/each} </div> </div>
Raw manifest:https://uipkge.dev/r/svelte/conversion-funnel.json