Stats — Band with Sparklines
blockmarketingMetric band pairing each headline figure with an inline sparkline and its period, so a number arrives with the shape of the trend behind it.
Installation
$pnpm dlx uipkge-ng@latest add stats-band-sparklines$npx uipkge-ng@latest add stats-band-sparklines$yarn dlx uipkge-ng@latest add stats-band-sparklines$bunx uipkge-ng@latest add stats-band-sparklinesManifest:
https://uipkge.dev/r/angular/stats-band-sparklines.jsonInstalls to:src/app/components/blocks/stats-band-sparklines/Variants
Loading interactive previews…
Loading interactive previews…
Schema
Type aliases exported from this item's source. Use these to shape the data you pass in.
SparklineMetricinterface SparklineMetric {
value: string
unit: string
label: string
period: string
series: number[]
}npm dependencies
Files installed (2)
src/app/components/blocks/stats-band-sparklines/stats-band-sparklines.component.ts3.7 kB
// Metric band pairing each headline figure with an inline sparkline and its period, // so a number arrives with the shape of the trend behind it. // Port of the Vue/React block 1:1 — inline SVG, no chart dependency. import { ChangeDetectionStrategy, Component, Input } from '@angular/core' import { cn } from '@/lib/utils' import { UiBadgeComponent } from '@/ui/badge/badge.component' import { UiSeparatorComponent } from '@/ui/separator/separator.component' interface SparklineMetric { value: string unit: string label: string period: string series: number[] } const metrics: SparklineMetric[] = [ { value: '4.2', unit: 'days', label: 'Median time to close', period: 'last 12 months', series: [9.4, 9.1, 8.7, 8.2, 7.4, 6.8, 6.1, 5.6, 5.1, 4.8, 4.4, 4.2], }, { value: '61', unit: '/mo', label: 'Ad-hoc data requests', period: 'last 12 months', series: [212, 198, 184, 160, 141, 122, 108, 96, 84, 74, 66, 61], }, { value: '340', unit: '', label: 'Certified metrics live', period: 'since launch', series: [0, 12, 38, 74, 112, 148, 181, 214, 248, 281, 312, 340], }, { value: '99.98', unit: '%', label: 'Query availability', period: 'rolling 90 days', series: [99.9, 99.95, 99.92, 99.97, 99.99, 99.96, 99.98, 99.99, 99.97, 99.98, 99.99, 99.98], }, ] @Component({ changeDetection: ChangeDetectionStrategy.Eager, selector: 'ui-stats-band-sparklines, [ui-stats-band-sparklines]', standalone: true, // Vue renders the root <section> itself: the host stays out of layout and `class` goes to the root. host: { '[attr.class]': '"contents"' }, imports: [UiBadgeComponent, UiSeparatorComponent], template: ` <section data-slot="stats-band-sparklines" [class]="rootClass"> <div class="mx-auto max-w-6xl px-6 py-12"> <span ui-badge variant="secondary">Measured</span> <dl class="mt-6 grid gap-8 sm:grid-cols-2 lg:grid-cols-4 lg:gap-0"> @for (metric of allMetrics; track metric.label; let idx = $index) { <div class="relative lg:px-6 lg:first:pl-0"> <dd class="font-display text-3xl font-bold tracking-tight"> {{ metric.value }}<span class="text-muted-foreground text-lg font-semibold">{{ metric.unit }}</span> </dd> <dt class="mt-1 text-sm font-medium">{{ metric.label }}</dt> <svg class="text-primary/70 mt-3 h-7 w-full" viewBox="0 0 100 28" preserveAspectRatio="none" aria-hidden="true" > <polyline [attr.points]="points(metric.series)" fill="none" stroke="currentColor" stroke-width="1.5" /> </svg> <p class="text-muted-foreground mt-1 font-mono text-xs">{{ metric.period }}</p> @if (idx < allMetrics.length - 1) { <div ui-separator orientation="vertical" class="absolute top-0 right-0 hidden h-full lg:block"></div> } </div> } </dl> </div> </section> `, }) export class UiStatsBandSparklinesComponent { protected readonly allMetrics = metrics @Input('class') className?: string get rootClass(): string { return cn('border-border bg-card border-y', this.className) } /** Normalise a series into a 100x28 viewBox so every sparkline shares a baseline. */ points(series: number[]): string { const min = Math.min(...series) const max = Math.max(...series) const span = max - min || 1 return series .map((value, index) => { const x = (index / (series.length - 1)) * 100 const y = 26 - ((value - min) / span) * 24 return `${x.toFixed(1)},${y.toFixed(1)}` }) .join(' ') } }src/app/components/blocks/stats-band-sparklines/index.ts0.1 kB
export { UiStatsBandSparklinesComponent } from './stats-band-sparklines.component'
Raw manifest:https://uipkge.dev/r/angular/stats-band-sparklines.json