Components
Pricing Table
A responsive row of pricing plan cards with a features list. Purely presentational — no Morphos equivalent.
Installation
npx kosmesis add pricing-tablepnpm dlx kosmesis add pricing-tableyarn dlx kosmesis add pricing-tablebunx kosmesis add pricing-tableInstall the following dependencies:
npm install @morphos/iconspnpm add @morphos/iconsyarn add @morphos/iconsbun add @morphos/iconsCopy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { Component } from "@praxisjs/decorators";import type { Children } from "@praxisjs/shared";import { Icon } from "@morphos/icons";import { cn } from "@/lib/utils";export interface PricingTableProps { class?: string; children?: Children;}@Component()export class PricingTable extends StatelessComponent<PricingTableProps> { render() { const { class: cls, children } = this.props; return ( <div data-slot="pricing-table" class={cn("grid grid-cols-1 gap-6 md:grid-cols-3", cls)}> {children} </div> ); }}export interface PricingPlanProps { highlighted?: boolean; class?: string; children?: Children;}@Component()export class PricingPlan extends StatelessComponent<PricingPlanProps> { render() { const { highlighted, class: cls, children } = this.props; return ( <div data-highlighted={highlighted ? "" : undefined} class={cn( "flex flex-col gap-4 rounded-xl border bg-card p-6 text-card-foreground", "data-[highlighted]:border-primary data-[highlighted]:shadow-lg", cls, )} > {children} </div> ); }}export interface PricingPlanPriceProps { price: string; period?: string; class?: string;}@Component()export class PricingPlanPrice extends StatelessComponent<PricingPlanPriceProps> { render() { const { price, period, class: cls } = this.props; return ( <div class={cn("flex items-baseline gap-1", cls)}> <span class="text-3xl font-bold text-foreground">{price}</span> {period && <span class="text-sm text-muted-foreground">{`/${period}`}</span>} </div> ); }}export interface PricingPlanFeatureProps { class?: string; children?: Children;}@Component()export class PricingPlanFeature extends StatelessComponent<PricingPlanFeatureProps> { render() { const { class: cls, children } = this.props; return ( <li class={cn("flex items-center gap-2 text-sm text-muted-foreground", cls)}> <span class="text-primary"><Icon name="Check" size={16} /></span> {children} </li> ); }}Install the following dependencies:
npm install @praxisjs/css @morphos/iconspnpm add @praxisjs/css @morphos/iconsyarn add @praxisjs/css @morphos/iconsbun add @praxisjs/css @morphos/iconsCopy 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 { Icon } from "@morphos/icons";import { KosmesisTokens } from "@/lib/kosmesis-theme";const t = tokenVars(KosmesisTokens);class PricingTableStyles extends Stylesheet { $root = this.css({ display: "grid", gridTemplateColumns: "1fr", gap: "1.5rem" }).on("@media (min-width: 768px)", { gridTemplateColumns: "repeat(3, 1fr)", }); $plan = this.css({ display: "flex", flexDirection: "column", gap: "1rem", borderRadius: "0.75rem", border: `1px solid ${t.border}`, backgroundColor: t.card, color: t.cardForeground, padding: "1.5rem", }).on("&[data-highlighted]", { borderColor: t.primary, boxShadow: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)", }); $price = this.css({ display: "flex", alignItems: "baseline", gap: "0.25rem" }); $priceValue = this.css({ fontSize: "1.875rem", fontWeight: 700, color: t.foreground }); $pricePeriod = this.css({ fontSize: "0.875rem", color: t.mutedForeground }); $feature = this.css({ display: "flex", alignItems: "center", gap: "0.5rem", fontSize: "0.875rem", color: t.mutedForeground }); $check = this.css({ color: t.primary });}export interface PricingTableProps { class?: string; children?: Children;}@Component()export class PricingTable extends StatelessComponent<PricingTableProps> { @Styled(PricingTableStyles) $s!: PricingTableStyles; render() { const { class: cls, children } = this.props; return ( <div data-slot="pricing-table" class={cx(this.$s.$root, cls)}> {children} </div> ); }}export interface PricingPlanProps { highlighted?: boolean; class?: string; children?: Children;}@Component()export class PricingPlan extends StatelessComponent<PricingPlanProps> { @Styled(PricingTableStyles) $s!: PricingTableStyles; render() { const { highlighted, class: cls, children } = this.props; return ( <div data-highlighted={highlighted ? "" : undefined} class={cx(this.$s.$plan, cls)}> {children} </div> ); }}export interface PricingPlanPriceProps { price: string; period?: string; class?: string;}@Component()export class PricingPlanPrice extends StatelessComponent<PricingPlanPriceProps> { @Styled(PricingTableStyles) $s!: PricingTableStyles; render() { const { price, period, class: cls } = this.props; return ( <div class={cx(this.$s.$price, cls)}> <span class={this.$s.$priceValue}>{price}</span> {period && <span class={this.$s.$pricePeriod}>{`/${period}`}</span>} </div> ); }}export interface PricingPlanFeatureProps { class?: string; children?: Children;}@Component()export class PricingPlanFeature extends StatelessComponent<PricingPlanFeatureProps> { @Styled(PricingTableStyles) $s!: PricingTableStyles; render() { const { class: cls, children } = this.props; return ( <li class={cx(this.$s.$feature, cls)}> <span class={this.$s.$check}><Icon name="Check" size={16} /></span> {children} </li> ); }}Examples
About
Purely presentational — no Morphos equivalent. PricingPlan's name/description are plain
children (a heading + paragraph) rather than dedicated slots, matching the public prop API of
Card — only PricingPlanPrice and PricingPlanFeature get dedicated components since their
formatting (price/period split, check-marked list item) is genuinely repetitive.
Usage
import { PricingPlan, PricingPlanFeature, PricingPlanPrice, PricingTable } from "@/components/ui/pricing-table";
<PricingTable>
<PricingPlan highlighted>
<h3>Pro</h3>
<PricingPlanPrice price="$19" period="mo" />
<ul>
<PricingPlanFeature>Unlimited projects</PricingPlanFeature>
<PricingPlanFeature>Priority support</PricingPlanFeature>
</ul>
<Button>Get started</Button>
</PricingPlan>
</PricingTable>Props
PricingPlan
| Prop | Type | Default |
|---|---|---|
highlighted | boolean | false |
class | string | — |
PricingPlanPrice
| Prop | Type | Default |
|---|---|---|
price | string | — |
period | string | — |
class | string | — |
PricingTable/PricingPlanFeature accept class and children only.