From b790f575316b0c263ee8ae60274ecc5d85181dc3 Mon Sep 17 00:00:00 2001 From: Jos Rothman Date: Wed, 4 Nov 2026 22:41:16 +0100 Subject: [PATCH] Calmer management UI: neutral buttons and badges, smaller buttons Navy as the only accent, secondary buttons for restart/shutdown, the destructive action as a red outline, status colour only in the badge dot, no underline on the active nav item. Co-Authored-By: Claude Opus 5.5 --- src/voxip_kiosk/web/static/app.css | 50 +++++++++----------- src/voxip_kiosk/web/templates/dashboard.html | 2 +- src/voxip_kiosk/web/templates/kiosk.html | 2 +- src/voxip_kiosk/web/templates/network.html | 2 +- src/voxip_kiosk/web/templates/system.html | 4 +- 5 files changed, 28 insertions(+), 32 deletions(-) diff --git a/src/voxip_kiosk/web/static/app.css b/src/voxip_kiosk/web/static/app.css index b3167ab..7d57dff 100644 --- a/src/voxip_kiosk/web/static/app.css +++ b/src/voxip_kiosk/web/static/app.css @@ -1,8 +1,8 @@ :root { --navy: #0b2545; --navy-2: #13315c; - --accent: #1d6fd8; - --accent-dark: #1559b0; + --accent: #0b2545; + --accent-dark: #13315c; --bg: #f2f5f9; --card: #ffffff; --text: #1b2433; @@ -13,8 +13,8 @@ --error: #d64545; --stopped: #8592a3; --starting: #2f80ed; - --radius: 12px; - --shadow: 0 1px 2px rgba(11, 37, 69, .06), 0 4px 16px rgba(11, 37, 69, .06); + --radius: 8px; + --shadow: none; font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; color: var(--text); background: var(--bg); @@ -34,13 +34,13 @@ h2 { font-size: 1.1rem; margin: 0 0 .9rem; } .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; } /* --- top bar --------------------------------------------------------------- */ -.topbar { background: var(--navy); color: #fff; box-shadow: 0 2px 8px rgba(0, 0, 0, .15); position: sticky; top: 0; z-index: 10; } -.topbar-inner { max-width: 1200px; margin: 0 auto; padding: 0 1rem; display: flex; align-items: center; gap: 1rem; min-height: 60px; flex-wrap: wrap; } +.topbar { background: var(--navy); color: #fff; position: sticky; top: 0; z-index: 10; } +.topbar-inner { max-width: 1200px; margin: 0 auto; padding: 0 1rem; display: flex; align-items: center; gap: 1rem; min-height: 56px; flex-wrap: wrap; } .brand { display: flex; align-items: center; gap: .6rem; color: #fff; text-decoration: none; font-size: 1.1rem; margin-right: auto; } .mainnav { display: flex; align-items: center; gap: .25rem; flex-wrap: wrap; } -.mainnav a, .mainnav button { color: #d6e2f3; text-decoration: none; padding: .5rem .75rem; border-radius: 8px; font: inherit; font-size: .95rem; background: none; border: 0; cursor: pointer; } +.mainnav a, .mainnav button { color: #d6e2f3; text-decoration: none; padding: .45rem .7rem; border-radius: 6px; font: inherit; font-size: .95rem; background: none; border: 0; cursor: pointer; } .mainnav a:hover, .mainnav button:hover { background: var(--navy-2); color: #fff; } -.mainnav a[aria-current="page"] { background: var(--navy-2); color: #fff; box-shadow: inset 0 -3px 0 #4f9cf9; } +.mainnav a[aria-current="page"] { background: var(--navy-2); color: #fff; } .nav-logout { margin: 0; } .nav-toggle { display: none; background: none; border: 1px solid rgba(255, 255, 255, .3); border-radius: 8px; width: 44px; height: 40px; cursor: pointer; } .nav-toggle .bars, .nav-toggle .bars::before, .nav-toggle .bars::after { display: block; width: 20px; height: 2px; background: #fff; margin: 0 auto; position: relative; content: ""; } @@ -71,36 +71,32 @@ h2 { font-size: 1.1rem; margin: 0 0 .9rem; } .kv dt { color: var(--muted); } .kv dd { margin: 0; min-width: 0; } .kv-tight { margin-top: 1rem; font-size: .92rem; } -.note { margin: 1rem 0 0; padding: .6rem .8rem; background: #fff4e5; border-radius: 8px; font-size: .9rem; } +.note { margin: 1rem 0 0; padding: .6rem .8rem; background: #f4f6f9; border-radius: 6px; font-size: .9rem; } /* --- status badges ------------------------------------------------------------- */ -.badge { display: inline-flex; align-items: center; gap: .45rem; padding: .2rem .7rem; border-radius: 999px; font-size: .9rem; font-weight: 600; background: #eef2f7; } +.badge { display: inline-flex; align-items: center; gap: .45rem; padding: .1rem .55rem; border-radius: 4px; font-size: .875rem; font-weight: 500; background: #eef1f5; color: var(--text); } .badge .dot { width: .6rem; height: .6rem; border-radius: 50%; background: var(--stopped); flex: none; } -.badge-ok { background: #e3f5ea; color: #146c3b; } .badge-ok .dot { background: var(--ok); } -.badge-warning { background: #fff1d6; color: #8a5800; } .badge-warning .dot { background: var(--warning); } -.badge-error { background: #fde6e6; color: #a32c2c; } .badge-error .dot { background: var(--error); } -.badge-starting { background: #e3eefc; color: #1d4f9c; } .badge-starting .dot { background: var(--starting); animation: pulse 1.2s infinite; } -.badge-stopped, .badge-unknown { color: #4a5668; } +.badge-ok .dot { background: var(--ok); } +.badge-warning .dot { background: var(--warning); } +.badge-error { color: #a32c2c; } .badge-error .dot { background: var(--error); } +.badge-starting .dot { background: var(--starting); animation: pulse 1.2s infinite; } +.badge-stopped, .badge-unknown { color: var(--muted); } @keyframes pulse { 50% { opacity: .35; } } .meter { height: 6px; border-radius: 3px; background: #e6ebf2; margin-top: .35rem; overflow: hidden; } -.meter span { display: block; height: 100%; width: 0; background: var(--accent); transition: width .4s; } +.meter span { display: block; height: 100%; width: 0; background: #7d8ba0; transition: width .4s; } .meter span.is-mid { background: var(--warning); } .meter span.is-high { background: var(--error); } /* --- buttons ---------------------------------------------------------------------- */ -.btn { display: inline-flex; align-items: center; justify-content: center; gap: .5rem; font: inherit; font-weight: 600; padding: .6rem 1.1rem; border-radius: 10px; border: 1px solid transparent; cursor: pointer; text-decoration: none; transition: background .15s, transform .05s; min-height: 44px; } -.btn:active { transform: translateY(1px); } +.btn { display: inline-flex; align-items: center; justify-content: center; gap: .5rem; font: inherit; font-size: .95rem; font-weight: 500; padding: .45rem .9rem; border-radius: 6px; border: 1px solid transparent; cursor: pointer; text-decoration: none; transition: background .15s; min-height: 38px; } .btn:disabled { opacity: .6; cursor: progress; } .btn-primary { background: var(--accent); color: #fff; } .btn-primary:hover { background: var(--accent-dark); } -.btn-secondary { background: #fff; color: var(--navy); border-color: var(--border); } .btn-secondary:hover { background: #f1f4f8; } -.btn-warning { background: #f0a020; color: #2b1d00; } .btn-warning:hover { background: #dd9010; } -.btn-danger { background: var(--error); color: #fff; } .btn-danger:hover { background: #b93636; } -.btn-success { background: var(--ok); color: #fff; } .btn-success:hover { background: #17834a; } -.btn-dark { background: var(--navy); color: #fff; } .btn-dark:hover { background: var(--navy-2); } -.btn-big { font-size: 1.05rem; padding: 1rem 1.5rem; min-height: 64px; min-width: 220px; border-radius: 14px; box-shadow: var(--shadow); } +.btn-secondary { background: #fff; color: var(--text); border-color: #c5cfdb; } .btn-secondary:hover { background: #f1f4f8; } +.btn-danger { background: #fff; color: #b03030; border-color: #e3b5b5; } .btn-danger:hover { background: #fcf1f1; } +.btn-big { padding: .55rem 1.1rem; min-height: 42px; } .btn-block { width: 100%; } -.actions-row { display: flex; flex-wrap: wrap; gap: .75rem; margin-bottom: 1rem; } +.actions-row { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 1rem; } .inline-form { margin: 0; } @media (max-width: 560px) { .actions-row .inline-form, .actions-row .btn-big { width: 100%; } @@ -113,7 +109,7 @@ h2 { font-size: 1.1rem; margin: 0 0 .9rem; } .form input[type=text], .form input[type=url], .form input[type=password], .form input[type=number], .form select { font: inherit; font-weight: 400; padding: .6rem .7rem; border: 1px solid #c5cfdb; border-radius: 8px; background: #fff; color: var(--text); width: 100%; min-height: 44px; } -.form input:focus, .form select:focus { outline: 2px solid #8ab8f5; outline-offset: 1px; border-color: var(--accent); } +.form input:focus, .form select:focus { outline: 2px solid #9fb3cc; outline-offset: 1px; border-color: var(--navy); } .form label.check { flex-direction: row; align-items: center; gap: .55rem; font-weight: 400; } .form label.check input { width: 1.15rem; height: 1.15rem; } .form .btn { align-self: flex-start; } @@ -135,7 +131,7 @@ h2 { font-size: 1.1rem; margin: 0 0 .9rem; } .plain li { margin-bottom: .4rem; } /* --- alerts --------------------------------------------------------------------------- */ -.alert { padding: .8rem 1rem; border-radius: 10px; margin-bottom: 1rem; border: 1px solid; } +.alert { padding: .7rem .9rem; border-radius: 6px; margin-bottom: 1rem; border: 1px solid; } .alert-success { background: #e3f5ea; border-color: #b6e2c6; color: #145c33; } .alert-error { background: #fde6e6; border-color: #f4bcbc; color: #8f2424; } .alert-warning { background: #fff1d6; border-color: #f3d39b; color: #7a4e00; } diff --git a/src/voxip_kiosk/web/templates/dashboard.html b/src/voxip_kiosk/web/templates/dashboard.html index 232a83f..ad56ae4 100644 --- a/src/voxip_kiosk/web/templates/dashboard.html +++ b/src/voxip_kiosk/web/templates/dashboard.html @@ -9,7 +9,7 @@
{{ action(url_for('ui.kiosk_reload'), "Pagina herladen", "btn-primary", big=True) }} - {{ action(url_for('ui.kiosk_restart'), "Chromium herstarten", "btn-warning", confirm="Chromium wordt afgesloten en opnieuw gestart. Het scherm is enkele seconden zwart.", big=True) }} + {{ action(url_for('ui.kiosk_restart'), "Chromium herstarten", "btn-secondary", confirm="Chromium wordt afgesloten en opnieuw gestart. Het scherm is enkele seconden zwart.", big=True) }} {{ action(url_for('ui.system_reboot'), "Raspberry Pi herstarten", "btn-danger", confirm="De Raspberry Pi herstart. Het scherm en de beheerinterface zijn ongeveer een minuut niet beschikbaar.", big=True) }}
diff --git a/src/voxip_kiosk/web/templates/kiosk.html b/src/voxip_kiosk/web/templates/kiosk.html index f9b2f7e..86ea579 100644 --- a/src/voxip_kiosk/web/templates/kiosk.html +++ b/src/voxip_kiosk/web/templates/kiosk.html @@ -9,7 +9,7 @@
{{ action(url_for('ui.kiosk_reload'), "Pagina herladen", "btn-primary", big=True) }} - {{ action(url_for('ui.kiosk_restart'), "Chromium herstarten", "btn-warning", confirm="Chromium wordt afgesloten en opnieuw gestart.", big=True) }} + {{ action(url_for('ui.kiosk_restart'), "Chromium herstarten", "btn-secondary", confirm="Chromium wordt afgesloten en opnieuw gestart.", big=True) }}
diff --git a/src/voxip_kiosk/web/templates/network.html b/src/voxip_kiosk/web/templates/network.html index 825e61b..2a67cbf 100644 --- a/src/voxip_kiosk/web/templates/network.html +++ b/src/voxip_kiosk/web/templates/network.html @@ -15,7 +15,7 @@

Is het adres veranderd? Open dan {{ admin_scheme }}://{{ pending.address.split('/')[0] }}:{{ admin_port }}/network, log in en bevestig daar.

{% endif %}
-
{{ csrf() }}
+
{{ csrf() }}
{{ csrf() }}
diff --git a/src/voxip_kiosk/web/templates/system.html b/src/voxip_kiosk/web/templates/system.html index c582e25..7f10733 100644 --- a/src/voxip_kiosk/web/templates/system.html +++ b/src/voxip_kiosk/web/templates/system.html @@ -5,9 +5,9 @@

Systeembeheer

- {{ action(url_for('ui.kiosk_restart'), "Chromium herstarten", "btn-warning", confirm="Chromium wordt afgesloten en opnieuw gestart.", big=True) }} + {{ action(url_for('ui.kiosk_restart'), "Chromium herstarten", "btn-secondary", confirm="Chromium wordt afgesloten en opnieuw gestart.", big=True) }} {{ action(url_for('ui.system_reboot'), "Raspberry Pi herstarten", "btn-danger", confirm="De Raspberry Pi herstart. Het scherm en de beheerinterface zijn ongeveer een minuut niet beschikbaar.", big=True) }} - {{ action(url_for('ui.system_poweroff'), "Veilig uitschakelen", "btn-dark", confirm="De Raspberry Pi wordt uitgeschakeld. Daarna kan hij alleen weer aan door de stroom los en weer vast te maken.", confirm_title="Raspberry Pi uitschakelen", big=True) }} + {{ action(url_for('ui.system_poweroff'), "Veilig uitschakelen", "btn-secondary", confirm="De Raspberry Pi wordt uitgeschakeld. Daarna kan hij alleen weer aan door de stroom los en weer vast te maken.", confirm_title="Raspberry Pi uitschakelen", big=True) }}