Skip to content

Commit

Permalink
feat(sdds-*): add Dropzone component
Browse files Browse the repository at this point in the history
  • Loading branch information
TitanKuzmich committed Nov 26, 2024
1 parent e27bf3e commit 3ed5a8b
Show file tree
Hide file tree
Showing 26 changed files with 593 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,87 +5,13 @@ title: Dropzone

import { PropsTable, Description } from '@site/src/components';

<Description name="Dropzone" />
<PropsTable name="Dropzone" exclude={['css']} />

# Dropzone
Компонент для загрузки файлов, без отображения индикации загрузки.
Компонент не предполагает наличия валиации, так как является частью Upload.
Но валидацию можно задать с помощью callback `validator`.
<PropsTable name="Dropzone" />

# Типизация

```tsx
type DropzoneProps = {
/**
* Массив форматов файлов, которые могут быть прикреплены (см. HTML-атрибут 'accept' для 'input').
*/
acceptedFileFormats?: string[];
/**
* Позовляет выбирать несколько файлов для загрузки
*/
multiple?: boolean;
/**
* Слот для Title
*/
title?: string;
/**
* Слот для описания
*/
description?: ReactNode;
/**
* Слот для иконки
*/
icon?: ReactNode;
/**
* Расположение иконки
* @default 'left'
*/
iconPlacement?: 'top' | 'left';
/**
* Размер компонента
*/
size?: string;
/**
* Вид компонента
*/
view?: string;
/**
* Компонент неактивен
*/
disabled?: boolean;
/**
* Компонент растягивается на всю доступную ширину
*/
stretch?: boolean;
/**
* Функция, вызываемая в момент вхождения курсора внутрь границ Dropzone
*/
onDragEnter?: () => void;
/**
* Функция, вызываемая в момент выхода курсора из Dropzone
*/
onDragLeave?: () => void;
/**
* Функция, вызываемая при нахождении курсора внутри Dropzone
*/
onDragOver?: () => void;
/**
* Функция, вызываемая при drop файлов
*/
onDrop?: () => void;
/**
* Функция, вызываемая для валидации файлов, перед onDropFiles
*/
validator?: (files: File[]) => ValidatorReturnType;
/**
* Функция, вызываемая при наличии файлов, после onDrop
*/
onDropFiles?: FileProcessHandler;
/**
* Функция, вызываемая при выборе файлов
*/
onChoseFiles?: FileProcessHandler;
} & Omit<InputHTMLAttributes<HTMLInputElement>, 'accept'>;
```

# Пример

Expand All @@ -106,10 +32,6 @@ export function App() {
console.log("onDrop")
}

const onDropFiles = () => {
console.log("onDropFiles")
}

const onChange = () => {
console.log("onChange")
}
Expand All @@ -127,7 +49,6 @@ export function App() {
onDragEnter={onDragEnter}
onDragLeave={onDragLeave}
onDrop={onDrop}
onDropFiles={onDropFiles}
onChange={onChange}
onChoseFiles={onChoseFiles}
/>
Expand Down
50 changes: 50 additions & 0 deletions packages/sdds-cs/src/components/Dropzone/Dropzone.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { css, dropzoneTokens } from '@salutejs/plasma-new-hope/styled-components';

export const config = {
defaults: {
view: 'default',
size: 'm',
},
variations: {
view: {
default: css`
${dropzoneTokens.background}: var(--surface-solid-card);
${dropzoneTokens.backgroundHover}: var(--surface-solid-card-hover);
${dropzoneTokens.overlayColorActive}: var(--overlay-soft);
${dropzoneTokens.borderColor}: var(--outline-solid-primary);
${dropzoneTokens.borderColorHover}: var(--outline-solid-primary-hover);
${dropzoneTokens.borderColorActive}: var(--outline-accent);
${dropzoneTokens.titleColor}: var(--text-primary);
${dropzoneTokens.descriptionColor}: var(--text-secondary);
`,
},
size: {
m: css`
${dropzoneTokens.padding}: 1.5rem;
${dropzoneTokens.borderRadius}: 1.25rem;
${dropzoneTokens.contentWrapperGap}: 0.75rem;
${dropzoneTokens.contentGap}: 0.375rem;
${dropzoneTokens.contentColumnGap}: 0.5rem;
${dropzoneTokens.titleFontFamily}: var(--plasma-typo-h4-font-family);
${dropzoneTokens.titleFontSize}: var(--plasma-typo-h4-font-size);
${dropzoneTokens.titleFontStyle}: var(--plasma-typo-h4-font-style);
${dropzoneTokens.titleFontWeight}: var(--plasma-typo-h4-bold-font-weight);
${dropzoneTokens.titleLetterSpacing}: var(--plasma-typo-h4-letter-spacing);
${dropzoneTokens.titleLineHeight}: var(--plasma-typo-h4-line-height);
${dropzoneTokens.descriptionFontFamily}: var(--plasma-typo-body-s-font-family);
${dropzoneTokens.descriptionFontSize}: var(--plasma-typo-body-s-font-size);
${dropzoneTokens.descriptionFontStyle}: var(--plasma-typo-body-s-font-style);
${dropzoneTokens.descriptionFontWeight}: var(--plasma-typo-body-s-font-weight);
${dropzoneTokens.descriptionLetterSpacing}: var(--plasma-typo-body-s-letter-spacing);
${dropzoneTokens.descriptionLineHeight}: var(--plasma-typo-body-s-line-height);
`,
},
disabled: {
true: css`
${dropzoneTokens.disabledOpacity}: 0.4;
`,
},
},
};
58 changes: 58 additions & 0 deletions packages/sdds-cs/src/components/Dropzone/Dropzone.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React, { ComponentProps } from 'react';
import type { StoryObj, Meta } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { InSpacingDecorator, disableProps } from '@salutejs/plasma-sb-utils';

import { Dropzone } from './Dropzone';

const onDragEnter = action('onDragEnter');
const onDragLeave = action('onDragLeave');
const onDrop = action('onDrop');
const onChange = action('onChange');
const onChoseFiles = action('onChoseFiles');

const iconPlacements = ['top', 'left'];

const meta: Meta<typeof Dropzone> = {
title: 'Controls/Dropzone',
component: Dropzone,
decorators: [InSpacingDecorator],
argTypes: {
iconPlacement: {
options: iconPlacements,
control: {
type: 'inline-radio',
},
defaultValue: 'top',
},
...disableProps(['view', 'size']),
},
};

export default meta;

type StoryPropsDefault = ComponentProps<typeof Dropzone>;

export const Default: StoryObj<StoryPropsDefault> = {
args: {
iconPlacement: 'top',
width: 400,
height: 280,
disabled: false,
stretch: false,
title: 'Click to upload',
description: 'or drag and drop files here',
},
render: (args) => (
<div style={{ height: '100vh' }}>
<Dropzone
{...args}
onDragEnter={onDragEnter}
onDragLeave={onDragLeave}
onDrop={onDrop}
onChange={onChange}
onChoseFiles={onChoseFiles}
/>
</div>
),
};
7 changes: 7 additions & 0 deletions packages/sdds-cs/src/components/Dropzone/Dropzone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { dropzoneConfig, component, mergeConfig } from '@salutejs/plasma-new-hope/styled-components';

import { config } from './Dropzone.config';

const mergedConfig = mergeConfig(dropzoneConfig, config);

export const Dropzone = component(mergedConfig);
2 changes: 2 additions & 0 deletions packages/sdds-cs/src/components/Dropzone/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { Dropzone } from './Dropzone';
export { dropzoneTokens, dropzoneClasses } from '@salutejs/plasma-new-hope/styled-components';
1 change: 1 addition & 0 deletions packages/sdds-cs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export * from './components/EmptyState';
export * from './components/Attach';
export * from './components/ViewContainer';
export * from './components/NumberInput';
export * from './components/Dropzone';

export * from './mixins';
export * from './tokens';
50 changes: 50 additions & 0 deletions packages/sdds-dfa/src/components/Dropzone/Dropzone.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { css, dropzoneTokens } from '@salutejs/plasma-new-hope/styled-components';

export const config = {
defaults: {
view: 'default',
size: 'm',
},
variations: {
view: {
default: css`
${dropzoneTokens.background}: var(--surface-solid-card);
${dropzoneTokens.backgroundHover}: var(--surface-solid-card-hover);
${dropzoneTokens.overlayColorActive}: var(--overlay-soft);
${dropzoneTokens.borderColor}: var(--outline-solid-secondary);
${dropzoneTokens.borderColorHover}: var(--outline-solid-secondary-hover);
${dropzoneTokens.borderColorActive}: var(--outline-accent);
${dropzoneTokens.titleColor}: var(--text-primary);
${dropzoneTokens.descriptionColor}: var(--text-secondary);
`,
},
size: {
m: css`
${dropzoneTokens.padding}: 1.5rem;
${dropzoneTokens.borderRadius}: 1.25rem;
${dropzoneTokens.contentWrapperGap}: 0.75rem;
${dropzoneTokens.contentGap}: 0.375rem;
${dropzoneTokens.contentColumnGap}: 0.5rem;
${dropzoneTokens.titleFontFamily}: var(--plasma-typo-h4-font-family);
${dropzoneTokens.titleFontSize}: var(--plasma-typo-h4-font-size);
${dropzoneTokens.titleFontStyle}: var(--plasma-typo-h4-font-style);
${dropzoneTokens.titleFontWeight}: var(--plasma-typo-h4-bold-font-weight);
${dropzoneTokens.titleLetterSpacing}: var(--plasma-typo-h4-letter-spacing);
${dropzoneTokens.titleLineHeight}: var(--plasma-typo-h4-line-height);
${dropzoneTokens.descriptionFontFamily}: var(--plasma-typo-body-s-font-family);
${dropzoneTokens.descriptionFontSize}: var(--plasma-typo-body-s-font-size);
${dropzoneTokens.descriptionFontStyle}: var(--plasma-typo-body-s-font-style);
${dropzoneTokens.descriptionFontWeight}: var(--plasma-typo-body-s-font-weight);
${dropzoneTokens.descriptionLetterSpacing}: var(--plasma-typo-body-s-letter-spacing);
${dropzoneTokens.descriptionLineHeight}: var(--plasma-typo-body-s-line-height);
`,
},
disabled: {
true: css`
${dropzoneTokens.disabledOpacity}: 0.4;
`,
},
},
};
58 changes: 58 additions & 0 deletions packages/sdds-dfa/src/components/Dropzone/Dropzone.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React, { ComponentProps } from 'react';
import type { StoryObj, Meta } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { InSpacingDecorator, disableProps } from '@salutejs/plasma-sb-utils';

import { Dropzone } from './Dropzone';

const onDragEnter = action('onDragEnter');
const onDragLeave = action('onDragLeave');
const onDrop = action('onDrop');
const onChange = action('onChange');
const onChoseFiles = action('onChoseFiles');

const iconPlacements = ['top', 'left'];

const meta: Meta<typeof Dropzone> = {
title: 'Controls/Dropzone',
component: Dropzone,
decorators: [InSpacingDecorator],
argTypes: {
iconPlacement: {
options: iconPlacements,
control: {
type: 'inline-radio',
},
defaultValue: 'top',
},
...disableProps(['view', 'size']),
},
};

export default meta;

type StoryPropsDefault = ComponentProps<typeof Dropzone>;

export const Default: StoryObj<StoryPropsDefault> = {
args: {
iconPlacement: 'top',
width: 400,
height: 280,
disabled: false,
stretch: false,
title: 'Click to upload',
description: 'or drag and drop files here',
},
render: (args) => (
<div style={{ height: '100vh' }}>
<Dropzone
{...args}
onDragEnter={onDragEnter}
onDragLeave={onDragLeave}
onDrop={onDrop}
onChange={onChange}
onChoseFiles={onChoseFiles}
/>
</div>
),
};
7 changes: 7 additions & 0 deletions packages/sdds-dfa/src/components/Dropzone/Dropzone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { dropzoneConfig, component, mergeConfig } from '@salutejs/plasma-new-hope/styled-components';

import { config } from './Dropzone.config';

const mergedConfig = mergeConfig(dropzoneConfig, config);

export const Dropzone = component(mergedConfig);
2 changes: 2 additions & 0 deletions packages/sdds-dfa/src/components/Dropzone/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { Dropzone } from './Dropzone';
export { dropzoneTokens, dropzoneClasses } from '@salutejs/plasma-new-hope/styled-components';
1 change: 1 addition & 0 deletions packages/sdds-dfa/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export * from './components/EmptyState';
export * from './components/Attach';
export * from './components/ViewContainer';
export * from './components/NumberInput';
export * from './components/Dropzone';

export * from './mixins';
export * from './tokens';
Loading

0 comments on commit 3ed5a8b

Please sign in to comment.