# Badge

> Small status label with Variants default, secondary, outline, destructive, success and warning.

Component · display. Registry item `badge`, shown in the vega Style. JSON: https://nativecn.dev/r/styles/vega/badge.json

## Installation

```sh
npx nativecn-cli@latest add badge
```

Also installs: [theme](https://nativecn.dev/docs/theme/theme), [text](https://nativecn.dev/docs/components/text).

## Usage

### Badge demo

A Badge in every Variant.

```tsx
import { View } from "react-native";

import { Badge } from "@/components/badge";
import { createStyles } from "@/theme";

export default function BadgeDemo() {
  const styles = useStyles();
  return (
    <View style={styles.row}>
      <Badge label="New" />
      <Badge label="Beta" variant="secondary" />
      <Badge label="Draft" variant="outline" />
      <Badge label="Failed" variant="destructive" />
      <Badge label="Paid" variant="success" />
      <Badge label="Pending" variant="warning" />
    </View>
  );
}

const useStyles = createStyles((t) => ({
  row: { flexDirection: "row", flexWrap: "wrap", gap: t.spacing[2] },
}));
```

## Props

| Prop | Type and description |
|---|---|
| `label` | string (required): the visible text and accessible name |
| `variant` | "default" (default) \| "secondary" \| "outline" \| "destructive" \| "success" \| "warning" |
| `style` | merged last |

## Variants

- `default`, `secondary`, `outline`, `destructive`, `success`, `warning`

## Accessibility

- Not interactive: its label is read as plain text.
- The label uses the caption text Variant, which caps the OS font scale at 1.5× when font scaling is on.

## Notes

Not pressable: for a selectable or removable pill use Chip. A Badge sizes to its label (alignSelf flex-start). Its size comes from the badge.root and badge.label Style Slots.

## Source

### {components}/badge.tsx

```tsx
import type { Ref } from "react";
import { View, type ViewProps } from "react-native";

import { Text, type TextColor } from "@/components/text";
import { createStyles, type ColorRole } from "@/theme";

/** Each Variant's Colour Roles: fill, content and (optional) border. */
const variants = {
  default: { background: "primary", foreground: "primaryForeground" },
  secondary: { background: "secondary", foreground: "secondaryForeground" },
  outline: { foreground: "foreground", border: "border" },
  destructive: { background: "destructive", foreground: "destructiveForeground" },
  success: { background: "success", foreground: "successForeground" },
  warning: { background: "warning", foreground: "warningForeground" },
} as const satisfies Record<
  string,
  { background?: ColorRole; foreground: TextColor; border?: ColorRole }
>;

export type BadgeVariant = keyof typeof variants;

export type BadgeProps = Omit<ViewProps, "children"> & {
  /** The visible text, which is also the accessible name. */
  label: string;
  /** Default `default`. */
  variant?: BadgeVariant;
  ref?: Ref<View>;
};

const useStyles = createStyles((t) => ({
  root: {
    ...{
    height: t.scaleValue(22),
    borderRadius: t.radius.sm,
    paddingHorizontal: t.spacing[2],
  },
    flexDirection: "row",
    alignItems: "center",
    alignSelf: "flex-start",
    borderCurve: "continuous",
    borderWidth: t.borderWidth.default,
    borderColor: "transparent",
  },
  label: { ...t.type.caption, fontFamily: t.type.label.fontFamily },
}));

const useVariantStyles = createStyles((t) => ({
  default: { backgroundColor: t.colors.primary },
  secondary: { backgroundColor: t.colors.secondary },
  outline: { backgroundColor: "transparent", borderColor: t.colors.border },
  destructive: { backgroundColor: t.colors.destructive },
  success: { backgroundColor: t.colors.success },
  warning: { backgroundColor: t.colors.warning },
}));

/**
 * A small status or count label. Not pressable; for a pressable or selectable pill use Chip.
 * Its `label` is the accessible name. `style` is merged last onto the root.
 */
export function Badge({ label, variant = "default", style, ...props }: BadgeProps) {
  const styles = useStyles();
  const variantStyles = useVariantStyles();
  return (
    <View style={[styles.root, variantStyles[variant], style]} {...props}>
      <Text
        variant="caption"
        color={variants[variant].foreground}
        numberOfLines={1}
        style={styles.label}
      >
        {label}
      </Text>
    </View>
  );
}
```
