import { useState } from "react";
import { Badge, Tag } from "@/component-lib/badge";
import { Button } from "@/component-lib/button";
import { Row, Section } from "./layout"; // Section and Row: page layout for the demo
const VARIANTS = ["neutral", "accent", "success", "warning", "danger", "info"] as const;
export function BadgeDemo() {
const [tags, setTags] = useState(["Kochi", "Berlin", "Austin"]);
return (
<>
{(["soft", "solid", "outline"] as const).map((appearance) => (
<Section key={appearance} title={`Badge · ${appearance}`}>
<Row>
{VARIANTS.map((variant) => (
<Badge key={variant} variant={variant} appearance={appearance}>
{variant}
</Badge>
))}
</Row>
</Section>
))}
<Section title="Badge · size, dot, count">
<Row>
<Badge size="sm">Small</Badge>
<Badge size="md">Medium</Badge>
<Badge variant="success" dot>
Online
</Badge>
<Badge variant="danger" appearance="solid" count={7} />
<Badge variant="accent" appearance="solid" count={1234} />
<Badge count={0} showZero />
<Badge count={0} />
</Row>
</Section>
<Section title="Tag · removable">
<Row>
{tags.map((tag) => (
<Tag key={tag} variant="accent" onRemove={() => setTags((list) => list.filter((t) => t !== tag))}>
{tag}
</Tag>
))}
<Tag disabled onRemove={() => {}}>
Locked
</Tag>
<Tag size="sm">Plain</Tag>
</Row>
{tags.length < 3 && (
<Button size="sm" variant="outline" onPress={() => setTags(["Kochi", "Berlin", "Austin"])}>
Reset tags
</Button>
)}
</Section>
</>
);
}Install
npx @grampro/kit@native add BadgeUsage
import { Badge, Tag } from "@/component-lib/badge";
<Badge variant="success">Paid</Badge>
<Badge count={128} max={99} />
<Tag onRemove={() => remove("react")}>React</Tag>Props
BadgeProps
| Prop | Type | Description |
|---|---|---|
children | ReactNode | |
variant | BadgeVariant | Default neutral. |
appearance | BadgeAppearance | Default soft. |
size | BadgeSize | Default md. |
count | number | A number instead of children. Above max it reads "99+". |
max | number | Where the count stops. Default 99. |
showZero | boolean | Show a count of zero. Default false: an empty counter is noise. |
formatValue | (value: number) => string | Format the number, e.g. with Intl.NumberFormat. |
dot | boolean | A small filled circle before the label, for a status. |
icon | ReactNode | An icon before the label, in place of dot. |
style | StyleProp<ViewStyle> | |
styles | Partial<{ root: StyleProp<ViewStyle>; dot: StyleProp<ViewStyle>; icon: StyleProp<ViewSt… |
Also accepts the props of Omit<ViewProps, "children" | "style">.
TagProps
| Prop | Type | Description |
|---|---|---|
children | ReactNode | |
variant | BadgeVariant | |
appearance | BadgeAppearance | |
size | BadgeSize | |
icon | ReactNode | An icon before the label. |
onRemove | () => void | Show a remove button. Without it a Tag is a Badge with a bit more padding. |
label | string | Names the remove button when the tag's own text is not a plain string. |
disabled | boolean | |
style | StyleProp<ViewStyle> | |
styles | Partial<{ root: StyleProp<ViewStyle>; icon: StyleProp<ViewStyle>; label: StyleProp<Text… | |
localeText | Partial<BadgeLocaleText> |
Also accepts the props of Omit<ViewProps, "children" | "style">.
Native and web
- A count's spoken text goes on the badge's
aria-label. - Web version: Badge & Tag on the web.