Files
Meister-Eder/openspec/changes/implement-web-chat/specs/chat-interface/spec.md
T
Claude b0ebd40302 docs(openspec): add chat-interface spec for implement-web-chat change
MODIFIED spec extending the scoping-phase chat-interface requirements with:
- WCAG 2.1 AA compliance (automated + manual screen reader)
- Full keyboard navigation and no keyboard traps
- Skip-to-content link
- ARIA live regions for agent messages (polite, completed only)
- Focus management after agent reply
- Colour contrast ≥ 4.5:1 (normal text), ≥ 3:1 (large text)
- prefers-reduced-motion: static indicator fallback
- Mobile viewport / virtual keyboard visibility
- Session persistence and graceful disconnect notification
- Chainlit implementation constraints and telemetry-off requirement

https://claude.ai/code/session_01SUWzMzFvSfWiHXA2p6rPg9
2026-02-22 05:18:43 +00:00

7.3 KiB

MODIFIED Requirements

Extends the chat-interface spec from define-project-scope. All previously defined requirements remain in force. This spec adds accessibility requirements and implementation constraints introduced by this change.


Requirement: WCAG 2.1 AA compliance

The chat interface SHALL conform to WCAG 2.1 Level AA in all user-facing interactions.

Scenario: Automated accessibility check passes

  • WHEN an automated accessibility audit (e.g. axe-core) is run against the chat page
  • THEN it SHALL report zero Level A and Level AA violations

Scenario: Manual screen reader test passes

  • WHEN a user navigates the chat using NVDA (Windows) or VoiceOver (macOS/iOS)
  • THEN they SHALL be able to read all messages and send a new message without using a mouse

Requirement: Full keyboard navigation

The chat interface SHALL be fully operable using only a keyboard.

Scenario: Sending a message by keyboard

  • WHEN a parent focuses the text input and types a message
  • THEN they SHALL be able to submit it with the Enter key without pressing a mouse button

Scenario: Tab order is logical

  • WHEN a parent presses Tab repeatedly from the top of the page
  • THEN focus SHALL move through interactive elements in a logical reading order (skip link → message list → text input → send button)

Scenario: No keyboard trap

  • WHEN focus enters any component (e.g. the text input)
  • THEN the parent SHALL be able to move focus out again using only the keyboard

The chat interface SHALL provide a skip navigation link as the first focusable element.

  • WHEN a keyboard user presses Tab on the chat page for the first time
  • THEN a "Skip to chat" link SHALL become visible and, when activated, move focus directly to the message input

Requirement: Screen reader announcements for new messages

Incoming agent messages SHALL be announced to screen readers without requiring focus change.

Scenario: Agent reply announced

  • WHEN the agent sends a new message
  • THEN a screen reader SHALL announce the message content via an ARIA live region (aria-live="polite")

Scenario: In-progress stream not announced mid-token

  • WHEN the agent is streaming a response token by token
  • THEN the live region SHALL NOT announce each individual token; only the completed message SHALL be announced

Requirement: Focus moves to agent reply on completion

After the agent finishes a response, keyboard focus SHALL be placed near the new message.

Scenario: Focus after reply

  • WHEN the agent finishes generating a response
  • THEN focus SHALL move to the new agent message element (or a wrapper with tabindex="-1") so the parent can read it immediately with a screen reader

Requirement: Sufficient colour contrast

All text in the chat interface SHALL meet WCAG 2.1 SC 1.4.3 contrast requirements.

Scenario: Normal text contrast

  • WHEN any text of normal size is rendered
  • THEN its contrast ratio against the background SHALL be ≥ 4.5:1

Scenario: Large text contrast

  • WHEN any text at 18pt (or 14pt bold) or larger is rendered
  • THEN its contrast ratio against the background SHALL be ≥ 3:1

Scenario: Input placeholder contrast

  • WHEN the text input displays placeholder text
  • THEN the placeholder contrast ratio SHALL be ≥ 4.5:1

Requirement: Typing indicator respects reduced-motion preference

The agent-processing indicator SHALL not use animation when the user has requested reduced motion.

Scenario: Reduced motion active

  • WHEN the OS or browser has prefers-reduced-motion: reduce set
  • AND the agent is generating a response
  • THEN the typing indicator SHALL display as a static element (e.g. "…" text) with no animation

Scenario: Reduced motion not active

  • WHEN prefers-reduced-motion is not set or is set to no-preference
  • THEN the typing indicator MAY display an animated element (e.g. bouncing dots)

Requirement: Mobile viewport input visibility

The text input SHALL remain visible when the virtual keyboard is open on mobile devices.

Scenario: iOS Safari virtual keyboard

  • WHEN a parent taps the text input on an iOS device and the virtual keyboard appears
  • THEN the input field SHALL remain in view and not be obscured by the keyboard

Scenario: Android Chrome virtual keyboard

  • WHEN a parent taps the text input on an Android device and the virtual keyboard appears
  • THEN the input field SHALL remain in view and the message list SHALL scroll to show the latest message above the keyboard

Requirement: Session state survives page refresh

Conversation history and registration state SHALL be preserved when the parent reloads the page within the same browser session.

Scenario: Page refresh mid-conversation

  • WHEN a parent refreshes the browser tab during an active conversation
  • THEN the full conversation history SHALL be displayed and the registration state SHALL be intact on reconnect

Scenario: Server restart loses state (acceptable degradation)

  • WHEN the server restarts while a session is active
  • THEN the parent SHALL see a notification that the session ended and be invited to start a new conversation

Requirement: Session-loss notification on disconnect

If the connection to the server is lost and cannot be recovered, the interface SHALL inform the parent.

Scenario: Unrecoverable disconnect

  • WHEN the WebSocket / SSE connection is lost and reconnection fails after a reasonable timeout
  • THEN the interface SHALL display a message explaining the session ended and suggest using email for longer registration processes

Requirement: Welcome message in the parent's language

The chat interface SHALL display a welcome message in German by default, with automatic language adaptation.

Scenario: Default welcome message

  • WHEN a parent opens the chat interface
  • THEN the welcome message SHALL be displayed in German

Scenario: Language adaptation

  • WHEN a parent sends their first message in English
  • THEN the agent SHALL respond in English for the remainder of the session

ADDED Requirements

Requirement: Chainlit-based implementation

The chat interface SHALL be implemented using the Chainlit framework.

Scenario: Application entry point

  • WHEN the server starts
  • THEN it SHALL run a Chainlit application with @cl.on_chat_start and @cl.on_message handlers

Scenario: Telemetry disabled

  • WHEN the application runs
  • THEN Chainlit telemetry SHALL be disabled (enable_telemetry = false in chainlit.toml)

Requirement: Custom accessibility CSS applied

The Chainlit default theme SHALL be extended with a custom CSS file that addresses accessibility gaps.

Scenario: Custom CSS loaded

  • WHEN the chat page is served
  • THEN the custom CSS file (/public/custom.css) SHALL be loaded and applied on top of the default Chainlit theme

Scenario: Custom CSS addresses contrast and motion

  • WHEN the page renders
  • THEN the custom CSS SHALL include contrast overrides achieving ≥ 4.5:1 for all normal text AND a prefers-reduced-motion block that suppresses typing-dot animation