<!-- Protocore Design System — FormatByte -->
# FormatByte

- **Category:** Data Display (`data-display`)
- **Slug:** `data-display/format-byte`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { FormatByte } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/data-display/format-byte

> A deterministic file-size renderer — 1536 becomes 1.5 KB, in mono tabular figures.

## The pure formatter

The math lives in an exported `formatBytes(bytes, options)` function — call it directly when you need the string outside JSX (a table cell value, a tooltip, an aria-label). Both the function and the component take an explicit `locale` (default `"en"`) so a server render and its client hydration produce identical output.

A non-finite input renders the literal value with a `data-invalid` marker rather than fabricating an authoritative-looking size.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `binary` | `boolean` | no | `false` | Use 1024-based (IEC: KiB/MiB) units instead of 1000-based (KB/MB). |
| `className` | `string` | no | — | — |
| `decimals` | `number` | no | `1` | Fractional digits on the scaled value. |
| `locale` | `string` | no | `"en"` | BCP-47 locale for the decimal separator. Fixed so SSR and hydration agree. |
| `style` | `CSSProperties` | no | — | — |
| `value` | `number` | yes | — | The size in bytes to format. |

## Examples

### Basics

Pass a byte count as `value`. It scales to the largest whole unit and renders mono tabular figures, so a column of sizes stays aligned. Sub-kilobyte values stay in whole bytes — you never see a fractional `B`.

```tsx
import { FormatByte } from "@protocore/pds";

export default function FormatByteBasics() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 8, alignItems: "flex-start" }}>
      <FormatByte value={512} />
      <FormatByte value={1536} />
      <FormatByte value={2_400_000} />
      <FormatByte value={5_368_709_120} />
    </div>
  );
}
```

### Binary units and precision

`binary` switches to 1024-based IEC units (`KiB`, `MiB`, `GiB`) for the cases where that distinction matters — disk usage, memory. `decimals` sets the fractional precision on the scaled value.

```tsx
import { FormatByte } from "@protocore/pds";

export default function FormatByteOptions() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 8, alignItems: "flex-start" }}>
      <FormatByte value={1_048_576} />
      <FormatByte value={1_048_576} binary />
      <FormatByte value={1_536_000} decimals={2} />
      <FormatByte value={1_536_000} decimals={0} />
    </div>
  );
}
```

## Usage

**Do**

- Pass a raw byte count and let the component pick the unit.
- Use `binary` for disk, memory, and anything the OS reports in KiB/MiB.
- Call `formatBytes` directly for strings outside JSX.
- Keep a fixed `locale` so SSR and client agree.

**Don't**

- Pre-divide the value; pass whole bytes.
- Mix binary and decimal units in one column; pick one basis.
- Expect fractional bytes; sub-KB values render as whole `B`.

## Accessibility

**Notes**

- Renders a plain `<span>`; the formatted string is the accessible text.
- Mono tabular figures keep a column of sizes vertically aligned.

## Related

`number-formatter`, `money-amount`, `relative-time`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
