Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
279 changes: 279 additions & 0 deletions flower/static/css/flower.css
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,282 @@ div.dataTables_wrapper .dataTables_filter input {
.overflow-auto::-webkit-scrollbar {
display: none;
}

/* Dark mode toggle button */
#theme-toggle {
background: none;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 4px;
color: #495057;
padding: 0.25rem 0.45rem;
cursor: pointer;
line-height: 1;
display: flex;
align-items: center;
}

#theme-toggle:hover {
border-color: #495057;
}

/* Dark mode — Bootstrap 5.2 has no built-in dark mode support, all overrides are manual */

[data-bs-theme="dark"] body {
background-color: #1a1e21;
color: #dee2e6;
}

/* Navbar */
[data-bs-theme="dark"] .bg-green {
background-color: #141f10 !important;
}

[data-bs-theme="dark"] .navbar-light .navbar-brand,
[data-bs-theme="dark"] .navbar-light .nav-link,
[data-bs-theme="dark"] .navbar-light .nav-link.text-dark {
color: rgba(255, 255, 255, 0.85) !important;
}

[data-bs-theme="dark"] .navbar-light .nav-link:hover,
[data-bs-theme="dark"] .navbar-light .nav-link.text-dark:hover {
color: #fff !important;
}

[data-bs-theme="dark"] .navbar-nav-svg {
color: rgba(255, 255, 255, 0.7);
}

[data-bs-theme="dark"] #theme-toggle {
border-color: rgba(255, 255, 255, 0.3);
color: rgba(255, 255, 255, 0.8);
}

[data-bs-theme="dark"] #theme-toggle:hover {
border-color: rgba(255, 255, 255, 0.6);
color: #fff;
}

/* Tables */
[data-bs-theme="dark"] .table {
color: #dee2e6;
border-color: #3d4349;
--bs-table-color: #dee2e6;
--bs-table-bg: #212529;
--bs-table-border-color: #3d4349;
--bs-table-striped-color: #dee2e6;
--bs-table-striped-bg: #1d2921;
--bs-table-accent-bg: #1d2921;
--bs-table-hover-color: #dee2e6;
--bs-table-hover-bg: #263022;
}

[data-bs-theme="dark"] .table > :not(caption) > * > * {
background-color: #212529;
color: #dee2e6;
border-color: #3d4349;
}

[data-bs-theme="dark"] .table-striped > tbody > tr:nth-of-type(odd) > * {
background-color: #1d2921 !important;
color: #dee2e6;
}

[data-bs-theme="dark"] .table-hover > tbody > tr:hover > * {
background-color: #263022 !important;
color: #fff;
}

[data-bs-theme="dark"] .table-bordered > :not(caption) > * {
border-color: #3d4349;
}

[data-bs-theme="dark"] .table > thead > tr > th {
border-color: #3d4349;
}

/* DataTables controls */
[data-bs-theme="dark"] .dataTables_wrapper {
border-color: #3d4349;
color: #dee2e6;
}

[data-bs-theme="dark"] div.dataTables_wrapper .dataTables_filter input {
background-color: #2a2e33;
border-color: #3d4349;
color: #dee2e6;
}

[data-bs-theme="dark"] .dataTables_length select {
background-color: #2a2e33;
border-color: #3d4349;
color: #dee2e6;
}

[data-bs-theme="dark"] .dataTables_info,
[data-bs-theme="dark"] .dataTables_length {
color: #9ca3af;
}

/* Pagination */
[data-bs-theme="dark"] .page-link {
background-color: #2a2e33;
border-color: #3d4349;
color: #adb5bd;
}

[data-bs-theme="dark"] .page-link:hover {
background-color: #3d4349;
color: #fff;
}

[data-bs-theme="dark"] .page-item.active .page-link {
background-color: #348613;
border-color: #348613;
color: #fff;
}

[data-bs-theme="dark"] .page-item.disabled .page-link {
background-color: #212529;
color: #6c757d;
border-color: #3d4349;
}

/* Dropdowns */
[data-bs-theme="dark"] .dropdown-menu {
background-color: #2a2e33;
border-color: #3d4349;
}

[data-bs-theme="dark"] .dropdown-item {
color: #dee2e6;
}

[data-bs-theme="dark"] .dropdown-item:hover,
[data-bs-theme="dark"] .dropdown-item:focus {
background-color: #3d4349;
color: #fff;
}

[data-bs-theme="dark"] .dropdown-divider {
border-color: #3d4349;
}

/* Form controls */
[data-bs-theme="dark"] .form-control,
[data-bs-theme="dark"] input[type="number"],
[data-bs-theme="dark"] input[type="text"] {
background-color: #2a2e33;
border-color: #3d4349;
color: #dee2e6;
}

[data-bs-theme="dark"] .form-control:focus,
[data-bs-theme="dark"] input[type="number"]:focus,
[data-bs-theme="dark"] input[type="text"]:focus {
background-color: #2a2e33;
color: #dee2e6;
border-color: #348613;
box-shadow: 0 0 0 0.2rem rgba(52, 134, 19, 0.3);
}

[data-bs-theme="dark"] .form-control::placeholder,
[data-bs-theme="dark"] input::placeholder {
color: #6c757d;
}

/* Nav tabs */
[data-bs-theme="dark"] .nav-tabs {
border-color: #3d4349;
}

[data-bs-theme="dark"] .nav-tabs .nav-link {
color: #9ca3af;
}

[data-bs-theme="dark"] .nav-tabs .nav-link:hover {
border-color: #3d4349 #3d4349 transparent;
color: #dee2e6;
}

[data-bs-theme="dark"] .nav-tabs .nav-link.active {
background-color: #1a1e21;
border-color: #3d4349 #3d4349 #1a1e21;
color: #dee2e6;
}

[data-bs-theme="dark"] .tab-content {
color: #dee2e6;
}

/* Links */
[data-bs-theme="dark"] a {
color: #5cb85c;
}

[data-bs-theme="dark"] a:hover {
color: #82cc82;
}

/* Buttons */
[data-bs-theme="dark"] .btn-primary {
background-color: #348613;
border-color: #348613;
}

[data-bs-theme="dark"] .btn-danger {
background-color: #842029;
border-color: #842029;
}

[data-bs-theme="dark"] .btn-close {
filter: invert(1);
}

/* Alerts */
[data-bs-theme="dark"] .alert-success {
background-color: #0d2610;
border-color: #1a4a1e;
color: #a3d4a8;
}

[data-bs-theme="dark"] .alert-danger {
background-color: #2c0b0e;
border-color: #4a1820;
color: #f1aeb5;
}

/* Badges */
[data-bs-theme="dark"] .badge.bg-secondary {
background-color: #495057 !important;
}

/* Table captions */
[data-bs-theme="dark"] caption {
color: #9ca3af;
}

/* Pre / tracebacks */
[data-bs-theme="dark"] pre {
color: #dee2e6;
background-color: #2a2e33;
padding: 0.5rem;
border-radius: 4px;
}

/* Text helpers */
[data-bs-theme="dark"] .text-muted {
color: #9ca3af !important;
}

[data-bs-theme="dark"] .text-dark {
color: #dee2e6 !important;
}

[data-bs-theme="dark"] h1,
[data-bs-theme="dark"] h2,
[data-bs-theme="dark"] h3,
[data-bs-theme="dark"] h4,
[data-bs-theme="dark"] h5,
[data-bs-theme="dark"] h6 {
color: #dee2e6;
}
25 changes: 25 additions & 0 deletions flower/static/js/flower.js
Original file line number Diff line number Diff line change
Expand Up @@ -690,4 +690,29 @@ var flower = (function () {

});

(function () {
var html = document.documentElement;
var btn = document.getElementById('theme-toggle');
var moon = document.getElementById('theme-icon-moon');
var sun = document.getElementById('theme-icon-sun');

function applyTheme(theme) {
html.setAttribute('data-bs-theme', theme);
localStorage.setItem('flower-theme', theme);
if (moon && sun) {
moon.style.display = theme === 'dark' ? 'none' : '';
sun.style.display = theme === 'dark' ? '' : 'none';
}
}

// Sync icon with whatever theme was restored from localStorage in <head>
applyTheme(html.getAttribute('data-bs-theme') || 'light');

if (btn) {
btn.addEventListener('click', function () {
applyTheme(html.getAttribute('data-bs-theme') === 'dark' ? 'light' : 'dark');
});
}
}());

}(jQuery));
3 changes: 2 additions & 1 deletion flower/templates/base.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{% import pprint %}
<!doctype html>
<html lang="en">
<html lang="en" data-bs-theme="light">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
Expand All @@ -9,6 +9,7 @@
<link rel="stylesheet" href="{{ static_url('css/bootstrap.min.css') }}">
<link rel="stylesheet" href="{{ static_url('css/datatables-1.13.4.min.css') }}">
<link href="{{ static_url('css/flower.css') }}" rel="stylesheet">
<script>(function(){var t=localStorage.getItem('flower-theme');if(t)document.documentElement.setAttribute('data-bs-theme',t);})();</script>
</head>
<body class="m-2">
{% block navbar %}
Expand Down
12 changes: 11 additions & 1 deletion flower/templates/navbar.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@
<small class="d-lg-none ms-2">GitHub</small>
</a>
</li>
<li class="nav-item col-6 col-lg-auto d-flex align-items-center px-0 px-lg-2">
<button id="theme-toggle" aria-label="Toggle dark mode" title="Toggle dark mode">
<svg id="theme-icon-moon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"/>
</svg>
<svg id="theme-icon-sun" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" style="display:none">
<path d="M8 11a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0 1a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707z"/>
</svg>
</button>
</li>
</ul>
</div>
</nav>
</nav>