fix(arr): make the provider reorder honest
`visibility: hidden` on the disabled reorder button left a control in the DOM that rendered as nothing. `disabled` already blocks the click and drops it out of the tab order, so the hiding was decoration; the shared `.control:disabled` colour says the same thing on screen, and the row does not reflow because the hidden button reserved its box anyway. Exposing it surfaced a second problem: `.control-quiet:hover` sits after `.control:disabled` at the same specificity, so a disabled quiet control lit accent-bright under the cursor and invited a click that does nothing. Guarded with `:not(:disabled)` in the shared rule rather than on this one control. `refreshProviderEdges` found the buttons by `button:nth-of-type(1|2)`. Position in the row is not a contract — a third button would have quietly moved the edge logic onto the wrong control. They carry `data-move` now. Closes #255
This commit is contained in:
+11
-6
@@ -722,13 +722,18 @@ export function settingsMain(views: { hide: () => void }[], goHome: () => void):
|
||||
* A reorder control: the same `control control-quiet control-icon` the
|
||||
* sibling rows in this view use (#231), with a chevron off the shared
|
||||
* glyph set (#251) rather than the words "up" and "down".
|
||||
*
|
||||
* `data-move` is how `refreshProviderEdges` finds it (#255). Position in
|
||||
* the row is not a contract — the day a third button joins the row, an
|
||||
* ordinal selector would quietly disable the wrong control.
|
||||
*/
|
||||
function moveButton(glyph: "chevronUp" | "chevronDown", label: string): HTMLButtonElement {
|
||||
function moveButton(direction: "up" | "down", label: string): HTMLButtonElement {
|
||||
const button = el("button", "control control-quiet control-icon provider-move");
|
||||
button.type = "button";
|
||||
button.dataset.move = direction;
|
||||
button.setAttribute("aria-label", label);
|
||||
button.title = label;
|
||||
button.append(icon(glyph));
|
||||
button.append(icon(direction === "up" ? "chevronUp" : "chevronDown"));
|
||||
return button;
|
||||
}
|
||||
|
||||
@@ -758,8 +763,8 @@ export function settingsMain(views: { hide: () => void }[], goHome: () => void):
|
||||
budgetInput.classList.add("provider-budget");
|
||||
budgetInput.setAttribute("aria-label", `${provider} daily budget`);
|
||||
|
||||
const up = moveButton("chevronUp", `move ${provider} up`);
|
||||
const down = moveButton("chevronDown", `move ${provider} down`);
|
||||
const up = moveButton("up", `move ${provider} up`);
|
||||
const down = moveButton("down", `move ${provider} down`);
|
||||
|
||||
up.addEventListener("click", () => {
|
||||
const previous = item.previousElementSibling;
|
||||
@@ -865,8 +870,8 @@ export function settingsMain(views: { hide: () => void }[], goHome: () => void):
|
||||
refreshProviderEdges = () => {
|
||||
const items = [...list.children];
|
||||
items.forEach((item, index) => {
|
||||
const up = item.querySelector<HTMLButtonElement>("button:nth-of-type(1)");
|
||||
const down = item.querySelector<HTMLButtonElement>("button:nth-of-type(2)");
|
||||
const up = item.querySelector<HTMLButtonElement>('[data-move="up"]');
|
||||
const down = item.querySelector<HTMLButtonElement>('[data-move="down"]');
|
||||
if (up) up.disabled = index === 0;
|
||||
if (down) down.disabled = index === items.length - 1;
|
||||
});
|
||||
|
||||
+4
-5
@@ -1093,7 +1093,10 @@ body {
|
||||
border-color: var(--line);
|
||||
}
|
||||
|
||||
.control-quiet:hover,
|
||||
/* `:not(:disabled)` because this rule sits after `.control:disabled` at the
|
||||
same specificity: without it a disabled quiet control lights accent-bright
|
||||
under the cursor and invites a click that does nothing (#255). */
|
||||
.control-quiet:hover:not(:disabled),
|
||||
.control-quiet[aria-expanded="true"] {
|
||||
color: var(--accent-bright);
|
||||
border-color: var(--accent);
|
||||
@@ -2407,7 +2410,3 @@ select.form-input {
|
||||
.provider-budget {
|
||||
width: 5.5rem;
|
||||
}
|
||||
|
||||
.provider-move:disabled {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user