Employee Pulse Survey Results
blockhrCulture Amp style company pulse and eNPS engagement survey results dashboard featuring executive KPI scorecards, department sentiment heatmaps, and priority engagement drivers with action items.
Installation
$pnpm dlx uipkge-ng@latest add employee-pulse-survey-results$npx uipkge-ng@latest add employee-pulse-survey-results$yarn dlx uipkge-ng@latest add employee-pulse-survey-results$bunx uipkge-ng@latest add employee-pulse-survey-resultsManifest:
https://uipkge.dev/r/angular/employee-pulse-survey-results.jsonInstalls to:src/app/components/blocks/employee-pulse-survey-results/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.
PrimaryMetricinterface PrimaryMetric {
id: string
title: string
value: string
unit?: string
badgeText: string
badgeVariant: BadgeVariant
detail: string
subtext: string
progress: number
icon: LucideIconData
}DepartmentRowinterface DepartmentRow {
name: string
responseCount: string
participationRate: string
cultureValues: number
managementEffectiveness: number
workLifeBalance: number
compensationGrowth: number
enpsFormatted: string
enpsRank: string
}DriverIteminterface DriverItem {
id: string
title: string
score: string
tag: string
impact: string
description: string
benchmarkDiff: string
}OpportunityIteminterface OpportunityItem {
id: string
title: string
score: string
statusBadge: string
owner: string
targetDate: string
actionSummary: string
}Files installed (2)
src/app/components/blocks/employee-pulse-survey-results/employee-pulse-survey-results.component.ts23.5 kB
// Culture Amp style company pulse and eNPS engagement survey results dashboard with executive // KPI scorecards, a department sentiment heatmap, and priority engagement drivers with action // items. Port of the React block 1:1. import { ChangeDetectionStrategy, Component, Input } from '@angular/core' import { AlertCircle, Award, FileDown, HeartHandshake, Lightbulb, LucideAngularModule, ShieldCheck, TrendingUp, Users, Zap, type LucideIconData, } from 'lucide-angular' import { cn } from '@/lib/utils' import { UiBadgeComponent, type BadgeVariant } from '@/ui/badge/badge.component' import { UiButtonComponent } from '@/ui/button/button.component' import { UiCardComponent, UiCardContentComponent, UiCardDescriptionComponent, UiCardHeaderComponent, UiCardTitleComponent, } from '@/ui/card/card.component' import { UiProgressComponent } from '@/ui/progress/progress.component' import { UiTableBodyComponent, UiTableCellComponent, UiTableComponent, UiTableHeadComponent, UiTableHeaderComponent, UiTableRowComponent, } from '@/ui/table/table.component' interface PrimaryMetric { id: string title: string value: string unit?: string badgeText: string badgeVariant: BadgeVariant detail: string subtext: string progress: number icon: LucideIconData } interface DepartmentRow { name: string responseCount: string participationRate: string cultureValues: number managementEffectiveness: number workLifeBalance: number compensationGrowth: number enpsFormatted: string enpsRank: string } interface DriverItem { id: string title: string score: string tag: string impact: string description: string benchmarkDiff: string } interface OpportunityItem { id: string title: string score: string statusBadge: string owner: string targetDate: string actionSummary: string } const primaryMetrics: PrimaryMetric[] = [ { id: 'enps-score', title: 'Employee Net Promoter Score', value: '+54', unit: 'eNPS', badgeText: '+22 vs tech benchmark', badgeVariant: 'success', detail: '64% Promoters · 26% Passives · 10% Detractors', subtext: 'Benchmark: +32 eNPS across peer tech scaleups', progress: 77, icon: TrendingUp, }, { id: 'engagement-index', title: 'Overall Engagement Index', value: '86%', unit: 'Favorable', badgeText: '+4% vs Q2', badgeVariant: 'success', detail: '86% Favorable · 10% Neutral · 4% Unfavorable', subtext: '4.3 / 5.0 mean agreement across all survey items', progress: 86, icon: HeartHandshake, }, { id: 'participation-rate', title: 'Survey Participation Rate', value: '94%', unit: '139 / 148', badgeText: 'High Confidence', badgeVariant: 'secondary', detail: '94% across 5 active departments', subtext: 'Statistically significant sample size (p < 0.01)', progress: 94, icon: Users, }, { id: 'retention-intent', title: 'Intent to Stay 2+ Years', value: '88%', unit: 'Retention', badgeText: '+6% vs Q2', badgeVariant: 'success', detail: '88% positive retention sentiment', subtext: 'Low voluntary flight risk across engineering & product', progress: 88, icon: ShieldCheck, }, ] const departments: DepartmentRow[] = [ { name: 'Engineering', responseCount: '46 / 48 responses', participationRate: '96%', cultureValues: 92, managementEffectiveness: 88, workLifeBalance: 84, compensationGrowth: 74, enpsFormatted: '+62', enpsRank: 'Top Quartile', }, { name: 'Product & Design', responseCount: '28 / 30 responses', participationRate: '93%', cultureValues: 94, managementEffectiveness: 91, workLifeBalance: 82, compensationGrowth: 76, enpsFormatted: '+58', enpsRank: 'Top Quartile', }, { name: 'Marketing', responseCount: '22 / 24 responses', participationRate: '92%', cultureValues: 89, managementEffectiveness: 85, workLifeBalance: 86, compensationGrowth: 71, enpsFormatted: '+48', enpsRank: 'Above Average', }, { name: 'Sales & GTM', responseCount: '25 / 26 responses', participationRate: '96%', cultureValues: 86, managementEffectiveness: 84, workLifeBalance: 78, compensationGrowth: 68, enpsFormatted: '+45', enpsRank: 'Above Average', }, { name: 'Operations', responseCount: '18 / 20 responses', participationRate: '90%', cultureValues: 90, managementEffectiveness: 87, workLifeBalance: 88, compensationGrowth: 72, enpsFormatted: '+52', enpsRank: 'Top Quartile', }, ] const topDrivers: DriverItem[] = [ { id: 'driver-1', title: 'Psychological safety & peer collaboration', score: '96% favorable', tag: 'Highest Scored Driver', impact: 'Highest correlation with company eNPS (+0.74 r)', description: 'Squads report high mutual trust, blameless incident reviews, and transparent pairing culture without fear of failure.', benchmarkDiff: '+14% vs tech benchmark', }, { id: 'driver-2', title: 'Mission alignment & executive transparency', score: '92% favorable', tag: 'Core Driver', impact: 'Strongest predictor of organizational retention', description: 'Bi-weekly all-hands, transparent financials, and crisp quarterly OKRs provide unequivocal clarity on company trajectory.', benchmarkDiff: '+11% vs tech benchmark', }, { id: 'driver-3', title: 'Manager trust & day-to-day autonomy', score: '90% favorable', tag: 'Core Driver', impact: 'Key catalyst for execution velocity & morale', description: 'Team members highlight minimal micromanagement, supportive weekly 1:1 coaching, and autonomy over technical decisions.', benchmarkDiff: '+9% vs tech benchmark', }, ] const opportunityAreas: OpportunityItem[] = [ { id: 'opp-1', title: 'Clarity on promotion cycles and IC compensation bands', score: '68% favorable', statusBadge: 'Action plan active', owner: 'People Ops & Total Rewards', targetDate: 'Q4 2026 Rollout', actionSummary: 'Publish transparent engineering & IC level matrices with defined salary bands, equity guidelines, and semi-annual calibration windows.', }, { id: 'opp-2', title: 'Cross-functional roadmap visibility & tool sprawl', score: '71% favorable', statusBadge: 'Action plan active', owner: 'Product Ops & Platform Squad', targetDate: 'End of Q3', actionSummary: 'Consolidate sprint tracking into unified Linear workspaces and establish bi-weekly cross-discipline demo showcases.', }, { id: 'opp-3', title: 'Focus time & meeting cadence optimization', score: '73% favorable', statusBadge: 'Action plan active', owner: 'Engineering Leadership Council', targetDate: 'Active Trial', actionSummary: 'Implement company-wide "No Meeting Wednesdays" and audit recurring status meetings in favor of asynchronous updates.', }, ] function getScoreBadgeClass(score: number): string { if (score >= 80) return 'border-success/20 bg-success/10 text-success' if (score >= 70) return 'border-warning/20 bg-warning/10 text-warning' return 'border-destructive/20 bg-destructive/10 text-destructive' } @Component({ changeDetection: ChangeDetectionStrategy.Eager, selector: 'ui-employee-pulse-survey-results, [ui-employee-pulse-survey-results]', standalone: true, // React renders the root <div> itself: the host stays out of layout and `class` goes to the root. host: { '[attr.class]': '"contents"' }, imports: [ LucideAngularModule, UiBadgeComponent, UiButtonComponent, UiCardComponent, UiCardContentComponent, UiCardDescriptionComponent, UiCardHeaderComponent, UiCardTitleComponent, UiProgressComponent, UiTableComponent, UiTableHeaderComponent, UiTableBodyComponent, UiTableRowComponent, UiTableHeadComponent, UiTableCellComponent, ], template: ` <div data-uipkge="" data-slot="employee-pulse-survey-results" [class]="rootClass"> <!-- Header Section --> <div ui-card class="border-border bg-card shadow-xs"> <div ui-card-content class="p-6"> <div class="flex flex-col gap-6 lg:flex-row lg:items-center lg:justify-between"> <div class="space-y-1.5"> <div class="flex flex-wrap items-center gap-2.5"> <h2 class="text-foreground text-xl font-bold tracking-tight sm:text-2xl"> Company Pulse & eNPS Engagement Survey </h2> <span ui-badge variant="outline" [wrap]="true" class="font-mono text-xs">Q3 2026</span> </div> <p class="text-muted-foreground text-xs leading-relaxed sm:text-sm"> Q3 2026 Pulse Survey · 94% Participation Rate · 139 / 148 Responses </p> </div> <div class="flex flex-wrap items-center gap-3"> <div class="border-success/30 bg-success/10 text-success dark:text-foreground flex min-w-0 items-center gap-2 rounded-lg border px-3.5 py-2 shadow-xs" > <lucide-icon [img]="TrendingUp" class="text-success size-4 shrink-0" /> <span class="text-sm font-bold tracking-tight tabular-nums">+54 eNPS · Excellent</span> </div> <button ui-button variant="outline" size="sm" class="gap-2 shadow-xs"> <lucide-icon [img]="FileDown" class="size-4" /> <span>Export Executive Summary</span> </button> </div> </div> </div> </div> <!-- 4 Primary Engagement KPI Cards --> <div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4"> @for (metric of primaryMetrics; track metric.id) { <div ui-card class="border-border bg-card hover:border-border/80 shadow-xs transition-colors"> <div ui-card-header class="flex flex-row items-center justify-between space-y-0 pb-2"> <h3 ui-card-title class="text-muted-foreground text-xs font-medium">{{ metric.title }}</h3> <lucide-icon [img]="metric.icon" class="text-muted-foreground size-4" /> </div> <div ui-card-content class="space-y-3"> <div class="flex flex-wrap items-baseline justify-between gap-2"> <div class="flex items-baseline gap-1.5"> <span class="text-foreground text-2xl font-bold tracking-tight tabular-nums sm:text-3xl">{{ metric.value }}</span> @if (metric.unit) { <span class="text-muted-foreground text-xs font-medium">{{ metric.unit }}</span> } </div> <span ui-badge [variant]="metric.badgeVariant" [wrap]="true" class="text-xs font-medium tabular-nums">{{ metric.badgeText }}</span> </div> <div class="space-y-1.5"> <ui-progress [value]="metric.progress" class="h-1.5 w-full" /> <div class="space-y-0.5 pt-0.5"> <p class="text-foreground text-xs leading-normal font-medium">{{ metric.detail }}</p> <p class="text-muted-foreground text-xs leading-normal">{{ metric.subtext }}</p> </div> </div> </div> </div> } </div> <!-- Department Sentiment Heatmap Table --> <div ui-card class="border-border bg-card shadow-xs"> <div ui-card-header class="pb-4"> <div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between"> <div> <div class="flex min-w-0 items-center gap-2"> <h3 ui-card-title class="text-base font-semibold">Department Sentiment Heatmap</h3> <span ui-badge variant="outline" [wrap]="true" class="text-xs font-normal" >5 Departments · 139 Responses</span > </div> <p ui-card-description class="mt-1 text-xs"> Culture Amp style multidimensional sentiment matrix mapped across key operational pillars. </p> </div> <!-- Heatmap Legend --> <div class="flex flex-wrap items-center gap-2 pt-1 text-xs sm:pt-0"> <span class="text-muted-foreground font-medium">Sentiment Scale:</span> <div class="border-success/20 bg-success/10 text-success flex items-center gap-1 rounded-md border px-2 py-0.5" > <span class="bg-success size-1.5 rounded-full"></span> <span class="font-medium">Favorable (≥80%)</span> </div> <div class="border-warning/20 bg-warning/10 text-warning flex items-center gap-1 rounded-md border px-2 py-0.5" > <span class="bg-warning size-1.5 rounded-full"></span> <span class="font-medium">Moderate (70-79%)</span> </div> <div class="border-destructive/20 bg-destructive/10 text-destructive flex items-center gap-1 rounded-md border px-2 py-0.5" > <span class="bg-destructive size-1.5 rounded-full"></span> <span class="font-medium">Opportunity (<70%)</span> </div> </div> </div> </div> <div ui-card-content class="p-0"> <div class="border-border overflow-x-auto border-t"> <table ui-table> <thead ui-table-header class="bg-muted/40"> <tr ui-table-row class="hover:bg-transparent"> <th ui-table-head class="text-foreground w-60 text-xs font-semibold"> Department & Participation </th> <th ui-table-head class="text-foreground text-center text-xs font-semibold">Culture & Values</th> <th ui-table-head class="text-foreground text-center text-xs font-semibold"> Management Effectiveness </th> <th ui-table-head class="text-foreground text-center text-xs font-semibold">Work-Life Balance</th> <th ui-table-head class="text-foreground text-center text-xs font-semibold"> Compensation & Growth </th> <th ui-table-head class="text-foreground text-right text-xs font-semibold">Overall eNPS Score</th> </tr> </thead> <tbody ui-table-body> @for (dept of departments; track dept.name) { <tr ui-table-row class="hover:bg-muted/30"> <td ui-table-cell class="py-3.5"> <div class="space-y-0.5"> <p class="text-foreground text-sm font-semibold">{{ dept.name }}</p> <p class="text-muted-foreground text-xs tabular-nums"> {{ dept.responseCount }} · <span class="text-foreground font-medium">{{ dept.participationRate }}</span> </p> </div> </td> <td ui-table-cell class="py-3.5 text-center"> <div class="inline-flex flex-col items-center gap-1"> <div [class]="scoreBadgeClass(dept.cultureValues)">{{ dept.cultureValues }}%</div> </div> </td> <td ui-table-cell class="py-3.5 text-center"> <div class="inline-flex flex-col items-center gap-1"> <div [class]="scoreBadgeClass(dept.managementEffectiveness)"> {{ dept.managementEffectiveness }}% </div> </div> </td> <td ui-table-cell class="py-3.5 text-center"> <div class="inline-flex flex-col items-center gap-1"> <div [class]="scoreBadgeClass(dept.workLifeBalance)">{{ dept.workLifeBalance }}%</div> </div> </td> <td ui-table-cell class="py-3.5 text-center"> <div class="inline-flex flex-col items-center gap-1"> <div [class]="scoreBadgeClass(dept.compensationGrowth)">{{ dept.compensationGrowth }}%</div> </div> </td> <td ui-table-cell class="py-3.5 text-right"> <div class="flex flex-col items-end gap-1"> <div class="border-success/30 bg-success/10 text-success inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs font-bold tabular-nums" > <lucide-icon [img]="TrendingUp" class="text-success size-3" /> <span>{{ dept.enpsFormatted }} eNPS</span> </div> <span class="text-muted-foreground text-xs font-normal">{{ dept.enpsRank }}</span> </div> </td> </tr> } </tbody> </table> </div> </div> </div> <!-- Top Engagement Drivers & Action Items --> <div class="grid grid-cols-1 gap-6 lg:grid-cols-2"> <!-- Left Column: Top Engagement Drivers --> <div ui-card class="border-border bg-card shadow-xs"> <div ui-card-header class="pb-4"> <div class="flex flex-wrap items-center justify-between gap-2"> <div class="space-y-1"> <div class="flex min-w-0 items-center gap-2"> <h3 ui-card-title class="text-base font-semibold">Top Engagement Drivers</h3> <span ui-badge variant="success" [wrap]="true" class="text-xs">Organizational Strengths</span> </div> <p ui-card-description class="text-xs"> Highest scored sentiment drivers providing outsized positive impact on overall eNPS. </p> </div> <lucide-icon [img]="Award" class="text-success size-5 shrink-0" /> </div> </div> <div ui-card-content class="space-y-4"> @for (driver of topDrivers; track driver.id) { <div class="bg-muted/30 border-border/80 space-y-2.5 rounded-lg border p-4 shadow-xs"> <div class="flex flex-wrap items-start justify-between gap-2"> <div class="space-y-1"> <div class="flex flex-wrap items-center gap-2"> <h4 class="text-foreground text-sm font-semibold">{{ driver.title }}</h4> <span ui-badge variant="outline" [wrap]="true" class="text-xs font-normal">{{ driver.tag }}</span> </div> <p class="text-muted-foreground text-xs">{{ driver.impact }}</p> </div> <div class="border-success/20 bg-success/10 text-success flex shrink-0 items-center gap-1 rounded-md border px-2.5 py-1 text-xs font-bold tabular-nums" > <lucide-icon [img]="TrendingUp" class="text-success size-3" /> <span>{{ driver.score }}</span> </div> </div> <p class="text-muted-foreground text-xs leading-relaxed">{{ driver.description }}</p> <div class="border-border/60 flex items-center justify-between border-t pt-2 text-xs"> <span class="text-muted-foreground">Peer Benchmark:</span> <span class="text-success font-semibold tabular-nums">{{ driver.benchmarkDiff }}</span> </div> </div> } </div> </div> <!-- Right Column: Priority Opportunity Areas --> <div ui-card class="border-border bg-card shadow-xs"> <div ui-card-header class="pb-4"> <div class="flex flex-wrap items-center justify-between gap-2"> <div class="space-y-1"> <div class="flex min-w-0 items-center gap-2"> <h3 ui-card-title class="text-base font-semibold">Priority Opportunity Areas</h3> <span ui-badge variant="warning" [wrap]="true" class="text-xs">Active Remediation</span> </div> <p ui-card-description class="text-xs"> Key focus areas requiring leadership follow-through and documented action plans. </p> </div> <lucide-icon [img]="Lightbulb" class="text-warning size-5 shrink-0" /> </div> </div> <div ui-card-content class="space-y-4"> @for (opp of opportunityAreas; track opp.id) { <div class="bg-muted/30 border-border/80 space-y-2.5 rounded-lg border p-4 shadow-xs"> <div class="flex flex-wrap items-start justify-between gap-2"> <div class="space-y-1"> <h4 class="text-foreground text-sm font-semibold">{{ opp.title }}</h4> <div class="flex flex-wrap items-center gap-2"> <span ui-badge variant="warning" [wrap]="true" class="text-xs font-medium">{{ opp.statusBadge }}</span> <span class="text-muted-foreground text-xs"> Target: <strong class="text-foreground font-medium">{{ opp.targetDate }}</strong> </span> </div> </div> <div class="border-warning/20 bg-warning/10 text-warning flex shrink-0 items-center gap-1 rounded-md border px-2.5 py-1 text-xs font-bold tabular-nums" > <lucide-icon [img]="AlertCircle" class="text-warning size-3" /> <span>{{ opp.score }}</span> </div> </div> <div class="bg-card/70 border-border/60 space-y-1 rounded-md border p-2.5"> <div class="text-foreground flex items-center gap-1 text-xs font-medium"> <lucide-icon [img]="Zap" class="text-primary size-3 shrink-0" /> <span>Action Plan & Deliverables</span> </div> <p class="text-muted-foreground text-xs leading-relaxed">{{ opp.actionSummary }}</p> </div> <div class="border-border/60 flex items-center justify-between border-t pt-2 text-xs"> <span class="text-muted-foreground">Action Owner:</span> <span class="text-foreground font-medium">{{ opp.owner }}</span> </div> </div> } </div> </div> </div> </div> `, }) export class UiEmployeePulseSurveyResultsComponent { protected readonly AlertCircle = AlertCircle protected readonly Award = Award protected readonly FileDown = FileDown protected readonly Lightbulb = Lightbulb protected readonly TrendingUp = TrendingUp protected readonly Zap = Zap protected readonly primaryMetrics = primaryMetrics protected readonly departments = departments protected readonly topDrivers = topDrivers protected readonly opportunityAreas = opportunityAreas @Input('class') className?: string get rootClass(): string { return cn('w-full space-y-6', this.className) } scoreBadgeClass(score: number): string { return cn( 'flex min-w-[72px] items-center justify-center rounded-md border px-3 py-1.5 text-xs font-bold tabular-nums shadow-xs', getScoreBadgeClass(score), ) } }src/app/components/blocks/employee-pulse-survey-results/index.ts0.1 kB
export { UiEmployeePulseSurveyResultsComponent } from './employee-pulse-survey-results.component'
Raw manifest:https://uipkge.dev/r/angular/employee-pulse-survey-results.json