From 38179cf00dec32cf134e438fbcdf2694bac3c3c7 Mon Sep 17 00:00:00 2001
From: Scott Halver <76669202+scott-tp@users.noreply.github.com>
Date: Thu, 8 Oct 2026 14:58:58 -0400
Subject: [PATCH] Move Open WebUI into the card header and replace
confirm-delete with REMOVE modal.
Native confirm/prompt dialogs are unreliable in embedded browsers; the in-page
modal types REMOVE, uses a quiet danger confirm, and keeps the card Remove
button as a normal primary.
---
app/static/css/dashboard.css | 77 +++++++++++++++-
app/static/css/theme.css | 2 +
app/static/js/components/device-card.js | 17 +++-
app/static/js/dashboard-app.js | 114 ++++++++++++++++++++++--
app/templates/index.html | 2 +-
tests/test_remove_device_ui.py | 36 ++++++++
6 files changed, 232 insertions(+), 16 deletions(-)
create mode 100644 tests/test_remove_device_ui.py
diff --git a/app/static/css/dashboard.css b/app/static/css/dashboard.css
index 6eb09b0..f67cc0a 100644
--- a/app/static/css/dashboard.css
+++ b/app/static/css/dashboard.css
@@ -99,6 +99,10 @@ summary {
}
.device-card-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--space-3);
margin: calc(-1 * var(--space-4));
margin-bottom: var(--space-3);
padding: var(--space-3) var(--space-4);
@@ -107,6 +111,67 @@ summary {
border-bottom: 1px solid rgba(255, 255, 255, 0.18);
}
+.device-card-header .device-card-title {
+ min-width: 0;
+}
+
+.header-open-webui {
+ flex-shrink: 0;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ box-sizing: border-box;
+ padding: 0.4rem 1rem;
+ background: #fff;
+ color: var(--color-nav);
+ border: 1px solid #fff;
+ border-radius: var(--radius-md);
+ font-weight: 600;
+ text-decoration: none;
+}
+
+.header-open-webui:hover,
+.header-open-webui:focus-visible {
+ background: color-mix(in srgb, #fff 86%, var(--color-nav));
+ border-color: color-mix(in srgb, #fff 86%, var(--color-nav));
+ color: var(--color-nav);
+ text-decoration: none;
+}
+
+button.button-danger-quiet {
+ background: transparent;
+ color: var(--color-danger);
+ border: 1px solid color-mix(in srgb, var(--color-danger) 55%, transparent);
+ font-weight: 500;
+}
+
+button.button-danger-quiet:hover {
+ background: color-mix(in srgb, var(--color-danger) 14%, transparent);
+ color: var(--color-danger);
+ border-color: var(--color-danger);
+}
+
+.delete-device-actions {
+ margin-top: var(--space-2);
+ align-items: center;
+ gap: var(--space-2);
+}
+
+.delete-device-actions button {
+ margin-top: 0;
+ min-width: 0;
+ min-height: 2rem;
+ height: 2rem;
+ padding: 0 1rem;
+ line-height: 1;
+}
+
+.delete-device-actions #delete-device-cancel {
+ background: transparent;
+ color: var(--color-text);
+ border: 1px solid color-mix(in srgb, var(--color-text) 28%, transparent);
+}
+
.device-section > h3,
.device-card-title {
margin: 0;
@@ -646,14 +711,22 @@ button:active {
.modal-close {
flex-shrink: 0;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ box-sizing: border-box;
+ width: 1.75rem;
+ height: 1.75rem;
margin: 0;
- padding: 0.15rem 0.45rem;
+ padding: 0;
line-height: 1;
- font-size: 1.35rem;
+ font-size: 1.25rem;
font-weight: 500;
background: transparent;
border: 1px solid color-mix(in srgb, var(--color-text) 25%, transparent);
color: var(--color-muted);
+ /* × sits high in the em box; nudge for optical center. */
+ transform: translateY(1px);
}
.modal-close:hover {
diff --git a/app/static/css/theme.css b/app/static/css/theme.css
index 5786a85..b6581f1 100644
--- a/app/static/css/theme.css
+++ b/app/static/css/theme.css
@@ -12,6 +12,7 @@ body {
--color-muted: #475569;
--color-accent: #0e6b86;
--color-accent-hover: #0b5a71;
+ --color-danger: hsl(5, 57%, 44%);
--color-nav: hsl(230, 33%, 33%);
--color-nav-text: #ffffff;
--space-1: 4px;
@@ -30,6 +31,7 @@ body {
--color-muted: hsl(220, 18%, 76%);
--color-accent: hsl(205, 65%, 52%);
--color-accent-hover: hsl(205, 72%, 60%);
+ --color-danger: hsl(5, 57%, 58%);
--color-nav: hsl(230, 33%, 30%);
--color-nav-text: #ffffff;
}
diff --git a/app/static/js/components/device-card.js b/app/static/js/components/device-card.js
index 4e87d7e..6fb7270 100644
--- a/app/static/js/components/device-card.js
+++ b/app/static/js/components/device-card.js
@@ -32,6 +32,17 @@ function deactivateScreenshotLink(link) {
link.setAttribute('aria-disabled', 'true');
}
+function renderHeaderOpenWebUi(device) {
+ const url = String(device.base_url || '').trim();
+ if (!url) {
+ return '';
+ }
+ return (
+ ``
+ );
+}
+
class DeviceCard extends HTMLElement {
constructor() {
super();
@@ -86,6 +97,7 @@ class DeviceCard extends HTMLElement {