AttachmentSquare

Квадратный тайл прикреплённого файла. По умолчанию показывает превью или иконку; при hover (или фокусе на actions) поверх появляется overlay с заголовком/описанием и actions.

Когда использовать

  • В галереях превью и сетках, где у файлов есть визуальный смысл.
  • Когда важна плотность — s (80×80) и m (100×100).

Анатомия

Size (default s)

  • s — 80×80.
  • m — 100×100.

Hover-overlay

При hover и при фокусе на любой action-кнопке (download/delete/retry) над основным контентом появляется overlay с заголовком/описанием и actions. В image-mode overlay плотный (solid neutral/background1Level) и перекрывает превью; в icon-mode — прозрачный, текст MainContent проступает сквозь, а Actions подменяют слот иконки. Состояние «фокус удерживает overlay» реализовано через внутренний контекст AttachmentFocusActionsContext.

State

  • loading — спиннер вместо превью, actions скрыты, hover-overlay отключён.
  • disabled — карточка не реагирует на клик, opacity снижается до effect/opacity/disabled.
  • error — фон тайла переключается на red/background, action retry заменяет download; в error-режиме overlay прозрачный, чтобы красная заливка пропускалась.
  • checked — accent-border + собственный checkedOverlay поверх MainContent с токенами activated/default/filledactivated/hovered/filled (Card-овский state-layer закрыт full-bleed image, поэтому overlay рендерится отдельным слоем). Check-badge в верхнем левом углу.

Установка

pnpm add @cloud-ru/ds-attachment
import { AttachmentSquare } from '@cloud-ru/ds-attachment'

Примеры использования

Базовый

БазовыйФайл с иконкой и кнопками
invoice-2026
PDF
tsx
import { AttachmentSquare } from '@cloud-ru/ds-attachment';

import { PDF_FILE } from './sample';

export function AttachmentSquareBasic() {
  return (
    <AttachmentSquare
      file={PDF_FILE}
      onDownload={file => console.info('download', file?.name)}
      onDelete={file => console.info('delete', file?.name)}
    />
  );
}

С изображением (size m)

С изображением (size m)Превью автоматически из image-файла
tsx
import { AttachmentSquare } from '@cloud-ru/ds-attachment';
import { useEffect, useState } from 'react';

import pictureUrl from './picture.jpg?url';

export function AttachmentSquareImage() {
  const [file, setFile] = useState<File>();

  useEffect(() => {
    fetch(pictureUrl)
      .then(r => r.blob())
      .then(blob => setFile(new File([blob], 'picture.jpg', { type: 'image/jpg' })));
  }, []);

  return (
    <AttachmentSquare
      size='m'
      file={file}
      onDownload={f => console.info('download', f?.name)}
      onDelete={f => console.info('delete', f?.name)}
    />
  );
}

Props

Types

PropsAttachmentSquareProps
PropTypeDefaultRequiredDescription
checkedbooleannoСостояние «выбран» (множественный выбор)
classNamestringnoCSS-класс корня
data-test-idstringno
descriptionstringfileExtensionnoОписание
disabledbooleannoЗаблокировано
errorstringnoСообщение об ошибке
fileFilenoФайл
iconJSXElementConstructor<{ size?: number; className?: string; }> | undefinednoИконка для файла @defaultIcon FileSVG
loadingbooleannoУправление состоянием загрузки
onClick((event: MouseEvent<HTMLDivElement, MouseEvent>) => void)noКлик по карточке
onDelete((file?: File) => void)noКолбек на клик по кнопке удаления
onDownload((file?: File) => void)noКолбек на клик по кнопке скачивания
onRetry(() => void)noКолбек на клик по кнопке повторения
size"m" | "s"snoРазмер
titlestringfileNamenoЗаголовок
truncateVariant"end" | "middle"noВариант обрезания строки: <br> - `end` — с конца; <br> - `middle` — по середине

Unions

Types

AttachmentSquareProps

Unions

Storybook

Figma