From 033bd63329bf0f7eaababd0d8d29d8f4925ab16b Mon Sep 17 00:00:00 2001 From: Echo Date: Tue, 10 Feb 2026 19:27:14 +0000 Subject: [PATCH] feat: US-007 - Frontend: Modal backdrop opacity and touch optimization --- dashboard/habits.html | 12 ++- dashboard/tests/test_habits_frontend.py | 135 ++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 4 deletions(-) diff --git a/dashboard/habits.html b/dashboard/habits.html index 8e8b8b1..4c445af 100644 --- a/dashboard/habits.html +++ b/dashboard/habits.html @@ -52,7 +52,7 @@ align-items: center; justify-content: center; min-width: 44px; - min-height: 36px; + min-height: 44px; padding: var(--space-2); border: 1px solid var(--border); border-radius: var(--radius-md); @@ -358,8 +358,8 @@ /* Compact check button */ .habit-card-check-btn-compact { - width: 32px; - height: 32px; + width: 44px; + height: 44px; border: 2px solid var(--accent); background: transparent; color: var(--accent); @@ -408,6 +408,8 @@ justify-content: center; border-radius: var(--radius-md); transition: all var(--transition-base); + min-width: 44px; + min-height: 44px; } .habit-card-action-btn:hover { @@ -484,7 +486,7 @@ left: 0; right: 0; bottom: 0; - background: rgba(0, 0, 0, 0.7); + background: rgba(0, 0, 0, 0.6); z-index: 1000; align-items: center; justify-content: center; @@ -530,6 +532,8 @@ justify-content: center; border-radius: var(--radius-md); transition: all var(--transition-base); + min-width: 44px; + min-height: 44px; } .modal-close:hover { diff --git a/dashboard/tests/test_habits_frontend.py b/dashboard/tests/test_habits_frontend.py index c344885..8c93c6d 100644 --- a/dashboard/tests/test_habits_frontend.py +++ b/dashboard/tests/test_habits_frontend.py @@ -1781,6 +1781,14 @@ def run_all_tests(): test_icon_picker_chevron_rotation, test_icon_picker_search_autofocus, test_typecheck_us006, + # US-007 tests (Modal backdrop and touch optimization) + test_modal_backdrop_opacity, + test_filter_icon_buttons_44px, + test_compact_check_button_44px, + test_action_buttons_44px, + test_modal_close_button_44px, + test_all_interactive_elements_touch_friendly, + test_typecheck_us007, ] print(f"\nRunning {len(tests)} frontend tests for US-002, US-003, US-004, US-005, US-006 through US-014...\n") @@ -2731,3 +2739,130 @@ def test_typecheck_us006(): assert result.returncode == 0, f"Typecheck failed: {result.stderr}" print("✓ Test 163 passed: Typecheck successful") + +# ======================================== +# US-007: Modal backdrop opacity and touch optimization +# ======================================== + +def test_modal_backdrop_opacity(): + """Test 164: Modal backdrop uses rgba(0, 0, 0, 0.6)""" + habits_path = Path(__file__).parent.parent / 'habits.html' + html = habits_path.read_text() + + # Find modal-overlay CSS + modal_overlay = html[html.find('.modal-overlay {'):html.find('.modal-overlay {') + 300] + assert 'background: rgba(0, 0, 0, 0.6)' in modal_overlay, "Modal backdrop should be rgba(0, 0, 0, 0.6)" + assert 'rgba(0, 0, 0, 0.7)' not in modal_overlay, "Should not use old opacity value 0.7" + + print("✓ Test 164 passed: Modal backdrop opacity is 0.6") + +def test_filter_icon_buttons_44px(): + """Test 165: Filter icon buttons have min-height 44px""" + habits_path = Path(__file__).parent.parent / 'habits.html' + html = habits_path.read_text() + + # Find filter-icon-btn CSS + filter_btn = html[html.find('.filter-icon-btn {'):html.find('.filter-icon-btn {') + 400] + assert 'min-width: 44px' in filter_btn, "Filter icon buttons should have min-width 44px" + assert 'min-height: 44px' in filter_btn, "Filter icon buttons should have min-height 44px" + assert 'min-height: 36px' not in filter_btn, "Should not use old min-height value 36px" + + print("✓ Test 165 passed: Filter icon buttons are 44x44px minimum") + +def test_compact_check_button_44px(): + """Test 166: Compact check button is 44x44px""" + habits_path = Path(__file__).parent.parent / 'habits.html' + html = habits_path.read_text() + + # Find habit-card-check-btn-compact CSS (base style, not mobile override) + check_btn_start = html.find('.habit-card-check-btn-compact {') + check_btn = html[check_btn_start:check_btn_start + 500] + assert 'width: 44px' in check_btn, "Compact check button should have width: 44px" + assert 'height: 44px' in check_btn, "Compact check button should have height: 44px" + assert 'width: 32px' not in check_btn, "Should not use old width value 32px" + assert 'height: 32px' not in check_btn, "Should not use old height value 32px" + + print("✓ Test 166 passed: Compact check button is 44x44px") + +def test_action_buttons_44px(): + """Test 167: Action buttons (edit/delete) have min 44x44px""" + habits_path = Path(__file__).parent.parent / 'habits.html' + html = habits_path.read_text() + + # Find habit-card-action-btn CSS (base style, not in media query) + # Search for all occurrences + action_btn_matches = [] + start = 0 + while True: + idx = html.find('.habit-card-action-btn {', start) + if idx == -1: + break + action_btn_matches.append(idx) + start = idx + 1 + + # Get the base style (should be the second one, after mobile styles) + assert len(action_btn_matches) >= 2, "Should have at least 2 .habit-card-action-btn definitions" + base_style_idx = action_btn_matches[1] # Second occurrence is the base style + action_btn = html[base_style_idx:base_style_idx + 500] + + assert 'min-width: 44px' in action_btn, "Action buttons should have min-width 44px in base style" + assert 'min-height: 44px' in action_btn, "Action buttons should have min-height 44px in base style" + + print("✓ Test 167 passed: Action buttons have min 44x44px touch targets") + +def test_modal_close_button_44px(): + """Test 168: Modal close button has min 44x44px""" + habits_path = Path(__file__).parent.parent / 'habits.html' + html = habits_path.read_text() + + # Find modal-close CSS (base style, not in media query) + # Search for all occurrences + modal_close_matches = [] + start = 0 + while True: + idx = html.find('.modal-close {', start) + if idx == -1: + break + modal_close_matches.append(idx) + start = idx + 1 + + # Get the base style (second occurrence) + assert len(modal_close_matches) >= 2, "Should have at least 2 .modal-close definitions" + base_style_idx = modal_close_matches[1] + modal_close = html[base_style_idx:base_style_idx + 500] + + assert 'min-width: 44px' in modal_close, "Modal close button should have min-width 44px in base style" + assert 'min-height: 44px' in modal_close, "Modal close button should have min-height 44px in base style" + + print("✓ Test 168 passed: Modal close button has min 44x44px touch target") + +def test_all_interactive_elements_touch_friendly(): + """Test 169: Verify all key interactive elements meet 44px minimum""" + habits_path = Path(__file__).parent.parent / 'habits.html' + html = habits_path.read_text() + + # List of interactive elements that should have proper touch targets + elements = [ + ('.habit-card-check-btn-compact', 'Check button'), + ('.habit-card-action-btn', 'Action buttons'), + ('.filter-icon-btn', 'Filter icon buttons'), + ('.modal-close', 'Modal close button'), + ] + + for selector, name in elements: + # Find in base styles (not just mobile) + assert f'{selector}' in html, f"{name} should exist" + # We've already tested these individually, this is a summary check + + print("✓ Test 169 passed: All interactive elements have touch-friendly sizes") + +def test_typecheck_us007(): + """Test 170: Typecheck passes after US-007 changes""" + result = subprocess.run( + ['python3', '-m', 'py_compile', 'dashboard/api.py', 'dashboard/habits_helpers.py'], + cwd='/home/moltbot/clawd', + capture_output=True, + text=True + ) + assert result.returncode == 0, f"Typecheck failed: {result.stderr}" + print("✓ Test 170 passed: Typecheck successful")