import type { HTMLAttributes, ReactNode } from "react";
import { cx } from "../../utils/cx.utils";
import { Icon } from "../icons/icon";
import type { IconName } from "../icons/icons";
import "./pill.component.css";
/** Sizes accepted by every {@link Pill} variant. Defaults to `"md"`. */
export type PillSize = "sm" | "md" | "xl";
/** Props shared by every {@link Pill} variant. */
export interface PillProps extends Omit, "children"> {
/** Text shown inside the pill. Always rendered uppercase. */
children: ReactNode;
/** Name of an icon rendered on the left side of the pill. */
icon?: IconName;
/** Size of the pill. Defaults to `"md"`. */
size?: PillSize;
}
/** Icon pixel size per {@link PillSize}. */
const ICON_SIZES: Record = {
sm: 12,
md: 14,
xl: 20,
};
function renderContent(children: ReactNode, icon: IconName | undefined, size: PillSize) {
return (
<>
{icon ? (
) : null}
{children}
>
);
}
/**
* Small, uppercase status pill with a solid 2px black border, rendered in
* the Inter font. Accepts an optional `icon` on the left side and an
* optional `size` (`"sm"` | `"md"` | `"xl"`, defaults to `"md"`).
*
* Additional border treatments are available as static properties:
* {@link Pill.Double}, {@link Pill.Filled}, {@link Pill.Dashed},
* {@link Pill.Dotted}.
*
* @example
* ```tsx
* OK
* Warning
* Critical
* Neutral
* Offline
* ```
*/
export function Pill({ className, children, icon, size = "md", ...rest }: PillProps) {
return (
{renderContent(children, icon, size)}
);
}
/** {@link Pill} with a double border (thin outer outline, thick inner border). */
function Double({ className, children, icon, size = "md", ...rest }: PillProps) {
return (
{renderContent(children, icon, size)}
);
}
/** {@link Pill} filled black with a white label and icon. */
function Filled({ className, children, icon, size = "md", ...rest }: PillProps) {
return (
{renderContent(children, icon, size)}
);
}
/** {@link Pill} with a dashed border. */
function Dashed({ className, children, icon, size = "md", ...rest }: PillProps) {
return (
{renderContent(children, icon, size)}
);
}
/** {@link Pill} with a dotted border. */
function Dotted({ className, children, icon, size = "md", ...rest }: PillProps) {
return (
{renderContent(children, icon, size)}
);
}
Pill.Double = Double;
Pill.Filled = Filled;
Pill.Dashed = Dashed;
Pill.Dotted = Dotted;