Skip to content

Commit 070a9ed

Browse files
committed
Update sub_button_wheel to v1.2.0
1 parent d6184e7 commit 070a9ed

File tree

6 files changed

+81
-8
lines changed

6 files changed

+81
-8
lines changed

modules/sub_button_wheel/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
### v1.2.0
4+
5+
<details><summary>See Changes</summary>
6+
7+
- Added support for using main button as the wheel opener. Use `wheel_opener: "main"` to enable this feature.
8+
- Existing tap actions will automatically be removed from the wheel opener button without manual configuration.
9+
10+
</details>
311
### v1.1.0
412

513
<details><summary>See Changes</summary>

modules/sub_button_wheel/__tests__/integration.test.js

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,47 @@ describe("sub_button_wheel - Integration Tests", () => {
129129

130130
// Verify wheel menu size matches button size
131131
expect(wheelMenu.style.width).toBe("36px");
132+
expect(wheelMenu.style.height).toBe("36px");
132133

133134
// Verify overlay is positioned correctly (before wheel menu in DOM)
134135
const overlay = document.querySelector(".wheel-overlay");
135136
expect(overlay.nextElementSibling).toBe(wheelMenu);
136137
});
138+
it("should remove default tap action on the wheel opener button", () => {
139+
// Setup - Basic configuration
140+
const originalButtonSelectors = [
141+
".bubble-sub-button-1",
142+
".bubble-sub-button-2",
143+
".bubble-sub-button-3",
144+
".bubble-sub-button-4",
145+
];
146+
mockThis.config.sub_button_wheel = {
147+
wheel_opener: "main",
148+
wheel_buttons: [{ sub_button: "1" }, { sub_button: "2" }, { sub_button: "3" }, { sub_button: "4" }],
149+
};
150+
151+
// Set up main button with initial tap action to verify it gets overridden
152+
const mainButton = mockCard.querySelector(".bubble-icon-container");
153+
mainButton.dataset.tapAction = JSON.stringify({ action: "toggle", entity: "light.main" });
154+
155+
// Verify initial DOM state
156+
originalButtonSelectors.forEach((selector) => {
157+
expect(mockCard.querySelector(selector)).toBeTruthy();
158+
});
159+
expect(document.querySelector(".wheel-menu")).toBeNull();
160+
161+
// Verify main button initially has the tap action we set
162+
expect(mainButton.getAttribute("data-tap-action")).toBe('{"action":"toggle","entity":"light.main"}');
163+
164+
// Exercise
165+
sub_button_wheel.call(mockThis, mockCard, mockHass);
166+
167+
// Verify
168+
const wheelMenu = document.querySelector(".wheel-menu");
169+
const openerButton = wheelMenu.querySelector(".wheel-open-button");
170+
171+
expect(openerButton.getAttribute("data-tap-action")).toBe('{"action":"none"}');
172+
});
137173

138174
it("should not create wheel when no buttons are configured", () => {
139175
// Setup - Empty configuration
@@ -753,6 +789,7 @@ describe("sub_button_wheel - Integration Tests", () => {
753789
// Verify - Sub-button-1 becomes opener, others become wheel buttons
754790
const wheelMenu = document.querySelector(".wheel-menu");
755791
expect(wheelMenu).toBeTruthy();
792+
expect(wheelMenu.classList).not.toContain("main-opener");
756793

757794
const openerButton = wheelMenu.querySelector(".wheel-open-button");
758795
expect(openerButton).toBeTruthy();
@@ -782,6 +819,7 @@ describe("sub_button_wheel - Integration Tests", () => {
782819
const wheelButtons = wheelMenu.querySelectorAll(".wheel-button");
783820

784821
expect(wheelMenu).toBeTruthy();
822+
expect(wheelMenu.classList).toContain("main-opener");
785823
expect(wheelButtons.length).toBe(2);
786824

787825
// Should use default even-circle layout with precise positioning
@@ -814,7 +852,7 @@ describe("sub_button_wheel - Integration Tests", () => {
814852
it("should handle partial configuration gracefully", () => {
815853
// Setup - Only layout specified, no animation config
816854
mockThis.config.sub_button_wheel = {
817-
wheel_opener: "main",
855+
wheel_opener: "main-button",
818856
layout_options: {
819857
wheel_layout: "progressive-arc",
820858
// No double_ring_inner_count specified
@@ -844,7 +882,7 @@ describe("sub_button_wheel - Integration Tests", () => {
844882
it("should handle single button configuration", () => {
845883
// Setup - Only one wheel button
846884
mockThis.config.sub_button_wheel = {
847-
wheel_opener: "main",
885+
wheel_opener: "main-button",
848886
wheel_buttons: [{ sub_button: "1" }],
849887
};
850888

@@ -863,7 +901,8 @@ describe("sub_button_wheel - Integration Tests", () => {
863901
const openerButton = wheelMenu.querySelector(".wheel-open-button");
864902

865903
openerButton.click();
866-
expect(wheelMenu.classList.contains("active")).toBe(true);
904+
expect(wheelMenu.classList).toContain("active");
905+
expect(wheelMenu.classList).toContain("main-opener");
867906
});
868907

869908
it("should handle maximum supported buttons for arc layouts", () => {

modules/sub_button_wheel/code.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { toArray } from "../helpers/utils/arrays.js";
33
export function sub_button_wheel(card, hass) {
44
// this allows IDEs to parse the file normally - will be removed automatically during build.
55
const { sub_button_wheel: config } = this.config;
6+
const mainButtonSelector = ".bubble-icon-container";
67

78
function shouldCloseOnClick(buttonConfig, globalConfig) {
89
// Individual button setting takes precedence
@@ -20,9 +21,12 @@ export function sub_button_wheel(card, hass) {
2021
return;
2122
}
2223

24+
const isMainButtonOpener = isMainButton(config.wheel_opener);
2325
const wheelMenu = document.createElement("div");
2426
wheelMenu.className = "wheel-menu";
25-
27+
if (isMainButtonOpener) {
28+
wheelMenu.classList.add("main-opener");
29+
}
2630
const overlay = document.createElement("div");
2731
overlay.className = "wheel-overlay";
2832

@@ -33,6 +37,8 @@ export function sub_button_wheel(card, hass) {
3337

3438
const orderedButtonConfigs = processButtonPositions([...wheelButtonsConfig]);
3539
// assume 36px as there are no variables in buttons until reported otherwise
40+
// if main button it will cause 6px difference in sizing due to the main icon
41+
// being 42px, but it will be centered anyway
3642
const buttonSize = 36;
3743
const wheelButtons = [];
3844

@@ -49,10 +55,15 @@ export function sub_button_wheel(card, hass) {
4955
});
5056

5157
wheelMenu.style.width = `${buttonSize}px`;
58+
wheelMenu.style.height = `${buttonSize}px`;
5259
wheelOpenerButton.replaceWith(wheelMenu);
5360
wheelMenu.before(overlay);
5461
wheelMenu.appendChild(wheelOpenerButton);
5562

63+
// remove existing default tap action from wheel opener button
64+
// https://github.com/Clooos/Bubble-Card/discussions/1714
65+
wheelOpenerButton.setAttribute("data-tap-action", JSON.stringify({ action: "none" }));
66+
5667
// Apply layout positioning directly to buttons
5768
const layoutManager = new WheelLayoutManager(buttonSize, config);
5869
const glassRingRadius = layoutManager.applyLayout(layout, orderedButtonConfigs, wheelButtons);
@@ -366,15 +377,19 @@ export function sub_button_wheel(card, hass) {
366377
}
367378

368379
function getElementSelector(button) {
369-
if (button === "main-button" || button === "main") {
370-
return ".bubble-icon-container";
380+
if (isMainButton(button)) {
381+
return mainButtonSelector;
371382
} else {
372383
return typeof button === "string" && button.startsWith("sub-button-")
373384
? `.bubble-${button}`
374385
: `.bubble-sub-button-${button}`;
375386
}
376387
}
377388

389+
function isMainButton(button) {
390+
return button === "main-button" || button === "main";
391+
}
392+
378393
const wheelOpener = config.wheel_opener;
379394
if (!wheelOpener) {
380395
return;

modules/sub_button_wheel/editor.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
editor:
22
- name: wheel_opener
3-
label: "Button to open the wheel (e.g. 'sub-button-1'). Must have no tap action."
3+
label: "Button to open the wheel ('main', or '1' for 'sub-button-1' etc.)"
44
selector:
55
text:
66
- name: close_on_sub_button_click

modules/sub_button_wheel/module.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module_info:
22
id: sub_button_wheel
33
name: Sub Button Wheel
4-
version: 1.1.0
4+
version: 1.2.0
55
creator: lsmarsden
66
link: https://github.com/lsmarsden/bubble-card-modules/tree/main/sub_button_wheel
77
supported:

modules/sub_button_wheel/styles.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@
55
align-items: center;
66
}
77

8+
.wheel-menu.main-opener {
9+
margin: 6px 9px 6px 11px;
10+
}
11+
12+
.wheel-menu .bubble-icon-container {
13+
/* When using main icon as the wheel opener, the margins interfere
14+
with styling, so reset and use the wheel-menu.main-opener margins instead for alignment
15+
*/
16+
margin: 0 !important;
17+
}
18+
819
.glass-ring {
920
--c-light: #fff;
1021
--c-dark: #000;

0 commit comments

Comments
 (0)