From 2c66cb1bfb82cf0c89b79db7ab982c680475ba62 Mon Sep 17 00:00:00 2001 From: bloodrizer Date: Tue, 7 Jan 2025 16:51:03 -0800 Subject: [PATCH 1/6] accessability options (keyboard navigation, taborder, titles). wip --- game.js | 2 +- index.html | 12 ++++++------ js/jsx/left.jsx.js | 26 ++++++++++++++++---------- js/jsx/toolbar.jsx.js | 32 +++++++++++++++++++++++--------- res/default.css | 1 + 5 files changed, 47 insertions(+), 26 deletions(-) diff --git a/game.js b/game.js index e1a6437c84..5fe81ae9b6 100644 --- a/game.js +++ b/game.js @@ -1843,7 +1843,7 @@ dojo.declare("com.nuclearunicorn.game.ui.GamePage", null, { // option settings //============================= forceShowLimits: false, - useWorkers: false, + useWorkers: true, colorScheme: "", unlockedSchemes: null, diff --git a/index.html b/index.html index c954bedbb5..7d0a12a120 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - + @@ -306,7 +306,7 @@
-
+
Kittens Game @@ -363,7 +363,7 @@
-
+
 Loading...

@@ -376,14 +376,14 @@
-
+
Loading...
-
+
Loading...
@@ -409,7 +409,7 @@
-
+
Calendar :V diff --git a/js/jsx/left.jsx.js b/js/jsx/left.jsx.js index eaa2b1d898..6b895aa708 100644 --- a/js/jsx/left.jsx.js +++ b/js/jsx/left.jsx.js @@ -25,6 +25,7 @@ WCollapsiblePanel = React.createClass({ className: "left" }, $r("a", { + href: "#!", className:"link collapse", onClick: this.toggleCollapsed }, @@ -204,13 +205,13 @@ WResourceRow = React.createClass({ (!res.visible ? " hidden" : "") ; - return $r("div", {className: resRowClass}, [ + return $r("div", {role: "row", className: resRowClass}, [ this.props.isEditMode ? $r("div", {className:"res-cell"}, $r("input", { type:"checkbox", checked: this.getIsVisible(), - + title: "Toggle " + $I("resources." + res.name + ".title"), onClick: this.toggleView, style:{display:"inline-block"}, }) @@ -220,17 +221,20 @@ WResourceRow = React.createClass({ className:"res-cell resource-name", style:resNameCss, onClick: this.onClickName, - title: res.title || res.name + title: (res.title || res.name) + " " + game.getDisplayValueExt(res.value) + "/" + game.getDisplayValueExt(res.maxValue) + " " + perTickVal, + role: "gridcell", + userFocus:"normal", + tabIndex:"0", }, res.title || res.name ), - $r("div", {className:"res-cell " + resAmtClassName + specialClass}, game.getDisplayValueExt(res.value)), - $r("div", {className:"res-cell maxRes"}, + $r("div", {className:"res-cell " + resAmtClassName + specialClass, role: "gridcell"}, game.getDisplayValueExt(res.value)), + $r("div", {className:"res-cell maxRes", role: "gridcell"}, res.maxValue ? "/" + game.getDisplayValueExt(res.maxValue) : "" ), - $r("div", {className:"res-cell resPerTick", ref:"perTickNode"}, + $r("div", {className:"res-cell resPerTick", role: "gridcell", ref:"perTickNode"}, isTimeParadox ? "???" : perTickVal), - $r("div", {className:"res-cell" + (weatherModCss ? " " + weatherModCss : "")}, weatherModValue) + $r("div", {className:"res-cell" + (weatherModCss ? " " + weatherModCss : ""), role: "gridcell"}, weatherModValue) ]); }, onClickName: function(e){ @@ -556,12 +560,13 @@ WResourceTable = React.createClass({ } //TODO: mixing special stuff like fatih and such here - return $r("div", null, [ + return $r("div", {ariaLabel:"Regular resources"}, [ $r("div", null,[ $r("div", { className:"res-toolbar left" }, $r("a", { + href: "#!", className:"link collapse", onClick: this.toggleCollapsed }, @@ -573,6 +578,7 @@ WResourceTable = React.createClass({ className: "link" + (this.state.isEditMode ? " toggled" : ""), onClick: this.toggleEdit, onKeyDown: this.onKeyDown, + title: "Resource settings", tabIndex: 0 }, "⚙"), $r(WTooltip, {body:"?"}, @@ -586,7 +592,7 @@ WResourceTable = React.createClass({ $r("a", {className:"link", onClick: game.ui.zoomUp.bind(game.ui)}, $I("left.font.inc")), $r("a", {className:"link", onClick: game.ui.zoomDown.bind(game.ui)}, $I("left.font.dec")), ]), - $r("div", {className:"res-table"}, resRows) + $r("div", {className:"res-table", role: "grid"}, resRows) ]), //TODO: this stuff should not be exposed to beginner player to not overwhelm them @@ -654,7 +660,7 @@ WCraftTable = React.createClass({ return null; } - return $r("div", null, [ + return $r("div", {ariaLabel:"Craftable resources"}, [ $r("div", null,[ $r("div", { className:"res-toolbar left", diff --git a/js/jsx/toolbar.jsx.js b/js/jsx/toolbar.jsx.js index 105b6b97c7..6f8dd49002 100644 --- a/js/jsx/toolbar.jsx.js +++ b/js/jsx/toolbar.jsx.js @@ -341,14 +341,16 @@ WLoginForm = React.createClass({ {onClick: function (e){ e.stopPropagation(); }}, [ $r("div", {className: "row"}, [ - "Email:", + $r("label", {for:"kgnet-email"}, "Email:"), $r("input", { + id:"kgnet-email", type: "email", onChange: this.setLogin, value: this.state.login } ), - "Password:", + $r("label", {for:"kgnet-password"}, "Password:"), $r("input", { + id:"kgnet-password", type: "password", onChange: this.setPassword, value: this.state.password @@ -646,15 +648,21 @@ WLogin = React.createClass({ }, $r("div", { - onClick: this.toggleExpanded + onClick: this.toggleExpanded, + onKeyDown: this.onKeyDown }, [ - $r("span", { - className: "kgnet-login-link status-indicator-" + (game.server.userProfile ? "online" : "offline") - + (lastBackup >= 7 ? " freshMessage" : "") - }, "* " + (game.server.userProfile ? - $I("ui.kgnet.online") : $I("ui.kgnet.login") - )), + $r("a", { + href:"#!", + onClick: this.toggleExpanded, + }, + $r("span", { + className: "kgnet-login-link status-indicator-" + (game.server.userProfile ? "online" : "offline") + + (lastBackup >= 7 ? " freshMessage" : "") + }, "* " + (game.server.userProfile ? + $I("ui.kgnet.online") : $I("ui.kgnet.login") + )), + ), this.state.isExpanded && $r("div", { className: "login-popup button_tooltip tooltip-block" }, @@ -677,6 +685,12 @@ WLogin = React.createClass({ this.setState({ isExpanded: !this.state.isExpanded }) + }, + + onKeyDown: function(e){ + if(e.key === "Escape") { + this.toggleExpanded() + } } }); diff --git a/res/default.css b/res/default.css index 1706c75a16..1a77b3ed4f 100644 --- a/res/default.css +++ b/res/default.css @@ -528,6 +528,7 @@ td.resLimitWarn, .res-cell.resLimitWarn { margin-bottom: 20px; padding: 15px; border: 1px solid #B0B0B0; + height: calc(100vh - 125px); } #toggleCenter { From 701c59c4e21c4a6e044fdf69d04a7f0566e49ec1 Mon Sep 17 00:00:00 2001 From: bloodrizer Date: Tue, 7 Jan 2025 16:56:44 -0800 Subject: [PATCH 2/6] use % values in tooltips to avoid re-rendering title constantly --- js/jsx/left.jsx.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/jsx/left.jsx.js b/js/jsx/left.jsx.js index 6b895aa708..d2853efc5a 100644 --- a/js/jsx/left.jsx.js +++ b/js/jsx/left.jsx.js @@ -205,6 +205,8 @@ WResourceRow = React.createClass({ (!res.visible ? " hidden" : "") ; + var resPercent = ((res.value / res.maxValue) * 100).toFixed(); + return $r("div", {role: "row", className: resRowClass}, [ this.props.isEditMode ? $r("div", {className:"res-cell"}, @@ -221,7 +223,7 @@ WResourceRow = React.createClass({ className:"res-cell resource-name", style:resNameCss, onClick: this.onClickName, - title: (res.title || res.name) + " " + game.getDisplayValueExt(res.value) + "/" + game.getDisplayValueExt(res.maxValue) + " " + perTickVal, + title: (res.title || res.name) + " " + resPercent + "%/" + game.getDisplayValueExt(res.maxValue) + " " + perTickVal, role: "gridcell", userFocus:"normal", tabIndex:"0", From 3fb49bbec65208713a2443d8c1b563093eb012e2 Mon Sep 17 00:00:00 2001 From: bloodrizer Date: Tue, 7 Jan 2025 17:13:18 -0800 Subject: [PATCH 3/6] better labels for the resource panel sections, exclude misc icons from the taborder priority --- js/jsx/left.jsx.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/js/jsx/left.jsx.js b/js/jsx/left.jsx.js index d2853efc5a..b0c6291c05 100644 --- a/js/jsx/left.jsx.js +++ b/js/jsx/left.jsx.js @@ -27,7 +27,9 @@ WCollapsiblePanel = React.createClass({ $r("a", { href: "#!", className:"link collapse", - onClick: this.toggleCollapsed + onClick: this.toggleCollapsed, + tabindex: 1, + title: this.props.title }, this.state.isCollapsed ? ">(" + this.props.title + ")" : "v" ) @@ -226,7 +228,7 @@ WResourceRow = React.createClass({ title: (res.title || res.name) + " " + resPercent + "%/" + game.getDisplayValueExt(res.maxValue) + " " + perTickVal, role: "gridcell", userFocus:"normal", - tabIndex:"0", + tabIndex: 0, }, res.title || res.name ), @@ -570,7 +572,9 @@ WResourceTable = React.createClass({ $r("a", { href: "#!", className:"link collapse", - onClick: this.toggleCollapsed + onClick: this.toggleCollapsed, + tabindex: 1, + title: "Toggle resources", }, this.state.isCollapsed ? ">(" + $I("left.resources") + ")" : "v" ) @@ -581,9 +585,9 @@ WResourceTable = React.createClass({ onClick: this.toggleEdit, onKeyDown: this.onKeyDown, title: "Resource settings", - tabIndex: 0 + tabIndex: 1 }, "⚙"), - $r(WTooltip, {body:"?"}, + $r(WTooltip, {body:"?", tabindex: 1}, $I("left.resources.tip")) ) @@ -669,7 +673,9 @@ WCraftTable = React.createClass({ }, $r("a", { className:"link collapse", - onClick: this.toggleCollapsed + onClick: this.toggleCollapsed, + tabindex: 1, + title: "Toggle craft", }, this.state.isCollapsed ? ">(" + $I("left.craft") + ")" : "v" ) @@ -679,7 +685,7 @@ WCraftTable = React.createClass({ className: "link" + (this.state.isEditMode ? " toggled" : ""), onClick: this.toggleEdit, onKeyDown: this.onKeyDown, - tabIndex: 0 + tabIndex: 1 }, "⚙") ) ]), @@ -865,7 +871,7 @@ WTooltip = React.createClass({ render: function(){ return $r("div", { - tabIndex: 0, + tabIndex: this.props.tabindex ?? 0, className: "tooltip-block", onMouseOver: this.onMouseOver, onMouseOut: this.onMouseOut, From 3b60d5d396df9bee94b6945b127b315fae4d9c3a Mon Sep 17 00:00:00 2001 From: bloodrizer Date: Tue, 7 Jan 2025 18:07:22 -0800 Subject: [PATCH 4/6] better button tooltip accessability --- core.js | 30 ++++++++++++++++++++++-------- game.js | 1 - index.html | 2 +- js/jsx/left.jsx.js | 2 +- res/default.css | 3 +++ res/i18n/en.json | 2 +- 6 files changed, 28 insertions(+), 12 deletions(-) diff --git a/core.js b/core.js index c343a8676b..ab1d922133 100644 --- a/core.js +++ b/core.js @@ -918,6 +918,7 @@ dojo.declare("com.nuclearunicorn.game.ui.Button", com.nuclearunicorn.core.Contro position: "relative", display: this.model.visible ? "block" : "none" }, + "aria-description": this.model.description, tabIndex: 0 }, btnContainer); @@ -944,11 +945,10 @@ dojo.declare("com.nuclearunicorn.game.ui.Button", com.nuclearunicorn.core.Contro } this.updateVisible(); + this.afterRender(); dojo.connect(this.domNode, "onclick", this, "onClick"); dojo.connect(this.domNode, "onkeypress", this, "onKeyPress"); - - this.afterRender(); }, animate: function(){ @@ -978,14 +978,13 @@ dojo.declare("com.nuclearunicorn.game.ui.Button", com.nuclearunicorn.core.Contro }, - onKeyPress: function(event){ - if (event.key == "Enter"){ - this.onClick(event); + onKeyPress: function(e){ + if (e.key == "Enter"){ + this.onClick(e); } }, afterRender: function(){ - var prices = this.model.prices; if (prices.length && !this.tooltip){ @@ -1031,8 +1030,11 @@ dojo.declare("com.nuclearunicorn.game.ui.Button", com.nuclearunicorn.core.Contro dojo.connect(this.domNode, "onmouseover", this, dojo.partial(function(tooltip){ dojo.style(tooltip, "display", ""); }, tooltip)); dojo.connect(this.domNode, "onmouseout", this, dojo.partial(function(tooltip){ dojo.style(tooltip, "display", "none"); }, tooltip)); + this.tooltip = tooltip; this.tooltipPricesNodes = tooltipPricesNodes; + + console.log("this after render", this); } }, @@ -2518,7 +2520,7 @@ UIUtils = { var gameNode = dojo.byId("game"); var tooltip = dojo.byId("tooltip"); - dojo.connect(container, "onmouseover", this, function() { + var showTooltip = function () { game.tooltipUpdateFunc = function(){ tooltip.innerHTML = dojo.hitch(game, htmlProvider)(); }; @@ -2549,12 +2551,24 @@ UIUtils = { if (tooltip.innerHTML) { dojo.style(tooltip, "display", ""); } - }); + }; + + dojo.connect(container, "onmouseover", this, showTooltip); dojo.connect(container, "onmouseout", this, function(){ game.tooltipUpdateFunc = null; dojo.style(tooltip, "display", "none"); }); + + dojo.connect(container, "onkeydown", this, function(e){ + if (e.code == "Space"){ + e.stopPropagation(); + e.preventDefault(); + + showTooltip(); + tooltip.focus(); + } + }); return htmlProvider; } diff --git a/game.js b/game.js index 5fe81ae9b6..e19dd52f8c 100644 --- a/game.js +++ b/game.js @@ -3991,7 +3991,6 @@ dojo.declare("com.nuclearunicorn.game.ui.GamePage", null, { dojo.connect(container, "onmouseout", this, function(){ dojo.style(container, "fontWeight", "normal"); }); - }, /** diff --git a/index.html b/index.html index 7d0a12a120..a3f55437cd 100644 --- a/index.html +++ b/index.html @@ -373,7 +373,7 @@