Skip to content

Accessibility

Accessibility is built into every decision in NS-OG 2.0. Nova Suite is designed to be usable by everyone, regardless of ability, device, or context. This page outlines our accessibility standards and implementation guidelines.

Core Principles

1. Perceivable

Information and user interface components must be presentable to users in ways they can perceive.

2. Operable

User interface components and navigation must be operable by everyone.

3. Understandable

Information and the operation of the user interface must be understandable.

4. Robust

Content must be robust enough to be interpreted by a wide variety of user agents, including assistive technologies.

Standards Compliance

Nova Suite adheres to:

  • WCAG 2.1 Level AA (minimum standard)
  • WCAG 2.2 Level AAA (where feasible)
  • Section 508 compliance
  • ARIA 1.2 specifications

Color & Contrast

Contrast Ratios

All text and interactive elements meet or exceed WCAG requirements:

Element Type Minimum Ratio Our Standard
Normal text (< 18px) 4.5:1 7:1
Large text (≥ 18px) 3:1 4.5:1
UI components 3:1 4.5:1
Graphics 3:1 4.5:1

Color Palette Accessibility

Orbit 2.0 colors are designed for maximum contrast:

/* Light mode - High contrast */
--text-primary: #1a1a1a;     /* 16:1 on white */
--text-secondary: #4a5568;   /* 7.2:1 on white */
--text-tertiary: #718096;    /* 4.8:1 on white */

/* Dark mode - High contrast */
--text-primary-dark: #f7fafc;     /* 18:1 on dark bg */
--text-secondary-dark: #cbd5e0;   /* 10:1 on dark bg */
--text-tertiary-dark: #a0aec0;    /* 6.5:1 on dark bg */

Testing Contrast

Use these tools to verify contrast:

Color Independence

Never rely on color alone to convey information:

<div class="alert alert-success">
  <svg class="icon-check">...</svg>
  <span>✓ Success: Your changes have been saved</span>
</div>
<div class="alert" style="background: green;">
  <span>Your changes have been saved</span>
</div>

Focus Management

Visible Focus Indicators

All interactive elements have clear focus states:

/* Default focus style */
*:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Custom focus for buttons */
.button:focus-visible {
  outline: 3px solid var(--primary);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.2);
}

Focus ring colors: - Light mode: #6366f1 (Indigo) - Dark mode: #818cf8 (Lighter indigo) - Contrast: Always 3:1 minimum against background

Focus Order

Ensure logical tab order matches visual layout:

<!-- Correct tab order -->
<form>
  <input type="text" tabindex="1" />  <!-- First -->
  <input type="email" tabindex="2" /> <!-- Second -->
  <button tabindex="3">Submit</button> <!-- Third -->
</form>

Best practices: - Don't use positive tabindex values unnecessarily - Use tabindex="0" to make custom elements focusable - Use tabindex="-1" to remove elements from tab order - Test keyboard navigation thoroughly

Provide skip navigation for keyboard users:

<a href="#main-content" class="skip-link">
  Skip to main content
</a>

<main id="main-content">
  <!-- Page content -->
</main>
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  background: var(--primary);
  color: white;
  padding: 8px;
  z-index: 1000;
}

.skip-link:focus {
  top: 0;
}

Interactive Elements

Touch Targets

Minimum size for all interactive elements:

/* Minimum 44×44px per WCAG 2.1 */
.button,
.link-interactive,
.checkbox,
.radio,
.toggle {
  min-width: 44px;
  min-height: 44px;
}

/* If visual size is smaller, use padding */
.icon-button {
  width: 24px;  /* Visual size */
  height: 24px;
  padding: 10px;  /* Total: 44px */
}

Target spacing: - Minimum 8px spacing between interactive elements - 16px recommended for complex interfaces

Button States

Provide clear visual feedback for all states:

.button {
  /* Default state */
  background: var(--primary);
  color: white;

  /* Hover state */
  &:hover {
    background: var(--primary-hover);
    transform: translateY(-1px);
  }

  /* Focus state */
  &:focus-visible {
    outline: 3px solid var(--focus-ring);
    outline-offset: 2px;
  }

  /* Active state */
  &:active {
    transform: translateY(0);
  }

  /* Disabled state */
  &:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
}

Semantic HTML

Use Proper Elements

<!-- ✅ Good: Semantic HTML -->
<nav aria-label="Main navigation">
  <ul>
    <li><a href="/home">Home</a></li>
    <li><a href="/about">About</a></li>
  </ul>
</nav>

<main>
  <article>
    <h1>Page Title</h1>
    <section>
      <h2>Section Heading</h2>
      <p>Content...</p>
    </section>
  </article>
</main>

<!-- ❌ Bad: Div soup -->
<div class="nav">
  <div class="link">Home</div>
  <div class="link">About</div>
</div>

<div class="main">
  <div class="title">Page Title</div>
  <div class="text">Content...</div>
</div>

Heading Hierarchy

Maintain logical heading structure:

<h1>Page Title</h1>          <!-- Only one H1 per page -->
  <h2>Major Section</h2>
    <h3>Subsection</h3>
    <h3>Another Subsection</h3>
  <h2>Another Major Section</h2>
    <h3>Subsection</h3>

Don't skip levels:

<!-- ❌ Bad: Skips H2 -->
<h1>Title</h1>
<h3>Subsection</h3>

<!-- ✅ Good: Proper hierarchy -->
<h1>Title</h1>
<h2>Section</h2>
<h3>Subsection</h3>

ARIA Implementation

ARIA Roles

Use ARIA roles to enhance semantic meaning:

<!-- Navigation -->
<nav role="navigation" aria-label="Main navigation">
  <ul role="list">
    <li role="listitem"><a href="/">Home</a></li>
  </ul>
</nav>

<!-- Search -->
<div role="search">
  <label for="search-input">Search</label>
  <input id="search-input" type="search" aria-label="Search documentation" />
</div>

<!-- Alert -->
<div role="alert" aria-live="polite">
  Your changes have been saved.
</div>

ARIA Labels

Provide descriptive labels for all interactive elements:

<!-- Icon buttons need labels -->
<button aria-label="Close dialog">
  <svg class="icon-close">...</svg>
</button>

<!-- Expandable sections -->
<button
  aria-expanded="false"
  aria-controls="section-content"
  aria-label="Expand section">
  Show more
</button>

<div id="section-content" hidden>
  <!-- Content -->
</div>

ARIA Live Regions

Announce dynamic content changes:

<!-- Polite: Announces when user is idle -->
<div aria-live="polite" aria-atomic="true">
  <p>3 new messages</p>
</div>

<!-- Assertive: Announces immediately -->
<div aria-live="assertive" role="alert">
  <p>Error: Form submission failed</p>
</div>

Screen Reader Support

Descriptive Text

Provide context for screen reader users:

<!-- Link text should be descriptive -->
<!-- ✅ Good -->
<a href="/docs">Read the documentation</a>

<!-- ❌ Bad -->
<a href="/docs">Click here</a>

<!-- Images need alt text -->
<img src="chart.png" alt="Sales increased 23% in Q4 2024" />

<!-- Decorative images -->
<img src="decoration.png" alt="" role="presentation" />

Visually Hidden Content

Provide additional context for screen readers:

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}
<button>
  <svg class="icon-trash">...</svg>
  <span class="sr-only">Delete item</span>
</button>

Forms & Inputs

Labels & Instructions

All inputs must have associated labels:

<!-- ✅ Explicit label -->
<label for="email">Email Address</label>
<input id="email" type="email" required />

<!-- ✅ Implicit label -->
<label>
  Email Address
  <input type="email" required />
</label>

<!-- ✅ With help text -->
<label for="password">Password</label>
<input
  id="password"
  type="password"
  aria-describedby="password-help"
  required
/>
<p id="password-help">Must be at least 8 characters</p>

Error Handling

Provide clear, accessible error messages:

<div class="form-group">
  <label for="username">Username</label>
  <input
    id="username"
    type="text"
    aria-invalid="true"
    aria-describedby="username-error"
    required
  />
  <p id="username-error" role="alert" class="error-message">
    Username is required and must be at least 3 characters
  </p>
</div>
/* Visual error indicator */
input[aria-invalid="true"] {
  border-color: var(--error);
  box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1);
}

.error-message {
  color: var(--error);
  font-size: 0.875rem;
  margin-top: var(--space-xs);
}

Mobile & Touch Accessibility

Touch Gestures

Provide alternatives to complex gestures:

  • Swipe: Provide button alternatives
  • Pinch-to-zoom: Allow browser zoom
  • Long press: Provide tap alternatives

Orientation Support

Support both portrait and landscape:

/* Don't lock orientation */
@media (orientation: landscape) {
  /* Adjust layout, don't hide content */
}

Reduced Motion

Respect user preferences for reduced motion:

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

Testing Checklist

Keyboard Navigation

  • All interactive elements are keyboard accessible
  • Tab order is logical and matches visual order
  • Focus indicators are clearly visible
  • No keyboard traps
  • Skip links work correctly

Screen Readers

  • Test with NVDA (Windows) or JAWS
  • Test with VoiceOver (macOS/iOS)
  • Test with TalkBack (Android)
  • All images have appropriate alt text
  • Form labels are properly associated

Color & Contrast

  • All text meets contrast requirements
  • Interactive elements meet contrast requirements
  • Color is not the only means of conveying information
  • Test in grayscale

Responsive & Zoom

  • Content is readable at 200% zoom
  • No horizontal scrolling at standard widths
  • Touch targets are at least 44×44px
  • Works on mobile devices

Tools

Use these tools for testing:

  • axe DevTools: Browser extension for accessibility audits
  • WAVE: Web accessibility evaluation tool
  • Lighthouse: Built into Chrome DevTools
  • pa11y: Automated accessibility testing
  • Screen reader: Test with real screen readers

Resources

Guidelines & Standards

Testing Tools

Learning


Accessibility is not optional—it's essential. By following these guidelines, we ensure Nova Suite is usable by everyone, creating a more inclusive digital experience.