Components
Badge
A small status/label pill. Purely presentational — no Morphos primitive to wrap.
Installation
npx kosmesis add badgepnpm dlx kosmesis add badgeyarn dlx kosmesis add badgebunx kosmesis add badgeInstall the following dependencies:
npm install class-variance-authoritypnpm add class-variance-authorityyarn add class-variance-authoritybun add class-variance-authorityCopy and paste the following code into your project.
import { cva, type VariantProps } from "class-variance-authority";import { StatelessComponent } from "@praxisjs/core";import { Component } from "@praxisjs/decorators";import type { Children } from "@praxisjs/shared";import { cn } from "@/lib/utils";export const badgeVariants = cva( "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 gap-1 [&_svg]:pointer-events-none [&_svg]:size-3", { variants: { variant: { default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90", secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90", outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground", }, }, defaultVariants: { variant: "default", }, },);export interface BadgeProps extends VariantProps<typeof badgeVariants> { as?: "span" | "a" | "div"; href?: string; class?: string; id?: string; children?: Children;}@Component()export class Badge extends StatelessComponent<BadgeProps> { render() { const { as: Tag = "span", variant, class: cls, id, href, children } = this.props; return ( <Tag id={id} href={Tag === "a" ? href : undefined} class={cn(badgeVariants({ variant }), cls)}> {children} </Tag> ); }}Install the following dependencies:
npm install @praxisjs/csspnpm add @praxisjs/cssyarn add @praxisjs/cssbun add @praxisjs/cssCopy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { cx, Stylesheet, Styled, tokenVars } from "@praxisjs/css";import { Component } from "@praxisjs/decorators";import type { Children } from "@praxisjs/shared";import { KosmesisTokens } from "@/lib/kosmesis-theme";const t = tokenVars(KosmesisTokens);class BadgeStyles extends Stylesheet { $root = this.css({ display: "inline-flex", alignItems: "center", justifyContent: "center", borderRadius: `calc(${t.radius} - 2px)`, padding: "0.125rem 0.5rem", fontSize: "0.75rem", fontWeight: 500, width: "fit-content", whiteSpace: "nowrap", flexShrink: 0, gap: "0.25rem", }).on("& svg", { pointerEvents: "none", width: "0.75rem", height: "0.75rem" }); $variantDefault = this.css({ border: "1px solid transparent", backgroundColor: t.primary, color: t.primaryForeground }).on( "&:is(a):hover", { backgroundColor: `color-mix(in oklab, ${t.primary} 90%, transparent)` }, ); $variantSecondary = this.css({ border: "1px solid transparent", backgroundColor: t.secondary, color: t.secondaryForeground, }).on("&:is(a):hover", { backgroundColor: `color-mix(in oklab, ${t.secondary} 90%, transparent)` }); $variantDestructive = this.css({ border: "1px solid transparent", backgroundColor: t.destructive, color: "white" }).on( "&:is(a):hover", { backgroundColor: `color-mix(in oklab, ${t.destructive} 90%, transparent)` }, ); $variantOutline = this.css({ color: t.foreground }).on("&:is(a):hover", { backgroundColor: t.accent, color: t.accentForeground, });}export type BadgeVariant = "default" | "secondary" | "destructive" | "outline";export interface BadgeProps { variant?: BadgeVariant; as?: "span" | "a" | "div"; href?: string; class?: string; id?: string; children?: Children;}@Component()export class Badge extends StatelessComponent<BadgeProps> { @Styled(BadgeStyles) $s!: BadgeStyles; render() { const { as: Tag = "span", variant = "default", class: cls, id, href, children } = this.props; const variants: Record<BadgeVariant, string> = { default: this.$s.$variantDefault, secondary: this.$s.$variantSecondary, destructive: this.$s.$variantDestructive, outline: this.$s.$variantOutline, }; return ( <Tag id={id} href={Tag === "a" ? href : undefined} class={cx(this.$s.$root, variants[variant], cls)}> {children} </Tag> ); }}Examples
About
Purely presentational — same as upstream shadcn/ui, since neither Morphos nor Radix has a badge
primitive. Variants are backed by class-variance-authority.
Usage
import { Badge } from "@/components/ui/badge";
<Badge>Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="destructive">Destructive</Badge>
<Badge variant="outline">Outline</Badge>
<Badge as="a" href="/status">Link badge</Badge>Props
| Prop | Type | Default |
|---|---|---|
variant | "default" | "secondary" | "destructive" | "outline" | "default" |
as | "span" | "a" | "div" | "span" |
href | string | — (used when as="a") |
class | string | — |