Use Cases Role Cards
blockmarketingGrid of role cards, each stating the job to be done, the first week of work, and the metric that role is measured on, so a reader can self-select without a tab interaction.
Installation
$pnpm dlx uipkge-ng@latest add use-cases-role-cards$npx uipkge-ng@latest add use-cases-role-cards$yarn dlx uipkge-ng@latest add use-cases-role-cards$bunx uipkge-ng@latest add use-cases-role-cardsManifest:
https://uipkge.dev/r/angular/use-cases-role-cards.jsonInstalls to:src/app/components/blocks/use-cases-role-cards/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.
RoleCardinterface RoleCard {
initials: string
role: string
job: string
week: string
metric: string
}Files installed (2)
src/app/components/blocks/use-cases-role-cards/use-cases-role-cards.component.ts4.8 kB
// Grid of role cards, each stating the job to be done, the first week of work, // and the metric that role is measured on, so a reader can self-select without // a tab interaction. Port of the React block 1:1 (static, no client state). import { ChangeDetectionStrategy, Component, Input } from '@angular/core' import { ArrowUpRight, LucideAngularModule } from 'lucide-angular' import { cn } from '@/lib/utils' import { UiAvatarComponent, UiAvatarFallbackComponent } from '@/ui/avatar/avatar.component' import { UiBadgeComponent } from '@/ui/badge/badge.component' import { UiButtonComponent } from '@/ui/button/button.component' import { UiCardComponent, UiCardContentComponent } from '@/ui/card/card.component' import { UiSeparatorComponent } from '@/ui/separator/separator.component' interface RoleCard { initials: string role: string job: string week: string metric: string } const roles: RoleCard[] = [ { initials: 'FC', role: 'Financial controller', job: 'Close the books without a reconciliation relay.', week: 'Reconcile revenue and margin against the ledger, then lock the period.', metric: 'Days to close', }, { initials: 'AL', role: 'Analytics lead', job: 'Stop being a query queue for the rest of the company.', week: 'Publish the ten numbers that generate the most tickets as certified metrics.', metric: 'Ad-hoc requests per month', }, { initials: 'RO', role: 'RevOps', job: 'Make forecast review about the forecast.', week: 'Agree one pipeline definition with finance and snapshot it weekly.', metric: 'Forecast accuracy band', }, { initials: 'DE', role: 'Data engineer', job: 'Stop owning an undocumented reporting service.', week: 'Move definitions into the repo and delete the bespoke extract jobs.', metric: 'Pipelines maintained', }, ] @Component({ changeDetection: ChangeDetectionStrategy.Eager, selector: 'ui-use-cases-role-cards, [ui-use-cases-role-cards]', 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, UiAvatarComponent, UiAvatarFallbackComponent, UiBadgeComponent, UiButtonComponent, UiCardComponent, UiCardContentComponent, UiSeparatorComponent, ], template: ` <section data-slot="use-cases-role-cards" [class]="rootClass"> <div class="mx-auto max-w-6xl px-6 py-20 lg:py-28"> <div class="max-w-2xl"> <span ui-badge variant="secondary">By role</span> <h2 class="mt-4 text-3xl font-semibold tracking-tight sm:text-4xl">Find the card with your job on it</h2> <p class="text-muted-foreground mt-3 text-lg"> Each one names the work of the first week and the number that role is actually judged on. </p> </div> <div class="mt-10 grid gap-4 sm:grid-cols-2"> @for (role of roles; track role.role) { <div ui-card class="group"> <div ui-card-content class="flex h-full flex-col p-6"> <div class="flex items-center gap-3"> <ui-avatar class="size-9"> <ui-avatar-fallback class="text-xs">{{ role.initials }}</ui-avatar-fallback> </ui-avatar> <p class="text-sm font-semibold">{{ role.role }}</p> </div> <p class="mt-4 text-base leading-snug font-medium text-balance">{{ role.job }}</p> <ui-separator class="my-4" /> <p class="text-muted-foreground font-mono text-xs tracking-[0.14em] uppercase">First week</p> <p class="text-muted-foreground mt-2 text-sm leading-relaxed">{{ role.week }}</p> <div class="border-border mt-auto flex items-center justify-between gap-3 border-t pt-4"> <span class="text-xs"> <span class="text-muted-foreground">Measured on </span> <span class="font-medium">{{ role.metric }}</span> </span> <button ui-button variant="ghost" size="sm" class="h-auto shrink-0 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" /> </button> </div> </div> </div> } </div> </div> </section> `, }) export class UiUseCasesRoleCardsComponent { protected readonly ArrowUpRight = ArrowUpRight protected readonly roles = roles @Input('class') className?: string get rootClass(): string { return cn('bg-background', this.className) } }src/app/components/blocks/use-cases-role-cards/index.ts0.1 kB
export { UiUseCasesRoleCardsComponent } from './use-cases-role-cards.component'
Raw manifest:https://uipkge.dev/r/angular/use-cases-role-cards.json