diff --git a/community/components/helpers/progress-bar/progress-bar.component.html b/community/components/helpers/progress-bar/progress-bar.component.html
new file mode 100644
index 00000000..ffc65cf6
--- /dev/null
+++ b/community/components/helpers/progress-bar/progress-bar.component.html
@@ -0,0 +1,20 @@
+
+
+{{ value() }}%
+
+@if (feedbackText(); as feedback) {
+
+}
diff --git a/community/components/helpers/progress-bar/progress-bar.component.scss b/community/components/helpers/progress-bar/progress-bar.component.scss
new file mode 100644
index 00000000..f625fe7d
--- /dev/null
+++ b/community/components/helpers/progress-bar/progress-bar.component.scss
@@ -0,0 +1,56 @@
+@use "@tedi-design-system/core/bootstrap-utility/breakpoints";
+
+.tedi-progress {
+ --_bar-height: var(--progress-bar-height, 8px);
+ --_bar-radius: var(--progress-bar-radius, 4px);
+ --_bar-background: var(--progress-bar-background-passive, #f9f9f9);
+ --_bar-border: var(--progress-bar-border-default, #838494);
+ --_progress-background: var(--progress-bar-background-active, #005aa3);
+
+ display: grid;
+ grid-template-areas: "bar bar" ". indicator";
+ grid-template-rows: 24px;
+ grid-template-columns: 1fr auto;
+ column-gap: var(--layout-grid-gutters-08, 8px);
+
+ &__bar {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ grid-area: bar;
+ height: var(--_bar-height);
+ border-radius: var(--_bar-radius);
+ border: 1px solid var(--_bar-border);
+ width: 100%;
+ align-self: center;
+
+ &::-webkit-progress-bar {
+ background: var(--_bar-background);
+ border-radius: var(--_bar-radius);
+ }
+
+ &::-webkit-progress-value {
+ background: var(--_progress-background);
+ border-radius: var(--_bar-radius);
+ }
+
+ &::-moz-progress-bar {
+ background: var(--_progress-background);
+ border-radius: var(--_bar-radius);
+ }
+ }
+
+ &__indicator {
+ grid-area: indicator;
+ }
+
+ &--small {
+ --_bar-height: var(--progress-bar-height-sm, 4px);
+ }
+
+ &--horizontal {
+ @include breakpoints.media-breakpoint-up(sm) {
+ grid-template-areas: "bar indicator";
+ }
+ }
+}
diff --git a/community/components/helpers/progress-bar/progress-bar.component.ts b/community/components/helpers/progress-bar/progress-bar.component.ts
new file mode 100644
index 00000000..911581c7
--- /dev/null
+++ b/community/components/helpers/progress-bar/progress-bar.component.ts
@@ -0,0 +1,30 @@
+import { booleanAttribute, ChangeDetectionStrategy, Component, computed, input, ViewEncapsulation } from "@angular/core";
+import { ComponentInputs, FeedbackTextComponent, generateUUID, LabelComponent } from "@tedi-design-system/angular/tedi";
+
+@Component({
+ selector: "tedi-progress-bar",
+ imports: [FeedbackTextComponent, LabelComponent],
+ templateUrl: "./progress-bar.component.html",
+ styleUrl: "./progress-bar.component.scss",
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ encapsulation: ViewEncapsulation.None,
+ host: {
+ "[class.tedi-progress]": "true",
+ "[class.tedi-progress--small]": "small()",
+ "[class.tedi-progress--horizontal]": "direction() === 'horizontal'",
+ },
+})
+export class ProgressBarComponent {
+ progressId = input();
+ value = input(0);
+ direction = input<'horizontal' | 'vertical'>("horizontal");
+ small = input(false, { transform: booleanAttribute });
+ feedbackText = input>();
+
+ feedbackTextId = computed(() => {
+ if (this.feedbackText()) {
+ return generateUUID();
+ }
+ return;
+ });
+}
diff --git a/community/components/helpers/progress-bar/progress-bar.stories.ts b/community/components/helpers/progress-bar/progress-bar.stories.ts
new file mode 100644
index 00000000..e77b6d56
--- /dev/null
+++ b/community/components/helpers/progress-bar/progress-bar.stories.ts
@@ -0,0 +1,86 @@
+import { Meta, moduleMetadata, StoryObj } from "@storybook/angular";
+import { ProgressBarComponent } from "./progress-bar.component";
+
+export default {
+ title: "Community/Helpers/ProgressBar",
+ component: ProgressBarComponent,
+ decorators: [
+ moduleMetadata({
+ imports: [ProgressBarComponent],
+ }),
+ ],
+ argTypes: {
+ progressId: {
+ description:
+ "Optional id for the progress element to bind with label etc.",
+ control: "text",
+ table: {
+ type: { summary: "string" },
+ },
+ },
+ value: {
+ description: "Progress value between 0 and 100",
+ control: { type: "number", min: 0, max: 100, step: 1 },
+ table: {
+ type: { summary: "number" },
+ defaultValue: { summary: "0" },
+ },
+ },
+ direction: {
+ description: "Orientation of the progress bar",
+ control: { type: "radio" },
+ options: ["horizontal", "vertical"],
+ table: {
+ type: { summary: "'horizontal' | 'vertical'" },
+ defaultValue: { summary: "horizontal" },
+ },
+ },
+ small: {
+ description: "Whether it's the small variant",
+ control: "boolean",
+ table: {
+ type: { summary: "boolean" },
+ defaultValue: { summary: "false" },
+ },
+ },
+ feedbackText: {
+ description:
+ "Optional feedback text displayed alongside the progress bar. Accepts `FeedbackTextComponent` inputs.",
+ control: "object",
+ table: {
+ type: { summary: "ComponentInputs" },
+ },
+ },
+ },
+} as Meta;
+
+export const Default: StoryObj = {
+ args: {
+ value: 50,
+ direction: "horizontal",
+ small: false,
+ },
+};
+
+export const Small: StoryObj = {
+ args: {
+ value: 50,
+ direction: "horizontal",
+ small: true,
+ },
+};
+
+export const WithFeedback: StoryObj = {
+ args: {
+ value: 50,
+ feedbackText: { text: "Uploading…", type: "hint", position: "left" },
+ },
+};
+
+export const Vertical: StoryObj = {
+ args: {
+ value: 50,
+ feedbackText: { text: "Uploading…", type: "hint", position: "left" },
+ direction: "vertical",
+ },
+};