


Paddle Design System
Source & Stack
\- Site:
Typography \- No custom font detected in page source โ likely system-font stack or self-hosted via \_next/static \- Type scale is clean and editorial: large display headlines (h1 hero, bold weight), smaller section labels (h2โh3), compact body copy \- Heading style: sentence case, high contrast against dark/light backgrounds \- Code blocks on engineering blog use monospace (likely JetBrains Mono or Fira Code via Astro)
Color Philosophy \- Primary brand: Deep navy / near-black backgrounds for hero sections with white text (inverted logo variant: paddle-logo-inverted.svg) \- Light mode: White page backgrounds with dark text; subtle hover states (--paddle-color-background-hover) \- Accent: Paddle green (used for CTAs, status badges, success indicators) \- Destructive / alert: Red tone for destructive actions in menus (e.g., "Revoke" API key) \- Neutral grays: Used for table rows, secondary labels, dividers \- Two-logo system confirms dual-mode support: paddle-logo.svg (dark) and paddle-logo-inverted.svg (light)
Spacing \- Base unit: 4px grid (inferred from UI screenshots showing 8/16/24/32/48px rhythm) \- Table cells: padding-top offset of 120px for overlay states; sticky offsets top: 80px \- Section spacing: generous vertical padding between marketing sections (~64โ96px)
Component Defaults
\- Tables: Composable (TableHeader, TableBody, TableColumn, TableRow, TableCell); horizontal scroll with fade gradient; full-width row hover via CSS box-shadow trick; React Portals for dropdowns
\- Buttons: Primary (filled, green/dark), Secondary (outlined or ghost), Destructive (red label)
\- Status pills / badges: Inline components within table cells
\- Pagination: URL-param driven, cursor-based; separate
Layout \- Max content width: ~1280px centered, full-bleed section backgrounds \- Nav: Top horizontal bar, dark/inverted background, mega-menu dropdowns \- Marketing pages: Full-width hero โ alternating feature cards โ social proof logos โ CTA footer \- Dashboard: Sidebar nav (dark) + content area; tables span full content width with extended hover backgrounds \- Responsive: Horizontal scroll on tables preferred over column hiding; mobile nav collapses to hamburger
/ ============================================================ PADDLE DESIGN SYSTEM โ CSS Custom Properties Source: inferred from paddle.com + paddle.engineering Framework: Next.js + React Aria ============================================================ /
:root { / --- Brand Colors --- / --paddle-color-brand-primary: #1a1a2e; / deep navy โ hero bg, nav / --paddle-color-brand-accent: #2ecc71; / paddle green โ CTA, success / --paddle-color-brand-accent-hover: #27ae60; / darker green on hover /
/ --- Background --- / --paddle-color-background-page: #ffffff; --paddle-color-background-section-alt: #f7f8fa; / light gray alt sections / --paddle-color-background-hover: #f0f2f5; / table row hover, referenced in eng blog / --paddle-color-background-overlay: rgba(255, 255, 255, 0.6); / pending overlay / --paddle-color-background-dark: #0f0f1a; / hero / nav dark bg / --paddle-color-background-card: #ffffff;
/ --- Text --- / --paddle-color-text-primary: #0f0f1a; / near-black for headings / --paddle-color-text-secondary: #4a5568; / muted body / labels / --paddle-color-text-tertiary: #718096; / placeholder, meta / --paddle-color-text-inverse: #ffffff; / text on dark bg / --paddle-color-text-link: #2ecc71; / anchor links, accent / --paddle-color-text-destructive: #e53e3e; / destructive actions /
/ --- Border --- / --paddle-color-border-default: #e2e8f0; --paddle-color-border-focus: #2ecc71; --paddle-color-border-subtle: #f0f2f5;
/ --- Status / Semantic --- / --paddle-color-status-success: #2ecc71; --paddle-color-status-success-bg: #f0fff4; --paddle-color-status-warning: #f6ad55; --paddle-color-status-warning-bg: #fffbeb; --paddle-color-status-error: #e53e3e; --paddle-color-status-error-bg: #fff5f5; --paddle-color-status-info: #4299e1; --paddle-color-status-info-bg: #ebf8ff; --paddle-color-status-neutral: #a0aec0; --paddle-color-status-neutral-bg: #f7fafc; / Active / Expiring Soon pill variants observed in dashboard screenshots / --paddle-color-status-expiring: #ed8936; --paddle-color-status-revoked: #718096;
/ --- Typography --- / --paddle-font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; --paddle-font-family-mono: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;
--paddle-font-size-xs: 0.75rem; / 12px / --paddle-font-size-sm: 0.875rem; / 14px / --paddle-font-size-base: 1rem; / 16px / --paddle-font-size-md: 1.125rem; / 18px / --paddle-font-size-lg: 1.25rem; / 20px / --paddle-font-size-xl: 1.5rem; / 24px / --paddle-font-size-2xl: 1.875rem; / 30px / --paddle-font-size-3xl: 2.25rem; / 36px / --paddle-font-size-4xl: 3rem; / 48px โ hero display /
--paddle-font-weight-regular: 400; --paddle-font-weight-medium: 500; --paddle-font-weight-semibold: 600; --paddle-font-weight-bold: 700;
--paddle-line-height-tight: 1.2; --paddle-line-height-snug: 1.375; --paddle-line-height-normal: 1.5; --paddle-line-height-relaxed: 1.625;
/ --- Spacing (4px base grid) --- / --paddle-space-1: 0.25rem; / 4px / --paddle-space-2: 0.5rem; / 8px / --paddle-space-3: 0.75rem; / 12px / --paddle-space-4: 1rem; / 16px / --paddle-space-5: 1.25rem; / 20px / --paddle-space-6: 1.5rem; / 24px / --paddle-space-8: 2rem; / 32px / --paddle-space-10: 2.5rem; / 40px / --paddle-space-12: 3rem; / 48px / --paddle-space-16: 4rem; / 64px / --paddle-space-20: 5rem; / 80px โ sticky top offset / --paddle-space-24: 6rem; / 96px / --paddle-space-30: 7.5rem; / 120px โ overlay padding /
/ --- Border Radius --- / --paddle-radius-sm: 4px; --paddle-radius-md: 8px; --paddle-radius-lg: 12px; --paddle-radius-xl: 16px; --paddle-radius-full: 9999px; / pills / badges /
/ --- Shadows --- / --paddle-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05); --paddle-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07), 0 1px 3px rgba(0, 0, 0, 0.06); --paddle-shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1), 0 4px 6px rgba(0, 0, 0, 0.05); --paddle-shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.1), 0 10px 10px rgba(0, 0, 0, 0.04); / Extended row background โ from eng blog source snippet / --row-background: transparent;
/ --- Transitions --- / --paddle-transition-fast: 100ms ease; --paddle-transition-base: 150ms ease; / used in table row hover (blog confirmed) / --paddle-transition-slow: 300ms ease;
/ --- Layout --- / --paddle-max-width-content: 1280px; --paddle-nav-height: 64px;
/ --- z-index scale --- / --paddle-z-base: 0; --paddle-z-above: 1; / pending overlay (blog confirmed) / --paddle-z-dropdown: 100; / portalled dropdowns / --paddle-z-modal: 200; --paddle-z-toast: 300; }
/ CSS @property for animatable gradient (from eng blog) /
@property --fade-color {
syntax: "
/ Dark mode โ nav/hero uses dark bg by default; dashboard sidebar is always dark / @media (prefers-color-scheme: dark) { :root { --paddle-color-background-page: #0f0f1a; --paddle-color-background-section-alt: #1a1a2e; --paddle-color-background-hover: #1e2030; --paddle-color-background-card: #16162a; --paddle-color-border-default: #2d3748; --paddle-color-border-subtle: #1a1a2e; --paddle-color-text-primary: #f7fafc; --paddle-color-text-secondary: #a0aec0; --paddle-color-text-tertiary: #718096; --paddle-color-background-overlay: rgba(15, 15, 26, 0.6); } }
Paddle Design Tokens Reference
Color Tokens
| Token | Value | Usage |
|---|---|---|
| --paddle-color-brand-primary | #1a1a2e | Nav, hero background |
| --paddle-color-brand-accent | #2ecc71 | Primary CTA, success, links |
| --paddle-color-brand-accent-hover | #27ae60 | CTA hover state |
| --paddle-color-background-page | #ffffff | Default page bg |
| --paddle-color-background-section-alt | #f7f8fa | Alternating sections |
| --paddle-color-background-hover | #f0f2f5 | Table row hover (confirmed in eng blog) |
| --paddle-color-background-dark | #0f0f1a | Hero / sidebar |
| --paddle-color-background-overlay | rgba(255,255,255,0.6) | Pending state overlay + blur |
| --paddle-color-text-primary | #0f0f1a | Headings, body |
| --paddle-color-text-secondary | #4a5568 | Labels, secondary copy |
| --paddle-color-text-inverse | #ffffff | Text on dark backgrounds |
| --paddle-color-text-destructive | #e53e3e | Destructive menu items |
| --paddle-color-border-default | #e2e8f0 | Card edges, dividers |
| --paddle-color-status-success | #2ecc71 | Active badge |
| --paddle-color-status-warning | #f6ad55 | Expiring Soon badge |
| --paddle-color-status-error | #e53e3e | Error / failed payment |
| --paddle-color-status-revoked | #718096 | Revoked / disabled state |
Spacing Scale (4px base grid)
| Token | rem | px | Usage |
|---|---|---|---|
| --paddle-space-1 | 0.25rem | 4px | Micro gaps |
| --paddle-space-2 | 0.5rem | 8px | Icon padding |
| --paddle-space-3 | 0.75rem | 12px | Compact padding |
| --paddle-space-4 | 1rem | 16px | Default padding |
| --paddle-space-6 | 1.5rem | 24px | Card inner padding |
| --paddle-space-8 | 2rem | 32px | Section gaps |
| --paddle-space-12 | 3rem | 48px | Large section padding |
| --paddle-space-16 | 4rem | 64px | XL section gaps |
| --paddle-space-20 | 5rem | 80px | Sticky offset (spinner top) |
| --paddle-space-30 | 7.5rem | 120px | Overlay push-down |
Typography Scale
| Token | Value | Usage |
|---|---|---|
| --paddle-font-size-xs | 0.75rem / 12px | Meta, captions |
| --paddle-font-size-sm | 0.875rem / 14px | Table cells, secondary |
| --paddle-font-size-base | 1rem / 16px | Body copy |
| --paddle-font-size-lg | 1.25rem / 20px | Card headings |
| --paddle-font-size-xl | 1.5rem / 24px | Section subheadings |
| --paddle-font-size-2xl | 1.875rem / 30px | H3 / feature titles |
| --paddle-font-size-3xl | 2.25rem / 36px | H2 section headings |
| --paddle-font-size-4xl | 3rem / 48px | H1 hero display |
| --paddle-font-weight-regular | 400 | Body |
| --paddle-font-weight-semibold | 600 | Labels, nav items |
| --paddle-font-weight-bold | 700 | Headings, CTAs |
| --paddle-line-height-normal | 1.5 | Body paragraphs |
| --paddle-line-height-tight | 1.2 | Display headings |
| --paddle-font-family-base | system-ui / sans-serif stack | All UI text |
| --paddle-font-family-mono | JetBrains Mono / Fira Code | Code, API keys |
Border Radius
| Token | Value | Usage |
|---|---|---|
| --paddle-radius-sm | 4px | Input fields, small chips |
| --paddle-radius-md | 8px | Cards, dropdowns |
| --paddle-radius-lg | 12px | Large cards, modals |
| --paddle-radius-xl | 16px | Feature panels |
| --paddle-radius-full | 9999px | Status pills / badges |
Shadows
| Token | Value | Usage |
|---|---|---|
| --paddle-shadow-sm | 0 1px 2px rgba(0,0,0,0.05) | Subtle card lift |
| --paddle-shadow-md | 0 4px 6px rgba(0,0,0,0.07) | Dropdowns, card hover |
| --paddle-shadow-lg | 0 10px 15px rgba(0,0,0,0.1) | Modals, overlays |
| --paddle-shadow-xl | 0 20px 25px rgba(0,0,0,0.1) | Full-screen drawers |
Transition Tokens
| Token | Value | Usage |
|---|---|---|
| --paddle-transition-fast | 100ms ease | Micro interactions |
| --paddle-transition-base | 150ms ease | Row hover, button states (confirmed) |
| --paddle-transition-slow | 300ms ease | Modal open/close |
Paddle Design Notes
Framework \- Marketing site: Next.js (React, App Router) โ confirmed via \_next/static paths and meta-next-size-adjust tag \- Engineering blog: Astro v6.4.8 โ confirmed via meta-generator \- CMS: Prismic โ all editorial images served from images.prismic.io and paddle.cdn.prismic.io \- Dashboard/app: React + React Aria as the component foundation โ explicitly stated in the Mar 2026 design system engineering post
Theme Support \- Dual-mode confirmed: Two logo SVG variants exist (paddle-logo.svg for light, paddle-logo-inverted.svg for dark/inverted nav) \- The marketing site uses a dark inverted nav bar over white page content โ not a full dark mode toggle, but the dashboard (Paddle Billing) likely supports dark mode via design system tokens \- CSS @property is actively used for animatable gradient custom properties, suggesting a modern CSS baseline (Chrome 85+, Safari 15.4+)
Data Source Confidence \- High confidence: Color philosophy (dark navy + green accent), component architecture (React Aria, compositional tables), spacing offsets (80px, 120px sticky/overlay values), transition duration (150ms), overlay backdrop-filter blur, status pill variants (Active/Expiring Soon/Revoked) โ all confirmed from the engineering blog source code snippets \- Medium confidence: Exact font family (no found; likely system font stack or self-hosted), specific hex values for green accent and navy (inferred from visual brand analysis) \- Inferred: Border radius scale, shadow scale, full spacing system โ derived from design patterns observed in screenshots and standard Next.js SaaS conventions
Notable Patterns \- Composition over configuration: Tables (and likely all components) use a composable sub-component API rather than props-heavy monolithic components โ mirrors Radix UI / shadcn/ui patterns \- CSS-first approach: Team explicitly prefers pure CSS over JavaScript for animations and layout (row hover extended backgrounds use box-shadow + clip-path trick; loading spinner uses position: sticky; gradient animation uses @property). Performance justification: CSS runs on GPU vs JS on CPU \- React Portals for z-index avoidance: Dropdowns and overlays are portalled to DOM root to avoid z-index escalation wars โ clean stacking context architecture \- Cursor-based pagination: Matches the public Paddle API โ the team eats their own dog food (dashboard uses the same API customers use) \- Platform-native interaction model: Trackpad momentum, mouse wheel, touch flick, and keyboard nav all handled via React Aria with zero custom reimplementation \- Accessibility-first: React Aria chosen explicitly for WCAG-compliant table navigation (20+ keyboard shortcuts, screen reader modes, focus management) \- URL-driven state: Pagination writes to URL params, enabling deep-linking and tab sharing across team members