Skip to content

Last updated:

Accessibility Overview

Accessibility in CPR is not just a best practice -- it is a necessity. As a medical records system used in clinical settings, CPR must be usable by all staff members, including those with visual impairments, motor disabilities, or situational limitations (such as operating the system with gloves in a procedural setting).

Why Accessibility Matters in Medical Applications

  • Regulatory compliance -- Healthcare applications may be subject to accessibility requirements under local regulations and international standards.
  • Diverse staff -- Clinical staff with varying abilities need full access to patient records, billing, and queue management.
  • High-stress environments -- Clinicians often operate under time pressure. Clear, navigable interfaces reduce errors.
  • Assistive technology users -- Screen readers, voice control, and alternative input devices must work with the application.

Built-in Accessibility Features in CPR

Keyboard Navigation

The UiModal component listens for the Escape key to close modals, a standard keyboard interaction pattern:

ts
// From UiModal.vue
onMounted(() => {
  const handleEscape = (e: KeyboardEvent) => {
    if (e.key === 'Escape' && props.modelValue) {
      close();
    }
  };
  document.addEventListener('keydown', handleEscape);
  onUnmounted(() => {
    document.removeEventListener('keydown', handleEscape);
  });
});

All UiButton components use native <button> elements, which are inherently keyboard-focusable and activatable with Enter or Space.

Semantic HTML

CPR's UI components use semantic HTML elements:

  • <button> for UiButton (not <div> or <span>)
  • <input> with associated <label> in UiInput
  • <table>, <thead>, <tbody>, <tr>, <th>, <td> in UiTable

Form Labels

The UiInput component automatically associates labels with their inputs using for/id pairing:

vue
<!-- From UiInput.vue -->
<label v-if="label" :for="id" class="text-xs font-bold text-gray-700 ...">
  {{ label }}
  <span v-if="required" class="text-red-500">*</span>
</label>
<input :id="id" ... />

Each UiInput generates a unique id if none is provided:

ts
id: () => `input-${Math.random().toString(36).slice(2, 9)}`,

Error Messages

Validation errors are displayed directly below the input field they relate to, visually connected through layout and color:

vue
<!-- From UiInput.vue -->
<div v-if="error" class="mt-1 text-xs text-red-500 font-medium">
  {{ error }}
</div>

Focus Management

  • UiInput has clear focus styles with a ring: focus:border-[#117ea7] focus:ring-4 focus:ring-[#117ea7]/10
  • UiButton includes focus:outline-none in the base classes and variant-specific focus ring styles
  • Disabled states show disabled:opacity-50 disabled:cursor-not-allowed

Accessibility Principles

Perceivable

  • All meaningful images should have alt text.
  • Color should not be the only way to convey information. The UiSnackBar uses both color and text to indicate success, error, or info states.
  • Text should meet minimum contrast ratios (see WCAG Guidelines).

Operable

  • All interactive elements must be keyboard-accessible.
  • No functionality should require mouse-only interaction.
  • Provide adequate time for users to read and interact with content (the snackbar has a configurable duration, defaulting to 3 seconds).

Understandable

  • Use clear, consistent labels across forms.
  • Display validation errors inline, next to the relevant field.
  • Use the confirmation dialog (UiConfirmDialog) before destructive actions like deleting patient records.

Robust

  • Use semantic HTML elements that work with assistive technologies.
  • Ensure the application works across modern browsers (Chromium, Firefox, WebKit).

Current Gaps and Improvements

The following areas should be addressed to improve CPR's accessibility:

  1. ARIA attributes on modals -- Add role="dialog", aria-modal="true", and aria-labelledby to UiModal.
  2. Live regions for snackbar -- Add role="alert" or aria-live="polite" to UiSnackBar so screen readers announce notifications.
  3. Focus trapping in modals -- When a modal is open, focus should be trapped within it so Tab does not reach elements behind the modal.
  4. Skip navigation link -- Add a "Skip to content" link for keyboard users to bypass the navigation menu.
  5. Error announcement -- Connect validation errors to inputs using aria-describedby so screen readers announce them.

CPR - Clinical Patient Records