Files
OTSSignsTheme/DESIGN_SYSTEM.md
Matt Batchelder efe206a589 init
2026-02-04 06:23:04 -05:00

10 KiB
Raw Blame History

Design System Reference Card

A quick visual and technical reference for the OTS Signage Modern Theme.

🎨 Color Palette

Brand Colors

--color-primary       #2563eb  ████████████ Blue
--color-primary-dark  #1d4ed8  ██████████ Darker Blue
--color-primary-light #3b82f6  ██████████████ Lighter Blue
--color-secondary     #7c3aed  ████████████ Purple

Status Colors

--color-success       #10b981  ██████████ Green
--color-warning       #f59e0b  ██████████ Amber
--color-danger        #ef4444  ██████████ Red
--color-info          #0ea5e9  ██████████ Cyan

Gray Scale (Neutral)

Level  Color         Hex      Usage
50     Very Light    #f9fafb  Backgrounds, light surfaces
100    Light         #f3f4f6  Hover states, borders
200    Light Gray    #e5e7eb  Borders, dividers
300    Gray          #d1d5db  Form inputs, disabled
400    Gray          #9ca3af  Placeholder text
500    Medium Gray   #6b7280  Secondary text
600    Dark Gray     #4b5563  Body text, labels
700    Darker Gray   #374151  Headings
800    Very Dark     #1f2937  Primary text
900    Darkest       #111827  High contrast text

Semantic Colors

--color-background       #ffffff (dark: #0f172a)
--color-surface          #f9fafb (dark: #1e293b)
--color-surface-elevated #ffffff (dark: #334155)
--color-text-primary     #1f2937 (dark: #f1f5f9)
--color-text-secondary   #6b7280 (dark: #cbd5e1)
--color-text-tertiary    #9ca3af (dark: #94a3b8)
--color-border           #e5e7eb (dark: #475569)

📝 Typography Scale

Font Family

--font-family-base: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif
--font-family-mono: "SF Mono", Monaco, "Cascadia Code", "Roboto Mono", Menlo, Courier, monospace

Font Sizes

Size           Pixels  Usage
--font-size-xs   12px  Small labels, badges, captions
--font-size-sm   14px  Form hints, table cells, small text
--font-size-base 16px  Body text, default size
--font-size-lg   18px  Subheadings, callouts
--font-size-xl   20px  Section headings
--font-size-2xl  24px  Page headings
--font-size-3xl  30px  Large headings
--font-size-4xl  36px  Main titles

Font Weights

Weight               Value  Usage
--font-weight-normal   400  Body text, regular content
--font-weight-medium   500  Form labels, emphasis
--font-weight-semibold 600  Headings, strong emphasis
--font-weight-bold     700  Major headings, highlights

Line Heights

Height                 Value  Usage
--line-height-tight     1.25  Tight headings
--line-height-snug      1.375 Subheadings
--line-height-normal    1.5   Default, body text
--line-height-relaxed   1.625 Large text blocks
--line-height-loose     2     Extra spacing

📏 Spacing Scale (8px base unit)

Token    Pixels  CSS Rem
--space-1   4px   0.25rem  Tightest spacing
--space-2   8px   0.5rem   Small padding
--space-3  12px   0.75rem  Medium-small
--space-4  16px   1rem     Standard padding
--space-5  20px   1.25rem  Medium spacing
--space-6  24px   1.5rem   Default margins
--space-7  28px   1.75rem  Large spacing
--space-8  32px   2rem     Section spacing
--space-10 40px   2.5rem   Large spacing
--space-12 48px   3rem     Very large
--space-16 64px   4rem     Extra large
--space-20 80px   5rem     Massive spacing

Usage Example:

.widget {
  padding: var(--space-6);           /* 24px all sides */
  margin-bottom: var(--space-8);     /* 32px below */
  gap: var(--space-4);               /* 16px between items */
}

🎭 Shadows (Elevation System)

Level   Shadow                                                    Usage
none    none                                                      No elevation
xs      0 1px 2px 0 rgba(0, 0, 0, 0.05)                          Subtle depth
sm      0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 ...         Small cards
base    0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px ...   Default cards
md      0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px ... Medium elevation
lg      0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px ...    Large hover
xl      0 25px 50px -12px rgba(0, 0, 0, 0.25)                   Maximum depth

🔲 Border Radius

Token           Pixels  Usage
--radius-none    0px    Sharp corners
--radius-sm      4px    Minimal rounding
--radius-base    6px    Default input fields
--radius-md      8px    Standard components
--radius-lg     12px    Cards, modals
--radius-xl     16px    Large containers
--radius-2xl    24px    Extra rounded
--radius-full   9999px  Fully rounded (pills, circles)

Transitions

Token               Duration  Easing         Usage
--transition-fast   150ms     ease-in-out    Hover, quick interactions
--transition-base   200ms     ease-in-out    Default, UI changes
--transition-slow   300ms     ease-in-out    Page transitions, major changes

Usage:

a {
  transition: color var(--transition-fast);
}

.widget {
  transition: box-shadow var(--transition-base), transform var(--transition-base);
}

📱 Responsive Breakpoints

Name    Width  Use Case
sm      640px  Mobile phones (landscape)
md      768px  Tablets
lg      1024px Desktop screens
xl      1280px Large desktops
2xl     1536px Ultra-wide displays

Usage Pattern (Mobile-First):

/* Mobile first (default) */
.widget {
  grid-template-columns: 1fr;
}

/* Tablets and up */
@media (min-width: 768px) {
  .widget {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* Desktops and up */
@media (min-width: 1024px) {
  .widget {
    grid-template-columns: repeat(3, 1fr);
  }
}

🎯 Component Reference

Buttons

.btn {
  padding: var(--space-3) var(--space-4);     /* 12px × 16px */
  border-radius: var(--radius-md);            /* 8px */
  font-weight: var(--font-weight-medium);     /* 500 */
  font-size: var(--font-size-base);           /* 16px */
}

.btn-primary {
  background: var(--color-primary);           /* #2563eb */
  color: var(--color-text-inverse);           /* White */
}

.btn-primary:hover {
  background: var(--color-primary-dark);      /* #1d4ed8 */
}

Form Inputs

input, textarea, select {
  background: var(--color-background);        /* #ffffff */
  border: 1px solid var(--color-border);      /* #e5e7eb */
  border-radius: var(--radius-md);            /* 8px */
  padding: var(--space-3) var(--space-4);     /* 12px × 16px */
  font-size: var(--font-size-base);           /* 16px */
}

input:focus {
  border-color: var(--color-primary);         /* #2563eb */
  box-shadow: 0 0 0 3px var(--color-primary-lighter);
}

Cards/Widgets

.widget {
  background: var(--color-surface-elevated);  /* #ffffff */
  border: 1px solid var(--color-border);      /* #e5e7eb */
  border-radius: var(--radius-lg);            /* 12px */
  box-shadow: var(--shadow-sm);               /* Subtle depth */
  padding: var(--space-6);                    /* 24px */
}

.widget:hover {
  box-shadow: var(--shadow-base);             /* More elevation */
  transform: translateY(-1px);                /* Slight lift */
}

Alerts

.alert {
  border-radius: var(--radius-md);            /* 8px */
  padding: var(--space-4) var(--space-6);     /* 16px × 24px */
  border-left: 4px solid var(--color-success);
}

🌙 Dark Mode

All colors automatically switch when prefers-color-scheme: dark is detected:

@media (prefers-color-scheme: dark) {
  :root {
    --color-background: #0f172a;              /* Deep navy */
    --color-surface: #1e293b;                 /* Slate */
    --color-text-primary: #f1f5f9;            /* Near white */
    /* ... other dark mode overrides ... */
  }
}

Test in Browser DevTools:

  1. F12 (Open DevTools)
  2. Ctrl+Shift+P (Search in Chrome)
  3. Type "rendering"
  4. Toggle "Prefers color scheme" to dark
  5. Page updates instantly

Accessibility

Color Contrast

Element                 Ratio   WCAG Level
Primary text on white   7:1     AAA
Secondary text on white 4.5:1   AA
Links on white          5:1     AA
Buttons                 4.5:1   AA

Focus Indicators

*:focus-visible {
  outline: 2px solid var(--color-primary);   /* #2563eb */
  outline-offset: 2px;
}

Keyboard Navigation

  • All interactive elements are tab-accessible
  • Logical tab order maintained
  • No keyboard traps
  • Focus always visible

🔧 Using CSS Variables

Override in Your Code

/* In your custom CSS, you can override tokens: */
:root {
  --color-primary: #006bb3;  /* Your brand blue */
  --font-size-base: 18px;    /* Larger default text */
}

/* All components using tokens will update automatically */

Reference in Components

.my-component {
  background: var(--color-surface);
  color: var(--color-text-primary);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-base);
}

With Fallbacks (IE11 compat, optional)

.my-component {
  background: #f9fafb;                        /* Fallback */
  background: var(--color-surface);           /* Modern */
  
  color: #1f2937;                             /* Fallback */
  color: var(--color-text-primary);           /* Modern */
}

📊 Quick Lookup Table

Need Variable Value
Brand color --color-primary #2563eb
Button padding --space-3 + --space-4 12px × 16px
Card shadow --shadow-base 4px 6px -1px rgba...
Body text --font-size-base 16px
Heading --font-size-2xl 24px
Default spacing --space-6 24px
Card radius --radius-lg 12px
Focus outline --color-primary #2563eb
Dark background --color-surface (dark mode) #1e293b

🎓 Pro Tips

  1. Always use variables — Don't hardcode colors or sizes
  2. Spacing is 8px-based — Use --space-* for consistency
  3. Test dark mode — Use DevTools (see above)
  4. Mobile-first queries — Styles default to mobile, expand on larger screens
  5. Focus states matter — Never remove outline without adding alternative
  6. Semantic colors — Use --color-surface instead of hardcoding #ffffff

Last Updated: February 2026
Theme Version: 1.0.0 (Modern)
Xibo Compatibility: 3.x+