Skip to content

Design System

The SUDIGITAL Design System provides a comprehensive foundation for building consistent, accessible, and beautiful user interfaces across all platform applications.

Overview

Our design system is built on the principles of simplicity, consistency, and scalability. It provides a unified language and shared components that enable teams to build products faster while maintaining high quality and coherent user experiences.

Philosophy

Design Principles

  1. Simplicity First

    • Remove complexity wherever possible
    • Focus on essential features and interactions
    • Provide clear visual hierarchy and information architecture
  2. Consistency Everywhere

    • Unified patterns across all touchpoints
    • Predictable behaviors and interactions
    • Standardized visual language and terminology
  3. Accessibility by Default

    • WCAG 2.1 AA compliance as a baseline
    • Inclusive design for all users and abilities
    • Keyboard navigation and screen reader support
  4. Performance Minded

    • Optimized assets and efficient rendering
    • Progressive enhancement strategies
    • Mobile-first responsive implementations

Design Tokens

Design tokens are the foundational elements that define the visual characteristics of our design system. They ensure consistency across all platforms and make it easy to maintain and evolve our design language.

Color Palette

Primary Colors

css
:root {
  /* Primary Brand Colors */
  --color-primary-50: #f0f9ff;
  --color-primary-100: #e0f2fe;
  --color-primary-200: #bae6fd;
  --color-primary-300: #7dd3fc;
  --color-primary-400: #38bdf8;
  --color-primary-500: #0ea5e9;
  --color-primary-600: #0284c7;
  --color-primary-700: #0369a1;
  --color-primary-800: #075985;
  --color-primary-900: #0c4a6e;
}

Semantic Colors

css
:root {
  /* Success */
  --color-success-50: #f0fdf4;
  --color-success-500: #22c55e;
  --color-success-600: #16a34a;

  /* Warning */
  --color-warning-50: #fffbeb;
  --color-warning-500: #f59e0b;
  --color-warning-600: #d97706;

  /* Error */
  --color-error-50: #fef2f2;
  --color-error-500: #ef4444;
  --color-error-600: #dc2626;

  /* Info */
  --color-info-50: #f0f9ff;
  --color-info-500: #3b82f6;
  --color-info-600: #2563eb;
}

Neutral Colors

css
:root {
  /* Grays */
  --color-gray-50: #f9fafb;
  --color-gray-100: #f3f4f6;
  --color-gray-200: #e5e7eb;
  --color-gray-300: #d1d5db;
  --color-gray-400: #9ca3af;
  --color-gray-500: #6b7280;
  --color-gray-600: #4b5563;
  --color-gray-700: #374151;
  --color-gray-800: #1f2937;
  --color-gray-900: #111827;
}

Typography

Font Families

css
:root {
  --font-family-sans: 'Inter', system-ui, -apple-system, sans-serif;
  --font-family-mono: 'JetBrains Mono', 'Fira Code', monospace;
  --font-family-display: 'Inter Display', system-ui, sans-serif;
}

Font Sizes

css
:root {
  /* Text Sizes */
  --text-xs: 0.75rem; /* 12px */
  --text-sm: 0.875rem; /* 14px */
  --text-base: 1rem; /* 16px */
  --text-lg: 1.125rem; /* 18px */
  --text-xl: 1.25rem; /* 20px */
  --text-2xl: 1.5rem; /* 24px */
  --text-3xl: 1.875rem; /* 30px */
  --text-4xl: 2.25rem; /* 36px */
  --text-5xl: 3rem; /* 48px */
  --text-6xl: 3.75rem; /* 60px */
}

Font Weights

css
:root {
  --font-weight-thin: 100;
  --font-weight-light: 300;
  --font-weight-normal: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;
  --font-weight-extrabold: 800;
}

Line Heights

css
:root {
  --line-height-none: 1;
  --line-height-tight: 1.25;
  --line-height-snug: 1.375;
  --line-height-normal: 1.5;
  --line-height-relaxed: 1.625;
  --line-height-loose: 2;
}

Spacing

css
:root {
  /* Spacing Scale */
  --space-0: 0;
  --space-1: 0.25rem; /* 4px */
  --space-2: 0.5rem; /* 8px */
  --space-3: 0.75rem; /* 12px */
  --space-4: 1rem; /* 16px */
  --space-5: 1.25rem; /* 20px */
  --space-6: 1.5rem; /* 24px */
  --space-8: 2rem; /* 32px */
  --space-10: 2.5rem; /* 40px */
  --space-12: 3rem; /* 48px */
  --space-16: 4rem; /* 64px */
  --space-20: 5rem; /* 80px */
  --space-24: 6rem; /* 96px */
  --space-32: 8rem; /* 128px */
}

Border Radius

css
:root {
  --radius-none: 0;
  --radius-sm: 0.125rem; /* 2px */
  --radius-default: 0.25rem; /* 4px */
  --radius-md: 0.375rem; /* 6px */
  --radius-lg: 0.5rem; /* 8px */
  --radius-xl: 0.75rem; /* 12px */
  --radius-2xl: 1rem; /* 16px */
  --radius-3xl: 1.5rem; /* 24px */
  --radius-full: 9999px;
}

Shadows

css
:root {
  /* Elevation Shadows */
  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --shadow-default:
    0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
  --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  --shadow-lg:
    0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
  --shadow-xl:
    0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
  --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
  --shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05);
}

Component Architecture

Component Categories

1. Foundation Components

  • Typography - Headings, body text, captions
  • Colors - Palettes, swatches, semantic colors
  • Icons - Icon library and usage guidelines
  • Spacing - Margin, padding, and layout utilities

2. Basic Components

  • Button - Primary, secondary, text, icon buttons
  • Input - Text fields, textareas, search inputs
  • Select - Dropdowns, multi-select, autocomplete
  • Checkbox - Single and group checkboxes
  • Radio - Radio buttons and radio groups
  • Switch - Toggle switches and controls

3. Composite Components

  • Form - Complete form layouts and validation
  • Card - Content containers with various layouts
  • Modal - Dialogs, alerts, and overlays
  • Navigation - Headers, sidebars, breadcrumbs
  • Table - Data tables with sorting and filtering
  • Pagination - Page navigation controls

4. Layout Components

  • Container - Page and section containers
  • Grid - Responsive grid systems
  • Stack - Vertical and horizontal stacking
  • Divider - Section separators and spacing
  • Spacer - Flexible spacing utilities

Component Naming Convention

typescript
// Component naming follows PascalCase
export const Button: React.FC<ButtonProps> = ({ ... }) => { ... }
export const FormField: React.FC<FormFieldProps> = ({ ... }) => { ... }
export const DataTable: React.FC<DataTableProps> = ({ ... }) => { ... }

// Props interfaces follow ComponentNameProps pattern
interface ButtonProps {
  variant: 'primary' | 'secondary' | 'outline' | 'ghost';
  size: 'sm' | 'md' | 'lg';
  disabled?: boolean;
  loading?: boolean;
  children: React.ReactNode;
  onClick?: () => void;
}

Component Variants

Each component supports multiple variants to handle different use cases:

typescript
// Size variants
type ComponentSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'

// Color variants
type ComponentVariant =
  | 'primary'
  | 'secondary'
  | 'success'
  | 'warning'
  | 'error'

// State variants
type ComponentState = 'default' | 'hover' | 'active' | 'focus' | 'disabled'

Layout System

Responsive Breakpoints

css
:root {
  /* Breakpoints */
  --breakpoint-xs: 0px;
  --breakpoint-sm: 640px;
  --breakpoint-md: 768px;
  --breakpoint-lg: 1024px;
  --breakpoint-xl: 1280px;
  --breakpoint-2xl: 1536px;
}

Grid System

css
.grid {
  display: grid;
  gap: var(--space-4);
}

.grid-cols-1 {
  grid-template-columns: repeat(1, minmax(0, 1fr));
}
.grid-cols-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid-cols-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.grid-cols-4 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.grid-cols-12 {
  grid-template-columns: repeat(12, minmax(0, 1fr));
}

/* Responsive grid */
@media (min-width: 768px) {
  .md\:grid-cols-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .md\:grid-cols-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

Container System

css
.container {
  width: 100%;
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--space-4);
  padding-right: var(--space-4);
}

@media (min-width: 640px) {
  .container {
    max-width: 640px;
  }
}

@media (min-width: 768px) {
  .container {
    max-width: 768px;
  }
}

@media (min-width: 1024px) {
  .container {
    max-width: 1024px;
  }
}

@media (min-width: 1280px) {
  .container {
    max-width: 1280px;
  }
}

Iconography

Icon Library

We use a curated set of icons from Heroicons and custom SUDIGITAL icons.

Icon Sizes

css
.icon-xs {
  width: 12px;
  height: 12px;
}
.icon-sm {
  width: 16px;
  height: 16px;
}
.icon-md {
  width: 20px;
  height: 20px;
}
.icon-lg {
  width: 24px;
  height: 24px;
}
.icon-xl {
  width: 32px;
  height: 32px;
}

Icon Usage

typescript
import { ChevronDownIcon, UserIcon, CogIcon } from '@heroicons/react/24/outline';
import { HeartIcon } from '@heroicons/react/24/solid';

// Icon component with consistent sizing
const Icon: React.FC<IconProps> = ({
  icon: IconComponent,
  size = 'md',
  className
}) => (
  <IconComponent
    className={`icon-${size} ${className}`}
    aria-hidden="true"
  />
);

Accessibility

WCAG 2.1 AA Compliance

All components meet WCAG 2.1 AA accessibility standards:

  1. Color Contrast

    • Minimum 4.5:1 ratio for normal text
    • Minimum 3:1 ratio for large text
    • Minimum 3:1 ratio for UI components
  2. Keyboard Navigation

    • All interactive elements are keyboard accessible
    • Logical tab order and focus management
    • Custom components support arrow key navigation
  3. Screen Reader Support

    • Semantic HTML elements
    • Proper ARIA labels and descriptions
    • Screen reader testing with VoiceOver and NVDA
  4. Focus Management

    • Visible focus indicators
    • Focus trapping in modals
    • Skip links for main content

Accessibility Guidelines

typescript
// Always include proper ARIA attributes
<button
  aria-label="Close dialog"
  aria-expanded={isOpen}
  aria-controls="dialog-content"
  onClick={onClose}
>
  <CloseIcon aria-hidden="true" />
</button>

// Use semantic HTML elements
<nav aria-label="Main navigation">
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/about">About</a></li>
  </ul>
</nav>

// Provide alternative text for images
<img
  src="chart.png"
  alt="Revenue growth chart showing 25% increase over last quarter"
/>

Animation & Motion

Motion Principles

  1. Purposeful - Every animation should have a clear purpose
  2. Performant - Use transform and opacity for smooth animations
  3. Respectful - Honor user preferences for reduced motion
  4. Subtle - Avoid distracting or excessive animations

Animation Tokens

css
:root {
  /* Duration */
  --duration-fast: 150ms;
  --duration-normal: 300ms;
  --duration-slow: 500ms;

  /* Easing */
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
  --ease-out: cubic-bezier(0, 0, 0.2, 1);
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
}

Common Animations

css
/* Fade transitions */
.fade-enter {
  opacity: 0;
  transform: translateY(8px);
}

.fade-enter-active {
  opacity: 1;
  transform: translateY(0);
  transition:
    opacity var(--duration-normal) var(--ease-out),
    transform var(--duration-normal) var(--ease-out);
}

/* Slide transitions */
.slide-enter {
  transform: translateX(-100%);
}

.slide-enter-active {
  transform: translateX(0);
  transition: transform var(--duration-normal) var(--ease-out);
}

/* Respect reduced motion preferences */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Implementation Guidelines

CSS Architecture

scss
// 1. Design tokens (variables)
@import 'tokens/colors';
@import 'tokens/typography';
@import 'tokens/spacing';

// 2. Base styles
@import 'base/reset';
@import 'base/typography';

// 3. Layout utilities
@import 'layout/container';
@import 'layout/grid';

// 4. Components
@import 'components/button';
@import 'components/form';
@import 'components/card';

// 5. Utilities
@import 'utilities/spacing';
@import 'utilities/colors';

Component Development

typescript
// Use TypeScript for all components
interface ButtonProps {
  variant?: 'primary' | 'secondary' | 'outline' | 'ghost';
  size?: 'sm' | 'md' | 'lg';
  disabled?: boolean;
  loading?: boolean;
  children: React.ReactNode;
  className?: string;
  onClick?: () => void;
}

export const Button: React.FC<ButtonProps> = ({
  variant = 'primary',
  size = 'md',
  disabled = false,
  loading = false,
  children,
  className = '',
  onClick,
  ...rest
}) => {
  const baseClasses = 'btn';
  const variantClasses = `btn--${variant}`;
  const sizeClasses = `btn--${size}`;
  const stateClasses = {
    'btn--disabled': disabled,
    'btn--loading': loading,
  };

  const classes = clsx(
    baseClasses,
    variantClasses,
    sizeClasses,
    stateClasses,
    className
  );

  return (
    <button
      className={classes}
      disabled={disabled || loading}
      onClick={onClick}
      aria-disabled={disabled || loading}
      {...rest}
    >
      {loading && <Spinner size="sm" />}
      {children}
    </button>
  );
};

Testing Components

typescript
import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from './Button';

describe('Button', () => {
  test('renders with correct text', () => {
    render(<Button>Click me</Button>);
    expect(screen.getByText('Click me')).toBeInTheDocument();
  });

  test('calls onClick when clicked', () => {
    const handleClick = jest.fn();
    render(<Button onClick={handleClick}>Click me</Button>);

    fireEvent.click(screen.getByRole('button'));
    expect(handleClick).toHaveBeenCalledTimes(1);
  });

  test('is disabled when loading', () => {
    render(<Button loading>Click me</Button>);
    expect(screen.getByRole('button')).toBeDisabled();
  });

  test('has correct accessibility attributes', () => {
    render(<Button disabled>Click me</Button>);
    expect(screen.getByRole('button')).toHaveAttribute('aria-disabled', 'true');
  });
});

Tools & Resources

Development Tools

  • Storybook - Component development and documentation
  • Figma - Design files and component specifications
  • VS Code Extensions - Snippets and IntelliSense support
  • ESLint/Prettier - Code formatting and best practices

Browser Support

BrowserVersion
ChromeLatest 2 versions
FirefoxLatest 2 versions
SafariLatest 2 versions
EdgeLatest 2 versions

Performance Targets

  • First Contentful Paint: < 1.5s
  • Largest Contentful Paint: < 2.5s
  • Cumulative Layout Shift: < 0.1
  • First Input Delay: < 100ms

Getting Started

Installation

bash
# Install the design system package
bun add @sudigital/design-system

# Install peer dependencies
bun add react react-dom

Basic Usage

typescript
import '@sudigital/design-system/styles.css';
import { Button, Card, Text } from '@sudigital/design-system';

function App() {
  return (
    <Card>
      <Text variant="h2">Welcome to SUDIGITAL</Text>
      <Button variant="primary" size="lg">
        Get Started
      </Button>
    </Card>
  );
}

Customization

css
/* Override design tokens */
:root {
  --color-primary-500: #your-brand-color;
  --font-family-sans: 'Your Custom Font', sans-serif;
}