Skip to content

Commit

Permalink
feat(Loader): add _view_circle
Browse files Browse the repository at this point in the history
closes #3589
closes #3545
closes #3543
closes #3519
closes #3847
  • Loading branch information
gizeasy committed Dec 4, 2024
1 parent a78ec16 commit 7cd604b
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 51 deletions.
9 changes: 8 additions & 1 deletion src/components/Button/Button.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
9 changes: 7 additions & 2 deletions src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -197,7 +198,11 @@ export const Button = forwardRefWithAs<Props, 'button'>((props, ref) => {
) : (
label
))}
{loading && <Loader className={cnButton('Loader')} size="s" />}
{loading && (
<div className={cnButton('Loader')}>
<Loader size="s" />
</div>
)}
</Tag>
);
});
106 changes: 70 additions & 36 deletions src/components/Loader/Loader.css
Original file line number Diff line number Diff line change
@@ -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);
}
}
21 changes: 10 additions & 11 deletions src/components/Loader/Loader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<HTMLDivElement, LoaderProps>(
(props, ref) => {
const { className, size = loaderPropSizeDefault, ...otherProps } = props;
const {
className,
size = 'm',
type = 'circle',
view = 'primary',
...otherProps
} = props;
return (
<div
{...otherProps}
ref={ref}
className={cnLoader({ size }, [className])}
className={cnLoader({ size, view, type }, [className])}
>
{sides.map((side, index) => (
<div
key={cnLoader('Dot', { index })}
className={cnLoader('Dot', { side })}
/>
))}
{type === 'dots' && <div className={cnLoader('Dot')} />}
</div>
);
},
Expand Down
4 changes: 3 additions & 1 deletion src/components/Loader/types.ts
Original file line number Diff line number Diff line change
@@ -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<Props, HTMLDivElement>;

0 comments on commit 7cd604b

Please sign in to comment.