Skip to content

Commit

Permalink
feat: Delegated focus
Browse files Browse the repository at this point in the history
  • Loading branch information
marc2332 committed Jan 19, 2025
1 parent c753f9a commit 28f1d4c
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 4 deletions.
20 changes: 16 additions & 4 deletions crates/hooks/src/use_focus.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use std::sync::Arc;


use dioxus_core::{
use_hook,
AttributeValue,
prelude::consume_context
};
use dioxus_hooks::{
use_context,
Expand Down Expand Up @@ -45,6 +47,12 @@ pub struct UseFocus {
}

impl UseFocus {
pub fn new_id() -> AccessibilityId {
let accessibility_generator = consume_context::<Arc<AccessibilityGenerator>>();

AccessibilityId(accessibility_generator.new_id())
}

/// Focus this node
pub fn focus(&mut self) {
if !*self.is_focused.peek() {
Expand Down Expand Up @@ -95,14 +103,18 @@ impl UseFocus {

/// Create a focus manager for a node.
pub fn use_focus() -> UseFocus {
let accessibility_generator = use_context::<Arc<AccessibilityGenerator>>();
let id = use_hook(|| UseFocus::new_id());

use_focus_from_id(id)
}

/// Create a focus manager for a node with the provided [AccessibilityId].
pub fn use_focus_from_id(id: AccessibilityId) -> UseFocus {
let focused_id = use_context::<Signal<AccessibilityId>>();
let navigation_mode = use_context::<Signal<NavigationMode>>();
let navigation_mark = use_context::<Signal<NavigationMark>>();
let platform = use_platform();

let id = use_hook(|| AccessibilityId(accessibility_generator.new_id()));

let is_focused = use_memo(move || id == *focused_id.read());

let is_selected =
Expand All @@ -116,4 +128,4 @@ pub fn use_focus() -> UseFocus {
navigation_mark,
platform,
})
}
}
77 changes: 77 additions & 0 deletions examples/delegated_focus.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#![cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]

use freya::prelude::*;
use freya_core::{prelude::EventMessage, types::AccessibilityId};

fn main() {
launch_with_props(app, "Controlled Focus", (400.0, 350.0));
}

fn app() -> Element {
let nodes = use_hook(|| [
UseFocus::new_id(),
UseFocus::new_id(),
UseFocus::new_id(),
UseFocus::new_id()
]);
let mut current = use_signal(|| 0);

let onwheel = move |_| {
current += 1;
if current() == 4 {
current.set(0);
}
};

use_effect(move || {
let platform = UsePlatform::new();
platform
.send(EventMessage::FocusAccessibilityNode(nodes[current()]))
.ok();
});

rsx!(
rect {
height: "100%",
width: "100%",
background: "black",
color: "white",
direction: "horizontal",
main_align: "center",
cross_align: "center",
onwheel,
for (i, id) in nodes.iter().enumerate() {
Card {
key: "{i}",
id: *id,
index: i
}
}
}
)
}

#[component]
fn Card(index: usize, id: AccessibilityId) -> Element {
let focus = use_focus_from_id(id);
let background = if focus.is_focused() {
"rgb(0, 119, 182)"
} else {
"black"
};

rsx!(
rect {
height: "100",
width: "100",
a11y_id: focus.attribute(),
background,
label {
"Card {index}"
}
}
)
}

0 comments on commit 28f1d4c

Please sign in to comment.