Kosmesis
Components

Plan Card

A single subscription/account plan card. Purely presentational — no Morphos equivalent.

Installation

npx kosmesis add plan-card
pnpm dlx kosmesis add plan-card
yarn dlx kosmesis add plan-card
bunx kosmesis add plan-card

Copy and paste the following code into your project.

plan-card.tsx
import { StatelessComponent } from "@praxisjs/core";import { Component } from "@praxisjs/decorators";import type { Children } from "@praxisjs/shared";import { cn } from "@/lib/utils";export interface PlanCardProps {  name: string;  price?: string;  description?: string;  current?: boolean;  class?: string;  children?: Children;}/** Distinct from `PricingPlan` (a comparison-table row): this is a single current-plan summary. */@Component()export class PlanCard extends StatelessComponent<PlanCardProps> {  render() {    const { name, price, description, current, class: cls, children } = this.props;    return (      <div data-slot="plan-card" class={cn("flex flex-col gap-3 rounded-xl border bg-card p-5 text-card-foreground", cls)}>        <div class="flex items-center justify-between">          <h3 class="font-semibold">{name}</h3>          {current && (            <span class="rounded-full bg-primary/10 px-2 py-0.5 text-xs font-medium text-primary">Current plan</span>          )}        </div>        {price && <p class="text-2xl font-bold">{price}</p>}        {description && <p class="text-sm text-muted-foreground">{description}</p>}        {children}      </div>    );  }}

Install the following dependencies:

npm install @praxisjs/css
pnpm add @praxisjs/css
yarn add @praxisjs/css
bun add @praxisjs/css

Copy and paste the following code into your project.

plan-card.tsx
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 PlanCardStyles extends Stylesheet {  $root = this.css({    display: "flex",    flexDirection: "column",    gap: "0.75rem",    borderRadius: "0.75rem",    border: `1px solid ${t.border}`,    backgroundColor: t.card,    color: t.cardForeground,    padding: "1.25rem",  });  $header = this.css({ display: "flex", alignItems: "center", justifyContent: "space-between" });  $name = this.css({ fontWeight: 600 });  $badge = this.css({    borderRadius: "9999px",    backgroundColor: `color-mix(in oklab, ${t.primary} 10%, transparent)`,    padding: "0.125rem 0.5rem",    fontSize: "0.75rem",    fontWeight: 500,    color: t.primary,  });  $price = this.css({ fontSize: "1.5rem", fontWeight: 700 });  $description = this.css({ fontSize: "0.875rem", color: t.mutedForeground });}export interface PlanCardProps {  name: string;  price?: string;  description?: string;  current?: boolean;  class?: string;  children?: Children;}/** Distinct from `PricingPlan` (a comparison-table row): this is a single current-plan summary. */@Component()export class PlanCard extends StatelessComponent<PlanCardProps> {  @Styled(PlanCardStyles) $s!: PlanCardStyles;  render() {    const { name, price, description, current, class: cls, children } = this.props;    return (      <div data-slot="plan-card" class={cx(this.$s.$root, cls)}>        <div class={this.$s.$header}>          <h3 class={this.$s.$name}>{name}</h3>          {current && <span class={this.$s.$badge}>Current plan</span>}        </div>        {price && <p class={this.$s.$price}>{price}</p>}        {description && <p class={this.$s.$description}>{description}</p>}        {children}      </div>    );  }}

Examples

About

Purely presentational — no Morphos equivalent. Distinct from PricingPlan (a row in a comparison table meant to be shown side by side): this is a single "your current plan" summary, e.g. on a billing settings page. children render below the description (e.g. a usage bar or an upgrade button).

Usage

import { PlanCard } from "@/components/ui/plan-card";

<PlanCard name="Pro" price="$19/mo" description="For growing teams" current>
  <Button variant="outline">Change plan</Button>
</PlanCard>

Props

PropTypeDefault
namestring
pricestring
descriptionstring
currentbooleanfalse
classstring

On this page