# Barcode

> One-dimensional barcodes drawn as SVG with jsbarcode (Code 128, EAN-13, EAN-8, UPC-A, Code 39, ITF, Codabar, Pharmacode), with input validation that explains the problem, SVG and PNG download and a generator card.

Source: https://docs.nasaqui.com/components/barcode

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/barcode.json
```

A barcode as inline SVG. jsbarcode draws the bars; Nasaq checks the value first, so a bad EAN shows why
("needs 13 digits", "check digit should be 1") instead of a blank or broken image.

## When to use

- Product, asset and order labels.
- A generator for staff who print their own codes.

## When not to use

- Links or free text for phones: use [`QrCode`](https://docs.nasaqui.com/components/qr-code).
- Anything secret: a barcode is plain data.

## Import

```tsx
import { Barcode, BarcodeGenerator } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"
```

## Quick start

```tsx
import { Barcode } from "@fadymondy/nasaq/web";

export function Label({ sku }: { sku: string }) {
  return <Barcode value={sku} format="CODE128" downloadable downloadName={sku} />;
}
```

## Anatomy

```
Barcode                         data-slot="barcode"
├─ error message                role="alert" (when the value is invalid)
├─ svg                          data-slot="barcode-svg" (role="img")
└─ actions (downloadable)       data-slot="barcode-actions": Download SVG, Download PNG
BarcodeGenerator                data-slot="barcode-generator" (Card): value, format, preview
```

## API

**Barcode**: every `div` prop except `children`, plus:

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `string` | required | What the bars encode. |
| `format` | `BarcodeFormat` | `"CODE128"` | `CODE128`, `EAN13`, `EAN8`, `UPC`, `CODE39`, `ITF14`, `ITF`, `codabar`, `pharmacode`. |
| `showValue` | `boolean` | `true` | Print the value under the bars. |
| `height`, `barWidth`, `margin` | `number` | `80`, `2`, `10` | Geometry in px. |
| `fg`, `bg` | `string` | black, white | Any CSS colour or token. |
| `downloadable` | `boolean` | `false` | Show Download SVG and PNG. |
| `downloadName`, `pngSize` | `string`, `number` | `"barcode"`, `1200` | File name and PNG width. |
| `onValidate` | `(problem \| null) => void` | | Called after each draw. |
| `labels` | `Partial<BarcodeLabels>` | | Override any string. |

**BarcodeGenerator**: `defaultValue`, `defaultFormat`, `formats`, `downloadName`, `labels`.

**Helpers** (pure, tested): `validateBarcode(format, value)` returns `{ kind, ... }` or `null`; `gtinCheckDigit(digitsWithoutCheck)`.

## Examples

**Validate before saving**

```tsx
import { validateBarcode } from "@fadymondy/nasaq/web";

export const ok = validateBarcode("EAN13", "4006381333931") === null;
```

**Only retail formats in the generator**

```tsx
import { BarcodeGenerator } from "@fadymondy/nasaq/web";

export const Retail = () => <BarcodeGenerator formats={["EAN13", "EAN8", "UPC"]} defaultFormat="EAN13" defaultValue="4006381333931" />;
```

## Accessibility

- The SVG is `role="img"` with a name that includes the format and value. Errors are `role="alert"`.
- Bars need contrast and a quiet zone: keep the default margin.

## RTL & i18n

- Bars and digits are always left-to-right (`dir="ltr"`), also in Arabic. The generator UI mirrors and has Arabic strings.

## Styling & tokens

- Black on white by default so scanners read it. Tokens resolve to concrete colours at download time.
- Target `[data-slot="barcode"]`, `[data-slot="barcode-svg"]`.

## Do / Don't

- Do let the check digit be computed for you with `gtinCheckDigit` when you generate EANs.
- Do print at least the size the format standard asks for.
- Don't stretch the SVG unevenly: it changes the bar ratio.

## Related

- [`QrCode`](https://docs.nasaqui.com/components/qr-code)

## Lab

https://docs.nasaqui.com/?path=/docs/components-utilities-barcode--docs

## Code

### React

```tsx
import { Barcode } from "@fadymondy/nasaq/web";

export function Label({ sku }: { sku: string }) {
  return <Barcode value={sku} format="CODE128" downloadable downloadName={sku} />;
}
```

### shadcn

```tsx
import { Barcode } from "@/components/ui/barcode";

export function Label({ sku }: { sku: string }) {
  return <Barcode value={sku} format="CODE128" downloadable downloadName={sku} />;
}
```

### Vue

```vue
<script setup lang="ts">
import { NqBarcode } from "@fadymondy/nasaq/vue";

const sku = "NSQ-2026-0042";
</script>

<template>
  <NqBarcode :value="sku" format="CODE128" downloadable :download-name="sku" />
</template>
```

### Blade

```blade
<x-nq::barcode value="NSQ-2026-0042" format="CODE128" downloadable download-name="sku" />
```

### HTML + Alpine

```html
<div data-slot="barcode" data-format="CODE128" dir="ltr"
    x-data="nqBarcode(JSON.parse('{\u0022value\u0022:\u0022NSQ-2026-0042\u0022,\u0022format\u0022:\u0022CODE128\u0022,\u0022showValue\u0022:true,\u0022height\u0022:80,\u0022barWidth\u0022:2,\u0022margin\u0022:10,\u0022fg\u0022:\u0022black\u0022,\u0022bg\u0022:\u0022white\u0022,\u0022pngSize\u0022:1200,\u0022downloadName\u0022:\u0022sku\u0022,\u0022jsbarcodeSrc\u0022:null}'))"
    x-modelable="value"
    x-bind:data-invalid="message ? '' : null"
    class="inline-flex max-w-full flex-col items-center gap-3">
    <p x-show="message" style="display: none" role="alert" dir="auto" x-text="message"
    class="rounded-control border border-dashed border-border px-4 py-6 text-center text-body-sm text-nq-danger-text"></p>
<svg data-slot="barcode-svg" role="img" x-show="!message" x-bind:aria-label="name" x-bind:style="{ background: bg }" style="background: white"
    class="h-auto max-w-full rounded-control border border-border"></svg>
    <div x-show="!message" class="flex flex-wrap items-center justify-center gap-2" dir="inherit" data-slot="barcode-actions">
        <button data-slot="button"
     type="button"                         x-on:click="save(&#039;svg&#039;)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M12 15V3"/>
  <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
  <path d="m7 10 5 5 5-5"/>
</svg>Download SVG</button>
        <button data-slot="button"
     type="button"                         x-on:click="save(&#039;png&#039;)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control-sm px-2.5">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M12 15V3"/>
  <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
  <path d="m7 10 5 5 5-5"/>
</svg>Download PNG</button>
    </div>
<p x-show="error" style="display: none" role="alert" class="text-caption text-nq-danger-text">Could not create the file. Try again.</p>
</div>
```
