diff --git a/openspec/changes/fix-combobox-flex-collapse/.openspec.yaml b/openspec/changes/fix-combobox-flex-collapse/.openspec.yaml new file mode 100644 index 0000000000..93831bd262 --- /dev/null +++ b/openspec/changes/fix-combobox-flex-collapse/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-05-13 diff --git a/openspec/changes/fix-combobox-flex-collapse/proposal.md b/openspec/changes/fix-combobox-flex-collapse/proposal.md new file mode 100644 index 0000000000..437061f260 --- /dev/null +++ b/openspec/changes/fix-combobox-flex-collapse/proposal.md @@ -0,0 +1,38 @@ +## Why + +Combobox shrinks to 1px when placed in a flex container with `align-items: center` (row). The widget becomes unusable — invisible to the user — without any CSS override from the app developer. + +## Root cause + +The actual DOM chain in the bug scenario: + +``` +.row-center (user's CSS: display:flex, flex-flow:row, align-items:center) + └─ .form-group.no-columns (Atlas: flex-direction:column, no explicit width) + └─ .widget-combobox (flex-grow:1 — grows height in column container, not width) + └─ .widget-combobox-input-container.form-control (Atlas: min-width:50px — too narrow) + └─ .widget-combobox-selected-items (min-width:0 — intentional for tag wrapping) + └─ .widget-combobox-input (max-width:0 unfocused, width:1px multiselect inactive) +``` + +The user created `.row-center`. Atlas injected `.form-group.no-columns` (column flex, no explicit width). Inside it, `flex-grow:1` on `.widget-combobox` distributes height, not width. Width is sized by content. + +Atlas has `min-width: 0` on `.widget-combobox` and `min-width: 50px` on `.form-control` (`.widget-combobox-input-container`). The `50px` floor propagates up — but it is too narrow: the down-arrow icon alone consumes ~53px, leaving zero space for text input. + +**Why native textbox is not affected:** + +Textbox renders `.form-control` directly inside `.form-group` — Atlas's `min-width: 50px` is wide enough for a plain input. Combobox `.form-control` must also contain the down-arrow icon, making `50px` insufficient. + +## What changes + +`packages/pluggableWidgets/combobox-web/src/ui/Combobox.scss` — `.widget-combobox-input-container` rule. + +Add `min-width: 15ch` — overrides Atlas's `50px` floor on `.form-control` with a value wide enough to be usable. Scoped to the combobox, not a global Atlas change. `ch` scales with font-size. + +## Impact + +Must not break: + +- Single-select combobox layout in all container types +- Multiselect combobox layout (active and inactive states) +- Atlas UI demo site rendering (already unaffected per ticket) diff --git a/openspec/changes/fix-combobox-flex-collapse/tests.md b/openspec/changes/fix-combobox-flex-collapse/tests.md new file mode 100644 index 0000000000..a1a1e9bef8 --- /dev/null +++ b/openspec/changes/fix-combobox-flex-collapse/tests.md @@ -0,0 +1,29 @@ +## Tests + +- [ ] **Combobox root element has min-width: 15ch in stylesheet** + - **Type:** unit + - **Given:** Combobox.scss source + - **When:** `.widget-combobox` rule is inspected + - **Then:** `min-width` is `15ch` + - **Status:** needs update — `src/__tests__/ComboboxStyles.spec.ts` currently asserts `min-content` + +- [ ] **Single-select combobox renders with visible width in flex container with align-items center** + - **Type:** e2e + - **Given:** Single-select Combobox on page `/p/combobox-flex-layout` (`.mx-name-comboBoxFlexSingle`) + - **When:** Page loads with no interaction + - **Then:** Combobox bounding rect width is greater than 10px + - **Status:** pending — needs test page in Studio Pro + +- [ ] **Multiselect combobox renders with visible width in flex container with align-items center** + - **Type:** e2e + - **Given:** Multiselect Combobox on page `/p/combobox-flex-layout` (`.mx-name-comboBoxFlexMulti`) + - **When:** Page loads with no interaction + - **Then:** Combobox bounding rect width is greater than 10px + - **Status:** pending — needs test page in Studio Pro + +- [x] **Multiselect inactive input still collapses to 1px (intentional behavior preserved)** + - **Type:** unit + - **Given:** Combobox.scss source + - **When:** multiselect inactive rule inspected + - **Then:** `.widget-combobox-input` has `width: 1px` + - **Status:** done — `src/__tests__/ComboboxStyles.spec.ts` diff --git a/packages/pluggableWidgets/combobox-web/e2e/Combobox.spec.js b/packages/pluggableWidgets/combobox-web/e2e/Combobox.spec.js index f9e2729342..64fab6dbf5 100644 --- a/packages/pluggableWidgets/combobox-web/e2e/Combobox.spec.js +++ b/packages/pluggableWidgets/combobox-web/e2e/Combobox.spec.js @@ -174,6 +174,28 @@ test.describe("combobox-web", () => { }); }); +// WC-3409: flex align-items center collapse fix +test.describe("flex container layout (WC-3409)", () => { + test.beforeEach(async ({ page }) => { + await page.goto("/p/combobox-flex-layout"); + await waitForMendixApp(page); + }); + + test("single-select combobox has visible width in flex align-items:center container", async ({ page }) => { + const comboBox = page.locator(".mx-name-comboBoxFlexSingle"); + await expect(comboBox).toBeVisible({ timeout: 10000 }); + const box = await comboBox.boundingBox(); + expect(box.width).toBeGreaterThan(10); + }); + + test("multiselect combobox has visible width in flex align-items:center container", async ({ page }) => { + const comboBox = page.locator(".mx-name-comboBoxFlexMulti"); + await expect(comboBox).toBeVisible({ timeout: 10000 }); + const box = await comboBox.boundingBox(); + expect(box.width).toBeGreaterThan(10); + }); +}); + function getOptions(combobox) { return combobox.locator(`[role=listbox] [role=option]`); } diff --git a/packages/pluggableWidgets/combobox-web/src/ui/Combobox.scss b/packages/pluggableWidgets/combobox-web/src/ui/Combobox.scss index 60297b500e..ebcb5f714f 100644 --- a/packages/pluggableWidgets/combobox-web/src/ui/Combobox.scss +++ b/packages/pluggableWidgets/combobox-web/src/ui/Combobox.scss @@ -18,7 +18,6 @@ $cb-skeleton-light: rgba(194, 194, 194, 0.2); $cb-skeleton-dark: #d2d2d2; .widget-combobox { - min-width: 0; flex-grow: 1; position: relative; transition: color 150ms ease 0s; @@ -141,6 +140,7 @@ $cb-skeleton-dark: #d2d2d2; .widget-combobox-input-container { flex-grow: 1; + min-width: 15ch; // overrides Atlas .form-control 50px floor; prevents collapse in column flex containers transition: box-shadow 150ms ease 0s; &-disabled {