azul_core/a11y.rs
1//! Accessibility types for screen reader support.
2//!
3//! Key types:
4//! - [`AccessibilityInfo`] — full accessibility metadata for a UI element
5//! - [`SmallAriaInfo`] — lightweight alternative for common cases (label + role + description)
6//! - [`AccessibilityRole`] — element purpose (button, link, checkbox, etc.)
7//! - [`AccessibilityState`] — dynamic state (focused, checked, expanded, etc.)
8//! - [`AccessibilityAction`] — actions performable on an element (click, scroll, etc.)
9//!
10//! These types are consumed by `layout/src/managers/a11y.rs` and mapped to
11//! platform accessibility backends in `dll/src/desktop/shell2/`.
12
13use azul_css::{
14 AzString, OptionF32, OptionString,
15 props::basic::length::FloatValue,
16};
17use crate::{
18 dom::OptionDomNodeId,
19 geom::LogicalPosition,
20 window::OptionVirtualKeyCodeCombo,
21};
22
23/// Holds information about a UI element for accessibility purposes (e.g., screen readers).
24/// This is a wrapper for platform-specific accessibility APIs like MSAA.
25#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
26#[repr(C)]
27pub struct AccessibilityInfo {
28 /// Get the "name" of the `IAccessible`, for example the
29 /// name of a button, checkbox or menu item. Try to use unique names
30 /// for each item in a dialog so that voice dictation software doesn't
31 /// have to deal with extra ambiguity.
32 pub accessibility_name: OptionString,
33 /// Get the "value" of the `IAccessible`, for example a number in a slider,
34 /// a URL for a link, the text a user entered in a field.
35 pub accessibility_value: OptionString,
36 /// Optional text description providing additional context about the element.
37 /// Maps to `aria-description` / accesskit's `set_description()`.
38 pub description: OptionString,
39 /// Optional keyboard accelerator.
40 pub accelerator: OptionVirtualKeyCodeCombo,
41 /// Optional "default action" description. Only used when there is at least
42 /// one `ComponentEventFilter::DefaultAction` callback present on this node.
43 pub default_action: OptionString,
44 /// Possible on/off states, such as focused, focusable, selected, selectable,
45 /// visible, protected (for passwords), checked, etc.
46 pub states: AccessibilityStateVec,
47 /// A list of actions the user can perform on this element.
48 /// Maps to accesskit's Action enum.
49 pub supported_actions: AccessibilityActionVec,
50 /// ID of another node that labels this one (for `aria-labelledby`).
51 pub labelled_by: OptionDomNodeId,
52 /// ID of another node that describes this one (for `aria-describedby`).
53 pub described_by: OptionDomNodeId,
54 /// Get an enumerated value representing what this IAccessible is used for,
55 /// for example is it a link, static text, editable text, a checkbox, or a table cell, etc.
56 pub role: AccessibilityRole,
57 /// For live regions that update automatically (e.g., chat messages, timers).
58 /// Maps to accesskit's `Live` property.
59 pub is_live_region: bool,
60}
61
62/// Actions that can be performed on an accessible element.
63/// This is a simplified version of accesskit::Action to avoid direct dependency in core.
64#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
65#[repr(C, u8)]
66pub enum AccessibilityAction {
67 /// The default action for the element (usually a click).
68 Default,
69 /// Set focus to this element.
70 Focus,
71 /// Remove focus from this element.
72 Blur,
73 /// Collapse an expandable element (e.g., tree node, accordion).
74 Collapse,
75 /// Expand a collapsible element (e.g., tree node, accordion).
76 Expand,
77 /// Scroll this element into view.
78 ScrollIntoView,
79 /// Increment a numeric value (e.g., slider, spinner).
80 Increment,
81 /// Decrement a numeric value (e.g., slider, spinner).
82 Decrement,
83 /// Show a context menu.
84 ShowContextMenu,
85 /// Hide a tooltip.
86 HideTooltip,
87 /// Show a tooltip.
88 ShowTooltip,
89 /// Scroll up.
90 ScrollUp,
91 /// Scroll down.
92 ScrollDown,
93 /// Scroll left.
94 ScrollLeft,
95 /// Scroll right.
96 ScrollRight,
97 /// Replace selected text with new text.
98 ReplaceSelectedText(AzString),
99 /// Scroll to a specific point.
100 ScrollToPoint(LogicalPosition),
101 /// Set scroll offset.
102 SetScrollOffset(LogicalPosition),
103 /// Set text selection.
104 SetTextSelection(TextSelectionStartEnd),
105 /// Set sequential focus navigation starting point.
106 SetSequentialFocusNavigationStartingPoint,
107 /// Set the value of a control.
108 SetValue(AzString),
109 /// Set numeric value of a control.
110 SetNumericValue(FloatValue),
111 /// Custom action with ID.
112 CustomAction(i32),
113}
114
115#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
116#[repr(C)]
117pub struct TextSelectionStartEnd {
118 pub selection_start: usize,
119 pub selection_end: usize,
120}
121
122impl_vec!(AccessibilityAction, AccessibilityActionVec, AccessibilityActionVecDestructor, AccessibilityActionVecDestructorType, AccessibilityActionVecSlice, OptionAccessibilityAction);
123impl_vec_debug!(AccessibilityAction, AccessibilityActionVec);
124impl_vec_clone!(
125 AccessibilityAction,
126 AccessibilityActionVec,
127 AccessibilityActionVecDestructor
128);
129impl_vec_partialeq!(AccessibilityAction, AccessibilityActionVec);
130impl_vec_eq!(AccessibilityAction, AccessibilityActionVec);
131impl_vec_partialord!(AccessibilityAction, AccessibilityActionVec);
132impl_vec_ord!(AccessibilityAction, AccessibilityActionVec);
133impl_vec_hash!(AccessibilityAction, AccessibilityActionVec);
134
135impl_option![
136 AccessibilityAction,
137 OptionAccessibilityAction,
138 copy = false,
139 [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
140];
141
142impl_option!(
143 AccessibilityInfo,
144 OptionAccessibilityInfo,
145 copy = false,
146 [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
147);
148
149/// Defines the element's purpose for accessibility APIs, informing assistive technologies
150/// like screen readers about the function of a UI element. Each variant corresponds to a
151/// standard control type or UI structure.
152///
153/// For more details, see the [MSDN Role Constants page](https://docs.microsoft.com/en-us/windows/winauto/object-roles).
154#[repr(C)]
155#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
156pub enum AccessibilityRole {
157 /// Represents the title or caption bar of a window.
158 /// - **Purpose**: To identify the title bar containing the window title and system commands.
159 /// - **When to use**: This role is typically inserted by the operating system for standard
160 /// windows.
161 /// - **Example**: The bar at the top of an application window displaying its name and the
162 /// minimize, maximize, and close buttons.
163 TitleBar,
164
165 /// Represents a menu bar at the top of a window.
166 /// - **Purpose**: To contain a set of top-level menus for an application.
167 /// - **When to use**: For the main menu bar of an application, such as one containing "File,"
168 /// "Edit," and "View."
169 /// - **Example**: The "File", "Edit", "View" menu bar at the top of a text editor.
170 MenuBar,
171
172 /// Represents a vertical or horizontal scroll bar.
173 /// - **Purpose**: To enable scrolling through content that is larger than the visible area.
174 /// - **When to use**: For any scrollable region of content.
175 /// - **Example**: The bar on the side of a web page that allows the user to scroll up and
176 /// down.
177 ScrollBar,
178
179 /// Represents a handle or grip used for moving or resizing.
180 /// - **Purpose**: To provide a user interface element for manipulating another element's size
181 /// or position.
182 /// - **When to use**: For handles that allow resizing of windows, panes, or other objects.
183 /// - **Example**: The small textured area in the bottom-right corner of a window that can be
184 /// dragged to resize it.
185 Grip,
186
187 /// Represents a system sound indicating an event.
188 /// - **Purpose**: To associate a sound with a UI event, providing an auditory cue.
189 /// - **When to use**: When a sound is the primary representation of an event.
190 /// - **Example**: A system notification sound that plays when a new message arrives.
191 Sound,
192
193 /// Represents the system's mouse pointer or other pointing device.
194 /// - **Purpose**: To indicate the screen position of the user's pointing device.
195 /// - **When to use**: This role is managed by the operating system.
196 /// - **Example**: The arrow that moves on the screen as you move the mouse.
197 Cursor,
198
199 /// Represents the text insertion point indicator.
200 /// - **Purpose**: To show the current text entry or editing position.
201 /// - **When to use**: This role is typically managed by the operating system for text input
202 /// fields.
203 /// - **Example**: The blinking vertical line in a text box that shows where the next character
204 /// will be typed.
205 Caret,
206
207 /// Represents an alert or notification.
208 /// - **Purpose**: To convey an important, non-modal message to the user.
209 /// - **When to use**: For non-intrusive notifications that do not require immediate user
210 /// interaction.
211 /// - **Example**: A small, temporary "toast" notification that appears to confirm an action,
212 /// like "Email sent."
213 Alert,
214
215 /// Represents a window frame.
216 /// - **Purpose**: To serve as the container for other objects like a title bar and client
217 /// area.
218 /// - **When to use**: This is a fundamental role, typically managed by the windowing system.
219 /// - **Example**: The main window of any application, which contains all other UI elements.
220 Window,
221
222 /// Represents a window's client area, where the main content is displayed.
223 /// - **Purpose**: To define the primary content area of a window.
224 /// - **When to use**: For the main content region of a window. It's often the default role for
225 /// a custom control container.
226 /// - **Example**: The area of a web browser where the web page content is rendered.
227 Client,
228
229 /// Represents a pop-up menu.
230 /// - **Purpose**: To display a list of `MenuItem` objects that appears when a user performs an
231 /// action.
232 /// - **When to use**: For context menus (right-click menus) or drop-down menus.
233 /// - **Example**: The menu that appears when you right-click on a file in a file explorer.
234 MenuPopup,
235
236 /// Represents an individual item within a menu.
237 /// - **Purpose**: To represent a single command, option, or separator within a menu.
238 /// - **When to use**: For individual options inside a `MenuBar` or `MenuPopup`.
239 /// - **Example**: The "Save" option within the "File" menu.
240 MenuItem,
241
242 /// Represents a small pop-up window that provides information.
243 /// - **Purpose**: To offer brief, contextual help or information about a UI element.
244 /// - **When to use**: For informational pop-ups that appear on mouse hover.
245 /// - **Example**: The small box of text that appears when you hover over a button in a
246 /// toolbar.
247 Tooltip,
248
249 /// Represents the main window of an application.
250 /// - **Purpose**: To identify the top-level window of an application.
251 /// - **When to use**: For the primary window that represents the application itself.
252 /// - **Example**: The main window of a calculator or notepad application.
253 Application,
254
255 /// Represents a document window within an application.
256 /// - **Purpose**: To represent a contained document, typically in a Multiple Document
257 /// Interface (MDI) application.
258 /// - **When to use**: For individual document windows inside a larger application shell.
259 /// - **Example**: In a photo editor that allows multiple images to be open in separate
260 /// windows, each image window would be a `Document`.
261 Document,
262
263 /// Represents a pane or a distinct section of a window.
264 /// - **Purpose**: To divide a window into visually and functionally distinct areas.
265 /// - **When to use**: For sub-regions of a window, like a navigation pane, preview pane, or
266 /// sidebar.
267 /// - **Example**: The preview pane in an email client that shows the content of the selected
268 /// email.
269 Pane,
270
271 /// Represents a graphical chart or graph.
272 /// - **Purpose**: To display data visually in a chart format.
273 /// - **When to use**: For any type of chart, such as a bar chart, line chart, or pie chart.
274 /// - **Example**: A bar chart displaying monthly sales figures.
275 Chart,
276
277 /// Represents a dialog box or message box.
278 /// - **Purpose**: To create a secondary window that requires user interaction before returning
279 /// to the main application.
280 /// - **When to use**: For modal or non-modal windows that prompt the user for information or a
281 /// response.
282 /// - **Example**: The "Open File" or "Print" dialog in most applications.
283 Dialog,
284
285 /// Represents a window's border.
286 /// - **Purpose**: To identify the border of a window, which is often used for resizing.
287 /// - **When to use**: This role is typically managed by the windowing system.
288 /// - **Example**: The decorative and functional frame around a window.
289 Border,
290
291 /// Represents a group of related controls.
292 /// - **Purpose**: To logically group other objects that share a common purpose.
293 /// - **When to use**: For grouping controls like a set of radio buttons or a fieldset with a
294 /// legend.
295 /// - **Example**: A "Settings" group box in a dialog that contains several related checkboxes.
296 Grouping,
297
298 /// Represents a visual separator.
299 /// - **Purpose**: To visually divide a space or a group of controls.
300 /// - **When to use**: For visual separators in menus, toolbars, or between panes.
301 /// - **Example**: The horizontal line in a menu that separates groups of related menu items.
302 Separator,
303
304 /// Represents a toolbar containing a group of controls.
305 /// - **Purpose**: To group controls, typically buttons, for quick access to frequently used
306 /// functions.
307 /// - **When to use**: For a bar of buttons or other controls, usually at the top of a window
308 /// or pane.
309 /// - **Example**: The toolbar at the top of a word processor with buttons for "Bold,"
310 /// "Italic," and "Underline."
311 Toolbar,
312
313 /// Represents a status bar for displaying information.
314 /// - **Purpose**: To display status information about the current state of the application.
315 /// - **When to use**: For a bar, typically at the bottom of a window, that displays messages.
316 /// - **Example**: The bar at the bottom of a web browser that shows the loading status of a
317 /// page.
318 StatusBar,
319
320 /// Represents a data table.
321 /// - **Purpose**: To present data in a two-dimensional grid of rows and columns.
322 /// - **When to use**: For grid-like data presentation.
323 /// - **Example**: A spreadsheet or a table of data in a database application.
324 Table,
325
326 /// Represents a column header in a table.
327 /// - **Purpose**: To provide a label for a column of data.
328 /// - **When to use**: For the headers of columns in a `Table`.
329 /// - **Example**: The header row in a spreadsheet with labels like "Name," "Date," and
330 /// "Amount."
331 ColumnHeader,
332
333 /// Represents a row header in a table.
334 /// - **Purpose**: To provide a label for a row of data.
335 /// - **When to use**: For the headers of rows in a `Table`.
336 /// - **Example**: The numbered rows on the left side of a spreadsheet.
337 RowHeader,
338
339 /// Represents a full column of cells in a table.
340 /// - **Purpose**: To represent an entire column as a single accessible object.
341 /// - **When to use**: When it is useful to interact with a column as a whole.
342 /// - **Example**: The "Amount" column in a financial data table.
343 Column,
344
345 /// Represents a full row of cells in a table.
346 /// - **Purpose**: To represent an entire row as a single accessible object.
347 /// - **When to use**: When it is useful to interact with a row as a whole.
348 /// - **Example**: A row representing a single customer's information in a customer list.
349 Row,
350
351 /// Represents a single cell within a table.
352 /// - **Purpose**: To represent a single data point or control within a `Table`.
353 /// - **When to use**: For individual cells in a grid or table.
354 /// - **Example**: A single cell in a spreadsheet containing a specific value.
355 Cell,
356
357 /// Represents a hyperlink to a resource.
358 /// - **Purpose**: To provide a navigational link to another document or location.
359 /// - **When to use**: For text or images that, when clicked, navigate to another resource.
360 /// - **Example**: A clickable link on a web page.
361 Link,
362
363 /// Represents a help balloon or pop-up.
364 /// - **Purpose**: To provide more detailed help information than a standard tooltip.
365 /// - **When to use**: For a pop-up that offers extended help text, often initiated by a help
366 /// button.
367 /// - **Example**: A pop-up balloon with a paragraph of help text that appears when a user
368 /// clicks a help icon.
369 HelpBalloon,
370
371 /// Represents an animated, character-like graphic object.
372 /// - **Purpose**: To provide an animated agent for user assistance or entertainment.
373 /// - **When to use**: For animated characters or avatars that provide help or guidance.
374 /// - **Example**: An animated paperclip that offers tips in a word processor (e.g.,
375 /// Microsoft's Clippy).
376 Character,
377
378 /// Represents a list of items.
379 /// - **Purpose**: To contain a set of `ListItem` objects.
380 /// - **When to use**: For list boxes or similar controls that present a list of selectable
381 /// items.
382 /// - **Example**: The list of files in a file selection dialog.
383 List,
384
385 /// Represents an individual item within a list.
386 /// - **Purpose**: To represent a single, selectable item within a `List`.
387 /// - **When to use**: For each individual item in a list box or combo box.
388 /// - **Example**: A single file name in a list of files.
389 ListItem,
390
391 /// Represents an outline or tree structure.
392 /// - **Purpose**: To display a hierarchical view of data.
393 /// - **When to use**: For tree-view controls that show nested items.
394 /// - **Example**: A file explorer's folder tree view.
395 Outline,
396
397 /// Represents an individual item within an outline or tree.
398 /// - **Purpose**: To represent a single node (which can be a leaf or a branch) in an
399 /// `Outline`.
400 /// - **When to use**: For each node in a tree view.
401 /// - **Example**: A single folder in a file explorer's tree view.
402 OutlineItem,
403
404 /// Represents a single tab in a tabbed interface.
405 /// - **Purpose**: To provide a control for switching between different `PropertyPage` views.
406 /// - **When to use**: For the individual tabs that the user can click to switch pages.
407 /// - **Example**: The "General" and "Security" tabs in a file properties dialog.
408 PageTab,
409
410 /// Represents the content of a page in a property sheet.
411 /// - **Purpose**: To serve as a container for the controls displayed when a `PageTab` is
412 /// selected.
413 /// - **When to use**: For the content area associated with a specific tab.
414 /// - **Example**: The set of options displayed when the "Security" tab is active.
415 PropertyPage,
416
417 /// Represents a visual indicator, like a slider thumb.
418 /// - **Purpose**: To visually indicate the current value or position of another control.
419 /// - **When to use**: For a sub-element that indicates status, like the thumb of a scrollbar.
420 /// - **Example**: The draggable thumb of a scrollbar that indicates the current scroll
421 /// position.
422 Indicator,
423
424 /// Represents a picture or graphical image.
425 /// - **Purpose**: To display a non-interactive image.
426 /// - **When to use**: For images and icons that are purely decorative or informational.
427 /// - **Example**: A company logo displayed in an application's "About" dialog.
428 Graphic,
429
430 /// Represents read-only text.
431 /// - **Purpose**: To provide a non-editable text label for another control or for displaying
432 /// information.
433 /// - **When to use**: For text that the user cannot edit.
434 /// - **Example**: The label "Username:" next to a text input field.
435 StaticText,
436
437 /// Represents editable text or a text area.
438 /// - **Purpose**: To allow for user text input or selection.
439 /// - **When to use**: For text input fields where the user can type.
440 /// - **Example**: A text box for entering a username or password.
441 Text,
442
443 /// Represents a standard push button.
444 /// - **Purpose**: To initiate an immediate action.
445 /// - **When to use**: For standard buttons that perform an action when clicked.
446 /// - **Example**: An "OK" or "Cancel" button in a dialog.
447 PushButton,
448
449 /// Represents a check box control.
450 /// - **Purpose**: To allow the user to make a binary choice (checked or unchecked).
451 /// - **When to use**: For options that can be toggled on or off independently.
452 /// - **Example**: A "Remember me" checkbox on a login form.
453 CheckButton,
454
455 /// Represents a radio button.
456 /// - **Purpose**: To allow the user to select one option from a mutually exclusive group.
457 /// - **When to use**: For a choice where only one option from a `Grouping` can be selected.
458 /// - **Example**: "Male" and "Female" radio buttons for selecting gender.
459 RadioButton,
460
461 /// Represents a combination of a text field and a drop-down list.
462 /// - **Purpose**: To allow the user to either type a value or select one from a list.
463 /// - **When to use**: For controls that offer a list of suggestions but also allow custom
464 /// input.
465 /// - **Example**: A font selector that allows you to type a font name or choose one from a
466 /// list.
467 ComboBox,
468
469 /// Represents a drop-down list box.
470 /// - **Purpose**: To allow the user to select an item from a non-editable list that drops
471 /// down.
472 /// - **When to use**: For selecting a single item from a predefined list of options.
473 /// - **Example**: A country selection drop-down menu.
474 DropList,
475
476 /// Represents a progress bar.
477 /// - **Purpose**: To indicate the progress of a lengthy operation.
478 /// - **When to use**: To provide feedback for tasks like file downloads or installations.
479 /// - **Example**: The bar that fills up to show the progress of a file copy operation.
480 ProgressBar,
481
482 /// Represents a dial or knob.
483 /// - **Purpose**: To allow selecting a value from a continuous or discrete range, often
484 /// circularly.
485 /// - **When to use**: For controls that resemble real-world dials, like a volume knob.
486 /// - **Example**: A volume control knob in a media player application.
487 Dial,
488
489 /// Represents a control for entering a keyboard shortcut.
490 /// - **Purpose**: To capture a key combination from the user.
491 /// - **When to use**: In settings where users can define their own keyboard shortcuts.
492 /// - **Example**: A text field in a settings dialog where a user can press a key combination
493 /// to assign it to a command.
494 HotkeyField,
495
496 /// Represents a slider for selecting a value within a range.
497 /// - **Purpose**: To allow the user to adjust a setting along a continuous or discrete range.
498 /// - **When to use**: For adjusting values like volume, brightness, or zoom level.
499 /// - **Example**: A slider to control the volume of a video.
500 Slider,
501
502 /// Represents a spin button (up/down arrows) for incrementing or decrementing a value.
503 /// - **Purpose**: To provide fine-tuned adjustment of a value, typically numeric.
504 /// - **When to use**: For controls that allow stepping through a range of values.
505 /// - **Example**: The up and down arrows next to a number input for setting the font size.
506 SpinButton,
507
508 /// Represents a diagram or flowchart.
509 /// - **Purpose**: To represent data or relationships in a schematic form.
510 /// - **When to use**: For visual representations of structures that are not charts, like a
511 /// database schema diagram.
512 /// - **Example**: A flowchart illustrating a business process.
513 Diagram,
514
515 /// Represents an animation control.
516 /// - **Purpose**: To display a sequence of images or indicate an ongoing process.
517 /// - **When to use**: For animations that show that an operation is in progress.
518 /// - **Example**: The animation that plays while files are being copied.
519 Animation,
520
521 /// Represents a mathematical equation.
522 /// - **Purpose**: To display a mathematical formula in the correct format.
523 /// - **When to use**: For displaying mathematical equations.
524 /// - **Example**: A rendered mathematical equation in a scientific document editor.
525 Equation,
526
527 /// Represents a button that drops down a list of items.
528 /// - **Purpose**: To combine a default action button with a list of alternative actions.
529 /// - **When to use**: For buttons that have a primary action and a secondary list of options.
530 /// - **Example**: A "Send" button with a dropdown arrow that reveals "Send and Archive."
531 ButtonDropdown,
532
533 /// Represents a button that drops down a full menu.
534 /// - **Purpose**: To provide a button that opens a menu of choices rather than performing a
535 /// single action.
536 /// - **When to use**: When a button's primary purpose is to reveal a menu.
537 /// - **Example**: A "Tools" button that opens a menu with various tool options.
538 ButtonMenu,
539
540 /// Represents a button that drops down a grid for selection.
541 /// - **Purpose**: To allow selection from a two-dimensional grid of options.
542 /// - **When to use**: For buttons that open a grid-based selection UI.
543 /// - **Example**: A color picker button that opens a grid of color swatches.
544 ButtonDropdownGrid,
545
546 /// Represents blank space between other objects.
547 /// - **Purpose**: To represent significant empty areas in a UI that are part of the layout.
548 /// - **When to use**: Sparingly, to signify that a large area is intentionally blank.
549 /// - **Example**: A large empty panel in a complex layout might use this role.
550 Whitespace,
551
552 /// Represents the container for a set of tabs.
553 /// - **Purpose**: To group a set of `PageTab` elements.
554 /// - **When to use**: To act as the parent container for a row or column of tabs.
555 /// - **Example**: The entire row of tabs at the top of a properties dialog.
556 PageTabList,
557
558 /// Represents a clock control.
559 /// - **Purpose**: To display the current time.
560 /// - **When to use**: For any UI element that displays time.
561 /// - **Example**: The clock in the system tray of the operating system.
562 Clock,
563
564 /// Represents a button with two parts: a default action and a dropdown.
565 /// - **Purpose**: To combine a frequently used action with a set of related, less-used
566 /// actions.
567 /// - **When to use**: When a button has a default action and other related actions available
568 /// in a dropdown.
569 /// - **Example**: A "Save" split button where the primary part saves, and the dropdown offers
570 /// "Save As."
571 SplitButton,
572
573 /// Represents a control for entering an IP address.
574 /// - **Purpose**: To provide a specialized input field for IP addresses, often with formatting
575 /// and validation.
576 /// - **When to use**: For dedicated IP address input fields.
577 /// - **Example**: A network configuration dialog with a field for entering a static IP
578 /// address.
579 IpAddress,
580
581 /// Represents an element with no specific role.
582 /// - **Purpose**: To indicate an element that has no semantic meaning for accessibility.
583 /// - **When to use**: Should be used sparingly for purely decorative elements that should be
584 /// ignored by assistive technologies.
585 /// - **Example**: A decorative graphical flourish that has no function or information to
586 /// convey.
587 Nothing,
588
589 /// Unknown or unspecified role.
590 /// - **Purpose**: Default fallback when no specific role is assigned.
591 /// - **When to use**: As a default value or when role information is unavailable.
592 Unknown,
593}
594
595impl_option!(
596 AccessibilityRole,
597 OptionAccessibilityRole,
598 [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
599);
600
601/// Defines the current state of an element for accessibility APIs (e.g., focused, checked).
602/// These states provide dynamic information to assistive technologies about the element's
603/// condition.
604///
605/// See the [MSDN State Constants page](https://docs.microsoft.com/en-us/windows/win32/winauto/object-state-constants) for more details.
606#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
607#[repr(C)]
608pub enum AccessibilityState {
609 /// The element is unavailable and cannot be interacted with.
610 /// - **Purpose**: To indicate that a control is disabled or grayed out.
611 /// - **When to use**: For disabled buttons, non-interactive menu items, or any control that is
612 /// temporarily non-functional.
613 /// - **Example**: A "Save" button that is disabled until the user makes changes to a document.
614 Unavailable,
615
616 /// The element is selected.
617 /// - **Purpose**: To indicate that an item is currently chosen or highlighted. This is
618 /// distinct from having focus.
619 /// - **When to use**: For selected items in a list, highlighted text, or the currently active
620 /// tab in a tab list.
621 /// - **Example**: A file highlighted in a file explorer, or multiple selected emails in an
622 /// inbox.
623 Selected,
624
625 /// The element has the keyboard focus.
626 /// - **Purpose**: To identify the single element that will receive keyboard input.
627 /// - **When to use**: For the control that is currently active and ready to be manipulated by
628 /// the keyboard.
629 /// - **Example**: A text box with a blinking cursor, or a button with a dotted outline around
630 /// it.
631 Focused,
632
633 /// The element is checked, toggled, or in an "on" state.
634 /// - **Purpose**: To represent checked checkboxes, selected radio buttons, and active toggles.
635 /// - **Example**: A checked "I agree" checkbox, a selected "Yes" radio button.
636 CheckedTrue,
637 /// The element is unchecked, untoggled, or in an "off" state.
638 /// - **Purpose**: To explicitly represent an unchecked checkbox or unselected radio button.
639 /// - **Example**: An unchecked checkbox that the user has not yet ticked.
640 CheckedFalse,
641
642 /// The element's content cannot be edited by the user.
643 /// - **Purpose**: To indicate that the element's value can be viewed and copied, but not
644 /// modified.
645 /// - **When to use**: For display-only text fields or documents.
646 /// - **Example**: A text box displaying a license agreement that the user can scroll through
647 /// but cannot edit.
648 Readonly,
649
650 /// The element is the default action in a dialog or form.
651 /// - **Purpose**: To identify the button that will be activated if the user presses the Enter
652 /// key.
653 /// - **When to use**: For the primary confirmation button in a dialog.
654 /// - **Example**: The "OK" button in a dialog box, which often has a thicker or colored
655 /// border.
656 Default,
657
658 /// The element is expanded, showing its child items.
659 /// - **Purpose**: To indicate that a collapsible element is currently open and its contents
660 /// are visible.
661 /// - **When to use**: For tree view nodes, combo boxes with their lists open, or expanded
662 /// accordion panels.
663 /// - **Example**: A folder in a file explorer's tree view that has been clicked to show its
664 /// subfolders.
665 Expanded,
666
667 /// The element is collapsed, hiding its child items.
668 /// - **Purpose**: To indicate that a collapsible element is closed and its contents are
669 /// hidden.
670 /// - **When to use**: The counterpart to `Expanded` for any collapsible UI element.
671 /// - **Example**: A closed folder in a file explorer's tree view, hiding its contents.
672 Collapsed,
673
674 /// The element is busy and cannot respond to user interaction.
675 /// - **Purpose**: To indicate that the element or application is performing an operation and
676 /// is temporarily unresponsive.
677 /// - **When to use**: When an application is loading, processing data, or otherwise occupied.
678 /// - **Example**: A window that is grayed out and shows a spinning cursor while saving a large
679 /// file.
680 Busy,
681
682 /// The element is not currently visible on the screen.
683 /// - **Purpose**: To indicate that an element exists but is currently scrolled out of the
684 /// visible area.
685 /// - **When to use**: For items in a long list or a large document that are not within the
686 /// current viewport.
687 /// - **Example**: A list item in a long dropdown that you would have to scroll down to see.
688 Offscreen,
689
690 /// The element can accept keyboard focus.
691 /// - **Purpose**: To indicate that the user can navigate to this element using the keyboard
692 /// (e.g., with the Tab key).
693 /// - **When to use**: On all interactive elements like buttons, links, and input fields,
694 /// whether they currently have focus or not.
695 /// - **Example**: A button that can receive focus, even if it is not the currently focused
696 /// element.
697 Focusable,
698
699 /// The element is a container whose children can be selected.
700 /// - **Purpose**: To indicate that the element contains items that can be chosen.
701 /// - **When to use**: On container controls like list boxes, tree views, or text spans where
702 /// text can be highlighted.
703 /// - **Example**: A list box control is `Selectable`, while its individual list items have the
704 /// `Selected` state when chosen.
705 Selectable,
706
707 /// The element is a hyperlink.
708 /// - **Purpose**: To identify an object that navigates to another resource or location when
709 /// activated.
710 /// - **When to use**: On any object that functions as a hyperlink.
711 /// - **Example**: Text or an image that, when clicked, opens a web page.
712 Linked,
713
714 /// The element is a hyperlink that has been visited.
715 /// - **Purpose**: To indicate that a hyperlink has already been followed by the user.
716 /// - **When to use**: On a `Linked` object that the user has previously activated.
717 /// - **Example**: A hyperlink on a web page that has changed color to show it has been
718 /// visited.
719 Traversed,
720
721 /// The element allows multiple of its children to be selected at once.
722 /// - **Purpose**: To indicate that a container control supports multi-selection.
723 /// - **When to use**: On container controls like list boxes or file explorers that support
724 /// multiple selections (e.g., with Ctrl-click).
725 /// - **Example**: A file list that allows the user to select several files at once for a copy
726 /// operation.
727 Multiselectable,
728
729 /// The element contains protected content that should not be read aloud.
730 /// - **Purpose**: To prevent assistive technologies from speaking the content of a sensitive
731 /// field.
732 /// - **When to use**: Primarily for password input fields.
733 /// - **Example**: A password text box where typed characters are masked with asterisks or
734 /// dots.
735 Protected,
736}
737
738impl_option!(
739 AccessibilityState,
740 OptionAccessibilityState,
741 [Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash]
742);
743
744impl_vec!(AccessibilityState, AccessibilityStateVec, AccessibilityStateVecDestructor, AccessibilityStateVecDestructorType, AccessibilityStateVecSlice, OptionAccessibilityState);
745impl_vec_clone!(
746 AccessibilityState,
747 AccessibilityStateVec,
748 AccessibilityStateVecDestructor
749);
750impl_vec_debug!(AccessibilityState, AccessibilityStateVec);
751impl_vec_partialeq!(AccessibilityState, AccessibilityStateVec);
752impl_vec_partialord!(AccessibilityState, AccessibilityStateVec);
753impl_vec_eq!(AccessibilityState, AccessibilityStateVec);
754impl_vec_ord!(AccessibilityState, AccessibilityStateVec);
755impl_vec_hash!(AccessibilityState, AccessibilityStateVec);
756
757/// Compact accessibility information for common use cases.
758///
759/// This is a lighter-weight alternative to `AccessibilityInfo` for cases where
760/// only basic accessibility properties are needed. Developers must explicitly
761/// pass `None` if they choose not to provide accessibility information.
762#[derive(Debug, Clone, PartialEq, Eq, Hash)]
763#[repr(C)]
764pub struct SmallAriaInfo {
765 /// Accessible label/name
766 pub label: OptionString,
767 /// Element's role (button, link, etc.)
768 pub role: OptionAccessibilityRole,
769 /// Additional description
770 pub description: OptionString,
771}
772
773impl_option!(
774 SmallAriaInfo,
775 OptionSmallAriaInfo,
776 copy = false,
777 [Debug, Clone, PartialEq, Eq, Hash]
778);
779
780impl SmallAriaInfo {
781 pub fn label<S: Into<AzString>>(text: S) -> Self {
782 Self {
783 label: OptionString::Some(text.into()),
784 role: OptionAccessibilityRole::None,
785 description: OptionString::None,
786 }
787 }
788
789 pub fn with_role(mut self, role: AccessibilityRole) -> Self {
790 self.role = OptionAccessibilityRole::Some(role);
791 self
792 }
793
794 pub fn with_description<S: Into<AzString>>(mut self, desc: S) -> Self {
795 self.description = OptionString::Some(desc.into());
796 self
797 }
798
799 /// Convert to full `AccessibilityInfo`
800 pub fn to_full_info(&self) -> AccessibilityInfo {
801 AccessibilityInfo {
802 accessibility_name: self.label.clone(),
803 accessibility_value: OptionString::None,
804 description: self.description.clone(),
805 role: match self.role {
806 OptionAccessibilityRole::Some(r) => r,
807 OptionAccessibilityRole::None => AccessibilityRole::Unknown,
808 },
809 states: Vec::new().into(),
810 accelerator: OptionVirtualKeyCodeCombo::None,
811 default_action: OptionString::None,
812 supported_actions: Vec::new().into(),
813 is_live_region: false,
814 labelled_by: OptionDomNodeId::None,
815 described_by: OptionDomNodeId::None,
816 }
817 }
818}
819
820/// Accessibility information for a `<progress>` indicator.
821///
822/// Mirrors HTML's `<progress value max>` plus an `indeterminate` flag for
823/// progress bars whose end is unknown. Maps to `AccessibilityRole::ProgressBar`.
824#[derive(Debug, Clone, PartialEq)]
825#[repr(C)]
826pub struct ProgressAriaInfo {
827 /// Accessible label describing the task being measured.
828 pub label: OptionString,
829 /// Current progress value. `None` for indeterminate progress.
830 pub current_value: OptionF32,
831 /// Maximum value the progress bar can reach. `None` falls back to `1.0`.
832 pub max: OptionF32,
833 /// `true` for spinners / progress with no known endpoint. Overrides `current_value`.
834 pub indeterminate: bool,
835 /// Optional extended description (`aria-describedby` equivalent).
836 pub description: OptionString,
837}
838
839impl_option!(
840 ProgressAriaInfo,
841 OptionProgressAriaInfo,
842 copy = false,
843 [Debug, Clone, PartialEq]
844);
845
846impl ProgressAriaInfo {
847 /// Creates a `ProgressAriaInfo` with only an accessible label.
848 pub fn create(label: AzString) -> Self {
849 Self {
850 label: OptionString::Some(label),
851 current_value: OptionF32::None,
852 max: OptionF32::None,
853 indeterminate: false,
854 description: OptionString::None,
855 }
856 }
857
858 /// Returns a copy with the given current value.
859 pub fn with_current_value(mut self, value: f32) -> Self {
860 self.current_value = OptionF32::Some(value);
861 self
862 }
863
864 /// Returns a copy with the given maximum value.
865 pub fn with_max(mut self, max: f32) -> Self {
866 self.max = OptionF32::Some(max);
867 self
868 }
869
870 /// Returns a copy with the indeterminate flag set.
871 pub fn with_indeterminate(mut self, indeterminate: bool) -> Self {
872 self.indeterminate = indeterminate;
873 self
874 }
875
876 /// Returns a copy with the given description.
877 pub fn with_description(mut self, desc: AzString) -> Self {
878 self.description = OptionString::Some(desc);
879 self
880 }
881
882 /// Convert to full `AccessibilityInfo` so the value can be installed on a node.
883 pub fn to_full_info(&self) -> AccessibilityInfo {
884 let value_string = if self.indeterminate {
885 OptionString::None
886 } else {
887 match self.current_value {
888 OptionF32::Some(v) => OptionString::Some(format!("{}", v).into()),
889 OptionF32::None => OptionString::None,
890 }
891 };
892 AccessibilityInfo {
893 accessibility_name: self.label.clone(),
894 accessibility_value: value_string,
895 description: self.description.clone(),
896 role: AccessibilityRole::ProgressBar,
897 states: Vec::new().into(),
898 accelerator: OptionVirtualKeyCodeCombo::None,
899 default_action: OptionString::None,
900 supported_actions: Vec::new().into(),
901 is_live_region: false,
902 labelled_by: OptionDomNodeId::None,
903 described_by: OptionDomNodeId::None,
904 }
905 }
906}
907
908/// Accessibility information for a `<meter>` gauge.
909///
910/// Unlike `<progress>`, `<meter>` always carries a known `value`/`min`/`max`
911/// triple, so those fields are required at construction time. Maps to
912/// `AccessibilityRole::Indicator`.
913#[derive(Debug, Clone, PartialEq)]
914#[repr(C)]
915pub struct MeterAriaInfo {
916 /// Accessible label describing what the meter measures.
917 pub label: OptionString,
918 /// Current value of the meter (within `[min, max]`).
919 pub current_value: f32,
920 /// Lower bound of the measurement range.
921 pub min: f32,
922 /// Upper bound of the measurement range.
923 pub max: f32,
924 /// Optional "low" threshold (values below this are considered low).
925 pub low: OptionF32,
926 /// Optional "high" threshold (values above this are considered high).
927 pub high: OptionF32,
928 /// Optional optimum value within the range.
929 pub optimum: OptionF32,
930 /// Optional extended description.
931 pub description: OptionString,
932}
933
934impl_option!(
935 MeterAriaInfo,
936 OptionMeterAriaInfo,
937 copy = false,
938 [Debug, Clone, PartialEq]
939);
940
941impl MeterAriaInfo {
942 /// Creates a `MeterAriaInfo` with the required label and value/range triple.
943 pub fn create(label: AzString, current_value: f32, min: f32, max: f32) -> Self {
944 Self {
945 label: OptionString::Some(label),
946 current_value,
947 min,
948 max,
949 low: OptionF32::None,
950 high: OptionF32::None,
951 optimum: OptionF32::None,
952 description: OptionString::None,
953 }
954 }
955
956 /// Returns a copy with the given low threshold.
957 pub fn with_low(mut self, low: f32) -> Self {
958 self.low = OptionF32::Some(low);
959 self
960 }
961
962 /// Returns a copy with the given high threshold.
963 pub fn with_high(mut self, high: f32) -> Self {
964 self.high = OptionF32::Some(high);
965 self
966 }
967
968 /// Returns a copy with the given optimum value.
969 pub fn with_optimum(mut self, optimum: f32) -> Self {
970 self.optimum = OptionF32::Some(optimum);
971 self
972 }
973
974 /// Returns a copy with the given description.
975 pub fn with_description(mut self, desc: AzString) -> Self {
976 self.description = OptionString::Some(desc);
977 self
978 }
979
980 /// Convert to full `AccessibilityInfo` so the value can be installed on a node.
981 pub fn to_full_info(&self) -> AccessibilityInfo {
982 AccessibilityInfo {
983 accessibility_name: self.label.clone(),
984 accessibility_value: OptionString::Some(format!("{}", self.current_value).into()),
985 description: self.description.clone(),
986 role: AccessibilityRole::Indicator,
987 states: Vec::new().into(),
988 accelerator: OptionVirtualKeyCodeCombo::None,
989 default_action: OptionString::None,
990 supported_actions: Vec::new().into(),
991 is_live_region: false,
992 labelled_by: OptionDomNodeId::None,
993 described_by: OptionDomNodeId::None,
994 }
995 }
996}
997
998/// Accessibility information for a `<dialog>` element.
999///
1000/// Captures the modal/non-modal distinction and a reference to a separate
1001/// node that describes the dialog (`aria-describedby`). The `role` defaults
1002/// to `AccessibilityRole::Dialog` but can be overridden (e.g., for alert
1003/// dialogs).
1004#[derive(Debug, Clone, PartialEq)]
1005#[repr(C)]
1006pub struct DialogAriaInfo {
1007 /// Accessible label / title for the dialog.
1008 pub label: OptionString,
1009 /// Optional ID of another node that describes the dialog content.
1010 pub described_by: OptionString,
1011 /// Optional inline description.
1012 pub description: OptionString,
1013 /// Role for the dialog. Defaults to `Dialog`; use `Alert` for urgent dialogs.
1014 pub role: AccessibilityRole,
1015 /// `true` if the dialog is modal (focus trapped, background inert).
1016 pub modal: bool,
1017}
1018
1019impl_option!(
1020 DialogAriaInfo,
1021 OptionDialogAriaInfo,
1022 copy = false,
1023 [Debug, Clone, PartialEq]
1024);
1025
1026impl DialogAriaInfo {
1027 /// Creates a `DialogAriaInfo` with the given accessible label. Defaults
1028 /// to a non-modal dialog with role `Dialog`.
1029 pub fn create(label: AzString) -> Self {
1030 Self {
1031 label: OptionString::Some(label),
1032 modal: false,
1033 described_by: OptionString::None,
1034 role: AccessibilityRole::Dialog,
1035 description: OptionString::None,
1036 }
1037 }
1038
1039 /// Returns a copy with the given modality flag.
1040 pub fn with_modal(mut self, modal: bool) -> Self {
1041 self.modal = modal;
1042 self
1043 }
1044
1045 /// Returns a copy with `aria-describedby` pointing at the given node ID.
1046 pub fn with_described_by(mut self, described_by: AzString) -> Self {
1047 self.described_by = OptionString::Some(described_by);
1048 self
1049 }
1050
1051 /// Returns a copy with the given role (defaults to `Dialog`).
1052 pub fn with_role(mut self, role: AccessibilityRole) -> Self {
1053 self.role = role;
1054 self
1055 }
1056
1057 /// Returns a copy with the given inline description.
1058 pub fn with_description(mut self, desc: AzString) -> Self {
1059 self.description = OptionString::Some(desc);
1060 self
1061 }
1062
1063 /// Convert to full `AccessibilityInfo` so the value can be installed on a node.
1064 pub fn to_full_info(&self) -> AccessibilityInfo {
1065 AccessibilityInfo {
1066 accessibility_name: self.label.clone(),
1067 accessibility_value: OptionString::None,
1068 description: self.description.clone(),
1069 role: self.role,
1070 states: Vec::new().into(),
1071 accelerator: OptionVirtualKeyCodeCombo::None,
1072 default_action: OptionString::None,
1073 supported_actions: Vec::new().into(),
1074 is_live_region: false,
1075 labelled_by: OptionDomNodeId::None,
1076 described_by: OptionDomNodeId::None,
1077 }
1078 }
1079}