Accessibility statement doc
Document type: Consolidated alignment statement and implementation inventory Language: English Last update: 2026-05-12
This document describes capabilities and patterns that are present in the product engineering. It is not a legal certificate, VPAT, or third-party audit report.
1. Purpose and scope
This statement describes how the Tiledesk chat widget product line positions its user interface engineering relative to internationally recognised accessibility norms. It applies to the Angular-based widget delivered through dynamic bootstrap and an embedded browsing context, as used on customer websites.
The scope is the interactive widget experience (launcher, conversations, forms, media, and related overlays) as implemented in this codebase.
This statement may be shared with customers, integrators, or accessibility specialists as context for how the widget is built and maintained. It does not replace project-specific accessibility assessments for a given website skin, content policy, or national transposition of accessibility law.
2. Reference frameworks (informative)
Accessibility work on this product is informed by the following technical and regulatory reference layers, which organisations commonly use when specifying digital accessibility for public-sector procurement and enterprise risk management:
W3C Web Content Accessibility Guidelines (WCAG) 2.2 (Level AA as design target)
Baseline for perceivable, operable, understandable, and robust UI behaviour.
W3C Accessible Rich Internet Applications (WAI-ARIA) 1.2
Patterns for custom components, regions, dialogs, live regions, and relationships where native HTML alone is insufficient.
ETSI EN 301 549 (European accessibility standard for ICT products and services, including WCAG 2.x–aligned requirements)
Procurement and conformity reference when customers require European accessibility clauses in contracts or technical specifications (e.g. chapters 9, 11).
Formal conformity claims for a specific deployment remain the responsibility of the deploying organisation and are typically supported by independent evaluation against the applicable version of WCAG and any regional transposition of EN 301 549.
3. Engineering posture (state of the art)
The widget is implemented as a focused single-page application within an iframe, with a parent-page bootstrap script responsible for embedding. Engineering attention is directed toward:
Semantic controls and naming: Primary navigation and chrome actions use native
buttonelements where the interaction model is activational; icon-only controls are paired with translatablearia-label(or equivalent) text from the product’s translation maps.Structured regions and bypass: Conversation views use landmark-style regions (for example
role="region") and skip affordances so keyboard users can move efficiently to the message composer.Modal and overlay semantics: Key flows such as customer satisfaction rating, department selection, and pre-chat entry use dialog semantics (
role="dialog",aria-modal, labelling) consistent with WAI-ARIA dialog guidance, with focus management support via Angular CDK where applied.Forms and errors: Dynamic form fields support programmatic association of labels, required state, invalid state, and error descriptions via ARIA relationships; error content uses live semantics where appropriate for time-sensitive feedback.
Rich content: Components for audio playback, carousels, and image preview follow patterns that expose control state and mark decorative graphics appropriately for assistive technologies.
Motion and perception: Stylesheets include reduced-motion handling so that users who prefer less animation receive a calmer visual experience.
Embedding context: The host iframe is given a descriptive title in the bootstrap layer so that the embedded application is identifiable in browsing contexts that surface frame titles.
Testing and quality assurance combine static template review, build verification, diagnostics, manual keyboard walk-through, screen reader smoke tests, and reduced-motion verification, in line with common industry practice for complex widgets.
4. Document metadata
Product
Tiledesk Web Widget
Package
@chat21/chat21-web-widget
Version
5.1.33
Stack
Angular 18.2.x (NgModule bootstrap), Angular CDK 17 (A11yModule), iframe-hosted (launch.js)
Standards orientation
WCAG 2.2 Level AA, WAI-ARIA 1.2 Authoring Practices, EN 301 549 v3.2.1 (informative reference for ICT accessibility chapters aligned with WCAG)
Document language
English
5. Accessibility engineering coverage (summary)
The table below is the engineering self-assessment summary used internally to track breadth of accessibility work across product areas. Numeric scores reflect internal review breadth and are not a third-party certification. Only areas where engineering practices are actively applied are listed.
Semantic HTML
4.5
WCAG 2.2 AA
Keyboard accessibility
4.5
WCAG 2.2 AA
ARIA compliance
4.5
WAI-ARIA 1.2
Forms accessibility
5.0
WCAG 2.2 AA
Dialog / Modal accessibility
4.5
WAI-ARIA 1.2 (focus trap via Angular CDK)
Live regions / SR announcements
4.0
WCAG 4.1.3
Reduced motion / animations
5.0
WCAG 2.3.3 / 2.2.2
Internationalization
4.5
WCAG 3.1.1 / 3.1.2
Iframe integration
4.5
WCAG 2.4.1 / 4.1.2
Overall self-assessment
4.5 / 5
WCAG 2.2 AA — engineering-oriented implementation
6. Project overview
Bootstrap mode
NgModule (AppModule) via platformBrowserDynamic().bootstrapModule(AppModule) (src/main.ts). The compiled bundle is injected into a same-origin iframe by src/launch.js, which builds and styles #tiledesk-container in the host page.
Standalone components
Not used; components are declared in AppModule (src/app/app.module.ts).
Routing
Not used at runtime: navigation between home, list-conversations, conversation, selection-department, prechat-form, star-rating-widget, error-alert is driven by template flags inside AppComponent.
i18n
@ngx-translate/core 16 with JSON dictionaries in src/assets/i18n/{en,it,es,fr}.json plus an optional remote dictionary. Active language is propagated to <html lang> in the widget document.
Accessibility libraries used
@angular/cdk/a11y (A11yModule) — focus trap support for modals where integrated.
7. Component inventory and accessibility highlights
The widget exposes 30+ components. The tables below cover interactive components that are part of the runtime surface; pure-data services and presentational helpers are omitted.
7.1 Shell components
AppComponent
chat-root
Application root
:focus-visible ring scoped to chat-root; prefers-reduced-motion honored
LauncherButtonComponent
chat-launcher-button
<button>
type="button", aria-label from BUTTON_OPEN_CHAT, focus-visible
EyeeyeCatcherCardComponent
chat-eyeeye-catcher-card
Buttons
All clickable areas are real <button type="button"> with aria-label
LastMessageComponent
chat-last-message
Buttons
Preview activator is <button> with aria-label; close is a real button
7.2 Home / list / department views
HomeComponent
role="region" + aria-label
<h1> welcome, <p> intro; close/maximize/minimize/center are buttons; social channels labelled
HomeConversationsComponent
role="list" + role="listitem"
"Show all conversations" and "Start new conversation" are buttons with aria-label; archived badge uses role="img"
ListAllConversationsComponent
role="region"
<h2> title; back is a button; dead altIconTitle SVG markup removed
ListConversationsComponent
List items
Each item activates a button; counters/badges marked aria-hidden="true"
SelectionDepartmentComponent
role="dialog" aria-modal="true" cdkTrapFocus
<h2> title, Escape closes, options are real buttons
7.3 Conversation surface
ConversationComponent
role="region"
Visible-on-focus skip link → composer (WCAG 2.4.1); scroll-to-bottom is a button with aria-label
ConversationHeaderComponent
<button> toolbar
Each control is <button type="button"> with aria-label; options popover uses aria-expanded/aria-haspopup="true"/aria-controls; popover items are real buttons grouped under role="group" (Esc closes)
ConversationContentComponent
role="log" aria-live="polite"
Each message wrapped in role="article"; carousel slides expose role="group" + aria-roledescription="slide"
ConversationFooterComponent
Form-like region
Attachment/emoji/send/record are buttons; emoji panel is role="dialog"; alert area is role="alert" aria-live="assertive"
ConversationAudioRecorderComponent
Buttons
Record toggle uses aria-pressed; play/pause/delete/send all labelled
ConversationPreviewComponent
role="dialog" aria-modal="true" cdkTrapFocus
aria-labelledby via LABEL_PREVIEW; Esc closes; close/send are buttons
ConversationInternalFrameComponent
Panel
Iframe has title, sandbox, referrerpolicy, loading="lazy"; spinner aria-hidden
MenuOptionsComponent
role="group" popover
Sound toggle uses aria-pressed; Esc closes; toggle button advertises aria-expanded/aria-haspopup="true"
7.4 Form components
PrechatFormComponent
role="dialog" aria-modal="true" cdkTrapFocus; <h2> title; Escape closes
FormBuilderComponent
Submit button is type="button"; native form semantics
FormTextComponent
<label for> ↔ <input id>; aria-required, aria-invalid, aria-describedby to error role="alert"; :focus-visible ring
FormTextareaComponent
Same pattern as FormText, plus aria-multiline
FormCheckboxComponent
Native <input type="checkbox"> linked to <label>; ARIA validation states wired
FormRadioButtonComponent
Native <input type="radio">
FormSelectComponent
Native <select>
FormLabelComponent
Pure label slot
7.5 Message bubble components
BubbleMessageComponent
Class-based selector replacing former duplicated id="bubble-message"; carries translation map down
TextComponent
Root is <div>; markdown rendered through marked pipe; CSS targets the .message_innerhtml wrapper
HtmlComponent
Class-based wrapper; sanitizer-aware
ImageComponent
Wrapped in <button> with aria-label; lightbox is a role="dialog" iframe with close button, Escape support and focus restoration
FrameComponent
Iframe hardened: dynamic title, sandbox, referrerpolicy, loading="lazy"
AudioComponent
Play/pause buttons labelled via BUTTON_PLAY_AUDIO / BUTTON_PAUSE_AUDIO
CarouselComponent
Wrapper exposes role="region" aria-roledescription="carousel" aria-label; each card is role="group" aria-roledescription="slide" aria-label="Slide N of M"; arrows and CTAs are buttons
ActionButtonComponent, LinkButtonComponent, TextButtonComponent
Real <button> / <a> with aria-label
ReturnReceiptComponent, LikeUnlikeComponent, AvatarComponent, InfoMessageComponent
Decorative iconography flagged aria-hidden="true"; semantic content carries text alternatives
7.6 Modals
ConfirmCloseComponent
role="dialog" aria-modal="true" cdkTrapFocus aria-labelledby="confirm-close-title"; <h2> heading; Escape closes; cancel/confirm are real buttons
ErrorAlertComponent
Provides translatable error messages
StarRatingWidgetComponent
Stars exposed as buttons; comment area is a labelled textarea
8. WCAG 2.2 compliance checklist (implemented patterns)
The following table lists success criteria for which the widget implements supporting patterns that were reviewed in the engineering statement. Each row documents what is present in the product line.
1.1.1 Non-text Content
A
Pass
All informational icons carry aria-label/alt; decorative SVGs use aria-hidden="true" and focusable="false"
1.3.1 Info and Relationships
A
Pass
<h1>/<h2> headings, role="log", role="article", role="list", programmatic <label for> ↔ <input id>
1.3.2 Meaningful Sequence
A
Pass
Tab order follows reading order; high tabindex values removed
1.4.3 Contrast (Minimum)
AA
Pass
Default theme passes 4.5:1; custom palettes remain integrator-validated
1.4.4 Resize Text
AA
Pass
Layout is em-based; honours user font scaling
1.4.10 Reflow
AA
Pass
Responsive layout; no horizontal scrolling at 320 CSS pixels
1.4.11 Non-text Contrast
AA
Pass
Focus ring is 2px solid #1a73e8, ≥ 3:1 against widget backgrounds
1.4.12 Text Spacing
AA
Pass
No critical fixed line-height/letter-spacing overrides
1.4.13 Content on Hover or Focus
AA
Pass
Tooltips use :hover/:focus, dismissable, persistent; no time-based dismissal
2.1.1 Keyboard
A
Pass
Every actionable element is reachable and operable from keyboard (real buttons, native form controls)
2.1.2 No Keyboard Trap
A
Pass
cdkTrapFocus traps only inside dialogs; Esc and dialog-close return focus
2.1.4 Character Key Shortcuts
A
Pass
The widget does not bind single-character shortcuts globally
2.2.2 Pause, Stop, Hide
A
Pass
Animations are decorative and short; reduced-motion media query disables them entirely
2.3.3 Animation from Interactions
AAA (informative)
Pass
prefers-reduced-motion: reduce neutralises animations and transitions inside chat-root
2.4.1 Bypass Blocks
A
Pass
Skip link in conversation surface jumps focus to the message composer
2.4.3 Focus Order
A
Pass
Logical order: header → log → composer → footer; high tabindex removed
2.4.7 Focus Visible
AA
Pass
Global outline: none removed; :focus-visible rule scoped to chat-root
2.4.11 Focus Not Obscured (Min)
AA
Pass
Sticky header/footer leave the active control visible; verified with launcher button
2.5.7 Dragging Movements
AA
Pass
Carousel can be operated by next/previous arrow buttons in addition to drag
2.5.8 Target Size (Minimum)
AA
Pass
All primary controls ≥ 24×24 CSS px
3.1.1 Language of Page
A
Pass
<html lang> synchronised with the active i18n language by TranslatorService.syncDocumentLang
3.2.1 On Focus
A
Pass
No context change on focus
3.2.2 On Input
A
Pass
No context change on input; the user always confirms
3.2.6 Consistent Help
A
Pass
Help / contact entry points (menu-options) are consistent across views
3.3.1 Error Identification
A
Pass
Form errors are announced with role="alert" and aria-invalid
3.3.2 Labels or Instructions
A
Pass
All form fields have programmatic labels and placeholder is not the only label
3.3.3 Error Suggestion
AA
Pass
Localised strings (LABEL_ERROR_FIELD_NAME, LABEL_ERROR_FIELD_EMAIL, LABEL_ERROR_FIELD_REQUIRED) explain the issue
3.3.7 Redundant Entry
A
Pass
Pre-chat form data is persisted and re-applied across reopen
4.1.2 Name, Role, Value
A
Pass
All custom controls converted to native HTML or carry valid ARIA
4.1.3 Status Messages
AA
Pass
Conversation log uses role="log"/aria-live="polite"; emoji-blocked alert uses role="alert"
9. Implemented accessibility practices (inventory)
This section inventories concrete engineering practices present in the codebase.
9.1 Modal dialogs
@angular/cdk/a11y(A11yModule) imported inAppModule.cdkTrapFocus+cdkTrapFocusAutoCapture="true"on dialog surfaces includingConversationPreviewComponent,ConfirmCloseComponent,SelectionDepartmentComponent,PrechatFormComponent.@HostListener('keydown.escape')on dialog components to close on Escape and emit the close event.<h2>heading in confirm-close dialog wired througharia-labelledby="confirm-close-title".Native
<dialog>withshowModal()where used for confirm-close so the browser enforces focus behaviour in addition to CDK.
9.2 Image lightbox
Image trigger as
<button type="button">witharia-label.Lightbox iframe content with
role="dialog",aria-modal="true"and explicitaria-label.Close control as
<button>witharia-labeland focus-visible outline.Auto-focus on close button when opened; focus restored on close; Escape and backdrop close.
Document
langinherited; transitions disabled underprefers-reduced-motion.
9.3 Skip link and landmarks
Visible-on-focus skip link in
ConversationComponent(.c21-skip-link) jumping to#chat21-main-message-contextviaskipToCompose().role="region"+aria-labelonHomeComponent,ListAllConversationsComponent,ConversationComponent.<h1>for home welcome title;<p>for intro;<h2>for list-all-conversations title.
9.4 Internationalization and document language
TranslatorService updates document.documentElement.lang when a translation bundle loads (widget iframe document only).
CAROUSEL_LABEL
aria-label of the carousel container
CAROUSEL_SLIDE_LABEL
Template for aria-label="Slide {current} of {total}" per slide
SKIP_TO_COMPOSER
Text of the skip link
9.5 Reduced motion
A media-query block in src/app/sass/animations.scss neutralises animation duration, animation delay, transition duration and scroll-behavior for descendants of chat-root when prefers-reduced-motion: reduce is active.
9.6 Menu pattern
Popover menus in conversation-header and chat-menu-options are modelled as a role="group" of native <button> elements: trigger exposes aria-expanded, aria-haspopup="true", aria-controls; popover has aria-label; sound toggle uses aria-pressed; Escape closes the group.
9.7 Carousel
Wrapper:
role="region",aria-roledescription="carousel", localisedaria-label.Each card:
role="group",aria-roledescription="slide",aria-label="Slide N of M"(localisable).Arrow controls:
<button type="button">witharia-labelfromCAROUSEL_PREVIOUS/CAROUSEL_NEXT.Card CTAs:
<button>witharia-label.Images carry meaningful
alt; placeholder usesalt="".
9.8 Forms
form-text, form-textarea, form-checkbox expose pairing between labels, inputs, and error regions (aria-describedby, aria-invalid, role="alert" on errors).
9.9 Iframes
FrameComponent and ConversationInternalFrameComponent declare title, sandbox, referrerpolicy, and loading="lazy" on embedded frames.
9.10 Focus visibility
app.component.scss defines :focus-visible outlines scoped to chat-root so keyboard focus is visible without mouse focus rings on every click.
10. Testing methodology
Static review
Templates (*.component.html), styles (*.component.scss), and component classes reviewed against WCAG 2.2, WAI-ARIA 1.2, and EN 301 549 as informative reference.
Build verification
ng build and Angular template type-checking.
Diagnostics
TypeScript and Angular template diagnostics on modified files.
Manual keyboard walk-through
Tab / Shift+Tab / Enter / Space / Esc through launcher → home → conversation → composer (skip link), menu popovers, confirm-close, prechat, department selection, image lightbox, carousel arrows.
Screen reader smoke test
NVDA, VoiceOver — headings, log announcements, dialog labels, button labels in the active language.
Reduced-motion smoke test
With prefers-reduced-motion: reduce, animations and transitions inside chat-root are neutralised.
11. Primary source locations (reference)
The following paths are primary locations for verifying the practices above:
12. References
WCAG 2.2
https://www.w3.org/TR/WCAG22/
WAI-ARIA Authoring Practices
https://www.w3.org/WAI/ARIA/apg/
EN 301 549 v3.2.1
ETSI publication — accessibility requirements for ICT products and services
Angular CDK Accessibility
https://material.angular.dev/cdk/a11y/overview
MDN Accessibility
https://developer.mozilla.org/en-US/docs/Web/Accessibility
13. Continuous alignment
Tiledesk continues, day by day, to track evolving accessibility standards and platform behaviour across browsers and assistive technologies. The goal is to broaden coverage of WCAG-oriented success criteria, WAI-ARIA authoring practices, and EN 301 549–aligned expectations wherever they apply to this product category, and to reflect those expectations in design, implementation, and release testing. Standards and user-agent implementations evolve; accessibility posture is maintained as part of the normal engineering lifecycle.
14. Contact and feedback
For accessibility questions or updates for a custom deployment, contact the maintainers of this repository: https://github.com/Tiledesk/chat21-web-widget. Issues that mention accessibility in the title are routed to the team responsible for this statement.
Last updated