diff --git a/src/components/Button/Button.css b/src/components/Button/Button.css index 2d8231547..44916402c 100755 --- a/src/components/Button/Button.css +++ b/src/components/Button/Button.css @@ -213,8 +213,15 @@ } & .Button-Loader { - --loaderBackgroundColor: var(--button-loader-color); + --loader-color-prop: var(--button-loader-color); position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; + display: flex; + justify-content: center; + align-items: center; } } } diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index cbd939be3..692837688 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -3,13 +3,14 @@ import './Button.css'; import { IconComponent, IconPropSize } from '@consta/icons/Icon'; import React, { HTMLProps, useRef } from 'react'; +import { Loader } from '##/components/Loader'; + import { useForkRef } from '../../hooks/useForkRef/useForkRef'; import { cnMixFocus } from '../../mixs/MixFocus/MixFocus'; import { cn } from '../../utils/bem'; import { getByMap } from '../../utils/getByMap'; import { forwardRefWithAs } from '../../utils/types/PropsWithAsAttributes'; import { usePropsHandler } from '../EventInterceptor/usePropsHandler'; -import { Loader } from '../LoaderDeprecated/LoaderDeprecated'; export const buttonPropSize = ['m', 'xs', 's', 'l'] as const; export type ButtonPropSize = typeof buttonPropSize[number]; @@ -197,7 +198,11 @@ export const Button = forwardRefWithAs((props, ref) => { ) : ( label ))} - {loading && } + {loading && ( +
+ +
+ )} ); }); diff --git a/src/components/Loader/Loader.css b/src/components/Loader/Loader.css index 1b3a00291..7d7f54fbf 100644 --- a/src/components/Loader/Loader.css +++ b/src/components/Loader/Loader.css @@ -1,55 +1,89 @@ .Loader { - --backgroundColor: - var( - --loaderBackgroundColor, - var(--color-control-bg-primary) - ); - display: inline-flex; - padding: calc(var(--loader-size) * 0.25); - gap: var(--loader-gap); - - &-Dot { - width: var(--loader-size); - height: var(--loader-size); - background: var(--backgroundColor); - border-radius: 50%; - animation: var(--loader-dot-animation); - - &_side { - &_left { - --loader-dot-animation: loader 1s ease infinite; - } - - &_center { - --loader-dot-animation: loader 1s -0.18s ease infinite; - } + --loader-color: var(--loaderBackgroundColor, var(--color-control-bg-primary)); - &_right { - --loader-dot-animation: loader 1s -0.36s ease infinite; - } - } - } + /* major: убрать --loader-color-finally, оставить --loader-color-prop для определения своего цвета */ + --loader-color-finally: var(--loader-color-prop, var(--loader-color)); + display: inline-flex; &_size { &_xs { - --loader-size: var(--space-2xs); - --loader-gap: var(--space-3xs); + --loader-circle-size: var(--space-s); + --loader-dot-size: var(--space-2xs); + --loader-dot-gap: var(--space-3xs); } &_s { - --loader-size: var(--space-2xs); - --loader-gap: var(--space-2xs); + --loader-circle-size: var(--space-m); + --loader-dot-size: var(--space-2xs); + --loader-dot-gap: var(--space-2xs); } &_m { - --loader-size: var(--space-xs); - --loader-gap: calc(var(--space-xs) - var(--space-3xs)); + --loader-circle-size: var(--space-xl); + --loader-dot-size: var(--space-xs); + --loader-dot-gap: calc(var(--space-xs) - var(--space-3xs)); + } + } + + &_type { + &_dots { + padding: calc(var(--loader-dot-size) * 0.25); + gap: var(--loader-dot-gap); + + &::before, + &::after, + .Loader-Dot { + width: var(--loader-dot-size); + height: var(--loader-dot-size); + background: var(--loader-color-finally); + border-radius: 50%; + animation: + Loader_Animate_type_dots 1s var(--loader-dot-animation-delay) + ease infinite; + } + + &::before, + &::after { + content: ''; + } + + &::before { + --loader-dot-animation-delay: 0s; + } + + &::after { + --loader-dot-animation-delay: 0.36s; + } + + .Loader-Dot { + --loader-dot-animation-delay: 0.18s; + } + } + + &_circle { + --loader-circle-mask: + conic-gradient(#0000 2%, #000), + linear-gradient(#000 0 0) content-box; + width: var(--loader-circle-size); + height: var(--loader-circle-size); + padding: 2px; + background: var(--loader-color-finally); + border-radius: 50%; + animation: Loader_Animate_type_circle 1.2s infinite linear; + mask: var(--loader-circle-mask); + mask-composite: subtract; } } } -@keyframes loader { +@keyframes Loader_Animate_type_dots { 50% { transform: scale(1.5); } } + +@keyframes Loader_Animate_type_circle { + to { + transform: rotate(1turn); + } +} diff --git a/src/components/Loader/Loader.tsx b/src/components/Loader/Loader.tsx index 20974f41d..d31bb4332 100644 --- a/src/components/Loader/Loader.tsx +++ b/src/components/Loader/Loader.tsx @@ -3,27 +3,26 @@ import './Loader.css'; import React from 'react'; import { cn } from '../../utils/bem'; -import { LoaderProps, loaderPropSizeDefault } from './types'; +import { LoaderProps } from './types'; export const cnLoader = cn('Loader'); -const sides = ['left', 'center', 'right']; - export const Loader = React.forwardRef( (props, ref) => { - const { className, size = loaderPropSizeDefault, ...otherProps } = props; + const { + className, + size = 'm', + type = 'circle', + view = 'primary', + ...otherProps + } = props; return (
- {sides.map((side, index) => ( -
- ))} + {type === 'dots' &&
}
); }, diff --git a/src/components/Loader/types.ts b/src/components/Loader/types.ts index dd72dab03..12dea7507 100644 --- a/src/components/Loader/types.ts +++ b/src/components/Loader/types.ts @@ -1,12 +1,14 @@ import { PropsWithHTMLAttributes } from '../../utils/types/PropsWithHTMLAttributes'; -export const loaderPropSize = ['m', 's', 'xs'] as const; +export const loaderPropSize = ['xs', 's', 'm'] as const; export type LoaderPropSize = typeof loaderPropSize[number]; export const loaderPropSizeDefault: LoaderPropSize = loaderPropSize[0]; type Props = { size?: LoaderPropSize; children?: never; + type?: 'dots' | 'circle'; + view?: 'primary' | 'clear'; }; export type LoaderProps = PropsWithHTMLAttributes;