diff --git a/src/assets/images/loader.png b/src/assets/images/loader.png new file mode 100644 index 0000000..c897b94 Binary files /dev/null and b/src/assets/images/loader.png differ diff --git a/src/assets/images/loaderGrey.png b/src/assets/images/loaderGrey.png new file mode 100644 index 0000000..9bdbd92 Binary files /dev/null and b/src/assets/images/loaderGrey.png differ diff --git a/src/assets/images/loaderGreySmall.png b/src/assets/images/loaderGreySmall.png new file mode 100644 index 0000000..bed8549 Binary files /dev/null and b/src/assets/images/loaderGreySmall.png differ diff --git a/src/assets/images/loaderSmall.png b/src/assets/images/loaderSmall.png new file mode 100644 index 0000000..7d47b2b Binary files /dev/null and b/src/assets/images/loaderSmall.png differ diff --git a/src/components/loader/__docs__/docs.mdx b/src/components/loader/__docs__/docs.mdx new file mode 100644 index 0000000..074233c --- /dev/null +++ b/src/components/loader/__docs__/docs.mdx @@ -0,0 +1,28 @@ +import {ArgsTable, Canvas, Meta, Story} from '@storybook/addon-docs'; +import {Loader} from '../loader'; + + + +# Loader + + + + + + + + +```typescript +import {Loader} from '@frontapp/ui-kit'; +``` + +Indicates that content is loading or that an action is taking place. + +
+ +## Props + + + +
+
diff --git a/src/components/loader/__docs__/index.stories.tsx b/src/components/loader/__docs__/index.stories.tsx new file mode 100644 index 0000000..7f763dc --- /dev/null +++ b/src/components/loader/__docs__/index.stories.tsx @@ -0,0 +1,28 @@ +/* eslint-disable storybook/story-exports */ +import {ComponentMeta} from '@storybook/react'; + +import {Loader} from '../loader'; +import DocumentationMDX from './docs.mdx'; + +/* + * Storybook. + */ + +export default { + title: 'Components/Loader', + component: Loader, + parameters: { + docs: { + page: DocumentationMDX + }, + previewTabs: { + canvas: { + hidden: true + } + }, + viewMode: 'docs' + }, + id: 'Components/Loader' +} as ComponentMeta; + +export {Basic, Big} from './stories/basic.stories'; diff --git a/src/components/loader/__docs__/stories/basic.stories.tsx b/src/components/loader/__docs__/stories/basic.stories.tsx new file mode 100644 index 0000000..5de2f9f --- /dev/null +++ b/src/components/loader/__docs__/stories/basic.stories.tsx @@ -0,0 +1,20 @@ +import {ComponentStory} from '@storybook/react'; +import React from 'react'; + +import {PaletteColorsEnum} from '../../../../helpers/colorHelpers'; +import {VisualSizesEnum} from '../../../../helpers/fontHelpers'; +import {Loader} from '../../loader'; + +export const Basic: ComponentStory = (args) => ( +
+ + +
+); + +export const Big: ComponentStory = (args) => ( +
+ + +
+); diff --git a/src/components/loader/loader.tsx b/src/components/loader/loader.tsx new file mode 100644 index 0000000..fe74cc6 --- /dev/null +++ b/src/components/loader/loader.tsx @@ -0,0 +1,85 @@ +import React, {FC} from 'react'; +import styled, {css, keyframes} from 'styled-components'; + +import loader from '../../assets/images/loader.png'; +import loaderGrey from '../../assets/images/loaderGrey.png'; +import loaderGreySmall from '../../assets/images/loaderGreySmall.png'; +import loaderSmall from '../../assets/images/loaderSmall.png'; +import {PaletteColorsEnum} from '../../helpers/colorHelpers'; +import {VisualSizesEnum} from '../../helpers/fontHelpers'; +import {makeSizeConstants} from '../../helpers/styleHelpers'; + +/* + * Props. + */ + +interface LoaderProps { + className?: string; + /** Size of the loader. */ + size?: VisualSizesEnum; + /** Color scheme of the loader. */ + color?: PaletteColorsEnum.GREY | PaletteColorsEnum.BLUE; + /** Whether or not the loader rotates. */ + isAnimated?: boolean; +} + +const defaultProps = { + size: VisualSizesEnum.LARGE, + color: PaletteColorsEnum.BLUE, + isAnimated: true +} as const; + +/* + * Style. + */ + +const sizes = makeSizeConstants(16, 20, 40); +const images = { + [PaletteColorsEnum.BLUE]: makeSizeConstants(loaderSmall, loaderSmall, loader), + [PaletteColorsEnum.GREY]: makeSizeConstants(loaderGreySmall, loaderGreySmall, loaderGrey) +}; + +interface LoaderStyleProps { + $size: VisualSizesEnum; + $variant: PaletteColorsEnum.GREY | PaletteColorsEnum.BLUE; + $isEnabled: boolean; +} +const StyledLoaderDiv = styled.div` + width: ${(p) => sizes[p.$size]}px; + height: ${(p) => sizes[p.$size]}px; + background-image: url(${(p) => images[p.$variant][p.$size]}); + background-size: ${(p) => sizes[p.$size]}px; + + ${(p) => maybeAnimate(p.$isEnabled)}; +`; + +const rotate360 = keyframes` + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +`; + +function maybeAnimate(isEnabled: boolean) { + if (!isEnabled) return ''; + + return css` + animation: ${rotate360} 0.6s linear infinite; + `; +} + +/* + * Component. + */ + +export const Loader: FC = (props) => ( + +); diff --git a/src/custom.d.ts b/src/custom.d.ts index 0cda6eb..4445e1b 100644 --- a/src/custom.d.ts +++ b/src/custom.d.ts @@ -7,3 +7,8 @@ declare module '*.svg' { export {ReactComponent}; export default ReactComponent; } + +declare module '*.png' { + const content: string; + export default content; +}