Design System

Server Components

ImportRSC

Available via @stackmates/ui-server-components

MetricCard

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

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

  • Value and label are visible text
  • Trend icon is decorative

PageHeader

Page title with optional description and action slot.

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';

Accessibility

  • Title renders as <h1>
  • 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';

Accessibility

  • Renders as semantic <div>
  • CardTitle should match heading hierarchy

EmptyState

Empty state with title, description, 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 should be a <button> or <a>
  • Illustration is decorative

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

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 via aria-current="page"

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"

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';

Accessibility

  • Uses role="alert" for screen reader announcement

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> — maintain hierarchy

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>
  • Strong renders as <strong>

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"
  • 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

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
  • Link text should describe destination