# Atlassian Design System Accessibility
> Comprehensive accessibility guidelines and best practices for building inclusive, accessible user interfaces with the Atlassian Design System. This guide ensures all users, regardless of ability, can effectively interact with Atlassian apps.
## Core Accessibility Principles
### WCAG 2.1 AA Compliance
The Atlassian Design System is built to meet WCAG 2.1 AA standards, ensuring:
- **Perceivable**: Information is presented in ways users can perceive
- **Operable**: Interface components are operable by all users
- **Understandable**: Information and operation are understandable
- **Robust**: Content is compatible with current and future assistive technologies
### Inclusive Design Philosophy
- Design for people, not just compliance
- Consider accessibility from the start of design
- Test with real users and assistive technologies
- Provide multiple ways to accomplish tasks
## Design Tokens for Accessibility
### Color and Contrast
Use design tokens to ensure proper contrast ratios:
```tsx
import { token } from '@atlaskit/tokens';
// High contrast text on backgrounds
const styles = css({
color: token('color.text'),
backgroundColor: token('color.background.neutral'),
});
// Ensure 4.5:1 contrast ratio for normal text
// Ensure 3:1 contrast ratio for large text (18pt+ or 14pt+ bold)
```
**Critical Color Tokens:**
- `color.text` - Primary text with proper contrast
- `color.text.subtle` - Secondary text (use sparingly)
- `color.text.disabled` - Disabled text (avoid for critical information)
- `color.border.focused` - Focus indicators
- `color.background.danger` - Error states
- `color.background.success` - Success states
### Typography and Readability
- Use `font.body` for main content (minimum 16px)
- Use `font.body.small` sparingly (minimum 14px)
- Maintain line height of at least 1.5 for readability
- Use `font.weight.medium` or `font.weight.semibold` for emphasis
- Use `Text` primitive for consistent typography
- Use `Heading` component for proper heading hierarchy
## Component Accessibility Guidelines
### Interactive Elements
#### Buttons and Pressable Elements
```tsx
import { Pressable, Focusable } from '@atlaskit/primitives/compiled';
import { VisuallyHidden } from '@atlaskit/visually-hidden';
// Always provide accessible labels
Save changes
// For icon-only buttons, use aria-label
// Custom interactive elements with focus ring
Custom interactive element
// Pressable with focus management
Interactive content
```
**Best Practices:**
- Never disable buttons without providing alternatives
- Use descriptive labels that explain the action
- Ensure focus indicators are visible with `Focusable`
- Support keyboard navigation (Enter, Space)
- Use `Pressable` primitive for custom interactive elements
- Use `Focusable` for elements that need focus management
- Avoid tooltips on disabled buttons
#### Links and Navigation
```tsx
import { Anchor } from '@atlaskit/primitives/compiled';
// External links with proper labeling
External resource
(opens in new window)
```
**Best Practices:**
- Use descriptive link text (avoid "click here")
- Indicate when links open in new windows
- Ensure link purpose is clear from context
- Use proper heading hierarchy for navigation
### Form Components
#### Input Fields and Labels
```tsx
import { TextField } from '@atlaskit/textfield';
// Always associate labels with inputs
Enter your work email address
```
**Best Practices:**
- Use `htmlFor` and `id` to associate labels with inputs
- Provide helpful error messages and descriptions
- Use `aria-required` for required fields
- Group related form elements with `fieldset` and `legend`
#### Form Validation
```tsx
// Provide clear, actionable error messages
Password must be at least 8 characters long
```
### Content and Media
#### Images and Alternative Text
```tsx
import { Image } from '@atlaskit/image';
// Decorative images
// Informative images
// Complex images need detailed descriptions
Detailed description of the diagram content...
```
**Alternative Text Guidelines:**
- Keep alt text under 125 characters
- Describe the purpose, not just the content
- Don't start with "Image of..." or "Picture of..."
- Leave empty for decorative images
#### Text and Typography
```tsx
import { Text } from '@atlaskit/primitives/compiled';
import { Heading } from '@atlaskit/heading';
// Use semantic heading hierarchy
Page TitleSection Title
// Use Text component for consistent styling
Regular paragraph textImportant information
```
### Layout and Structure
#### Semantic HTML
```tsx
import { Box } from '@atlaskit/primitives/compiled';
// Use semantic elements
Section Title
Content here
```
#### Focus Management
```tsx
import { useRef, useEffect } from 'react';
// Manage focus in modals and dialogs
const modalRef = useRef(null);
useEffect(() => {
if (isOpen && modalRef.current) {
modalRef.current.focus();
}
}, [isOpen]);
```
## ARIA Usage Guidelines
### ARIA Roles and States
```tsx
// Use ARIA sparingly - prefer semantic HTML
Custom button
// Live regions for dynamic content
{statusMessage}
// Landmarks for page structure
```
### Common ARIA Patterns
#### Dialog and Modal
```tsx
import { ModalDialog } from '@atlaskit/modal-dialog';
import { Focusable } from '@atlaskit/primitives/compiled';
```
## Keyboard Navigation
### Focus Management
- Ensure logical tab order
- Provide visible focus indicators
- Handle focus trapping in modals
- Return focus when dialogs close
### Keyboard Shortcuts
```tsx
// Support standard keyboard interactions
const handleKeyDown = (event: KeyboardEvent) => {
switch (event.key) {
case 'Enter':
case ' ':
handleActivate();
break;
case 'Escape':
handleClose();
break;
case 'Tab':
// Handle focus management
break;
}
};
```
## Screen Reader Support
### Announcements and Live Regions
```tsx
// Announce dynamic content changes using aria-live
{count} items selected
// For drag and drop operations
import { announce } from '@atlaskit/pragmatic-drag-and-drop-live-region';
announce('Task "Clean dishes" moved to list "Doing" from "Todo".');
```
**Best Practices:**
- Use `aria-live="polite"` for status updates
- Use `aria-live="assertive"` for critical alerts
- Avoid announcing the same message repeatedly
- Keep live regions in the DOM for consistent announcements
### Skip Links
```tsx
// Built-in skip links in navigation system
import { NavigationSystem } from '@atlaskit/navigation-system';
// Custom skip links
Skip to main content
```
## Testing and Validation
### Automated Testing
```tsx
// Use Atlassian's accessibility testing utilities
import { toHaveNoViolations, checkColorContrast } from '@af/accessibility-testing';
expect.extend(toHaveNoViolations);
// Unit test accessibility
test('should not have accessibility violations', async () => {
const { container } = render();
const results = await axe(container);
expect(results).toHaveNoViolations();
});
// Visual regression test for color contrast
test('should have sufficient contrast', async () => {
const url = getExampleUrl(SomeURL);
const { page } = global;
await loadPage(page, url);
const results = await checkColorContrast(page);
expect(results.incomplete.length).toEqual(0);
expect(results).toHaveNoViolations();
});
// Enable accessibility audit on unit tests
// Set environment variable: IS_A11Y_AUDIT_ENABLED=true
```
### Manual Testing Checklist
- [ ] Test with keyboard navigation only
- [ ] Test with screen readers (NVDA, JAWS, VoiceOver)
- [ ] Test with high contrast mode
- [ ] Test with zoom (200% and 400%)
- [ ] Test with reduced motion preferences
- [ ] Test with different color vision types
- [ ] Test focus management in modals and dialogs
- [ ] Test ARIA live regions and announcements
- [ ] Test skip links functionality
## Common Accessibility Issues
### Avoid These Patterns
```tsx
// ❌ Don't rely on color alone for information
Error message
// ✅ Use multiple indicators
Error message
// ❌ Don't use generic labels
// ✅ Use descriptive labels
// ❌ Don't hide focus indicators
button:focus { outline: none; }
// ✅ Ensure focus is visible
button:focus { outline: 2px solid token('color.border.focused'); }
```
## Resources and Tools
### Official Documentation
- [Atlassian Design System Accessibility](https://atlassian.design/foundations/accessibility)
- [WCAG 2.1 Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)
- [ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/)
### Testing Tools
- [axe DevTools](https://www.deque.com/axe/browser-extensions/)
- [WAVE Web Accessibility Evaluator](https://wave.webaim.org/)
- [Lighthouse Accessibility Audit](https://developers.google.com/web/tools/lighthouse)
### Screen Readers
- [NVDA](https://www.nvaccess.org/) (Windows, free)
- [JAWS](https://www.freedomscientific.com/products/software/jaws/) (Windows)
- [VoiceOver](https://www.apple.com/accessibility/vision/) (macOS/iOS, built-in)
- [TalkBack](https://support.google.com/accessibility/android/answer/6283677) (Android, built-in)
## Component-Specific Accessibility
### Focus Management Components
```tsx
import { Focusable } from '@atlaskit/primitives/compiled';
// Built-in focus ring for interactive elements
Click me
// Custom focus management with inset focus ring
Custom interactive element
// Focusable with custom styling
Styled button
```
### Button Components
- Use `Button` for primary actions
- Use `ButtonGroup` for related actions
- Avoid disabled buttons with tooltips
- Provide loading states with `aria-busy`
- Use `Pressable` primitive for custom interactive elements
### Form Components
- Use `TextField`, `Select`, `Checkbox`, `Radio` for consistent behavior
- Implement proper validation with `aria-invalid`
- Use `Field` wrapper for consistent labeling
- Use `MessageWrapper` for form validation announcements
### Navigation Components
- Use `Breadcrumbs` for hierarchical navigation with proper focus management
- Use `Tabs` for content organization with ARIA tab patterns
- Use `Menu` for dropdown navigation with focus trapping
- Use `NavigationSystem` with built-in skip links
### Feedback Components
- Use `Flag` for status messages
- Use `InlineMessage` for contextual feedback
- Use `Toast` for temporary notifications
- Use `aria-live` regions for screen reader announcements
### Layout Components
- Use `PageLayout` with built-in accessibility features
- Use `Drawer` with proper focus management
- Use `ModalDialog` with focus trapping and return focus
- Use `Popup` with accessible focus management
### Data Display Components
- Use `Table` with proper headers and captions
- Use `Tree` with keyboard navigation support
- Use `Avatar` and `AvatarGroup` with proper alt text
- Use `Badge` and `Lozenge` for status indicators
## Optional
### Advanced ARIA Patterns
- [Complex Widget Patterns](https://www.w3.org/WAI/ARIA/apg/patterns/)
- [Live Region Best Practices](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions)
- [Focus Management Strategies](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/)
### Drag and Drop Accessibility
```tsx
import { announce } from '@atlaskit/pragmatic-drag-and-drop-live-region';
// Always provide alternatives to drag operations
// Use buttons, menus, and forms for accessible interactions
// Announce state changes to screen readers
announce('Item moved successfully');
```
### Performance Considerations
- Minimize DOM updates for screen readers
- Use `aria-live` judiciously
- Optimize for keyboard navigation performance
- Use `shouldAnnounce` to prevent unnecessary announcements
### Internationalization
- Support right-to-left languages
- Consider cultural accessibility differences
- Test with translated content
- Use `VisuallyHidden` instead of `aria-label` for better translation support
### Advanced Focus Management
```tsx
// Focus trapping in modals
import { useFocusManager } from '@atlaskit/popup';
import { Focusable } from '@atlaskit/primitives/compiled';
// Custom focus restoration
const handleClose = () => {
triggerRef.current?.focus();
onClose();
};
// Custom focusable elements with proper focus management
{
if (e.key === 'Enter' || e.key === ' ') {
handleActivate();
}
}}
>
Custom focusable element
```
### Accessibility Testing Tools
- [@af/accessibility-testing](https://atlassian.design/components/accessibility-testing) - Atlassian's testing utilities
- [axe-core](https://github.com/dequelabs/axe-core) - Automated accessibility testing
- [@sa11y/jest](https://github.com/salesforce/sa11y) - Jest integration for accessibility testing
## ADS Fix Patterns for Accessibility Violations
### Form Control Violations
**Common Issues**: Missing labels, unassociated form controls, missing descriptions
**ADS Solution**: Use ADS form components that handle accessibility automatically
```tsx
// ❌ Problematic code
// ✅ ADS solution
import { TextField } from '@atlaskit/textfield';
Enter your work email address
```
### Interactive Element Violations
**Common Issues**: Missing accessible names, keyboard navigation, focus management
**ADS Solution**: Use Focusable component for custom elements or Button for standard interactions
```tsx
// ❌ Problematic code
Click me
// ✅ ADS solution
import { Focusable } from '@atlaskit/primitives/compiled';
import { Button } from '@atlaskit/button';
// For custom interactive elements
{
if (e.key === 'Enter' || e.key === ' ') {
handleClick();
}
}}
>
Interactive content
// For standard buttons
```
### Image Violations
**Common Issues**: Missing alt text, decorative images not marked
**ADS Solution**: Use Image component with proper alt text handling
```tsx
// ❌ Problematic code
// ✅ ADS solution
import { Image } from '@atlaskit/image';
// Informative image
// Decorative image
// Complex image with description
Detailed description of the diagram content...
```
### Color and Contrast Violations
**Common Issues**: Insufficient contrast, relying on color alone
**ADS Solution**: Use design tokens for consistent contrast ratios
```tsx
// ❌ Problematic code
Error message
// ✅ ADS solution
import { token } from '@atlaskit/tokens';
import { Text } from '@atlaskit/primitives/compiled';
// Use design tokens
const styles = css({
color: token('color.text'),
backgroundColor: token('color.background.neutral'),
});
// Use Text component with color prop
Error message
```
### Structure and Semantics Violations
**Common Issues**: Missing landmarks, improper heading hierarchy, list structure
**ADS Solution**: Use semantic HTML elements and ADS layout components
```tsx
// ❌ Problematic code
Main heading
Sub heading
// ✅ ADS solution
import { Text } from '@atlaskit/primitives/compiled';
import { Box } from '@atlaskit/primitives/compiled';
// Proper heading hierarchy
Main headingSub heading
// Semantic structure
Section TitleContent here
// Proper list structure
List item 1
List item 2
```
### Focus Management Violations
**Common Issues**: Missing focus indicators, improper focus order
**ADS Solution**: Use Focusable component with built-in focus management
```tsx
// ❌ Problematic code
button:focus { outline: none; }
// ✅ ADS solution
import { Focusable } from '@atlaskit/primitives/compiled';
Click me
```
### Screen Reader Violations
**Common Issues**: Missing announcements, improper live regions
**ADS Solution**: Use aria-live regions and proper ARIA attributes
```tsx
// ❌ Problematic code
Status updated
// ✅ ADS solution
Status updated successfully
// For form validation
Please fix the errors above
```
### General Fix Patterns
1. **Replace custom implementations with ADS components**
- Use `TextField` instead of raw ``
- Use `Button` instead of custom button elements
- Use `Focusable` for custom interactive elements
2. **Use design tokens for styling**
- Replace hardcoded colors with `token()` function
- Use `Text` component with color props
- Ensure proper contrast ratios
3. **Implement proper labeling**
- Use `aria-label` for icon-only elements
- Use `VisuallyHidden` for screen reader text
- Associate labels with form controls
4. **Add keyboard support**
- Support Enter and Space for activation
- Support Escape for closing/canceling
- Ensure logical tab order
5. **Test with assistive technologies**
- Test with screen readers
- Test with keyboard navigation only
- Test with high contrast mode