@prood/ui
The Prood design system and shared React components, from shadcn/Radix primitives to commerce and product UI.
@prood/ui is the Prood design system and the shared UI layer for every Prood application. It holds the tokens, the logo, shadcn/ui primitives (Radix + Tailwind) and the components for catalog, cart, checkout, account and product UI. Photography and film live next door in @prood/media.
Design system
One system runs every surface: marketing, dashboard, admin, docs, storefront and hosted checkout. The rules live in packages/ui/DESIGN.md, positioning and voice in _docs/BRAND.md, and the living reference is prood.com/design.
It hangs on three physical things from a shop on a Portuguese street:
- Receipt paper: Paper, the warm canvas, and the
Receiptcomponent. - The roof tile: Telha, the one signal color, and
TileEdgeandTileField, filled tiles from the wordmark's ring that always hang downward. - The people behind the counter: real hands and faces in natural light, with one shared photo grade.
| Concept | What to use |
|---|---|
| Colors | background, foreground, primary (Ink) and brand (Telha). Fixed ink, paper and telha inside components. Never hardcode a color in an app |
| Surfaces | surface-ink and surface-telha restyle every token inside them, so components need no variants. Add surface-photo when text sits on a photograph |
| Type | Bricolage Grotesque for headings, Instrument Sans for UI, Geist Mono for code. text-display-xl to text-display-sm, text-lead and text-eyebrow on marketing; PageHeader in product UI |
| Shape | Controls rounded-lg, panels rounded-xl, large frames rounded-3xl. Borders over shadows |
| Merchant surfaces | Storefront and hosted checkout use the same system on the neutral theme: no Telha, no Prood logo |
Installation
Already a workspace dependency. Import directly:
import { Button } from '@prood/ui/components/button'
import { ProductGrid } from '@prood/ui/components/product-grid'
import { CartDrawer } from '@prood/ui/components/cart-drawer'Import global styles in your app's root layout:
import '@prood/ui/globals.css'
import '@prood/ui/themes/prood.css'Import exactly one theme next to globals.css: prood.css for Prood's own apps, neutral.css for merchant surfaces.
Component categories
Product
| Component | Import | Description |
|---|---|---|
ProductCard | @prood/ui/components/product-card | Product thumbnail with price and add-to-cart |
ProductGrid | @prood/ui/components/product-grid | Responsive product grid layout |
ProductGallery | @prood/ui/components/product-gallery | Image gallery with zoom |
ProductPrice | @prood/ui/components/product-price | Formatted price with compare-at |
Cart
| Component | Import | Description |
|---|---|---|
CartDrawer | @prood/ui/components/cart-drawer | Slide-out cart panel |
CartItem | @prood/ui/components/cart-item | Single cart line item |
CartSummary | @prood/ui/components/cart-summary | Totals breakdown |
QuantitySelector | @prood/ui/components/quantity-selector | +/- quantity control |
Order
| Component | Import | Description |
|---|---|---|
OrderCard | @prood/ui/components/order-card | Order summary card |
OrderTimeline | @prood/ui/components/order-timeline | Status timeline |
Navigation & search
| Component | Import | Description |
|---|---|---|
SearchPalette | @prood/ui/components/search-palette | Command-k style search |
Product UI
Every dashboard and admin page is built from these.
| Component | Import | Description |
|---|---|---|
PageHeader | @prood/ui/components/page-header | Page title, a sentence of context and one primary action |
StatGrid, Stat | @prood/ui/components/stat-grid | A row of headline numbers, joined by hairlines |
StatusBadge | @prood/ui/components/status-badge | Status of an order, domain or provider. Tones: neutral, brand, success, warning, danger, info |
Panel | @prood/ui/components/panel | Titled, bordered block around a table, list or form. Pass flush for tables |
AuthShell | @prood/ui/components/auth-shell | Sign-in, sign-up and onboarding: the form beside a MediaImage passed as aside |
import { PageHeader } from '@prood/ui/components/page-header'
import { Panel } from '@prood/ui/components/panel'
import { StatusBadge } from '@prood/ui/components/status-badge'
<PageHeader title="Orders" description="Everything your customers have bought." />
<Panel title="Recent orders" flush>
<StatusBadge tone="success">Paid</StatusBadge>
</Panel>Marketing
| Component | Import | Description |
|---|---|---|
HeroBanner | @prood/ui/components/hero-banner | Full-width hero section |
Receipt | @prood/ui/components/receipt | The signature fragment: a torn till receipt for a sale or order moment. Sample data only |
TileEdge, TileField | @prood/ui/components/tile | The hanging tile motif. TileEdge at section seams, with awning under a photograph, TileField behind Ink and Telha panels |
BrowserFrame, PhoneFrame | @prood/ui/components/device-frame | Device chrome around real components, never drawings of a screen |
Reviews
| Component | Import | Description |
|---|---|---|
ReviewStars | @prood/ui/components/review-stars | Star rating display |
Common
| Component | Import | Description |
|---|---|---|
EmptyState | @prood/ui/components/empty-state | Empty list placeholder |
ProductTypeBadge | @prood/ui/components/product-type-badge | Product type indicator |
shadcn primitives
Standard shadcn/ui components in @prood/ui/components/:
button, input, label, card, dialog, dropdown-menu, sheet, table, tabs, badge, skeleton, sonner, sidebar, etc.
Utility functions
import { formatPrice, localized } from '@prood/ui/lib/commerce'
formatPrice(9999, 'EUR') // → "€99.99"
localized(product.name, 'en') // → "T-Shirt"Adding new components
Install shadcn primitives:
pnpm dlx shadcn@latest add dialog -c packages/uiCommerce components are hand-authored in packages/ui/src/components/.
Theming
Uses CSS variables with Tailwind v4. Dark mode via next-themes:
import { ThemeProvider } from 'next-themes'
<ThemeProvider attribute="class" defaultTheme="system">
{children}
</ThemeProvider>Color tokens are defined in packages/ui/src/styles/themes/prood.css and neutral.css. packages/ui/src/styles/globals.css maps them to Tailwind with @theme inline and holds the display type scale.