Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions tests/test_button_effects.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/bin/bash
# Test button tactile interaction effects
# Verifies CSS interaction properties exist in VSCode webview stylesheets

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"

PLAN_CSS="$PROJECT_ROOT/vscode/webview/plan/styles.css"
SETTINGS_CSS="$PROJECT_ROOT/vscode/webview/settings/styles.css"

ERRORS=0

echo "=== Testing Button Tactile Effects ==="
echo ""

# Test 1: Base button hover state
echo -n "Test 1: Base button has :hover state... "
if grep -q "button:hover" "$PLAN_CSS"; then
echo "PASS"
else
echo "FAIL"
ERRORS=$((ERRORS + 1))
fi

# Test 2: Base button active state
echo -n "Test 2: Base button has :active state... "
if grep -q "button:active" "$PLAN_CSS"; then
echo "PASS"
else
echo "FAIL"
ERRORS=$((ERRORS + 1))
fi

# Test 3: Base button transition property
echo -n "Test 3: Base button has transition property... "
if grep -A12 "^button {" "$PLAN_CSS" | grep -q "transition:"; then
echo "PASS"
else
echo "FAIL"
ERRORS=$((ERRORS + 1))
fi

# Test 4: Widget button variants have hover state
echo -n "Test 4: Widget buttons have :hover state... "
if grep -q "\.widget-button:hover" "$PLAN_CSS"; then
echo "PASS"
else
echo "FAIL"
ERRORS=$((ERRORS + 1))
fi

# Test 5: Widget button variants have active state
echo -n "Test 5: Widget buttons have :active state... "
if grep -q "\.widget-button:active" "$PLAN_CSS"; then
echo "PASS"
else
echo "FAIL"
ERRORS=$((ERRORS + 1))
fi

# Test 6: Icon buttons (toggle) have hover state
echo -n "Test 6: Toggle buttons have :hover state... "
if grep -q "\.toggle:hover" "$PLAN_CSS"; then
echo "PASS"
else
echo "FAIL"
ERRORS=$((ERRORS + 1))
fi

# Test 7: Icon buttons (toggle) have active state
echo -n "Test 7: Toggle buttons have :active state... "
if grep -q "\.toggle:active" "$PLAN_CSS"; then
echo "PASS"
else
echo "FAIL"
ERRORS=$((ERRORS + 1))
fi

# Test 8: Terminal toggle has hover state
echo -n "Test 8: Terminal toggle has :hover state... "
if grep -q "\.terminal-toggle:hover" "$PLAN_CSS"; then
echo "PASS"
else
echo "FAIL"
ERRORS=$((ERRORS + 1))
fi

# Test 9: Terminal toggle has active state
echo -n "Test 9: Terminal toggle has :active state... "
if grep -q "\.terminal-toggle:active" "$PLAN_CSS"; then
echo "PASS"
else
echo "FAIL"
ERRORS=$((ERRORS + 1))
fi

# Test 10: Settings link has active state
echo -n "Test 10: Settings link has :active state... "
if grep -q "\.settings-link:active" "$SETTINGS_CSS"; then
echo "PASS"
else
echo "FAIL"
ERRORS=$((ERRORS + 1))
fi

# Test 11: prefers-reduced-motion media query in plan/styles.css
echo -n "Test 11: prefers-reduced-motion in plan/styles.css... "
if grep -q "prefers-reduced-motion" "$PLAN_CSS"; then
echo "PASS"
else
echo "FAIL"
ERRORS=$((ERRORS + 1))
fi

# Test 12: prefers-reduced-motion media query in settings/styles.css
echo -n "Test 12: prefers-reduced-motion in settings/styles.css... "
if grep -q "prefers-reduced-motion" "$SETTINGS_CSS"; then
echo "PASS"
else
echo "FAIL"
ERRORS=$((ERRORS + 1))
fi

# Test 13: 120ms transition timing
echo -n "Test 13: Transition timing is 120ms... "
if grep -q "120ms" "$PLAN_CSS"; then
echo "PASS"
else
echo "FAIL"
ERRORS=$((ERRORS + 1))
fi

echo ""
if [ $ERRORS -eq 0 ]; then
echo "=== All tests passed! ==="
exit 0
else
echo "=== $ERRORS test(s) failed ==="
exit 1
fi
93 changes: 93 additions & 0 deletions vscode/webview/plan/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ button {
color: var(--text);
padding: 6px 10px;
cursor: pointer;
/* Tactile feedback: smooth transitions for hover/active states */
transition: transform 120ms ease-out, box-shadow 120ms ease-out, background-color 120ms ease-out;
}

button:hover {
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}

button:active {
transform: translateY(1px);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

button.primary {
Expand Down Expand Up @@ -187,6 +199,18 @@ button:disabled {
font-weight: 700;
color: var(--accent);
padding: 0 6px;
/* Borderless buttons use opacity/scale instead of shadow for tactile feedback */
transition: opacity 120ms ease-out, transform 120ms ease-out;
}

.toggle:hover {
opacity: 0.8;
transform: scale(1.05);
}

.toggle:active {
opacity: 0.6;
transform: scale(0.95);
}

.delete {
Expand Down Expand Up @@ -262,6 +286,18 @@ button:disabled {
padding: 0 4px;
cursor: pointer;
font-size: 12px;
/* Borderless buttons use opacity/scale instead of shadow for tactile feedback */
transition: opacity 120ms ease-out, transform 120ms ease-out;
}

.terminal-toggle:hover {
opacity: 0.8;
transform: scale(1.05);
}

.terminal-toggle:active {
opacity: 0.6;
transform: scale(0.95);
}

.terminal-title {
Expand Down Expand Up @@ -324,24 +360,72 @@ button:disabled {
/* Equal-width buttons: flex distributes space evenly, min-width prevents truncation. */
flex: 1 1 0;
min-width: 70px;
/* Tactile feedback: smooth transitions for hover/active states */
transition: transform 120ms ease-out, box-shadow 120ms ease-out, background-color 120ms ease-out;
}

.widget-button:hover {
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}

.widget-button:active {
transform: translateY(1px);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

.widget-button-primary {
border-color: var(--accent);
background: var(--accent);
color: #ffffff;
/* Tactile feedback: smooth transitions for hover/active states */
transition: transform 120ms ease-out, box-shadow 120ms ease-out, background-color 120ms ease-out;
}

.widget-button-primary:hover {
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}

.widget-button-primary:active {
transform: translateY(1px);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

.widget-button-danger {
border-color: var(--error);
color: var(--error);
background: rgba(156, 42, 42, 0.08);
/* Tactile feedback: smooth transitions for hover/active states */
transition: transform 120ms ease-out, box-shadow 120ms ease-out, background-color 120ms ease-out;
}

.widget-button-danger:hover {
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}

.widget-button-danger:active {
transform: translateY(1px);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

.widget-button-ghost {
border-color: var(--border);
color: var(--accent);
background: rgba(15, 110, 110, 0.08);
/* Tactile feedback: smooth transitions for hover/active states */
transition: transform 120ms ease-out, box-shadow 120ms ease-out, background-color 120ms ease-out;
}

.widget-button-ghost:hover {
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}

.widget-button-ghost:active {
transform: translateY(1px);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

.widget-input {
Expand Down Expand Up @@ -492,3 +576,12 @@ button:disabled {
flex-wrap: wrap;
}
}

/* Accessibility: disable animations for users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
button, .widget-button, .widget-button-primary, .widget-button-danger,
.widget-button-ghost, .toggle, .terminal-toggle {
transition: none;
transform: none;
}
}
18 changes: 17 additions & 1 deletion vscode/webview/settings/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,20 @@
text-decoration: none;
transition:
border-color 120ms ease-out,
background 120ms ease-out;
background 120ms ease-out,
color 150ms ease,
transform 120ms ease-out;
}

.settings-link:hover {
border-color: rgba(15, 110, 110, 0.42);
background: rgba(15, 110, 110, 0.08);
color: var(--accent);
transform: translateX(2px);
}

.settings-link:active {
transform: translateX(4px);
}

.settings-link:focus-visible {
Expand All @@ -103,3 +111,11 @@
padding: 18px 14px;
}
}

/* Accessibility: disable animations for users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
.settings-link {
transition: none;
transform: none;
}
}