Repository: consta-design-system/uikit (ts)

Issue:
User: не работает elepsis
Если текст слишком большой и указан без пробела, то elepsis не работает 

Pull request:
fix(User): fix word wrap
closes #2251


Patch:
diff --git a/src/components/ProgressLine/ProgressLine.css b/src/components/ProgressLine/ProgressLine.css
new file mode 100644
index 00000000..b133f2ee
--- /dev/null
+++ b/src/components/ProgressLine/ProgressLine.css
@@ -0,0 +1,54 @@
+.ProgressLine {
+  position: relative;
+  overflow-x: hidden;
+  width: 100%;
+  height: var(--progress-line-height);
+  background: var(--color-bg-system);
+
+  &::after {
+    content: '';
+    position: absolute;
+    top: 0;
+    height: 100%;
+    background-color: var(--color-bg-brand);
+    transition: transform 0.3s;
+  }
+
+  &_size {
+    &_s {
+      --progress-line-height: var(--space-3xs);
+    }
+
+    &_m {
+      --progress-line-height: var(--space-2xs);
+    }
+  }
+
+  &_mode {
+    &_determinate {
+      &::after {
+        width: 100%;
+        transform: scaleX(var(--progress-line-value));
+        transform-origin: left;
+      }
+    }
+
+    &_indeterminate {
+      &::after {
+        width: 80%;
+        transform-origin: left;
+        animation: ProgressLineAnimation 2s linear infinite;
+      }
+    }
+  }
+}
+
+@keyframes ProgressLineAnimation {
+  0% {
+    transform: translateX(-100%);
+  }
+
+  100% {
+    transform: translateX(130%);
+  }
+}
diff --git a/src/components/ProgressLine/ProgressLine.tsx b/src/components/ProgressLine/ProgressLine.tsx
new file mode 100644
index 00000000..30ec8f27
--- /dev/null
+++ b/src/components/ProgressLine/ProgressLine.tsx
@@ -0,0 +1,43 @@
+import './ProgressLine.css';
+
+import React, { forwardRef } from 'react';
+
+import { cn } from '../../utils/bem';
+import { isNumber } from '../../utils/type-guards';
+
+import { ProgressLineComponent } from './types';
+
+const cnProgressLine = cn('ProgressLine');
+
+const getProgress = (progress: number) => {
+  const progressNormal = Math.ceil(progress);
+
+  if (progressNormal >= 100) {
+    return 1;
+  }
+
+  if (progressNormal <= 0) {
+    return 0;
+  }
+
+  return progressNormal / 100;
+};
+
+export const ProgressLine: ProgressLineComponent = forwardRef((props, ref) => {
+  const { size = 'm', value, style, ...otherProps } = props;
+
+  return (
+    <div
+      {...otherProps}
+      ref={ref}
+      style={{
+        ...style,
+        ['--progress-line-value' as string]: `${getProgress(value ?? 0)}`,
+      }}
+      className={cnProgressLine({
+        size,
+        mode: isNumber(value) ? 'determinate' : 'indeterminate',
+      })}
+    />
+  );
+});
diff --git a/src/components/ProgressLine/__stories__/ProgressLine.docs.mdx b/src/components/ProgressLine/__stories__/ProgressLine.docs.mdx
new file mode 100644
index 00000000..e61348e3
--- /dev/null
+++ b/src/components/ProgressLine/__stories__/ProgressLine.docs.mdx
@@ -0,0 +1,62 @@
+import { ProgressLineExampleMode } from './examples/ProgressLineExampleMode/ProgressLineExampleMode';
+import { ProgressLineExampleSize } from './examples/ProgressLineExampleSize/ProgressLineExampleSize';
+
+# ProgressLine
+
+```tsx
+import { ProgressLine } from '@consta/uikit/ProgressLine';
+```
+
+Индикатор загрузки для ваших проектов
+
+## Тип
+
+Для указания конкретного прогресса нужно указать свойство `value`, иначе будет проигрываться бесконечнная анимация.
+
+<ProgressLineExampleMode />
+
+```tsx
+<ProgressLine />
+<ProgressLine value={30} />
+```
+
+## Размер
+
+Свойство `size` отвечает за размер индикатора. Доступные размеры `s` и `m`.
+
+<ProgressLineExampleSize />
+
+```tsx
+<ProgressLine size="s" />
+<ProgressLine size="m" />
+```
+
+## Импорт
+
+```tsx
+import { ProgressLine } from '@consta/uikit/ProgressLine';
+```
+
+## Свойства
+
+```tsx
+type ProgressLinePropMode = 'determinate' | 'indeterminate';
+```
+
+| Свойство           | Тип                         | По умолчанию | Описание                                  |
+| ------------------ | --------------------------- | ------------ | ----------------------------------------- |
+| [`size?`](#размер) | `'s', 'm'`                  | `'m'`        | Размер индикатора                         |
+| [`value?`](#тип)   | `number`                    | -            | Прогресс выполнения                       |
+| `className?`       | `string`                    | -            | Дополнительный CSS-класс                  |
+| `ref?`             | `React.Ref<HTMLDivElement>` | -            | Ссылка на корневой DOM-элемент компонента |
+
+## Пример
+
+```tsx
+import React, { useState } from 'react';
+import { ProgressLine } from '@consta/uikit/ProgressLine';
+
+const App = () => {
+  return <ProgressLine size="s" value={20} />;
+};
+```
diff --git a/src/components/ProgressLine/__stories__/ProgressLine.stories.tsx b/src/components/ProgressLine/__stories__/ProgressLine.stories.tsx
new file mode 100644
index 00000000..6cbe418c
--- /dev/null
+++ b/src/components/ProgressLine/__stories__/ProgressLine.stories.tsx
@@ -0,0 +1,34 @@
+import React from 'react';
+import { number, select } from '@storybook/addon-knobs';
+
+import { createMetadata } from '../../../utils/storybook';
+import { ProgressLine } from '../ProgressLine';
+import { defaultProgressLinePropSize, progressLinePropSize } from '../types';
+
+import mdx from './ProgressLine.docs.mdx';
+
+const defaultKnobs = () => ({
+  mode: select('mode', ['determinate', 'indeterminate'], 'indeterminate'),
+  size: select('size', progressLinePropSize, defaultProgressLinePropSize),
+  value: number('progresvalues', 50),
+});
+
+export function Playground() {
+  const { mode, size, value } = defaultKnobs();
+
+  return <ProgressLine size={size} value={mode === 'determinate' ? value : undefined} />;
+}
+
+export default createMetadata({
+  title: 'Компоненты|/Обратная связь/ProgressLine',
+  id: 'components/ProgressLine',
+  parameters: {
+    docs: {
+      page: mdx,
+    },
+    design: {
+      type: 'figma',
+      url: 'https://www.figma.com/file/v9Jkm2GrymD277dIGpRBSH/Consta-UI-Kit?node-id=5164%3A84922',
+    },
+  },
+});
diff --git a/src/components/ProgressLine/__stories__/examples/ProgressLineExampleMode/ProgressLineExampleMode.tsx b/src/components/ProgressLine/__stories__/examples/ProgressLineExampleMode/ProgressLineExampleMode.tsx
new file mode 100644
index 00000000..dcf5bd94
--- /dev/null
+++ b/src/components/ProgressLine/__stories__/examples/ProgressLineExampleMode/ProgressLineExampleMode.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+
+import { cnDocsDecorator } from '../../../../../uiKit/components/DocsDecorator/DocsDecorator';
+import { StoryBookExample } from '../../../../../uiKit/components/StoryBookExample/StoryBookExample';
+import { ProgressLine } from '../../../ProgressLine';
+
+export const ProgressLineExampleMode = () => {
+  return (
+    <StoryBookExample className={cnDocsDecorator('Section')}>
+      <div>
+        <ProgressLine />
+      </div>
+      <div>
+        <ProgressLine value={30} />
+      </div>
+    </StoryBookExample>
+  );
+};
diff --git a/src/components/ProgressLine/__stories__/examples/ProgressLineExampleSize/ProgressLineExampleSize.tsx b/src/components/ProgressLine/__stories__/examples/ProgressLineExampleSize/ProgressLineExampleSize.tsx
new file mode 100644
index 00000000..ef714c62
--- /dev/null
+++ b/src/components/ProgressLine/__stories__/examples/ProgressLineExampleSize/ProgressLineExampleSize.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+
+import { cnDocsDecorator } from '../../../../../uiKit/components/DocsDecorator/DocsDecorator';
+import { StoryBookExample } from '../../../../../uiKit/components/StoryBookExample/StoryBookExample';
+import { ProgressLine } from '../../../ProgressLine';
+
+export const ProgressLineExampleSize = () => {
+  return (
+    <StoryBookExample className={cnDocsDecorator('Section')}>
+      <div>
+        <ProgressLine size="s" />
+      </div>
+      <div>
+        <ProgressLine size="m" />
+      </div>
+    </StoryBookExample>
+  );
+};
diff --git a/src/components/ProgressLine/types.ts b/src/components/ProgressLine/types.ts
new file mode 100644
index 00000000..d4e3e60a
--- /dev/null
+++ b/src/components/ProgressLine/types.ts
@@ -0,0 +1,17 @@
+import React from 'react';
+
+import { PropsWithHTMLAttributesAndRef } from '../../utils/types/PropsWithHTMLAttributes';
+
+export const progressLinePropSize = ['m', 's'] as const;
+export type PropgressLinePropSize = typeof progressLinePropSize[number];
+export const defaultProgressLinePropSize = progressLinePropSize[0];
+
+export type ProgressLineProps = PropsWithHTMLAttributesAndRef<
+  {
+    size?: PropgressLinePropSize;
+    value?: number;
+  },
+  HTMLDivElement
+>;
+
+export type ProgressLineComponent = (props: ProgressLineProps) => React.ReactElement | null;
diff --git a/src/components/ProgressSpin/ProgressSpin.tsx b/src/components/ProgressSpin/ProgressSpin.tsx
index c45fa5a4..0b65a87b 100644
--- a/src/components/ProgressSpin/ProgressSpin.tsx
+++ b/src/components/ProgressSpin/ProgressSpin.tsx
@@ -15,6 +15,7 @@ type Props = {
   size?: ProgressSpinPropSize;
   className?: string;
   progress?: number;
+  value?: number;
   animation?: boolean;
   children?: never;
 };
@@ -50,7 +51,8 @@ function getSvgParamsBySize(size: ProgressSpinPropSize): [number, number, number
 export const ProgressSpin = React.forwardRef<SVGSVGElement, ProgressSpinProps>((props, ref) => {
   const {
     size = progressSpinPropSizeDefault,
-    progress,
+    progress: progressProp,
+    value,
     animation,
     className,
     ...otherProps
@@ -60,6 +62,8 @@ export const ProgressSpin = React.forwardRef<SVGSVGElement, ProgressSpinProps>((
     [size],
   );
 
+  const progress = value ?? progressProp;
+
   const animatedProgress = isNumber(progress) ? progress : 50;
   const strokeDashoffset = strokeDasharray - (strokeDasharray * animatedProgress) / 100;
 
diff --git a/src/components/ProgressSpin/__stories__/ProgressSpin.docs.mdx b/src/components/ProgressSpin/__stories__/ProgressSpin.docs.mdx
index a1e5c3d7..cd3f8683 100644
--- a/src/components/ProgressSpin/__stories__/ProgressSpin.docs.mdx
+++ b/src/components/ProgressSpin/__stories__/ProgressSpin.docs.mdx
@@ -23,19 +23,19 @@ import { ProgressSpin } from '@consta/uikit/ProgressSpin';
 ## Процент готовности
 
 Если хотите показать, сколько ещё ждать, укажите в процентах, насколько процесс
-близок к завершению — с помощью свойства `progress`.
+близок к завершению — с помощью свойства `value`.
 
 Чтобы анимировать индикатор, добавьте `animation` (тогда он плавно прокрутится до величины,
-которую вы указали в `progress`).
+которую вы указали в `value`).
 
 Если опустить это свойство, то индикатор будет бесконечно крутиться.
 
 ```ts
 <ProgressSpin size="m" />
-<ProgressSpin progress={20} size="m" />
-<ProgressSpin progress={40} size="m" />
-<ProgressSpin progress={60} size="m" />
-<ProgressSpin animation progress={80} size="m" />
+<ProgressSpin value={20} size="m" />
+<ProgressSpin value={40} size="m" />
+<ProgressSpin value={60} size="m" />
+<ProgressSpin animation value={80} size="m" />
 ```
 
 <ProgressSpinExampleProgress />
@@ -45,11 +45,11 @@ import { ProgressSpin } from '@consta/uikit/ProgressSpin';
 За размер индикатора отвечает свойство `size`.
 
 ```ts
-<ProgressSpin progress={70} size="2xl" />
-<ProgressSpin progress={70} size="xl" />
-<ProgressSpin progress={70} size="l" />
-<ProgressSpin progress={70} size="m" />
-<ProgressSpin progress={70} size="s" />
+<ProgressSpin value={70} size="2xl" />
+<ProgressSpin value={70} size="xl" />
+<ProgressSpin value={70} size="l" />
+<ProgressSpin value={70} size="m" />
+<ProgressSpin value={70} size="s" />
 ```
 
 <ProgressSpinExampleSize />
@@ -64,7 +64,7 @@ import { ProgressSpin } from '@consta/uikit/ProgressSpin';
 
 | Свойство                            | Тип                        | По умолчанию | Описание                                                                           |
 | ----------------------------------- | -------------------------- | ------------ | ---------------------------------------------------------------------------------- |
-| [`progress?`](#процент-готовности)  | `number`                   | -            | Выполненная часть процесса в процентах (определяет заполненную область индикатора) |
+| [`value?`](#процент-готовности)     | `number`                   | -            | Выполненная часть процесса в процентах (определяет заполненную область индикатора) |
 | [`animation?`](#процент-готовности) | `boolean`                  | -            | Включает плавное изменение индикатора до величины, указанной в `progress`          |
 | [`size?`](#размер)                  | `'m','s','l','xl','2xl'`   | `'m'`        | Размер                                                                             |
 | `className?`                        | `string`                   | -            | Дополнительный класс                                                               |
@@ -78,6 +78,6 @@ import React from 'react';
 import { ProgressSpin } from '@consta/uikit/ProgressSpin';
 
 const App = () => {
-  return <ProgressSpin progress={70} />;
+  return <ProgressSpin value={70} />;
 };
 ```
diff --git a/src/components/ProgressSpin/__stories__/ProgressSpin.stories.tsx b/src/components/ProgressSpin/__stories__/ProgressSpin.stories.tsx
index 76367e0f..f847e9b6 100644
--- a/src/components/ProgressSpin/__stories__/ProgressSpin.stories.tsx
+++ b/src/components/ProgressSpin/__stories__/ProgressSpin.stories.tsx
@@ -8,7 +8,7 @@ import { ProgressSpin, progressSpinPropSize, progressSpinPropSizeDefault } from
 import mdx from './ProgressSpin.docs.mdx';
 
 const defaultKnobs = () => ({
-  progress: number('progress', 50),
+  value: number('value', 50),
   size: select('size', progressSpinPropSize, progressSpinPropSizeDefault),
   animation: boolean('animation', false),
 });
@@ -16,11 +16,11 @@ const defaultKnobs = () => ({
 const cnProgressSpinStories = cn('ProgressSpinStories');
 
 export function Playground() {
-  const { progress, size, animation } = defaultKnobs();
+  const { value, size, animation } = defaultKnobs();
 
   return (
     <div className={cnProgressSpinStories()}>
-      <ProgressSpin size={size} progress={progress} animation={animation} />
+      <ProgressSpin size={size} value={value} animation={animation} />
     </div>
   );
 }
diff --git a/src/components/ProgressSpin/__stories__/examples/ProgressSpinExampleProgress/ProgressSpinExampleProgress.tsx b/src/components/ProgressSpin/__stories__/examples/ProgressSpinExampleProgress/ProgressSpinExampleProgress.tsx
index b6ff7c58..05fafd97 100644
--- a/src/components/ProgressSpin/__stories__/examples/ProgressSpinExampleProgress/ProgressSpinExampleProgress.tsx
+++ b/src/components/ProgressSpin/__stories__/examples/ProgressSpinExampleProgress/ProgressSpinExampleProgress.tsx
@@ -7,9 +7,9 @@ import { ProgressSpin } from '../../../ProgressSpin';
 export const ProgressSpinExampleProgress = () => (
   <StoryBookExample className={cnDocsDecorator('Section')}>
     <ProgressSpin size="m" />
-    <ProgressSpin progress={20} size="m" />
-    <ProgressSpin progress={40} size="m" />
-    <ProgressSpin progress={60} size="m" />
-    <ProgressSpin progress={80} size="m" />
+    <ProgressSpin value={20} size="m" />
+    <ProgressSpin value={40} size="m" />
+    <ProgressSpin value={60} size="m" />
+    <ProgressSpin value={80} size="m" />
   </StoryBookExample>
 );
diff --git a/src/components/ProgressSpin/__stories__/examples/ProgressSpinExampleSize/ProgressSpinExampleSize.tsx b/src/components/ProgressSpin/__stories__/examples/ProgressSpinExampleSize/ProgressSpinExampleSize.tsx
index 3f79836b..d0db3289 100644
--- a/src/components/ProgressSpin/__stories__/examples/ProgressSpinExampleSize/ProgressSpinExampleSize.tsx
+++ b/src/components/ProgressSpin/__stories__/examples/ProgressSpinExampleSize/ProgressSpinExampleSize.tsx
@@ -6,10 +6,10 @@ import { ProgressSpin } from '../../../ProgressSpin';
 
 export const ProgressSpinExampleSize = () => (
   <StoryBookExample className={cnDocsDecorator('Section')}>
-    <ProgressSpin progress={70} size="2xl" />
-    <ProgressSpin progress={70} size="xl" />
-    <ProgressSpin progress={70} size="l" />
-    <ProgressSpin progress={70} size="m" />
-    <ProgressSpin progress={70} size="s" />
+    <ProgressSpin value={70} size="2xl" />
+    <ProgressSpin value={70} size="xl" />
+    <ProgressSpin value={70} size="l" />
+    <ProgressSpin value={70} size="m" />
+    <ProgressSpin value={70} size="s" />
   </StoryBookExample>
 );
diff --git a/src/components/User/User.css b/src/components/User/User.css
index b317a62e..a6481aae 100644
--- a/src/components/User/User.css
+++ b/src/components/User/User.css
@@ -68,6 +68,7 @@
   &-Info {
     display: -webkit-box;
     overflow: hidden;
+    word-wrap: break-word;
     -webkit-line-clamp: 1;
     -webkit-box-orient: vertical;
   }


Test patch:
diff --git a/src/components/ProgressSpin/__tests__/ProgressSpin.test.tsx b/src/components/ProgressSpin/__tests__/ProgressSpin.test.tsx
index ad457067..cc2c2c8a 100644
--- a/src/components/ProgressSpin/__tests__/ProgressSpin.test.tsx
+++ b/src/components/ProgressSpin/__tests__/ProgressSpin.test.tsx
@@ -31,7 +31,7 @@ describe('Компонент ProgressSpin', () => {
       expect(getRender()).toHaveClass(cnProgressSpin({ spin: true }));
     });
     it(`при указанном loadingProgress ProgressSpin не должен крутитьтся`, () => {
-      renderComponent({ progress: 1 });
+      renderComponent({ value: 1 });
 
       expect(getRender()).not.toHaveClass(cnProgressSpin({ spin: true }));
     });