Skip to main content

repose_core/
semantics.rs

1/// High‑level semantic role of a view, similar to ARIA roles.
2#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
3pub enum Role {
4    Text,
5    Button,
6    Tab,
7    TextField,
8    #[default]
9    Container,
10    Checkbox,
11    RadioButton,
12    Switch,
13    Slider,
14    ProgressBar,
15    Dialog,
16    Image,
17    DropdownList,
18    ValuePicker,
19    Carousel,
20}
21
22/// Live-region politeness for screen-reader announcements.
23#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
24pub enum LiveRegion {
25    #[default]
26    Polite,
27    Assertive,
28}
29
30/// Numeric range info for sliders and progress indicators.
31#[derive(Clone, Copy, Debug, PartialEq)]
32pub struct ProgressRangeInfo {
33    pub current: f32,
34    pub min: f32,
35    pub max: f32,
36    pub step: Option<f32>,
37}
38
39/// Semantics attached to a `View`, used to build the accessibility tree.
40#[derive(Clone, Debug)]
41pub struct Semantics {
42    /// Primary role of this node (what kind of thing it is).
43    pub role: Role,
44    /// Human‑readable label for screen readers. For buttons, this is the
45    /// “name” that is announced.
46    pub label: Option<String>,
47    /// Whether this node is currently focused.
48    pub focused: bool,
49    /// Whether this node is actionable. Disabled nodes remain in the tree
50    /// but are marked not enabled.
51    pub enabled: bool,
52    /// Marks this node as a collection of horizontally or vertically stacked
53    /// selectable elements (ex: Tabs, RadioButtons).
54    pub selectable_group: bool,
55    pub checked: Option<bool>,
56    pub selected: Option<bool>,
57    pub value: Option<String>,
58    pub heading: bool,
59    pub live_region: Option<LiveRegion>,
60    pub state_description: Option<String>,
61    pub traversal_index: Option<f32>,
62    pub is_traversal_group: bool,
63    pub hidden: bool,
64    pub collection_rows: Option<usize>,
65    pub collection_columns: Option<usize>,
66    pub row_index: Option<usize>,
67    pub column_index: Option<usize>,
68    pub progress: Option<ProgressRangeInfo>,
69    pub error: Option<String>,
70    pub expanded: Option<bool>,
71}
72
73impl Semantics {
74    pub fn new(role: Role) -> Self {
75        Self {
76            role,
77            label: None,
78            focused: false,
79            enabled: true,
80            selectable_group: false,
81            checked: None,
82            selected: None,
83            value: None,
84            heading: false,
85            live_region: None,
86            state_description: None,
87            traversal_index: None,
88            is_traversal_group: false,
89            hidden: false,
90            collection_rows: None,
91            collection_columns: None,
92            row_index: None,
93            column_index: None,
94            progress: None,
95            error: None,
96            expanded: None,
97        }
98    }
99    pub fn with_label(mut self, label: impl Into<String>) -> Self {
100        self.label = Some(label.into());
101        self
102    }
103    pub fn with_selectable_group(mut self) -> Self {
104        self.selectable_group = true;
105        self
106    }
107    pub fn with_checked(mut self, checked: bool) -> Self {
108        self.checked = Some(checked);
109        self
110    }
111    pub fn with_selected(mut self, selected: bool) -> Self {
112        self.selected = Some(selected);
113        self
114    }
115    pub fn with_value(mut self, value: impl Into<String>) -> Self {
116        self.value = Some(value.into());
117        self
118    }
119    pub fn with_heading(mut self) -> Self {
120        self.heading = true;
121        self
122    }
123    pub fn with_live_region(mut self, region: LiveRegion) -> Self {
124        self.live_region = Some(region);
125        self
126    }
127    pub fn with_state_description(mut self, description: impl Into<String>) -> Self {
128        self.state_description = Some(description.into());
129        self
130    }
131    pub fn with_traversal_index(mut self, index: f32) -> Self {
132        self.traversal_index = Some(index);
133        self
134    }
135    pub fn with_traversal_group(mut self) -> Self {
136        self.is_traversal_group = true;
137        self
138    }
139    pub fn with_hidden(mut self) -> Self {
140        self.hidden = true;
141        self
142    }
143    pub fn with_collection(mut self, rows: usize, columns: usize) -> Self {
144        self.collection_rows = Some(rows);
145        self.collection_columns = Some(columns);
146        self
147    }
148    pub fn with_collection_item(mut self, row: usize, column: usize) -> Self {
149        self.row_index = Some(row);
150        self.column_index = Some(column);
151        self
152    }
153    pub fn with_progress_range(mut self, info: ProgressRangeInfo) -> Self {
154        self.progress = Some(info);
155        self
156    }
157    pub fn with_error(mut self, message: impl Into<String>) -> Self {
158        self.error = Some(message.into());
159        self
160    }
161    pub fn with_expanded(mut self, expanded: bool) -> Self {
162        self.expanded = Some(expanded);
163        self
164    }
165}
166
167impl Default for Semantics {
168    fn default() -> Self {
169        Self::new(Role::default())
170    }
171}