diff --git a/libs/angular/src/tools/achievements/achievement-card.component.html b/libs/angular/src/tools/achievements/achievement-card.component.html
new file mode 100644
index 00000000000..fb611b2e44d
--- /dev/null
+++ b/libs/angular/src/tools/achievements/achievement-card.component.html
@@ -0,0 +1,10 @@
+
+
+
+
+ {{ title() }}
+ {{ description() }}
+ @if (earned()) {
+ {{ date() }}
+ }
+
diff --git a/libs/angular/src/tools/achievements/achievement-card.component.ts b/libs/angular/src/tools/achievements/achievement-card.component.ts
new file mode 100644
index 00000000000..e483538e3af
--- /dev/null
+++ b/libs/angular/src/tools/achievements/achievement-card.component.ts
@@ -0,0 +1,52 @@
+import { CommonModule } from "@angular/common";
+import { Component, effect, input, untracked } from "@angular/core";
+
+import {
+ ButtonModule,
+ CardComponent,
+ Icon,
+ IconModule,
+ ItemModule,
+ TypographyModule,
+} from "@bitwarden/components";
+
+import { AchievementIcon } from "./achievement-icon";
+import { NotAchievedIcon } from "./not-achieved-icon";
+
+@Component({
+ selector: "achievement-card",
+ templateUrl: "achievement-card.component.html",
+ standalone: true,
+ imports: [CommonModule, ItemModule, ButtonModule, IconModule, TypographyModule, CardComponent],
+})
+export class AchievementCard {
+ protected icon: Icon = NotAchievedIcon;
+
+ title = input.required();
+ description = input.required();
+
+ earned = input(false);
+ progress = input(0);
+ date = input();
+
+ protected cardClass: string;
+ constructor() {
+ effect(() => {
+ const earned = this.earned();
+ const progress = this.progress();
+
+ untracked(() => {
+ if (earned) {
+ this.icon = AchievementIcon;
+ this.cardClass = "tw-bg-success-100";
+ } else if (progress > 0) {
+ this.icon = AchievementIcon;
+ this.cardClass = "tw-bg-info-100";
+ } else {
+ this.icon = NotAchievedIcon;
+ this.cardClass = "";
+ }
+ });
+ });
+ }
+}