5.5 KiB
5.5 KiB
Beautify “Connect to Device” Popup (Tauri + HTML)
Goal
Redesign the Connect to Device popup/modal to match the app’s glassmorphism + neon purple style:
- Frosted glass modal
- Blurred/dimmed overlay background
- Clean device list with hover + selected states
- Premium rounded corners and soft glow
- Works smoothly inside Tauri WebView (desktop)
Requirements
Functional
-
Modal opens/closes via existing app logic (do not change behavior).
-
Device list supports:
- Hover highlight
- Single selected device (one at a time)
- Click selects device (and triggers existing handler)
-
“Cancel” button closes modal (existing handler).
-
Include “This Computer (Local Playback)” option at top.
Visual
- Overlay blur + dark tint behind modal.
- Modal background: semi-transparent glass with blur.
- No harsh borders; use subtle border + soft shadow.
- Selected device: gradient accent + glow.
- Smooth animation on open (scale + fade).
- Desktop-friendly sizing (320–420px wide).
Tauri Safety / Performance
- Keep CSS lightweight.
- Avoid heavy SVG masks or expensive filters beyond
backdrop-filter: blur(...). - Ensure modal area is
-webkit-app-region: no-dragif you use draggable window headers.
Target Structure
HTML (keep semantic + simple)
Use or adapt this structure in the renderer HTML:
<div id="deviceOverlay" class="overlay hidden" aria-hidden="true">
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="deviceTitle">
<h2 id="deviceTitle">Connect to Device</h2>
<ul id="deviceList" class="device-list">
<!-- Render device items here -->
<!-- Example item:
<li class="device local selected" data-device="local">
<div class="device-main">This Computer</div>
<div class="device-sub">Local Playback</div>
</li>
-->
</ul>
<button id="deviceCancelBtn" class="btn cancel" type="button">Cancel</button>
</div>
</div>
Notes:
- Use
hiddenclass to toggle visibility. - Each
<li>must havedata-device="<name-or-id>"for click handling. - Selected item uses
.selected.
CSS (Glassmorphism Modal)
Add/merge this CSS into your stylesheet:
/* Overlay */
.overlay {
position: fixed;
inset: 0;
background: rgba(20, 10, 35, 0.45);
backdrop-filter: blur(14px);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.hidden { display: none !important; }
/* Modal */
.modal {
width: min(420px, calc(100vw - 48px));
padding: 22px;
border-radius: 22px;
background: rgba(30, 30, 40, 0.82);
border: 1px solid rgba(255,255,255,0.12);
box-shadow: 0 30px 80px rgba(0,0,0,0.6);
color: #fff;
animation: pop 0.22s ease;
-webkit-app-region: no-drag;
}
@keyframes pop {
from { transform: scale(0.94); opacity: 0; }
to { transform: scale(1); opacity: 1; }
}
.modal h2 {
margin: 0 0 14px;
text-align: center;
font-size: 20px;
}
/* Device list */
.device-list {
list-style: none;
padding: 0;
margin: 0 0 18px;
max-height: 360px;
overflow: auto;
}
/* Device row */
.device {
padding: 12px 14px;
border-radius: 14px;
margin-bottom: 8px;
cursor: pointer;
background: rgba(255,255,255,0.05);
transition: transform 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
}
.device:hover {
background: rgba(255,255,255,0.10);
transform: translateY(-1px);
}
.device .device-main {
font-size: 15px;
}
.device .device-sub {
margin-top: 3px;
font-size: 12px;
opacity: 0.7;
}
/* Selected device */
.device.selected {
background: linear-gradient(135deg, #c77dff, #8b5cf6);
box-shadow: 0 0 18px rgba(199,125,255,0.65);
color: #111;
}
.device.selected .device-sub {
opacity: 0.85;
}
/* Optional: disabled group devices */
.device.disabled {
opacity: 0.45;
pointer-events: none;
}
/* Cancel button */
.btn.cancel {
width: 100%;
padding: 12px;
border-radius: 999px;
border: none;
background: #d16b7d;
color: #fff;
font-size: 15px;
cursor: pointer;
transition: transform 0.15s ease;
}
.btn.cancel:hover {
transform: scale(1.02);
}
JavaScript Behavior (Minimal)
Selection logic
-
When a device row is clicked:
- Remove
.selectedfrom all device<li> - Add
.selectedto clicked<li> - Call existing “connect/cast to device” handler with
data-device
- Remove
Pseudo-code (adapt to existing app code):
deviceList.addEventListener("click", (e) => {
const item = e.target.closest(".device");
if (!item) return;
deviceList.querySelectorAll(".device.selected")
.forEach(el => el.classList.remove("selected"));
item.classList.add("selected");
const deviceName = item.dataset.device;
// call existing connect logic:
// connectToDevice(deviceName);
});
Close modal
- Cancel button closes modal (existing function):
deviceCancelBtn.addEventListener("click", closeDeviceModal);
Optional: close on overlay click
- Only if app UX allows:
deviceOverlay.addEventListener("click", (e) => {
if (e.target === deviceOverlay) closeDeviceModal();
});
Acceptance Criteria
- Popup visually matches glassmorphism theme.
- Overlay dims and blurs background.
- Device list has hover + selected glow.
- Exactly one device can be selected.
- Cancel closes modal.
- Runs smoothly in Tauri WebView without lag.
Notes / Future Enhancements (Optional)
- Mark “Speaker Groups” as
.disabledif casting library can’t support them. - Add small icons per device type (local vs cast).
- Remember last selected device and preselect it on open.