From 07a87dfba7f5da7819202847f6db71dafd6d217b Mon Sep 17 00:00:00 2001 From: egrs Date: Wed, 18 Feb 2026 13:13:12 +0100 Subject: [PATCH] fix tabIndex default for interactive elements per spec interactive elements (input, button, a, select, textarea, iframe) default to 0 when tabindex attribute is absent; others default to -1. also add TODO for hidden "until-found" tristate. --- .../tests/element/html/htmlelement-props.html | 17 +++++++++++++++++ src/browser/webapi/element/Html.zig | 10 +++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/browser/tests/element/html/htmlelement-props.html b/src/browser/tests/element/html/htmlelement-props.html index d8f8c905..a008adc5 100644 --- a/src/browser/tests/element/html/htmlelement-props.html +++ b/src/browser/tests/element/html/htmlelement-props.html @@ -30,10 +30,27 @@ i1.tabIndex = 10; testing.expectEqual(10, i1.tabIndex); + // Non-interactive elements default to -1 const d3 = document.getElementById('d3'); testing.expectEqual(-1, d3.tabIndex); d3.tabIndex = 0; testing.expectEqual(0, d3.tabIndex); + + // Interactive elements default to 0 per spec + const input = document.createElement('input'); + testing.expectEqual(0, input.tabIndex); + + const button = document.createElement('button'); + testing.expectEqual(0, button.tabIndex); + + const a = document.createElement('a'); + testing.expectEqual(0, a.tabIndex); + + const select = document.createElement('select'); + testing.expectEqual(0, select.tabIndex); + + const textarea = document.createElement('textarea'); + testing.expectEqual(0, textarea.tabIndex); } diff --git a/src/browser/webapi/element/Html.zig b/src/browser/webapi/element/Html.zig index 7639d204..ba6361d3 100644 --- a/src/browser/webapi/element/Html.zig +++ b/src/browser/webapi/element/Html.zig @@ -342,6 +342,8 @@ pub fn click(self: *HtmlElement, page: *Page) !void { try page._event_manager.dispatch(self.asEventTarget(), event); } +// TODO: Per spec, hidden is a tristate: true | false | "until-found". +// We only support boolean for now; "until-found" would need bridge union support. pub fn getHidden(self: *HtmlElement) bool { return self.asElement().getAttributeSafe(comptime .wrap("hidden")) != null; } @@ -355,7 +357,13 @@ pub fn setHidden(self: *HtmlElement, hidden: bool, page: *Page) !void { } pub fn getTabIndex(self: *HtmlElement) i32 { - const attr = self.asElement().getAttributeSafe(comptime .wrap("tabindex")) orelse return -1; + const attr = self.asElement().getAttributeSafe(comptime .wrap("tabindex")) orelse { + // Per spec, interactive/focusable elements default to 0 when tabindex is absent + return switch (self._type) { + .anchor, .area, .button, .input, .select, .textarea, .iframe => 0, + else => -1, + }; + }; return std.fmt.parseInt(i32, attr, 10) catch -1; }