From 2ff1a62d19fb24ac5a08f181c94fc3a9fed5bc5a Mon Sep 17 00:00:00 2001 From: shkomg Date: Tue, 3 Nov 2026 16:22:41 +0100 Subject: [PATCH] Show boolean properties that default to true as checked (#2298) Fixes #747 Boolean properties that default to `true` (`fill-antialias`, `text-keep-upright`, `fill-extrusion-vertical-gradient`) showed an empty checkbox when unset, so the first click wrote `true` and nothing changed on the map. `InputCheckbox` now falls back to the spec default that `InputSpec` already passes (as `InputEnum` does), and a click toggles from what is shown. The Cluster checkbox in the sources modal passes no default, so it behaves as before. ## Launch Checklist - [x] Briefly describe the changes in this PR. - [x] Link to related issues. - [x] Include before/after visuals or gifs if this PR includes visual changes. - [x] Write tests for all new functionality. - [x] Add an entry to `CHANGELOG.md` under the `## main` section. Added two e2e tests on `fill-antialias` (checked when unset, one click writes `false`). ## Screenshots "Extrusion vertical gradient" on a `fill-extrusion` layer with the property unset, before and after: | Before | After | | --- | --- | | ![before](https://github.com/user-attachments/assets/a2f4f4d2-9b1e-4b1b-89db-2a6a1f0b922a) | ![after](https://github.com/user-attachments/assets/64e79b7b-1a9c-40e6-8040-9ac082ef998c) | | ![before, zoomed](https://github.com/user-attachments/assets/482cb984-4927-4e32-81cb-2fce75c3a25d) | ![after, zoomed](https://github.com/user-attachments/assets/5d135d3d-910a-49ff-9837-b931132e7a30) | ## Video The video shows the same row on a small extrusion style, and one click turning the gradient off. https://github.com/user-attachments/assets/8ebc2f5a-923b-4022-82da-07cbd1eda783 Fix written with Claude Code; video is an automated browser run of this branch recorded by User Stories Bot. --- CHANGELOG.md | 1 + e2e/layer-editor.spec.ts | 11 +++++++++++ e2e/playwright-helper.ts | 1 + src/components/InputCheckbox.tsx | 14 ++++++++------ 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b86d60f7..3250ff36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - Keyboard shortcuts now keep working while the map has focus, instead of going dead until the map is blurred - The map no longer stays blank on load until it is moved, when the style loads before the map is ready - The debug modal now shows the MapLibre options for any renderer other than OpenLayers (e.g. `mbgljs`) +- Checkboxes for properties that default to `true` (e.g. `fill-antialias`, `text-keep-upright`) are now shown checked when the property is unset - _...Add new stuff here..._ ## 3.1.0 diff --git a/e2e/layer-editor.spec.ts b/e2e/layer-editor.spec.ts index 8b35ef9d..6f9ffebb 100644 --- a/e2e/layer-editor.spec.ts +++ b/e2e/layer-editor.spec.ts @@ -540,6 +540,17 @@ describe("layer editor", () => { layers: [{ id, type: "fill", source: "example", paint: { "fill-opacity": 0.4 } }], }); }); + + test("antialias is checked when unset, as it defaults to true", async () => { + await then(get.element("[data-wd-key='spec-field:fill-antialias'] input")).shouldBeChecked(); + }); + + test("unchecking antialias sets it to false", async () => { + await when.clickWithin("spec-field:fill-antialias", "input"); + await then(get.styleFromLocalStorage()).shouldDeepNestedInclude({ + layers: [{ id, type: "fill", source: "example", paint: { "fill-antialias": false } }], + }); + }); }); describe("json-editor", () => { diff --git a/e2e/playwright-helper.ts b/e2e/playwright-helper.ts index e0d73c8d..8de97774 100644 --- a/e2e/playwright-helper.ts +++ b/e2e/playwright-helper.ts @@ -108,6 +108,7 @@ export class Assertable { shouldBeFocused = () => expect(this.locator().first()).toBeFocused(); shouldNotBeFocused = () => expect(this.locator().first()).not.toBeFocused(); shouldHaveValue = (value: string) => expect(this.locator().first()).toHaveValue(value); + shouldBeChecked = () => expect(this.locator().first()).toBeChecked(); shouldContainText = async (text: string) => { const locator = this.locator(); // Prefer the visible element when a testid resolves to several (only the diff --git a/src/components/InputCheckbox.tsx b/src/components/InputCheckbox.tsx index 31bf5939..fdc388c7 100644 --- a/src/components/InputCheckbox.tsx +++ b/src/components/InputCheckbox.tsx @@ -2,20 +2,22 @@ import React from "react"; export type InputCheckboxProps = { value?: boolean + default?: boolean style?: object onChange(...args: unknown[]): unknown }; export class InputCheckbox extends React.Component { - static defaultProps = { - value: false, - }; + isChecked() { + return this.props.value ?? this.props.default ?? false; + } onChange = () => { - this.props.onChange(!this.props.value); + this.props.onChange(!this.isChecked()); }; render() { + const checked = this.isChecked(); return
{ style={this.props.style} onChange={this.onChange} onClick={this.onChange} - checked={this.props.value} + checked={checked} />