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 <noreply@anthropic.com>
This commit is contained in:
rothmanandClaude Opus 5.5 committed 2026-11-04 22:41:16 +01:00
1 parent 1eabb839d3
commit b790f57531
5 files changed
+28 -32

No files matched your search

+23 -27
View File
@@ -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; }
+1 -1
View File
@@ -9,7 +9,7 @@
<section class="actions-row" aria-label="Snelle acties">
{{ 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) }}
</section>
+1 -1
View File
@@ -9,7 +9,7 @@
<section class="actions-row">
{{ 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) }}
</section>
<div class="grid grid-2">
+1 -1
View File
@@ -15,7 +15,7 @@
<p class="muted">Is het adres veranderd? Open dan <code>{{ admin_scheme }}://{{ pending.address.split('/')[0] }}:{{ admin_port }}/network</code>, log in en bevestig daar.</p>
{% endif %}
<div class="actions-row">
<form method="post" action="{{ url_for('ui.network_confirm') }}" class="inline-form">{{ csrf() }}<button class="btn btn-success btn-big">Bevestigen</button></form>
<form method="post" action="{{ url_for('ui.network_confirm') }}" class="inline-form">{{ csrf() }}<button class="btn btn-primary btn-big">Bevestigen</button></form>
<form method="post" action="{{ url_for('ui.network_rollback') }}" class="inline-form">{{ csrf() }}<button class="btn btn-secondary btn-big">Nu terugdraaien</button></form>
</div>
</section>
+2 -2
View File
@@ -5,9 +5,9 @@
<div class="page-head"><h1>Systeembeheer</h1></div>
<section class="actions-row">
{{ 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) }}
</section>
<div class="grid grid-2">