Improve login page UI and fix hot-dev script for macOS

This commit is contained in:
courtmanr@gmail.com 2025-11-20 12:21:49 +00:00
parent 1626b0e3ae
commit 1e229d5f38
3 changed files with 131 additions and 61 deletions

View file

@ -368,7 +368,7 @@ const LoginForm: Component<{
<div class="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 via-white to-cyan-50 dark:from-gray-900 dark:via-gray-800 dark:to-blue-900 py-12 px-4 sm:px-6 lg:px-8"> <div class="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 via-white to-cyan-50 dark:from-gray-900 dark:via-gray-800 dark:to-blue-900 py-12 px-4 sm:px-6 lg:px-8">
<div class="max-w-md w-full space-y-8"> <div class="max-w-md w-full space-y-8">
<div class="animate-fade-in"> <div class="animate-fade-in">
<div class="flex justify-center mb-4"> <div class="flex justify-center mb-8">
<div class="relative group"> <div class="relative group">
<div class="absolute -inset-1 bg-gradient-to-r from-blue-600 to-cyan-600 rounded-full blur opacity-25 group-hover:opacity-75 transition duration-1000 group-hover:duration-200 animate-pulse-slow"></div> <div class="absolute -inset-1 bg-gradient-to-r from-blue-600 to-cyan-600 rounded-full blur opacity-25 group-hover:opacity-75 transition duration-1000 group-hover:duration-200 animate-pulse-slow"></div>
<img <img
@ -378,10 +378,12 @@ const LoginForm: Component<{
/> />
</div> </div>
</div> </div>
<h2 class="mt-6 text-center text-3xl font-extrabold bg-gradient-to-r from-blue-600 to-cyan-600 bg-clip-text text-transparent">
<h2 class="mt-6 text-center text-4xl font-extrabold bg-gradient-to-r from-blue-600 to-cyan-600 bg-clip-text text-transparent animate-fade-in delay-100 pb-1">
Welcome to Pulse Welcome to Pulse
</h2> </h2>
<p class="mt-2 text-center text-sm text-gray-600 dark:text-gray-400">
<p class="mt-3 text-center text-sm text-gray-600 dark:text-gray-400 animate-fade-in delay-200">
Enter your credentials to continue Enter your credentials to continue
</p> </p>
</div> </div>
@ -524,11 +526,10 @@ const LoginForm: Component<{
<Show when={error()}> <Show when={error()}>
<div <div
class={`rounded-md p-4 ${ class={`rounded-md p-4 ${error().includes('locked')
error().includes('locked') ? 'bg-orange-50 dark:bg-orange-900/20'
? 'bg-orange-50 dark:bg-orange-900/20' : 'bg-red-50 dark:bg-red-900/20'
: 'bg-red-50 dark:bg-red-900/20' }`}
}`}
> >
<div class="flex"> <div class="flex">
<div class="flex-shrink-0"> <div class="flex-shrink-0">
@ -555,11 +556,10 @@ const LoginForm: Component<{
</div> </div>
<div class="ml-3"> <div class="ml-3">
<p <p
class={`text-sm ${ class={`text-sm ${error().includes('locked')
error().includes('locked') ? 'text-orange-800 dark:text-orange-200'
? 'text-orange-800 dark:text-orange-200' : 'text-red-800 dark:text-red-200'
: 'text-red-800 dark:text-red-200' }`}
}`}
> >
{error()} {error()}
</p> </p>

View file

@ -8,6 +8,7 @@
transform: translateY(-100%); transform: translateY(-100%);
opacity: 0; opacity: 0;
} }
to { to {
transform: translateY(0); transform: translateY(0);
opacity: 1; opacity: 1;
@ -25,6 +26,7 @@
transform: translateX(100%) scale(0.95); transform: translateX(100%) scale(0.95);
filter: blur(4px); filter: blur(4px);
} }
to { to {
opacity: 1; opacity: 1;
transform: translateX(0) scale(1); transform: translateX(0) scale(1);
@ -80,7 +82,8 @@
/* Slider thumb styles with value display */ /* Slider thumb styles with value display */
.threshold-slider::-webkit-slider-thumb { .threshold-slider::-webkit-slider-thumb {
@apply appearance-none w-12 h-5 rounded-full cursor-pointer relative; @apply appearance-none w-12 h-5 rounded-full cursor-pointer relative;
margin-top: -2.5px; /* Center thumb on track */ margin-top: -2.5px;
/* Center thumb on track */
background: white; background: white;
border: 2px solid currentColor; border: 2px solid currentColor;
box-shadow: box-shadow:
@ -99,15 +102,18 @@
/* Color coding for different metrics */ /* Color coding for different metrics */
.threshold-slider.slider-cpu { .threshold-slider.slider-cpu {
color: #3b82f6; /* blue-500 */ color: #3b82f6;
/* blue-500 */
} }
.threshold-slider.slider-memory { .threshold-slider.slider-memory {
color: #10b981; /* green-500 */ color: #10b981;
/* green-500 */
} }
.threshold-slider.slider-disk { .threshold-slider.slider-disk {
color: #f59e0b; /* amber-500 */ color: #f59e0b;
/* amber-500 */
} }
/* Value display inside thumb */ /* Value display inside thumb */
@ -227,20 +233,24 @@
/* Global scrollbar styling */ /* Global scrollbar styling */
* { * {
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: rgba(156, 163, 175, 0.5) transparent; /* gray-400 with transparency */ scrollbar-color: rgba(156, 163, 175, 0.5) transparent;
/* gray-400 with transparency */
} }
.dark * { .dark * {
scrollbar-color: rgba(55, 65, 81, 0.5) transparent; /* gray-700 with transparency */ scrollbar-color: rgba(55, 65, 81, 0.5) transparent;
/* gray-700 with transparency */
} }
/* Make scrollbars even more subtle on hover */ /* Make scrollbars even more subtle on hover */
*:hover { *:hover {
scrollbar-color: rgba(156, 163, 175, 0.7) rgba(243, 244, 246, 0.5); /* Slightly more visible on hover */ scrollbar-color: rgba(156, 163, 175, 0.7) rgba(243, 244, 246, 0.5);
/* Slightly more visible on hover */
} }
.dark *:hover { .dark *:hover {
scrollbar-color: rgba(75, 85, 99, 0.7) rgba(31, 41, 55, 0.3); /* dark mode hover */ scrollbar-color: rgba(75, 85, 99, 0.7) rgba(31, 41, 55, 0.3);
/* dark mode hover */
} }
*::-webkit-scrollbar { *::-webkit-scrollbar {
@ -311,20 +321,24 @@ body,
0% { 0% {
transform: scale(1); transform: scale(1);
} }
25% { 25% {
transform: scale(1.05); transform: scale(1.05);
} }
50% { 50% {
transform: scale(1); transform: scale(1);
} }
} }
@keyframes pulse-ring { @keyframes pulse-ring {
0%, 0%,
100% { 100% {
opacity: 0.92; opacity: 0.92;
transform: scale(1); transform: scale(1);
} }
50% { 50% {
opacity: 0.6; opacity: 0.6;
transform: scale(1.1); transform: scale(1.1);
@ -376,6 +390,7 @@ body,
opacity: 0; opacity: 0;
transform: translateY(-10px); transform: translateY(-10px);
} }
to { to {
opacity: 1; opacity: 1;
transform: translateY(0); transform: translateY(0);
@ -387,6 +402,7 @@ body,
opacity: 0; opacity: 0;
transform: translateY(20px); transform: translateY(20px);
} }
to { to {
opacity: 1; opacity: 1;
transform: translateY(0); transform: translateY(0);
@ -394,17 +410,19 @@ body,
} }
@keyframes pulse-slow { @keyframes pulse-slow {
0%, 0%,
100% { 100% {
opacity: 0.25; opacity: 0.25;
} }
50% { 50% {
opacity: 0.75; opacity: 0.75;
} }
} }
.animate-fade-in { .animate-fade-in {
animation: fade-in 0.6s ease-out; animation: fade-in 0.6s ease-out forwards;
} }
.animate-slide-up { .animate-slide-up {
@ -414,3 +432,50 @@ body,
.animate-pulse-slow { .animate-pulse-slow {
animation: pulse-slow 3s cubic-bezier(0.4, 0, 0.6, 1) infinite; animation: pulse-slow 3s cubic-bezier(0.4, 0, 0.6, 1) infinite;
} }
/* New Premium Animations */
@keyframes float {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-10px);
}
}
.animate-float {
animation: float 6s ease-in-out infinite;
}
@keyframes gradient-x {
0%,
100% {
background-size: 200% 200%;
background-position: left center;
}
50% {
background-size: 200% 200%;
background-position: right center;
}
}
.animate-gradient-x {
animation: gradient-x 3s ease infinite;
}
.delay-100 {
animation-delay: 100ms;
}
.delay-200 {
animation-delay: 200ms;
}
.delay-300 {
animation-delay: 300ms;
}

View file

@ -123,14 +123,14 @@ kill_port() {
printf "[hot-dev] Cleaning up existing processes...\n" printf "[hot-dev] Cleaning up existing processes...\n"
# Don't stop ourselves if we're running under systemd # Don't stop ourselves if we're running under systemd
if [[ -z "${INVOCATION_ID:-}" ]]; then # if [[ -z "${INVOCATION_ID:-}" ]]; then
# Not running under systemd, safe to stop the service # Not running under systemd, safe to stop the service
sudo systemctl stop pulse-hot-dev 2>/dev/null || true # sudo systemctl stop pulse-hot-dev 2>/dev/null || true
fi # fi
sudo systemctl stop pulse-backend 2>/dev/null || true # sudo systemctl stop pulse-backend 2>/dev/null || true
sudo systemctl stop pulse 2>/dev/null || true # sudo systemctl stop pulse 2>/dev/null || true
sudo systemctl stop pulse-frontend 2>/dev/null || true # sudo systemctl stop pulse-frontend 2>/dev/null || true
pkill -f "backend-watch.sh" 2>/dev/null || true pkill -f "backend-watch.sh" 2>/dev/null || true
pkill -f vite 2>/dev/null || true pkill -f vite 2>/dev/null || true
@ -271,47 +271,52 @@ printf "[hot-dev] Starting backend file watcher...\n"
cd "${ROOT_DIR}" cd "${ROOT_DIR}"
while true; do while true; do
# Watch for changes to .go files (excluding vendor and node_modules) # Watch for changes to .go files (excluding vendor and node_modules)
inotifywait -r -e modify,create,delete,move \ if command -v inotifywait >/dev/null 2>&1; then
--exclude '(vendor/|node_modules/|\.git/|\.swp$|\.tmp$|~$)' \ inotifywait -r -e modify,create,delete,move \
--format '%e %w%f' \ --exclude '(vendor/|node_modules/|\.git/|\.swp$|\.tmp$|~$)' \
"${ROOT_DIR}/cmd" "${ROOT_DIR}/internal" "${ROOT_DIR}/pkg" 2>/dev/null | \ --format '%e %w%f' \
while read -r event changed_file; do "${ROOT_DIR}/cmd" "${ROOT_DIR}/internal" "${ROOT_DIR}/pkg" 2>/dev/null | \
# Rebuild on any .go file change OR any create/delete event (catches new files) while read -r event changed_file; do
if [[ "$changed_file" == *.go ]] || [[ "$event" =~ CREATE|DELETE|MOVED ]]; then # Rebuild on any .go file change OR any create/delete event (catches new files)
echo "" if [[ "$changed_file" == *.go ]] || [[ "$event" =~ CREATE|DELETE|MOVED ]]; then
echo "[hot-dev] 🔄 Change detected: $event $(basename "$changed_file")" echo ""
echo "[hot-dev] Rebuilding backend..." echo "[hot-dev] 🔄 Change detected: $event $(basename "$changed_file")"
echo "[hot-dev] Rebuilding backend..."
# Rebuild the binary # Rebuild the binary
if go build -o pulse ./cmd/pulse 2>&1 | grep -v "^#"; then if go build -o pulse ./cmd/pulse 2>&1 | grep -v "^#"; then
echo "[hot-dev] ✓ Build successful, restarting backend..." echo "[hot-dev] ✓ Build successful, restarting backend..."
# Find and kill old backend # Find and kill old backend
OLD_PID=$(pgrep -f "^\./pulse$" || true) OLD_PID=$(pgrep -f "^\./pulse$" || true)
if [[ -n "$OLD_PID" ]]; then if [[ -n "$OLD_PID" ]]; then
kill "$OLD_PID" 2>/dev/null || true kill "$OLD_PID" 2>/dev/null || true
sleep 1 sleep 1
if kill -0 "$OLD_PID" 2>/dev/null; then if kill -0 "$OLD_PID" 2>/dev/null; then
kill -9 "$OLD_PID" 2>/dev/null || true kill -9 "$OLD_PID" 2>/dev/null || true
fi
fi fi
fi
# Start new backend with same environment # Start new backend with same environment
FRONTEND_PORT=${PULSE_DEV_API_PORT} PORT=${PULSE_DEV_API_PORT} PULSE_DATA_DIR=${PULSE_DATA_DIR} ./pulse & FRONTEND_PORT=${PULSE_DEV_API_PORT} PORT=${PULSE_DEV_API_PORT} PULSE_DATA_DIR=${PULSE_DATA_DIR} ./pulse &
NEW_PID=$! NEW_PID=$!
sleep 1 sleep 1
if kill -0 "$NEW_PID" 2>/dev/null; then if kill -0 "$NEW_PID" 2>/dev/null; then
echo "[hot-dev] ✓ Backend restarted (PID: $NEW_PID)" echo "[hot-dev] ✓ Backend restarted (PID: $NEW_PID)"
else
echo "[hot-dev] ✗ Backend failed to start!"
fi
else else
echo "[hot-dev] ✗ Backend failed to start!" echo "[hot-dev] ✗ Build failed!"
fi fi
else echo "[hot-dev] Watching for changes..."
echo "[hot-dev] ✗ Build failed!"
fi fi
echo "[hot-dev] Watching for changes..." done
fi else
done echo "[hot-dev] inotifywait not found. Auto-rebuild disabled."
sleep 3600
fi
done done
) & ) &
WATCHER_PID=$! WATCHER_PID=$!