= (args) => (
+
+);
+
+export const Primary = Template.bind({});
+Primary.args = {currentStep: 0, steps: 10};
diff --git a/libs/react/ui-core/src/lib/progress/progress.tsx b/libs/react/ui-core/src/lib/progress/progress.tsx
new file mode 100644
index 0000000..b282785
--- /dev/null
+++ b/libs/react/ui-core/src/lib/progress/progress.tsx
@@ -0,0 +1,127 @@
+import styles from './progress.module.scss';
+import { forwardRef, memo, useMemo } from 'react';
+import { ProgressProps } from './ProgressProps';
+import { useProgress } from './useProgress';
+import Icon from '../icon/icon';
+
+const LinearBar = memo(({ fillPercentage }: { fillPercentage: string }) => {
+ return (
+
+ );
+});
+
+const RadialBar = memo(
+ ({ dashArray, dashOffset }: { dashArray: number; dashOffset: number }) => {
+ return (
+
+ );
+ }
+);
+
+const Label = memo(
+ ({
+ labelText,
+ state,
+ type,
+ minWidth,
+ }: {
+ labelText?: string;
+ state?: 'progress' | 'error' | 'success';
+ type?: 'linear' | 'radial';
+ minWidth?: string;
+ }) => {
+ const content = useMemo(() => {
+ switch (state) {
+ case 'progress':
+ return (
+
+ {labelText}
+
+ );
+ break;
+ case 'error':
+ return (
+
+ );
+ break;
+ case 'success':
+ return (
+
+ );
+ break;
+ default:
+ return {labelText}
;
+ break;
+ }
+ }, [labelText, state, type]);
+ return content;
+ }
+);
+
+export const Progress = forwardRef((props: ProgressProps, ref: any) => {
+ const { classes, fillPercentage, labelText, dashArray, dashOffset } =
+ useProgress(props);
+ return (
+
+ {props.type === 'linear' ? (
+
+ ) : (
+
+ )}
+
+
+ );
+});
+
+Progress.defaultProps = {
+ size: 'standart',
+ type: 'linear',
+ state: 'progress',
+ minLabelWidth: '40px',
+ format: (currentStep: number, steps: number) => `${currentStep}/${steps}`,
+};
diff --git a/libs/react/ui-core/src/lib/progress/useProgress.ts b/libs/react/ui-core/src/lib/progress/useProgress.ts
new file mode 100644
index 0000000..8d7e065
--- /dev/null
+++ b/libs/react/ui-core/src/lib/progress/useProgress.ts
@@ -0,0 +1,52 @@
+import styles from './progress.module.scss';
+import { useMemo } from 'react';
+import { getClasses } from '../../utils/getClasses';
+import { ProgressProps } from './ProgressProps';
+
+export function useProgress(props: ProgressProps) {
+ const classes = useMemo(() => {
+ const conditions = {
+ 'progress': true,
+ 'progress-success': props.state === 'success',
+ 'progress-error': props.state === 'error',
+ 'progress-regular': props.state === 'progress',
+ 'progress-radial': props.type === 'radial',
+ 'progress-linear': props.type === 'linear',
+ 'progress-small': props.size === 'small',
+ 'progress-standart': props.size === 'standart',
+ };
+ return getClasses(conditions, styles, props.className);
+ }, [props.state, props.size, props.className, props.type]);
+
+ const fillPortion = useMemo(() => {
+ // Rounds to 2 digits.
+ const portion = Math.round((props.currentStep / props.steps) * 100) / 100;
+ return portion <= 1 ? (portion >= 0 ? portion : 0) : 1;
+ }, [props.currentStep, props.steps]);
+
+ const dashArray = useMemo(() => {
+ const radius = 72;
+ return 2 * Math.PI * radius;
+ }, [props.size]);
+
+ const dashOffset = useMemo(() => {
+ return dashArray * (1 - fillPortion);
+ }, [dashArray, fillPortion]);
+
+ const fillPercentage = useMemo(() => {
+ return `${fillPortion * 100}%`;
+ }, [fillPortion]);
+
+ const labelText = useMemo(() => {
+ return props.format?.(props.currentStep, props.steps);
+ }, [props.currentStep, props.steps, props.format]);
+
+ return {
+ classes,
+ fillPortion,
+ fillPercentage,
+ labelText,
+ dashArray,
+ dashOffset,
+ };
+}
diff --git a/styles/components/progress/index.scss b/styles/components/progress/index.scss
new file mode 100644
index 0000000..ffaaed6
--- /dev/null
+++ b/styles/components/progress/index.scss
@@ -0,0 +1,174 @@
+@use '../../../styles/design-tokens' as dt;
+
+.progress {
+ position: relative;
+ box-sizing: border-box;
+
+ .label {
+ font-family: dt.$typo-font-p-regular-family;
+ font-style: dt.$typo-font-p-regular-style;
+ color: dt.$general-100;
+ }
+
+ .indicator {
+ transition: width 250ms, stroke-dashoffset 250ms;
+ }
+
+ &-linear {
+ display: flex;
+ align-items: center;
+ gap: 15px;
+ width: 100%;
+
+ .figure {
+ position: relative;
+ width: 100%;
+ }
+
+ .track {
+ background-color: dt.$general-40;
+ border-radius: 10px;
+ }
+
+ .indicator {
+ top: 0;
+ position: absolute;
+ background-color: dt.$general-100;
+ border-radius: 10px;
+ }
+
+ .track,
+ .indicator {
+ height: 100%;
+ }
+
+ .label {
+ font-weight: dt.$typo-font-p-regular-weight;
+ line-height: 24px;
+ text-align: end;
+ }
+ }
+
+ &-radial {
+ display: inline-block;
+ .label,
+ .label-icon {
+ position: absolute;
+ transform: translate(-50%, -50%);
+ top: 50%;
+ left: 50%;
+ }
+
+ .label {
+ font-weight: dt.$typo-font-p-medium-weight;
+ }
+
+ .figure {
+ transform: rotate(-90deg);
+ }
+
+ .track {
+ stroke: dt.$general-40;
+ }
+ }
+
+ // Colors
+ &-success {
+ .label-icon {
+ color: dt.$green-80;
+ }
+ }
+
+ &-error {
+ .label-icon {
+ color: dt.$red-100;
+ }
+ }
+
+ &-linear.progress-success {
+ .indicator {
+ background-color: dt.$green-80;
+ }
+ }
+ &-linear.progress-error {
+ .indicator {
+ background-color: dt.$red-100;
+ }
+ }
+ &-linear.progress-regular {
+ .indicator {
+ background-color: dt.$primary-100;
+ }
+ }
+
+ &-radial.progress-success {
+ .indicator {
+ stroke: dt.$green-80;
+ }
+ }
+ &-radial.progress-error {
+ .indicator {
+ stroke: dt.$red-100;
+ }
+ }
+ &-radial.progress-regular {
+ .indicator {
+ stroke: dt.$primary-100;
+ }
+ }
+
+ // Sizes
+ &-linear.progress-standart {
+ height: 20px;
+ .figure {
+ height: 11px;
+ }
+ .label {
+ font-size: dt.$typo-font-p-regular-size;
+ }
+ .label-icon {
+ font-size: 20px;
+ }
+ }
+
+ &-linear.progress-small {
+ height: 15px;
+ .figure {
+ height: 7px;
+ }
+ .label {
+ font-size: 12px;
+ }
+ .label-icon {
+ font-size: 15px;
+ }
+ }
+
+ &-radial.progress-standart {
+ height: 164px;
+ .figure {
+ height: 164px;
+ }
+ .label {
+ font-size: 36px;
+ line-height: 44px;
+ }
+ .label-icon {
+ font-size: 55px;
+ }
+ }
+
+ &-radial.progress-small {
+ height: 82px;
+ .figure {
+ height: 82px;
+ }
+ .label {
+ font-size: 18px;
+ line-height: 22px;
+ }
+ .label-icon {
+ font-size: 20px;
+ }
+ }
+}