# File Type Icon

Show a file’s type as a document icon with its extension.

File type icons for common files

[Complete TSX file](/examples/file-type-icon/default.tsx)

```tsx
"use client";

import { FileTypeIcon } from "@/siteplane/components/file-type-icon";

const files = [
  "file.pdf",
  "file.jpg",
  "file.mp4",
  "file.docx",
  "file.xlsx",
  "file.zip",
  "file.tsx",
  "file",
];

export default function Example() {
  return (
    <ul className="grid w-full max-w-md grid-cols-4 gap-y-5">
      {files.map((name) => (
        <li className="flex flex-col items-center gap-2" key={name}>
          <FileTypeIcon name={name} />
          <span className="text-muted-foreground text-xs">{name}</span>
        </li>
      ))}
    </ul>
  );
}
```

## Installation

Complete [one-time setup](/docs/installation/) first.

```bash
pnpm dlx shadcn@4.18.0 add @siteplane/file-type-icon
```

With npm: `npx shadcn@4.18.0 add @siteplane/file-type-icon`. [Registry JSON](/registry/file-type-icon.json) lists source files and dependencies.

## Usage

```tsx
import { FileTypeIcon } from "@/siteplane/components/file-type-icon";

<FileTypeIcon name="file.pdf" />;
```

## Supported types

The icon is chosen from the file’s extension. Each type has its own glyph on a document sheet that follows the theme, and a label that shows the extension in capitals. The label color comes from the kit and depends on the type. PDFs are red, spreadsheets green, and slides and archives orange. Documents, images, vector files, video and audio take the accent. Code and files of an unknown type are gray. The colors follow the theme, and a brand override of the accent reaches the label.

Icons by file type

[Complete TSX file](/examples/file-type-icon/types.tsx)

```tsx
"use client";

import { FileTypeIcon } from "@/siteplane/components/file-type-icon";

const types = [
  { label: "PDF", sample: "Report.pdf", extensions: "pdf" },
  {
    label: "Documents",
    sample: "Notes.docx",
    extensions: "doc, docx, txt, md",
  },
  {
    label: "Spreadsheets",
    sample: "Budget.xlsx",
    extensions: "xls, xlsx, csv, ods",
  },
  {
    label: "Presentations",
    sample: "Pitch.pptx",
    extensions: "ppt, pptx, odp",
  },
  { label: "Images", sample: "Photo.jpg", extensions: "jpg, png, gif, heic" },
  { label: "Vector", sample: "Logo.svg", extensions: "svg, eps, dwg" },
  { label: "Video", sample: "Demo.mp4", extensions: "mp4, mov, avi, webm" },
  { label: "Audio", sample: "Podcast.mp3", extensions: "mp3, wav, flac, m4a" },
  { label: "Archives", sample: "Backup.zip", extensions: "zip, gz, rar, 7z" },
  { label: "Code", sample: "App.tsx", extensions: "js, ts, tsx, json" },
  { label: "Fonts", sample: "Inter.ttf", extensions: "ttf, otf, woff" },
  { label: "3D models", sample: "Chair.obj", extensions: "obj, 3ds, skp" },
];

export default function Example() {
  return (
    <ul className="grid w-full grid-cols-[repeat(auto-fill,minmax(11rem,1fr))] gap-x-6 gap-y-5">
      {types.map((type) => (
        <li className="flex items-center gap-3" key={type.label}>
          <FileTypeIcon name={type.sample} />
          <div className="grid gap-0.5 text-sm">
            <span className="font-medium">{type.label}</span>
            <span className="text-muted-foreground text-xs">
              {type.extensions}
            </span>
          </div>
        </li>
      ))}
    </ul>
  );
}
```

The glyphs come from [react-file-icon](https://github.com/corygibbons/react-file-icon), which the registry installs with the component. Fonts and 3D models show their own glyph on a gray label, and so do other types such as executables and disk images. An extension it does not know shows a plain document with a gray label.

The label shows up to five letters or digits. A name without a suffix, such as `README`, a dotfile such as `.gitignore`, and an extension that is longer or contains other characters show `FILE`. Only the last suffix counts, so `archive.tar.gz` is labeled `GZ`.

## Sizes

There is no size prop. By default the icon fills a box 40 px high and 34 px wide, which matches the 5:6 proportion of the sheet. Resize the box with `className`, keeping that proportion, and the sheet, glyph and label scale with it. Below about 32 px the label becomes too small to read, so rely on the file name beside the icon.

Icon sizes

[Complete TSX file](/examples/file-type-icon/sizes.tsx)

```tsx
"use client";

import { FileTypeIcon } from "@/siteplane/components/file-type-icon";

const sizes = [
  { className: "h-6 w-5", label: "24 px" },
  { className: "h-8 w-[27px]", label: "32 px" },
  // The default box: no className needed.
  { className: undefined, label: "40 px" },
  { className: "h-12 w-10", label: "48 px" },
  { className: "h-16 w-[53px]", label: "64 px" },
];

export default function Example() {
  return (
    <ul className="flex flex-wrap items-end justify-center gap-x-6 gap-y-5">
      {sizes.map((size) => (
        <li className="flex flex-col items-center gap-2" key={size.label}>
          <FileTypeIcon className={size.className} name="Report.pdf" />
          <span className="text-muted-foreground text-xs">{size.label}</span>
        </li>
      ))}
    </ul>
  );
}
```

## In a file list

The icon is decorative and hidden from assistive technology. Always show the file name next to it.

Icons beside file names

[Complete TSX file](/examples/file-type-icon/list.tsx)

```tsx
"use client";

import { FileTypeIcon } from "@/siteplane/components/file-type-icon";

const files = [
  { name: "Quarterly-report.pdf", size: "2.4 MB" },
  { name: "Budget-2026.xlsx", size: "180 KB" },
  { name: "Brand-assets.zip", size: "48 MB" },
  { name: "Team-photo.jpg", size: "1.1 MB" },
];

export default function Example() {
  return (
    <ul className="grid w-full max-w-sm gap-4">
      {files.map((file) => (
        <li className="flex items-center gap-3" key={file.name}>
          <FileTypeIcon name={file.name} />
          <div className="grid text-sm">
            <span className="font-medium">{file.name}</span>
            <span className="text-muted-foreground">{file.size}</span>
          </div>
        </li>
      ))}
    </ul>
  );
}
```

## Files without a suffix

Pass `extension` when the name does not carry the file type, such as a document title or a download name without its suffix. It replaces the extension in `name`; a leading dot and capital letters are ignored.

Icons chosen by extension

[Complete TSX file](/examples/file-type-icon/extension.tsx)

```tsx
"use client";

import { FileTypeIcon } from "@/siteplane/components/file-type-icon";

const files = [
  { name: "Meeting notes", extension: "docx" },
  { name: "Quarterly report", extension: "pdf" },
  { name: "Makefile", extension: undefined },
];

export default function Example() {
  return (
    <ul className="flex flex-wrap justify-center gap-x-8 gap-y-5">
      {files.map((file) => (
        <li className="flex flex-col items-center gap-2" key={file.name}>
          <FileTypeIcon extension={file.extension} name={file.name} />
          <span className="text-muted-foreground text-xs">{file.name}</span>
        </li>
      ))}
    </ul>
  );
}
```

## API reference

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| FileTypeIcon.name | string | required | File name, with or without folders. The text after its last dot chooses the icon. |
| FileTypeIcon.extension | string | unset | Extension that replaces the one in name, with or without the leading dot. |
| FileTypeIcon.className | string | unset | Classes for the icon box. Set its height and width to resize the icon. |

FileTypeIconProps has only these three props: the icon renders an `aria-hidden` span with a `data-extension` attribute around the SVG, and accepts no other native props or refs.

[Read the installed source](/source/file-type-icon).

## Usage notes

The icon takes its type from the name only; it does not read the file or its MIME type. For images and videos a thumbnail often identifies a file better, so keep the icon for lists and upload rows without a preview.

[File Upload](/docs/patterns/file-upload/) uses this icon for its rows, and the invoice in [Inline CTA](/docs/patterns/inline-cta/#invoice) uses it as a detail icon.
