@chat21/chat21-web-widget 5.1.33-rc9 → 5.1.34-rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/package.json +1 -1
  3. package/src/app/component/conversation-detail/conversation/conversation.component.ts +3 -1
  4. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.spec.ts +0 -7
  5. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.ts +7 -5
  6. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.html +4 -3
  7. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.scss +18 -18
  8. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +6 -0
  9. package/src/app/component/conversation-detail/stream-audio-spectrum/stream-audio-spectrum.component.html +8 -5
  10. package/src/app/component/conversation-detail/stream-audio-spectrum/stream-audio-spectrum.component.scss +5 -1
  11. package/src/app/component/form/inputs/form-text/form-text.component.ts +9 -3
  12. package/src/app/component/message/bubble-message/bubble-message.component.scss +5 -0
  13. package/src/app/component/message/bubble-message/bubble-message.component.ts +14 -0
  14. package/src/app/component/message/json-sources/json-sources.component.scss +12 -8
  15. package/src/app/pipe/marked.pipe.ts +51 -41
  16. package/src/app/providers/global-settings.service.ts +31 -0
  17. package/src/app/providers/json-sources-parser.service.ts +25 -32
  18. package/src/app/providers/voice/voice-streaming.service.ts +11 -19
  19. package/src/app/providers/voice/voice-streaming.types.ts +0 -1
  20. package/src/app/providers/voice/voice.service.spec.ts +12 -45
  21. package/src/app/providers/voice/voice.service.ts +215 -45
  22. package/src/app/utils/globals.ts +10 -0
  23. package/src/assets/i18n/en.json +106 -125
  24. package/src/assets/i18n/es.json +1 -0
  25. package/src/assets/i18n/fr.json +1 -0
  26. package/src/assets/i18n/it.json +1 -0
  27. package/src/assets/sounds/keyboard.mp3 +0 -0
  28. package/src/assets/twp/chatbot-panel.html +3 -1
  29. package/src/chat21-core/utils/utils-message.ts +15 -5
  30. package/src/widget-config-template.json +1 -0
  31. package/src/widget-config.json +30 -28
  32. package/.playwright-mcp/console-2026-05-08T15-31-09-000Z.log +0 -17
  33. package/.playwright-mcp/console-2026-05-08T15-32-19-412Z.log +0 -89
  34. package/.playwright-mcp/console-2026-05-08T16-18-48-424Z.log +0 -133
  35. package/.playwright-mcp/console-2026-05-11T12-54-06-869Z.log +0 -13
  36. package/.playwright-mcp/console-2026-05-11T12-54-56-229Z.log +0 -147
  37. package/.playwright-mcp/console-2026-05-11T12-55-47-174Z.log +0 -183
  38. package/.playwright-mcp/console-2026-05-11T15-34-03-590Z.log +0 -210
  39. package/.playwright-mcp/console-2026-05-12T15-07-31-880Z.log +0 -118
  40. package/.playwright-mcp/page-2026-05-08T15-32-19-900Z.yml +0 -851
  41. package/.playwright-mcp/page-2026-05-08T15-32-47-264Z.yml +0 -857
  42. package/.playwright-mcp/page-2026-05-08T15-33-17-089Z.yml +0 -1110
  43. package/.playwright-mcp/page-2026-05-08T15-33-23-486Z.yml +0 -1069
  44. package/.playwright-mcp/page-2026-05-08T15-33-45-390Z.yml +0 -1076
  45. package/.playwright-mcp/page-2026-05-08T15-33-52-666Z.yml +0 -1072
  46. package/.playwright-mcp/page-2026-05-08T15-34-01-338Z.yml +0 -1085
  47. package/.playwright-mcp/page-2026-05-08T15-34-07-227Z.yml +0 -1072
  48. package/.playwright-mcp/page-2026-05-08T15-34-13-875Z.yml +0 -1072
  49. package/.playwright-mcp/page-2026-05-08T15-34-21-885Z.yml +0 -1109
  50. package/.playwright-mcp/page-2026-05-08T15-34-32-755Z.yml +0 -1109
  51. package/.playwright-mcp/page-2026-05-08T15-35-09-607Z.yml +0 -1119
  52. package/.playwright-mcp/page-2026-05-08T15-35-14-242Z.yml +0 -1109
  53. package/.playwright-mcp/page-2026-05-08T16-18-48-671Z.yml +0 -44
  54. package/.playwright-mcp/page-2026-05-08T16-18-52-753Z.png +0 -0
  55. package/.playwright-mcp/page-2026-05-08T16-19-13-919Z.yml +0 -68
  56. package/.playwright-mcp/page-2026-05-08T16-19-17-977Z.png +0 -0
  57. package/.playwright-mcp/page-2026-05-08T16-19-25-733Z.yml +0 -120
  58. package/.playwright-mcp/page-2026-05-08T16-19-29-252Z.png +0 -0
  59. package/.playwright-mcp/page-2026-05-08T16-19-39-269Z.yml +0 -80
  60. package/.playwright-mcp/page-2026-05-08T16-19-43-915Z.png +0 -0
  61. package/.playwright-mcp/page-2026-05-08T16-20-04-407Z.yml +0 -81
  62. package/.playwright-mcp/page-2026-05-08T16-20-08-984Z.png +0 -0
  63. package/.playwright-mcp/page-2026-05-08T16-20-32-397Z.png +0 -0
  64. package/.playwright-mcp/page-2026-05-08T16-20-58-658Z.png +0 -0
  65. package/.playwright-mcp/page-2026-05-08T16-21-12-320Z.yml +0 -86
  66. package/.playwright-mcp/page-2026-05-08T16-21-39-154Z.yml +0 -91
  67. package/.playwright-mcp/page-2026-05-08T16-21-45-420Z.png +0 -0
  68. package/.playwright-mcp/page-2026-05-08T16-22-21-062Z.yml +0 -0
  69. package/.playwright-mcp/page-2026-05-08T16-22-58-232Z.yml +0 -91
  70. package/.playwright-mcp/page-2026-05-08T16-23-36-520Z.yml +0 -0
  71. package/.playwright-mcp/page-2026-05-08T16-23-46-805Z.yml +0 -100
  72. package/.playwright-mcp/page-2026-05-08T16-23-55-169Z.png +0 -0
  73. package/.playwright-mcp/page-2026-05-08T16-24-26-574Z.yml +0 -91
  74. package/.playwright-mcp/page-2026-05-08T16-25-34-414Z.png +0 -0
  75. package/.playwright-mcp/page-2026-05-08T16-25-59-831Z.png +0 -0
  76. package/.playwright-mcp/page-2026-05-08T16-26-21-809Z.yml +0 -91
  77. package/.playwright-mcp/page-2026-05-08T16-26-47-443Z.yml +0 -105
  78. package/.playwright-mcp/page-2026-05-08T16-26-56-136Z.png +0 -0
  79. package/.playwright-mcp/page-2026-05-08T16-27-59-610Z.yml +0 -48
  80. package/.playwright-mcp/page-2026-05-11T12-54-07-180Z.yml +0 -44
  81. package/.playwright-mcp/page-2026-05-11T12-54-56-946Z.yml +0 -4
  82. package/.playwright-mcp/page-2026-05-11T12-55-47-503Z.yml +0 -24
  83. package/.playwright-mcp/page-2026-05-11T12-56-00-766Z.yml +0 -28
  84. package/.playwright-mcp/page-2026-05-11T12-56-06-438Z.yml +0 -90
  85. package/.playwright-mcp/page-2026-05-11T12-57-56-838Z.yml +0 -106
  86. package/.playwright-mcp/page-2026-05-11T12-58-00-124Z.yml +0 -106
  87. package/.playwright-mcp/page-2026-05-11T12-59-08-836Z.yml +0 -61
  88. package/.playwright-mcp/page-2026-05-11T12-59-12-088Z.yml +0 -61
  89. package/.playwright-mcp/page-2026-05-11T12-59-26-215Z.yml +0 -69
  90. package/.playwright-mcp/page-2026-05-11T12-59-29-519Z.yml +0 -69
  91. package/.playwright-mcp/page-2026-05-11T12-59-37-309Z.yml +0 -0
  92. package/.playwright-mcp/page-2026-05-11T12-59-39-968Z.yml +0 -79
  93. package/.playwright-mcp/page-2026-05-11T12-59-45-983Z.yml +0 -78
  94. package/.playwright-mcp/page-2026-05-11T12-59-49-951Z.yml +0 -78
  95. package/.playwright-mcp/page-2026-05-11T15-34-04-515Z.yml +0 -0
  96. package/.playwright-mcp/page-2026-05-12T15-07-32-171Z.yml +0 -44
  97. package/.playwright-mcp/page-2026-05-12T15-08-09-820Z.yml +0 -119
  98. package/docs/TILEDESK_WIDGET_ACCESSIBILITY_STATEMENT_COMPLETE.md +0 -379
  99. package/playwright-report/index.html +0 -90
  100. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component copy.html +0 -172
  101. package/test-results/.last-run.json +0 -4
@@ -1,379 +0,0 @@
1
- # Tiledesk Web Widget — Complete Accessibility Statement
2
-
3
- **Document type:** Consolidated alignment statement and implementation inventory
4
- **Language:** English
5
- **Last update:** 2026-05-12
6
-
7
- This document merges the narrative posture of `TILEDESK_WIDGET_ACCESSIBILITY_ALIGNMENT.md` with the structured inventory and tables from `ACCESSIBILITY-STATEMENT.md`. It describes **capabilities and patterns that are present** in the product engineering. It is **not** a legal certificate, VPAT, or third-party audit report.
8
-
9
- ---
10
-
11
- ## 1. Purpose and scope
12
-
13
- 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.
14
-
15
- The scope is the interactive widget experience (launcher, conversations, forms, media, and related overlays) as implemented in this codebase.
16
-
17
- 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.
18
-
19
- ---
20
-
21
- ## 2. Reference frameworks (informative)
22
-
23
- 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:
24
-
25
- | Reference | Role in product engineering |
26
- |-----------|----------------------------|
27
- | **W3C Web Content Accessibility Guidelines (WCAG) 2.2** (Level AA as design target) | Baseline for perceivable, operable, understandable, and robust UI behaviour. |
28
- | **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. |
29
- | **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). |
30
-
31
- 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.
32
-
33
- ---
34
-
35
- ## 3. Engineering posture (state of the art)
36
-
37
- 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:
38
-
39
- - **Semantic controls and naming:** Primary navigation and chrome actions use native `button` elements where the interaction model is activational; icon-only controls are paired with translatable `aria-label` (or equivalent) text from the product’s translation maps.
40
- - **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.
41
- - **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.
42
- - **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.
43
- - **Rich content:** Components for audio playback, carousels, and image preview follow patterns that expose control state and mark decorative graphics appropriately for assistive technologies.
44
- - **Motion and perception:** Stylesheets include reduced-motion handling so that users who prefer less animation receive a calmer visual experience.
45
- - **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.
46
-
47
- 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.
48
-
49
- ---
50
-
51
- ## 4. Document metadata
52
-
53
- | Field | Value |
54
- |---|---|
55
- | Product | Tiledesk Web Widget |
56
- | Package | `@chat21/chat21-web-widget` |
57
- | Version | 5.1.33 |
58
- | Stack | Angular 18.2.x (NgModule bootstrap), Angular CDK 17 (`A11yModule`), iframe-hosted (`launch.js`) |
59
- | 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) |
60
- | Document language | English |
61
-
62
- ---
63
-
64
- ## 5. Accessibility engineering coverage (summary)
65
-
66
- 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.
67
-
68
- | Area | Score (0–5) | Conformance level targeted |
69
- |---|---|---|
70
- | Semantic HTML | 4.5 | WCAG 2.2 AA |
71
- | Keyboard accessibility | 4.5 | WCAG 2.2 AA |
72
- | ARIA compliance | 4.5 | WAI-ARIA 1.2 |
73
- | Forms accessibility | 5.0 | WCAG 2.2 AA |
74
- | Dialog / Modal accessibility | 4.5 | WAI-ARIA 1.2 (focus trap via Angular CDK) |
75
- | Live regions / SR announcements | 4.0 | WCAG 4.1.3 |
76
- | Reduced motion / animations | 5.0 | WCAG 2.3.3 / 2.2.2 |
77
- | Internationalization | 4.5 | WCAG 3.1.1 / 3.1.2 |
78
- | Iframe integration | 4.5 | WCAG 2.4.1 / 4.1.2 |
79
- | **Overall self-assessment** | **4.5 / 5** | **WCAG 2.2 AA — engineering-oriented implementation** |
80
-
81
- ---
82
-
83
- ## 6. Project overview
84
-
85
- | Topic | Detail |
86
- |---|---|
87
- | **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. |
88
- | **Standalone components** | Not used; components are declared in `AppModule` (`src/app/app.module.ts`). |
89
- | **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`. |
90
- | **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. |
91
- | **Accessibility libraries used** | `@angular/cdk/a11y` (`A11yModule`) — focus trap support for modals where integrated. |
92
-
93
- ---
94
-
95
- ## 7. Component inventory and accessibility highlights
96
-
97
- 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.
98
-
99
- ### 7.1 Shell components
100
-
101
- | Component | Selector | Role / landmark | Accessibility highlights |
102
- |---|---|---|---|
103
- | `AppComponent` | `chat-root` | Application root | `:focus-visible` ring scoped to `chat-root`; `prefers-reduced-motion` honored |
104
- | `LauncherButtonComponent` | `chat-launcher-button` | `<button>` | `type="button"`, `aria-label` from `BUTTON_OPEN_CHAT`, focus-visible |
105
- | `EyeeyeCatcherCardComponent` | `chat-eyeeye-catcher-card` | Buttons | All clickable areas are real `<button type="button">` with `aria-label` |
106
- | `LastMessageComponent` | `chat-last-message` | Buttons | Preview activator is `<button>` with `aria-label`; close is a real button |
107
-
108
- ### 7.2 Home / list / department views
109
-
110
- | Component | Role / landmark | Highlights |
111
- |---|---|---|
112
- | `HomeComponent` | `role="region"` + `aria-label` | `<h1>` welcome, `<p>` intro; close/maximize/minimize/center are buttons; social channels labelled |
113
- | `HomeConversationsComponent` | `role="list"` + `role="listitem"` | "Show all conversations" and "Start new conversation" are buttons with `aria-label`; archived badge uses `role="img"` |
114
- | `ListAllConversationsComponent` | `role="region"` | `<h2>` title; back is a button; dead `altIconTitle` SVG markup removed |
115
- | `ListConversationsComponent` | List items | Each item activates a button; counters/badges marked `aria-hidden="true"` |
116
- | `SelectionDepartmentComponent` | `role="dialog"` `aria-modal="true"` `cdkTrapFocus` | `<h2>` title, Escape closes, options are real buttons |
117
-
118
- ### 7.3 Conversation surface
119
-
120
- | Component | Role / landmark | Highlights |
121
- |---|---|---|
122
- | `ConversationComponent` | `role="region"` | Visible-on-focus skip link → composer (WCAG 2.4.1); scroll-to-bottom is a button with `aria-label` |
123
- | `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) |
124
- | `ConversationContentComponent` | `role="log"` `aria-live="polite"` | Each message wrapped in `role="article"`; carousel slides expose `role="group"` + `aria-roledescription="slide"` |
125
- | `ConversationFooterComponent` | Form-like region | Attachment/emoji/send/record are buttons; emoji panel is `role="dialog"`; alert area is `role="alert"` `aria-live="assertive"` |
126
- | `ConversationAudioRecorderComponent` | Buttons | Record toggle uses `aria-pressed`; play/pause/delete/send all labelled |
127
- | `ConversationPreviewComponent` | `role="dialog"` `aria-modal="true"` `cdkTrapFocus` | `aria-labelledby` via `LABEL_PREVIEW`; Esc closes; close/send are buttons |
128
- | `ConversationInternalFrameComponent` | Panel | Iframe has `title`, `sandbox`, `referrerpolicy`, `loading="lazy"`; spinner `aria-hidden` |
129
- | `MenuOptionsComponent` | `role="group"` popover | Sound toggle uses `aria-pressed`; Esc closes; toggle button advertises `aria-expanded`/`aria-haspopup="true"` |
130
-
131
- ### 7.4 Form components
132
-
133
- | Component | Highlights |
134
- |---|---|
135
- | `PrechatFormComponent` | `role="dialog"` `aria-modal="true"` `cdkTrapFocus`; `<h2>` title; Escape closes |
136
- | `FormBuilderComponent` | Submit button is `type="button"`; native form semantics |
137
- | `FormTextComponent` | `<label for>` ↔ `<input id>`; `aria-required`, `aria-invalid`, `aria-describedby` to error `role="alert"`; `:focus-visible` ring |
138
- | `FormTextareaComponent` | Same pattern as `FormText`, plus `aria-multiline` |
139
- | `FormCheckboxComponent` | Native `<input type="checkbox">` linked to `<label>`; ARIA validation states wired |
140
- | `FormRadioButtonComponent` | Native `<input type="radio">` |
141
- | `FormSelectComponent` | Native `<select>` |
142
- | `FormLabelComponent` | Pure label slot |
143
-
144
- ### 7.5 Message bubble components
145
-
146
- | Component | Highlights |
147
- |---|---|
148
- | `BubbleMessageComponent` | Class-based selector replacing former duplicated `id="bubble-message"`; carries translation map down |
149
- | `TextComponent` | Root is `<div>`; markdown rendered through `marked` pipe; CSS targets the `.message_innerhtml` wrapper |
150
- | `HtmlComponent` | Class-based wrapper; sanitizer-aware |
151
- | `ImageComponent` | Wrapped in `<button>` with `aria-label`; lightbox is a `role="dialog"` iframe with close button, Escape support and focus restoration |
152
- | `FrameComponent` | Iframe hardened: dynamic `title`, `sandbox`, `referrerpolicy`, `loading="lazy"` |
153
- | `AudioComponent` | Play/pause buttons labelled via `BUTTON_PLAY_AUDIO` / `BUTTON_PAUSE_AUDIO` |
154
- | `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 |
155
- | `ActionButtonComponent`, `LinkButtonComponent`, `TextButtonComponent` | Real `<button>` / `<a>` with `aria-label` |
156
- | `ReturnReceiptComponent`, `LikeUnlikeComponent`, `AvatarComponent`, `InfoMessageComponent` | Decorative iconography flagged `aria-hidden="true"`; semantic content carries text alternatives |
157
-
158
- ### 7.6 Modals
159
-
160
- | Component | Highlights |
161
- |---|---|
162
- | `ConfirmCloseComponent` | `role="dialog"` `aria-modal="true"` `cdkTrapFocus` `aria-labelledby="confirm-close-title"`; `<h2>` heading; Escape closes; cancel/confirm are real buttons |
163
- | `ErrorAlertComponent` | Provides translatable error messages |
164
- | `StarRatingWidgetComponent` | Stars exposed as buttons; comment area is a labelled textarea |
165
-
166
- ---
167
-
168
- ## 8. WCAG 2.2 compliance checklist (implemented patterns)
169
-
170
- 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. Criteria that are not triggered by widget functionality (for example criteria scoped entirely to authentication flows the widget does not provide) are omitted from this checklist rather than listed separately.
171
-
172
- | Success Criterion | Level | Status | Evidence |
173
- |---|---|---|---|
174
- | 1.1.1 Non-text Content | A | Pass | All informational icons carry `aria-label`/`alt`; decorative SVGs use `aria-hidden="true"` and `focusable="false"` |
175
- | 1.3.1 Info and Relationships | A | Pass | `<h1>`/`<h2>` headings, `role="log"`, `role="article"`, `role="list"`, programmatic `<label for>` ↔ `<input id>` |
176
- | 1.3.2 Meaningful Sequence | A | Pass | Tab order follows reading order; high `tabindex` values removed |
177
- | 1.4.3 Contrast (Minimum) | AA | Pass | Default theme passes 4.5:1; custom palettes remain integrator-validated |
178
- | 1.4.4 Resize Text | AA | Pass | Layout is em-based; honours user font scaling |
179
- | 1.4.10 Reflow | AA | Pass | Responsive layout; no horizontal scrolling at 320 CSS pixels |
180
- | 1.4.11 Non-text Contrast | AA | Pass | Focus ring is `2px solid #1a73e8`, ≥ 3:1 against widget backgrounds |
181
- | 1.4.12 Text Spacing | AA | Pass | No critical fixed line-height/letter-spacing overrides |
182
- | 1.4.13 Content on Hover or Focus | AA | Pass | Tooltips use `:hover`/`:focus`, dismissable, persistent; no time-based dismissal |
183
- | 2.1.1 Keyboard | A | Pass | Every actionable element is reachable and operable from keyboard (real buttons, native form controls) |
184
- | 2.1.2 No Keyboard Trap | A | Pass | `cdkTrapFocus` traps only inside dialogs; Esc and dialog-close return focus |
185
- | 2.1.4 Character Key Shortcuts | A | Pass | The widget does not bind single-character shortcuts globally |
186
- | 2.2.2 Pause, Stop, Hide | A | Pass | Animations are decorative and short; reduced-motion media query disables them entirely |
187
- | 2.3.3 Animation from Interactions | AAA (informative) | Pass | `prefers-reduced-motion: reduce` neutralises animations and transitions inside `chat-root` |
188
- | 2.4.1 Bypass Blocks | A | Pass | Skip link in conversation surface jumps focus to the message composer |
189
- | 2.4.3 Focus Order | A | Pass | Logical order: header → log → composer → footer; high `tabindex` removed |
190
- | 2.4.7 Focus Visible | AA | Pass | Global `outline: none` removed; `:focus-visible` rule scoped to `chat-root` |
191
- | 2.4.11 Focus Not Obscured (Min) | AA | Pass | Sticky header/footer leave the active control visible; verified with launcher button |
192
- | 2.5.7 Dragging Movements | AA | Pass | Carousel can be operated by next/previous arrow buttons in addition to drag |
193
- | 2.5.8 Target Size (Minimum) | AA | Pass | All primary controls ≥ 24×24 CSS px |
194
- | 3.1.1 Language of Page | A | Pass | `<html lang>` synchronised with the active i18n language by `TranslatorService.syncDocumentLang` |
195
- | 3.2.1 On Focus | A | Pass | No context change on focus |
196
- | 3.2.2 On Input | A | Pass | No context change on input; the user always confirms |
197
- | 3.2.6 Consistent Help | A | Pass | Help / contact entry points (`menu-options`) are consistent across views |
198
- | 3.3.1 Error Identification | A | Pass | Form errors are announced with `role="alert"` and `aria-invalid` |
199
- | 3.3.2 Labels or Instructions | A | Pass | All form fields have programmatic labels and placeholder is not the only label |
200
- | 3.3.3 Error Suggestion | AA | Pass | Localised strings (`LABEL_ERROR_FIELD_NAME`, `LABEL_ERROR_FIELD_EMAIL`, `LABEL_ERROR_FIELD_REQUIRED`) explain the issue |
201
- | 3.3.7 Redundant Entry | A | Pass | Pre-chat form data is persisted and re-applied across reopen |
202
- | 4.1.2 Name, Role, Value | A | Pass | All custom controls converted to native HTML or carry valid ARIA |
203
- | 4.1.3 Status Messages | AA | Pass | Conversation log uses `role="log"`/`aria-live="polite"`; emoji-blocked alert uses `role="alert"` |
204
-
205
- ---
206
-
207
- ## 9. Implemented accessibility practices (inventory)
208
-
209
- This section inventories **concrete engineering practices** present in the codebase.
210
-
211
- ### 9.1 Modal dialogs
212
-
213
- - `@angular/cdk/a11y` (`A11yModule`) imported in `AppModule`.
214
- - `cdkTrapFocus` + `cdkTrapFocusAutoCapture="true"` on dialog surfaces including `ConversationPreviewComponent`, `ConfirmCloseComponent`, `SelectionDepartmentComponent`, `PrechatFormComponent`.
215
- - `@HostListener('keydown.escape')` on dialog components to close on Escape and emit the close event.
216
- - `<h2>` heading in confirm-close dialog wired through `aria-labelledby="confirm-close-title"`.
217
- - Native `<dialog>` with `showModal()` where used for confirm-close so the browser enforces focus behaviour in addition to CDK.
218
-
219
- ### 9.2 Image lightbox
220
-
221
- - Image trigger as `<button type="button">` with `aria-label`.
222
- - Lightbox iframe content with `role="dialog"`, `aria-modal="true"` and explicit `aria-label`.
223
- - Close control as `<button>` with `aria-label` and focus-visible outline.
224
- - Auto-focus on close button when opened; focus restored on close; Escape and backdrop close.
225
- - Document `lang` inherited; transitions disabled under `prefers-reduced-motion`.
226
-
227
- ### 9.3 Skip link and landmarks
228
-
229
- - Visible-on-focus skip link in `ConversationComponent` (`.c21-skip-link`) jumping to `#chat21-main-message-context` via `skipToCompose()`.
230
- - `role="region"` + `aria-label` on `HomeComponent`, `ListAllConversationsComponent`, `ConversationComponent`.
231
- - `<h1>` for home welcome title; `<p>` for intro; `<h2>` for list-all-conversations title.
232
-
233
- ### 9.4 Internationalization and document language
234
-
235
- `TranslatorService` updates `document.documentElement.lang` when a translation bundle loads (widget iframe document only).
236
-
237
- | Key | Purpose |
238
- |---|---|
239
- | `CAROUSEL_LABEL` | `aria-label` of the carousel container |
240
- | `CAROUSEL_SLIDE_LABEL` | Template for `aria-label="Slide {current} of {total}"` per slide |
241
- | `SKIP_TO_COMPOSER` | Text of the skip link |
242
-
243
- ### 9.5 Reduced motion
244
-
245
- 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.
246
-
247
- ### 9.6 Menu pattern
248
-
249
- 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.
250
-
251
- ### 9.7 Carousel
252
-
253
- - Wrapper: `role="region"`, `aria-roledescription="carousel"`, localised `aria-label`.
254
- - Each card: `role="group"`, `aria-roledescription="slide"`, `aria-label="Slide N of M"` (localisable).
255
- - Arrow controls: `<button type="button">` with `aria-label` from `CAROUSEL_PREVIOUS` / `CAROUSEL_NEXT`.
256
- - Card CTAs: `<button>` with `aria-label`.
257
- - Images carry meaningful `alt`; placeholder uses `alt=""`.
258
-
259
- ### 9.8 Forms
260
-
261
- `form-text`, `form-textarea`, `form-checkbox` expose pairing between labels, inputs, and error regions (`aria-describedby`, `aria-invalid`, `role="alert"` on errors).
262
-
263
- ### 9.9 Iframes
264
-
265
- `FrameComponent` and `ConversationInternalFrameComponent` declare `title`, `sandbox`, `referrerpolicy`, and `loading="lazy"` on embedded frames.
266
-
267
- ### 9.10 Focus visibility
268
-
269
- `app.component.scss` defines `:focus-visible` outlines scoped to `chat-root` so keyboard focus is visible without mouse focus rings on every click.
270
-
271
- ---
272
-
273
- ## 10. Testing methodology
274
-
275
- | Layer | Activity |
276
- |---|---|
277
- | 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. |
278
- | Build verification | `ng build` and Angular template type-checking. |
279
- | Diagnostics | TypeScript and Angular template diagnostics on modified files. |
280
- | 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. |
281
- | Screen reader smoke test | NVDA, VoiceOver — headings, log announcements, dialog labels, button labels in the active language. |
282
- | Reduced-motion smoke test | With `prefers-reduced-motion: reduce`, animations and transitions inside `chat-root` are neutralised. |
283
-
284
- ---
285
-
286
- ## 11. Primary source locations (reference)
287
-
288
- The following paths are primary locations for verifying the practices above:
289
-
290
- ```
291
- src/app/app.module.ts
292
- src/app/app.component.html
293
- src/app/app.component.scss
294
- src/app/sass/animations.scss
295
- src/app/providers/translator.service.ts
296
- src/app/providers/brand.service.ts
297
- src/app/utils/utils-resources.ts
298
- src/app/utils/globals.ts
299
- src/app/component/home/home.component.html
300
- src/app/component/home/home.component.scss
301
- src/app/component/home-conversations/home-conversations.component.html
302
- src/app/component/list-all-conversations/list-all-conversations.component.html
303
- src/app/component/list-all-conversations/list-all-conversations.component.scss
304
- src/app/component/selection-department/selection-department.component.html
305
- src/app/component/selection-department/selection-department.component.ts
306
- src/app/component/conversation-detail/conversation/conversation.component.html
307
- src/app/component/conversation-detail/conversation/conversation.component.scss
308
- src/app/component/conversation-detail/conversation/conversation.component.ts
309
- src/app/component/conversation-detail/conversation-header/conversation-header.component.html
310
- src/app/component/conversation-detail/conversation-content/conversation-content.component.html
311
- src/app/component/conversation-detail/conversation-footer/conversation-footer.component.html
312
- src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts
313
- src/app/component/conversation-detail/conversation-preview/conversation-preview.component.html
314
- src/app/component/conversation-detail/conversation-preview/conversation-preview.component.ts
315
- src/app/component/conversation-detail/conversation-internal-frame/conversation-internal-frame.component.html
316
- src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.html
317
- src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.ts
318
- src/app/component/menu-options/menu-options.component.html
319
- src/app/component/eyeeye-catcher-card/eyeeye-catcher-card.component.html
320
- src/app/component/eyeeye-catcher-card/eyeeye-catcher-card.component.scss
321
- src/app/component/last-message/last-message.component.html
322
- src/app/component/last-message/last-message.component.scss
323
- src/app/component/launcher-button/launcher-button.component.html
324
- src/app/component/send-button/send-button.component.html
325
- src/app/component/star-rating-widget/star-rating-widget.component.html
326
- src/app/component/form/prechat-form/prechat-form.component.html
327
- src/app/component/form/prechat-form/prechat-form.component.ts
328
- src/app/component/form/form-builder/form-builder.component.html
329
- src/app/component/form/inputs/form-text/*
330
- src/app/component/form/inputs/form-textarea/*
331
- src/app/component/form/inputs/form-checkbox/*
332
- src/app/component/message/bubble-message/bubble-message.component.html
333
- src/app/component/message/text/text.component.html
334
- src/app/component/message/text/text.component.scss
335
- src/app/component/message/html/html.component.html
336
- src/app/component/message/html/html.component.scss
337
- src/app/component/message/image/image.component.html
338
- src/app/component/message/image/image.component.scss
339
- src/app/component/message/image/image.component.ts
340
- src/app/component/message/audio/audio.component.html
341
- src/app/component/message/audio/audio.component.ts
342
- src/app/component/message/frame/frame.component.html
343
- src/app/component/message/frame/frame.component.ts
344
- src/app/component/message/buttons/action-button/action-button.component.html
345
- src/app/component/message/carousel/carousel.component.html
346
- src/app/component/message/carousel/carousel.component.scss
347
- src/app/component/message/carousel/carousel.component.ts
348
- src/app/modals/confirm-close/confirm-close.component.html
349
- src/app/modals/confirm-close/confirm-close.component.scss
350
- src/app/modals/confirm-close/confirm-close.component.ts
351
- src/assets/i18n/en.json
352
- src/assets/i18n/it.json
353
- src/assets/i18n/es.json
354
- src/assets/i18n/fr.json
355
- ```
356
-
357
- ---
358
-
359
- ## 12. References
360
-
361
- | Resource | URL |
362
- |---|---|
363
- | WCAG 2.2 | https://www.w3.org/TR/WCAG22/ |
364
- | WAI-ARIA Authoring Practices | https://www.w3.org/WAI/ARIA/apg/ |
365
- | EN 301 549 v3.2.1 | ETSI publication — accessibility requirements for ICT products and services |
366
- | Angular CDK Accessibility | https://material.angular.dev/cdk/a11y/overview |
367
- | MDN Accessibility | https://developer.mozilla.org/en-US/docs/Web/Accessibility |
368
-
369
- ---
370
-
371
- ## 13. Continuous alignment
372
-
373
- 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.
374
-
375
- ---
376
-
377
- ## 14. Contact and feedback
378
-
379
- 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.