Use Cases — Industry Grid
blockmarketingFilterable industry use-case grid: segment chips narrow a six-card grid in place, each card carrying an icon, industry label, outcome headline, proof metric, and a quiet read-more link.
Installation
$pnpm dlx uipkge-ng@latest add use-cases-industry-grid$npx uipkge-ng@latest add use-cases-industry-grid$yarn dlx uipkge-ng@latest add use-cases-industry-grid$bunx uipkge-ng@latest add use-cases-industry-gridManifest:
https://uipkge.dev/r/angular/use-cases-industry-grid.jsonInstalls to:src/app/components/blocks/use-cases-industry-grid/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.
IndustryUseCaseinterface IndustryUseCase {
icon: unknown
segment: string
title: string
body: string
metric: string
}npm dependencies
Includes
Files installed (2)
src/app/components/blocks/use-cases-industry-grid/use-cases-industry-grid.component.ts6.3 kB
// Filterable industry use-case grid: segment chips narrow a six-card grid in place, // each card carrying an icon, industry label, outcome headline, proof metric, and a // quiet read-more link. Port of the React block 1:1. import { ChangeDetectionStrategy, Component, Input, computed, signal } from '@angular/core' import { ArrowUpRight, Banknote, Factory, HeartPulse, LucideAngularModule, Ship, ShoppingCart, Truck, } from 'lucide-angular' import { cn } from '@/lib/utils' import { UiBadgeComponent } from '@/ui/badge/badge.component' import { UiButtonComponent } from '@/ui/button/button.component' import { UiCardComponent, UiCardContentComponent } from '@/ui/card/card.component' import { UiToggleGroupComponent, UiToggleGroupItemComponent } from '@/ui/toggle-group/toggle-group.component' interface IndustryUseCase { icon: unknown segment: string title: string body: string metric: string } const useCases: IndustryUseCase[] = [ { icon: Banknote, segment: 'Financial services', title: 'Close the books without a spreadsheet relay', body: 'Ledger-reconciled metrics that lock on period close, with an auditable trail for every restatement.', metric: '5 days off close', }, { icon: HeartPulse, segment: 'Healthcare', title: 'Report on care quality without exposing PHI', body: 'Row-level scoping evaluated per query, so a shared dashboard never leaks a chart the viewer cannot open.', metric: 'HIPAA-scoped by default', }, { icon: ShoppingCart, segment: 'Retail', title: 'One margin definition across every channel', body: 'Store, marketplace, and wholesale roll up to the same certified metric instead of three competing exports.', metric: '3 channels, 1 number', }, { icon: Truck, segment: 'Logistics', title: 'Track service levels against the contract', body: 'On-time thresholds encoded per customer contract, so breach reporting stops being a manual comparison.', metric: '98.2% SLA visibility', }, { icon: Factory, segment: 'Manufacturing', title: 'Yield reporting that survives a line change', body: 'Definitions version with the production line, so last quarter’s numbers stay comparable after a retool.', metric: '12 lines reconciled', }, { icon: Ship, segment: 'Logistics', title: 'Landed cost per shipment, not per guess', body: 'Freight, duty, and demurrage join at query time against the booking rather than a monthly allocation.', metric: 'Per-shipment costing', }, ] const ALL = 'All' @Component({ changeDetection: ChangeDetectionStrategy.Eager, selector: 'ui-use-cases-industry-grid, [ui-use-cases-industry-grid]', standalone: true, // React renders the root <section> itself: the host stays out of layout and `class` goes to the root. host: { '[attr.class]': '"contents"' }, imports: [ LucideAngularModule, UiBadgeComponent, UiButtonComponent, UiCardComponent, UiCardContentComponent, UiToggleGroupComponent, UiToggleGroupItemComponent, ], template: ` <section data-slot="use-cases-industry-grid" [class]="rootClass"> <div class="mx-auto max-w-6xl px-6 py-20 lg:py-28"> <div class="flex flex-wrap items-end justify-between gap-6"> <div class="max-w-2xl"> <span ui-badge variant="secondary">By industry</span> <h2 class="mt-4 text-3xl font-semibold tracking-tight sm:text-4xl">Where teams start</h2> <p class="text-muted-foreground mt-3 text-lg"> Six rollouts we run often enough to have opinions about. Filter to yours. </p> </div> <div ui-toggle-group type="single" variant="outline" size="sm" class="flex-nowrap overflow-x-auto" aria-label="Filter use cases by industry" [value]="active()" (valueChange)="onSegmentChange($event)" > @for (segment of segments(); track segment) { <button ui-toggle-group-item [value]="segment">{{ segment }}</button> } </div> </div> <div class="mt-10 grid gap-4 sm:grid-cols-2 lg:grid-cols-3"> @for (useCase of visible(); track useCase.title) { <div ui-card class="group"> <div ui-card-content class="flex h-full flex-col p-6"> <lucide-icon [img]="useCase.icon" class="text-muted-foreground size-5" aria-hidden="true" /> <p class="text-muted-foreground mt-4 font-mono text-xs tracking-[0.14em] uppercase"> {{ useCase.segment }} </p> <h3 class="mt-2 text-base leading-snug font-semibold">{{ useCase.title }}</h3> <p class="text-muted-foreground mt-2 text-sm leading-relaxed">{{ useCase.body }}</p> <div class="border-border mt-auto flex items-center justify-between gap-3 border-t pt-4"> <span class="text-sm font-medium">{{ useCase.metric }}</span> <button ui-button variant="ghost" size="sm" class="h-auto px-2 py-1"> Read <lucide-icon [img]="ArrowUpRight" class="ml-1 size-3.5 transition-transform group-hover:translate-x-0.5 group-hover:-translate-y-0.5" aria-hidden="true" /> </button> </div> </div> </div> } </div> </div> </section> `, }) export class UiUseCasesIndustryGridComponent { protected readonly ArrowUpRight = ArrowUpRight @Input('class') className?: string @Input() set initialSegment(v: string | undefined) { if (v) this.active.set(v) } readonly active = signal(ALL) readonly segments = computed(() => [ALL, ...new Set(useCases.map((u) => u.segment))]) readonly visible = computed(() => this.active() === ALL ? useCases : useCases.filter((u) => u.segment === this.active()), ) get rootClass(): string { return cn('bg-background', this.className) } // ToggleGroup single-select emits '' when the active item is pressed again; // fall back to ALL so the grid can never end up empty. onSegmentChange(value: unknown): void { this.active.set(typeof value === 'string' && value ? value : ALL) } }src/app/components/blocks/use-cases-industry-grid/index.ts0.1 kB
export { UiUseCasesIndustryGridComponent } from './use-cases-industry-grid.component'
Raw manifest:https://uipkge.dev/r/angular/use-cases-industry-grid.json