From 1bb41feaba0dcecac7eea2d4242807dbaba0839e Mon Sep 17 00:00:00 2001
From: bananarama92 <bananarama921@outlook.com>
Date: Sun, 30 Mar 2025 21:12:11 +0200
Subject: [PATCH 1/2] MAINT: Use DOM lists for the crafting component of button
 tooltips

---
 BondageClub/CSS/button.css     |  3 ++
 BondageClub/Scripts/Element.js | 62 +++++++++++++++++++---------------
 2 files changed, 38 insertions(+), 27 deletions(-)

diff --git a/BondageClub/CSS/button.css b/BondageClub/CSS/button.css
index c1f560c2ea..e3bcaad45e 100644
--- a/BondageClub/CSS/button.css
+++ b/BondageClub/CSS/button.css
@@ -57,6 +57,9 @@
 }
 
 .button-tooltip-craft {
+	list-style-type: none;
+	padding: unset;
+	margin: unset;
 	padding-left: 1em;
 }
 
diff --git a/BondageClub/Scripts/Element.js b/BondageClub/Scripts/Element.js
index dc7379e24d..eef00263f2 100644
--- a/BondageClub/Scripts/Element.js
+++ b/BondageClub/Scripts/Element.js
@@ -1110,7 +1110,7 @@ var ElementButton = {
 	 * Parse the passed icon list, returning its corresponding `<img>` grid and tooltip if non-empty
 	 * @param {string} id - The ID of the parent element
 	 * @param {readonly (InventoryIcon | ElementButton.CustomIcon)[]} [icons] - The (optional) list of icons
-	 * @returns {null | { iconGrid: HTMLDivElement, tooltip: [string, HTMLElement, HTMLElement] }} - `null` if the provided icon list is empty and otherwise an object containing the icon grid and a icon-specific tooltip
+	 * @returns {null | { iconGrid: HTMLDivElement, tooltip: [string, HTMLElement] }} - `null` if the provided icon list is empty and otherwise an object containing the icon grid and a icon-specific tooltip
 	 */
 	_ParseIcons: function _ParseIcons(id, icons) {
 		icons = icons?.filter(i => i != null);
@@ -1178,7 +1178,7 @@ var ElementButton = {
 				parent: iconGrid,
 			});
 		});
-		return { iconGrid, tooltip: [InterfaceTextGet("StatusAndEffects"), ElementCreate({ tag: "br" }), tooltip] };
+		return { iconGrid, tooltip: [InterfaceTextGet("StatusAndEffects"), tooltip] };
 	},
 
 	/**
@@ -1394,32 +1394,40 @@ var ElementButton = {
 				children: [InterfaceTextGet("DialogMenuCrafting") + ":"],
 			},
 			{
-				tag: "div",
+				tag: "ul",
 				classList: ["button-tooltip-craft"],
 				children: [
-					...(item.Craft.Property ? [
-						InterfaceTextGet("CraftingProperty").replace("CraftProperty", ""),
-						{ tag: "q", children: [
-							{ tag: "dfn", children: [item.Craft.Property] },
-							" - ",
-						]},
-						{ tag: "br" },
-					] : []),
-					...((item.Craft.MemberName && item.Craft.MemberNumber) ? [
-						InterfaceTextGet("CraftingMember").replace("MemberName (MemberNumber)", ""),
-						{ tag: "q", children: [`${item.Craft.MemberName} (${item.Craft.MemberNumber})`] },
-						{ tag: "br" },
-					] : []),
-					...([
-						InterfaceTextGet("CraftingPrivate").replace("CraftPrivate", ""),
-						{ tag: "q", children: [CommonCapitalize(item.Craft.Private.toString())] },
-						{ tag: "br" },
-					]),
-					...(item.Craft.Description ? [
-						InterfaceTextGet("CraftingDescription").replace("CraftDescription", ""),
-						{ tag: "q", children: CraftingDescription.DecodeToHTML(item.Craft.Description) },
-						{ tag: "br" },
-					] : []),
+					item.Craft.Property ? {
+						tag: "li",
+						children: [
+							InterfaceTextGet("CraftingProperty").replace("CraftProperty", ""),
+							{
+								tag: "q",
+								children: [{ tag: "dfn", children: [item.Craft.Property] }, " - "],
+							},
+						],
+					} : undefined,
+					(item.Craft.MemberName && item.Craft.MemberNumber) ? {
+						tag: "li",
+						children: [
+							InterfaceTextGet("CraftingMember").replace("MemberName (MemberNumber)", ""),
+							{ tag: "q", children: [`${item.Craft.MemberName} (${item.Craft.MemberNumber})`] },
+						],
+					} : undefined,
+					{
+						tag: "li",
+						children: [
+							InterfaceTextGet("CraftingPrivate").replace("CraftPrivate", ""),
+							{ tag: "q", children: [CommonCapitalize(item.Craft.Private.toString())] },
+						],
+					},
+					item.Craft.Description ? {
+						tag: "li",
+						children: [
+							InterfaceTextGet("CraftingDescription").replace("CraftDescription", ""),
+							{ tag: "q", children: CraftingDescription.DecodeToHTML(item.Craft.Description) },
+						],
+					} : undefined,
 				],
 			},
 		]);
@@ -1520,7 +1528,7 @@ var ElementButton = {
 		if (iconGrid && !button.contains(iconGrid)) {
 			button.append(iconGrid);
 		}
-		if (tooltip[2] && !button.contains(tooltip[2])) {
+		if (tooltip[1] && !button.contains(tooltip[1])) {
 			button.querySelector(".button-tooltip")?.append(...tooltip);
 		}
 		return true;

From afb7e4886b97c65115cd3c225d4957727f310d5a Mon Sep 17 00:00:00 2001
From: bananarama92 <bananarama921@outlook.com>
Date: Sun, 30 Mar 2025 21:12:22 +0200
Subject: [PATCH 2/2] MAINT: Use DOM lists for the crafted dialog panel

---
 BondageClub/CSS/dialog.css    |  6 ++++++
 BondageClub/Scripts/Dialog.js | 31 +++++++++++++++++++++----------
 2 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/BondageClub/CSS/dialog.css b/BondageClub/CSS/dialog.css
index 59b36a1643..3425554484 100644
--- a/BondageClub/CSS/dialog.css
+++ b/BondageClub/CSS/dialog.css
@@ -222,6 +222,12 @@
 		"dialog-crafted-footer dialog-crafted-footer dialog-crafted-footer dialog-crafted-footer" minmax(auto, min-content) / auto var(--gap) min(100%, calc(0.8 * var(--button-height))) var(--scrollbar-gutter)
 }
 
+#dialog-crafted ul {
+	padding: unset;
+	margin: unset;
+	list-style-type: none;
+}
+
 .dialog-crafted-info {
 	font: inherit;
 	overflow-wrap: break-word;
diff --git a/BondageClub/Scripts/Dialog.js b/BondageClub/Scripts/Dialog.js
index b1c85b242b..995ed05327 100644
--- a/BondageClub/Scripts/Dialog.js
+++ b/BondageClub/Scripts/Dialog.js
@@ -4066,6 +4066,7 @@ class _DialogCraftedMenu extends _DialogFocusMenu {
 		const ids = this.ids;
 		return document.getElementById(ids.root) ?? ElementCreate({
 			tag: "div",
+			attributes: { "aria-owns": ids.icon },
 			children: [
 				{
 					tag: "span",
@@ -4073,23 +4074,33 @@ class _DialogCraftedMenu extends _DialogFocusMenu {
 					classList: ["dialog-status", "scroll-box"],
 				},
 				{
-					tag: "div",
+					tag: "ul",
 					attributes: { id: ids.info, "aria-labelledby": ids.status },
 					children: [
-						{ tag: "span", attributes: { id: ids.name }, classList: [ids.info] },
-						{ tag: "span", attributes: { id: ids.crafter }, classList: [ids.info] },
-						{ tag: "span", attributes: { id: ids.property }, classList: [ids.info] },
-						{ tag: "span", attributes: { id: ids.private }, classList: [ids.info] },
-						{ tag: "div", attributes: { id: ids.gap } },
-						{ tag: "div", classList: ["button", "blank-button", "button-styling", "dialog-grid-button", "dialog-icon"], attributes: { id: ids.icon } },
+						{ tag: "li", attributes: { id: ids.name }, classList: [ids.info] },
+						{ tag: "li", attributes: { id: ids.crafter }, classList: [ids.info] },
+						{ tag: "li", attributes: { id: ids.property }, classList: [ids.info] },
+						{ tag: "li", attributes: { id: ids.private }, classList: [ids.info] },
+						{ tag: "div", attributes: { id: ids.gap, "aria-hidden": "true" } },
 						{
 							tag: "div",
+							classList: ["button", "blank-button", "button-styling", "dialog-grid-button", "dialog-icon"],
+							attributes: { id: ids.icon, role: "img", "aria-labelledby": `${ids.icon}-label` },
+						},
+						{
+							tag: "li",
 							attributes: { id: ids.footer },
 							classList: [ids.info, "scroll-box"],
 							children: [
-								{ tag: "span", attributes: { id: ids.description } },
-							],
-						},
+								{
+									tag: "ul",
+									children: [
+										{ tag: "li", attributes: { id: ids.description } },
+									],
+								},
+							]
+						}
+
 					],
 				},
 			],