Design System

Server Components

ImportRSC

Available via @stackmates/ui-server-components

MetricCard

KPI card with value, label, optional variant coloring and trend indicator. Supports clickable href.

142

Total Contacts

38+12.5%

Active Deals

7-3.2%

Overdue Tasks

$24.5kThis month

Pipeline Value

89

Conversion Rate %

50+

Browse All Contacts

MetricCardProps

PropTypeDefaultDescription
value*string | numberPrimary display value
label*stringLabel below the value
variant'default' | 'success' | 'danger' | 'warning' | 'info''default'Color variant for the value
trend{ change?: number; label?: string; direction?: "up" | "down" }Optional trend indicator with change percentage or label
hrefstringMakes the entire card a clickable link

Installation

typescript
import { MetricCard } from '@stackmates/ui-server-components';

Usage

Basic

tsx
<MetricCard value={142} label="Total Contacts" />

With trend

tsx
<MetricCard value={38} label="Active Deals" variant="success" trend={{ change: 12.5 }} />

Accessibility

  • Renders as a <div> (or <a> when href is provided)
  • Value and label are visible text — no additional ARIA needed
  • Trend icon is decorative — color is not the only indicator

PageHeader

Page title with optional description and action slot (children).

Contacts

Manage your organization's contacts and relationships.

+ Add Contact

Dashboard

PageHeaderProps

PropTypeDefaultDescription
title*stringPage title text
descriptionstringSubtitle text below the title
childrenReactNodeAction slot (buttons, links) rendered on the right

Installation

typescript
import { PageHeader } from '@stackmates/ui-server-components';

Usage

With description and action

tsx
<PageHeader title="Contacts" description="Manage contacts.">
  <Button>Add Contact</Button>
</PageHeader>

Accessibility

  • Title renders as <h1> — one per page
  • Description provides context for screen readers

Card

Compound card with header, title, description, content, and footer slots.

Project Overview
Current project status and metrics.

3 active tasks, 2 pending review.

Updated 2 min ago
Team
Alice ChenLead
Bob MartinezDev

CardProps

PropTypeDefaultDescription
children*ReactNodeCard content — compose with CardHeader, CardContent, CardFooter
classNamestringAdditional CSS classes

Installation

typescript
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@stackmates/ui-server-components';

Usage

Full compound card

tsx
<Card>
  <CardHeader>
    <CardTitle>Title</CardTitle>
    <CardDescription>Subtitle</CardDescription>
  </CardHeader>
  <CardContent>Content here</CardContent>
  <CardFooter>Footer</CardFooter>
</Card>

Accessibility

  • Renders as semantic <div> — add role="region" if card is a landmark
  • CardTitle should match heading hierarchy of the page

EmptyState

Empty state with title, description, optional variant illustration, and action slot.

No Contacts Yet

Add your first contact to start building relationships.

Add Contact
$

No Deals Found

Create a deal to track your sales pipeline.

EmptyStateProps

PropTypeDefaultDescription
variant'contacts' | 'deals' | 'default''default'Illustration variant
title*stringEmpty state heading
description*stringExplanation text
actionsReactNodeCTA button or link slot

Installation

typescript
import { EmptyState } from '@stackmates/ui-server-components';

Accessibility

  • CTA within actions slot should be a <button> or <a> for keyboard access
  • Illustration is decorative — hidden from screen readers

AccessDenied

403-style inline access denied. Renders in-place, not a redirect.

403

Access Denied

You don't have permission to access this feature. Contact your organisation admin to request access.

Go to Home

AccessDeniedProps

PropTypeDefaultDescription
featurestringFeature name shown in the denial message

Installation

typescript
import { AccessDenied } from '@stackmates/ui-server-components';

Accessibility

  • Uses role="alert" to announce denial to screen readers
  • Feature name provides context for the denied action

PaginationControls

URL-based pagination using Next.js Link. Handles ellipsis for large ranges.

PaginationControlsProps

PropTypeDefaultDescription
currentPage*numberActive page number (1-based)
totalPages*numberTotal number of pages
basePath*stringURL path to append ?page=N to

Installation

typescript
import { PaginationControls } from '@stackmates/ui-server-components';

Accessibility

  • Uses <nav> with aria-label="Pagination"
  • Current page announced via aria-current="page"
  • Previous/Next links are keyboard accessible

PaginationSummary

Text summary line for pagination context.

Showing 1-25 of 142 contacts50 Total

PaginationSummaryProps

PropTypeDefaultDescription
text*stringSummary text (e.g. "Showing 1-25 of 142")

Installation

typescript
import { PaginationSummary } from '@stackmates/ui-server-components';

Accessibility

  • Renders as <p> with aria-live="polite" for dynamic updates

AlertRx

Alert banner with title and description. Supports default and destructive variants.

AlertRxProps

PropTypeDefaultDescription
variant'default' | 'destructive''default'Alert style variant
children*ReactNodeAlert content — compose with AlertRxTitle, AlertRxDescription

Installation

typescript
import { AlertRx, AlertRxTitle, AlertRxDescription } from '@stackmates/ui-server-components';

Usage

Default

tsx
<AlertRx>
  <Info className="h-4 w-4" />
  <AlertRxTitle>Info</AlertRxTitle>
  <AlertRxDescription>Message here</AlertRxDescription>
</AlertRx>

Destructive

tsx
<AlertRx variant="destructive">
  <AlertCircle className="h-4 w-4" />
  <AlertRxTitle>Error</AlertRxTitle>
  <AlertRxDescription>Something went wrong</AlertRxDescription>
</AlertRx>

Accessibility

  • Uses role="alert" for screen reader announcement
  • Icon is decorative — pair with AlertRxTitle for meaning

Heading / Subheading

Semantic heading and subheading components with consistent typography.

Heading level 1

Heading level 2

Subheading level 2

Subheading level 3

HeadingProps

PropTypeDefaultDescription
level*1 | 2 | 3 | 4 | 5 | 6HTML heading level (h1-h6)
children*ReactNodeHeading text content

Installation

typescript
import { Heading, Subheading } from '@stackmates/ui-server-components';

Accessibility

  • Renders semantic <h1>-<h6> elements — maintain hierarchy
  • Never skip heading levels (e.g. h1 to h3 without h2)

Text / TextLink / Strong / Code

Inline typography primitives for body text, links, emphasis, and code.

Standard text paragraph rendered on the server.

With TextLink, Strong, and Code inline.

PropsContribute this section

Installation

typescript
import { Text, TextLink, Strong, Code } from '@stackmates/ui-server-components';

Accessibility

  • TextLink renders as <a> — keyboard accessible by default
  • Strong renders as <strong> — conveyed by screen readers
  • Code renders as <code> — announced as code by assistive technology

ErrorMessage

Inline form error message with destructive styling.

ErrorMessageProps

PropTypeDefaultDescription
message*stringError message text to display

Installation

typescript
import { ErrorMessage } from '@stackmates/ui-server-components';

Accessibility

  • Uses role="alert" for immediate screen reader announcement
  • Pair with aria-describedby on the related input

Skeleton

Loading placeholder with pulse animation. Shape via className.

SkeletonProps

PropTypeDefaultDescription
classNamestringWidth, height, and border-radius via Tailwind classes

Installation

typescript
import { Skeleton } from '@stackmates/ui-server-components';

Accessibility

  • Use aria-busy="true" on the container while loading
  • Provide aria-label on the skeleton region for context

Link

Next.js Link wrapper for internal navigation.

PropsContribute this section

Installation

typescript
import { Link } from '@stackmates/ui-server-components';

Accessibility

  • Renders as <a> — keyboard accessible by default
  • Link text should describe the destination, not "click here"