From b13cc3c324112f90256148bd0b1ae494ca343147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kucharczyk?= Date: Fri, 19 Jun 2026 18:42:52 +0200 Subject: [PATCH] Keep not-allowed cursor on disabled SearchSelect input Excluding the inner search box from the global disabled rule also dropped its cursor: not-allowed, so the pointer flickered between not-allowed (wrapper) and the text I-beam (input) when moving across the disabled widget. Add disabled:cursor-not-allowed to the search input so the cursor stays consistent. e2e: assert the disabled inner input computes cursor: not-allowed. Co-Authored-By: Claude Opus 4.8 --- common/components/search_select.py | 6 +++++- e2e/test_widgets_e2e.py | 3 +++ games/static/base.css | 5 +++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/common/components/search_select.py b/common/components/search_select.py index a14dac3..7e219b4 100644 --- a/common/components/search_select.py +++ b/common/components/search_select.py @@ -66,9 +66,13 @@ _CONTAINER_CLASS = ( "has-[:disabled]:opacity-50 has-[:disabled]:cursor-not-allowed" ) _PILLS_CLASS = "contents" +# disabled:cursor-not-allowed matches the wrapper's cursor so hovering across +# the whole widget stays consistent — the inner input is excluded from the +# global disabled rule (input.css), which would otherwise have set it. _SEARCH_CLASS = ( "flex-1 min-w-[8rem] border-0 bg-transparent text-sm text-heading " - "focus:ring-0 focus:outline-hidden placeholder:text-body" + "focus:ring-0 focus:outline-hidden placeholder:text-body " + "disabled:cursor-not-allowed" ) # top-full anchors the panel to the container's bottom edge: as an absolutely # positioned child of the flex field, its static position would otherwise be diff --git a/e2e/test_widgets_e2e.py b/e2e/test_widgets_e2e.py index 7c9dc0d..007d1ce 100644 --- a/e2e/test_widgets_e2e.py +++ b/e2e/test_widgets_e2e.py @@ -178,6 +178,9 @@ def test_add_purchase_type_game_disables_related_game_search( # disabled-input surface) so the widget reads as one element, not a nested # box. transparent is mode-independent, so this holds in light and dark. assert search.evaluate("el => getComputedStyle(el).backgroundColor") == "rgba(0, 0, 0, 0)" + # The inner input carries the same not-allowed cursor as the wrapper, so the + # cursor doesn't flicker as the pointer crosses the widget. + assert search.evaluate("el => getComputedStyle(el).cursor") == "not-allowed" page.select_option("#id_type", "dlc") expect(search).to_be_enabled() diff --git a/games/static/base.css b/games/static/base.css index aa346d1..a1c24bf 100644 --- a/games/static/base.css +++ b/games/static/base.css @@ -3430,6 +3430,11 @@ outline-style: none; } } + .disabled\:cursor-not-allowed { + &:disabled { + cursor: not-allowed; + } + } .has-\[\:disabled\]\:cursor-not-allowed { &:has(*:is(:disabled)) { cursor: not-allowed;