CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-primer--octicons-react

React components for GitHub's Octicons icon library providing scalable SVG icons with tree-shaking support and TypeScript definitions.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

accessibility.mddocs/

Accessibility Features

Overview

@primer/octicons-react provides comprehensive accessibility support through ARIA attributes, semantic markup, and keyboard navigation features. All icons are designed to work seamlessly with screen readers and assistive technologies.

ARIA Attributes

Automatic ARIA Behavior

Icons automatically set aria-hidden and role attributes based on labeling:

  • When aria-label or aria-labelledby is provided: role="img" and aria-hidden is unset
  • When no labeling is provided: aria-hidden="true" (decorative)

Labeling Options

interface AriaProps {
  /** Accessible label for screen readers */
  'aria-label'?: string
  /** References element that labels this icon */
  'aria-labelledby'?: string
  /** Title text for tooltips and additional context */
  title?: string | React.ReactElement<any>
}

aria-label Usage

Use aria-label to provide descriptive text for icons that convey meaning:

import { PlusIcon, AlertIcon, CheckIcon } from '@primer/octicons-react'

function AccessibleIcons() {
  return (
    <div>
      <button>
        <PlusIcon aria-label="Add new item" />
        New
      </button>
      
      <div>
        <AlertIcon aria-label="Warning: Please review your input" />
        Form validation error
      </div>
      
      <span>
        <CheckIcon aria-label="Task completed successfully" />
        Done
      </span>
    </div>
  )
}

aria-labelledby Usage

Use aria-labelledby when an existing element provides the label:

import { PlusIcon, GearIcon } from '@primer/octicons-react'

function LabelledByExample() {
  return (
    <div>
      <h2 id="settings-title">Account Settings</h2>
      <GearIcon aria-labelledby="settings-title" />
      
      <button>
        <PlusIcon aria-labelledby="add-button-label" title="Create new project" />
        <span id="add-button-label">Add Project</span>
      </button>
    </div>
  )
}

Keyboard Navigation

Tab Index Control

interface KeyboardProps {
  /** Tab order for keyboard navigation */
  tabIndex?: number
}

Tab Index Values:

  • 0: Include in natural tab order
  • -1: Focusable via JavaScript but not in tab order
  • undefined (default): Not focusable
import { SearchIcon, CloseIcon } from '@primer/octicons-react'

function InteractiveIcons() {
  return (
    <div>
      {/* Focusable search icon */}
      <SearchIcon 
        aria-label="Open search"
        tabIndex={0}
        onClick={handleSearch}
        onKeyDown={handleKeyDown}
      />
      
      {/* Close button that's keyboard accessible */}
      <CloseIcon
        aria-label="Close dialog"
        tabIndex={0}
        role="button"
        onClick={handleClose}
        onKeyDown={(e) => {
          if (e.key === 'Enter' || e.key === ' ') {
            handleClose()
          }
        }}
      />
      
      {/* Decorative icon - not focusable */}
      <StarIcon aria-hidden="true" />
    </div>
  )
}

SVG Accessibility Features

Automatic ARIA Handling

Icons automatically manage ARIA attributes based on provided props:

interface AutoAriaProps {
  /** Automatically set based on other props */
  'aria-hidden'?: 'true' | undefined
  /** Automatically set when aria-label or aria-labelledby provided */
  role?: 'img' | undefined
  /** Controlled by tabIndex prop */
  focusable?: 'true' | 'false'
}

Automatic Behavior:

  • aria-hidden="true" when no accessibility props provided
  • role="img" when aria-label or aria-labelledby provided
  • focusable="false" when tabIndex is undefined or negative
  • focusable="true" when tabIndex is 0 or positive

Title Elements

The title prop creates an SVG <title> element for additional context:

import { InfoIcon, WarningIcon } from '@primer/octicons-react'

function TitledIcons() {
  return (
    <div>
      <InfoIcon 
        title="Additional information available"
        aria-label="Information"
      />
      
      <WarningIcon 
        title="This action cannot be undone"
        aria-label="Warning"
      />
    </div>
  )
}

Decorative vs Semantic Icons

Decorative Icons

Icons that don't convey unique information should be hidden from screen readers:

import { StarIcon, HeartIcon } from '@primer/octicons-react'

function DecorativeIcons() {
  return (
    <div>
      {/* Text already conveys the meaning */}
      <span>
        <StarIcon aria-hidden="true" />
        Starred Repository
      </span>
      
      {/* Icon is purely visual decoration */}
      <h1>
        <HeartIcon aria-hidden="true" />
        Favorite Projects
      </h1>
    </div>
  )
}

Semantic Icons

Icons that convey important information need accessibility attributes:

import { AlertIcon, CheckCircleIcon, XCircleIcon } from '@primer/octicons-react'

function SemanticIcons() {
  return (
    <div>
      {/* Status indicators */}
      <div>
        <CheckCircleIcon aria-label="Success" fill="green" />
        Operation completed
      </div>
      
      <div>
        <AlertIcon aria-label="Warning" fill="orange" />
        Please review your input
      </div>
      
      <div>
        <XCircleIcon aria-label="Error" fill="red" />
        Failed to save changes
      </div>
    </div>
  )
}

Interactive Icons

Button Icons

When icons function as buttons, provide proper button semantics:

import { GearIcon, BellIcon, SearchIcon } from '@primer/octicons-react'

function IconButtons() {
  return (
    <div>
      {/* Proper button with icon */}
      <button 
        type="button"
        aria-label="Open settings"
      >
        <GearIcon aria-hidden="true" />
      </button>
      
      {/* Icon as button with role */}
      <GearIcon
        role="button"
        tabIndex={0}
        aria-label="Toggle notifications"
        onClick={toggleNotifications}
        onKeyDown={handleButtonKeyDown}
      />
      
      {/* Icon link */}
      <a href="/search" aria-label="Search">
        <SearchIcon aria-hidden="true" />
      </a>
    </div>
  )
}

function handleButtonKeyDown(event) {
  if (event.key === 'Enter' || event.key === ' ') {
    event.preventDefault()
    event.target.click()
  }
}

Screen Reader Testing

Announcement Patterns

Different icon usage patterns produce different screen reader announcements:

// "button, Add new item"
<button>
  <PlusIcon aria-label="Add new item" />
</button>

// "image, Warning icon"  
<AlertIcon aria-label="Warning icon" />

// "Starred repositories" (icon ignored)
<span>
  <StarIcon aria-hidden="true" />
  Starred repositories
</span>

// "button, Settings, Open user preferences"
<button aria-label="Settings" title="Open user preferences">
  <GearIcon aria-hidden="true" />
</button>

Best Practices

Labeling Guidelines

  • Use concise, descriptive labels that explain the icon's purpose
  • Avoid redundant phrases like "icon" or "image" in labels
  • Match label tone and terminology with surrounding content
  • Test labels with actual screen reader users when possible

Focus Management

Icons automatically manage the focusable attribute based on the tabIndex prop:

  • When tabIndex is undefined (default): focusable="false" (prevents assistive technology delays)
  • When tabIndex >= 0: focusable="true" (enables keyboard navigation)
// Non-focusable (default) - good for decorative icons
<AlertIcon aria-hidden="true" />

// Focusable and interactive
<GearIcon 
  tabIndex={0} 
  aria-label="Settings"
  onClick={openSettings}
/>

Best Practices:

  • Only make icons focusable when they perform actions
  • Ensure focused icons have visible focus indicators
  • Group related interactive icons for efficient navigation
  • Provide keyboard alternatives for complex icon interactions

Color and Contrast

  • Never rely solely on color to convey information
  • Ensure icon colors meet WCAG contrast requirements
  • Provide text alternatives when color indicates status
  • Test icon visibility in high contrast mode

Context and Relationships

  • Use aria-labelledby to connect icons with related headings
  • Group related icons using appropriate markup (lists, toolbars)
  • Provide context for standalone icons through surrounding content
  • Consider icon placement within heading hierarchy

Testing Checklist

  • Test with screen readers (NVDA, JAWS, VoiceOver)
  • Verify keyboard navigation works properly
  • Check focus indicators are visible
  • Validate ARIA attributes with accessibility tools
  • Test in high contrast mode
  • Review color contrast ratios
  • Verify icons scale appropriately for zoom levels

Install with Tessl CLI

npx tessl i tessl/npm-primer--octicons-react

docs

accessibility.md

customization.md

icon-components.md

index.md

styling.md

tile.json