Add support for prefers-color-scheme using Bootstrap classes. (#3327)

* Add support for prefers-color-scheme using Bootstrap classes.
* Move stylesheet changes to separate javascript file.
* fix(html): don't specify the integrity hash in the tag for style.js
* fix(log): debug-log integrity hashes for troubleshooting
* fix(css): move to using bootstrap standard variables for colours and theming
* fix(js): rewrite to simplify and use standard bootstrap functionality
* fix(makefile): codespell thingie was complaining
* run prettier on css/js.

---------

Co-authored-by: James Hodgkinson <james@terminaloutcomes.com>
This commit is contained in:
George Wu 2025-01-06 02:58:42 -08:00 committed by GitHub
parent 761dda688e
commit a3358828a8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 65 additions and 22 deletions

View file

@ -178,9 +178,8 @@ codespell:
--skip='*.svg' \
--skip='*.br' \
--skip='./rlm_python/mods-available/eap' \
--skip='./server/lib/src/constants/system_config.rs'
--skip='./pykanidm/site' \
--skip='./server/lib/src/constants/*.json'
--skip='./server/lib/src/constants/system_config.rs' \
--skip='./pykanidm/site'
.PHONY: test/pykanidm/pytest
test/pykanidm/pytest: ## python library testing

View file

@ -140,11 +140,13 @@ pub(crate) fn get_js_files(role: ServerRole) -> Result<Vec<JavaScriptFile>, ()>
"external/base64.js",
"modules/cred_update.mjs",
"pkhtml.js",
"style.js",
];
for filepath in filelist {
match generate_integrity_hash(format!("{}/{}", pkg_path, filepath,)) {
Ok(hash) => {
debug!("Integrity hash for {}: {}", filepath, hash);
let js = JavaScriptFile { hash };
all_pages.push(js)
}

View file

@ -39,7 +39,7 @@ body {
&:hover,
&.active {
background-color: var(--bs-gray-300);
background-color: var(--bs-tertiary-bg);
}
.icon-container img {
@ -57,6 +57,23 @@ body {
/*
* Navbar
*/
nav.kanidm_navbar {
background-color: var(--bs-navbar-brand-color);
}
nav a.navbar-brand,
nav a.nav-link {
color: var(--bs-body-bg);
}
nav a.navbar-brand:hover,
nav a.nav-link:hover {
color: var(--bs-secondary-bg);
}
footer {
background-color: var(--bs-tertiary-bg);
}
.kanidm_logo {
width: 12em;
@ -79,7 +96,7 @@ body {
align-items: center;
margin: auto;
border-radius: 15px;
background: #21252915;
background-color: #21252915;
box-shadow:
-5px -5px 11px #ededed,
5px 5px 11px #ffffff;
@ -122,15 +139,15 @@ body {
}
.totp-timer__path-remaining.green {
color: rgb(65, 184, 131);
color: var(--bs-success);
}
.totp-timer__path-remaining.orange {
color: orange;
color: var(--bs-warning);
}
.totp-timer__path-remaining.red {
color: red;
color: var(--bs-danger);
}
.totp-timer__path-remaining.no-transition {

View file

@ -0,0 +1,19 @@
/** Queries the user's preferred colour scheme and returns the appropriate value.
From https://getbootstrap.com/docs/5.3/customize/color-modes/#javascript
*/
function getPreferredTheme() {
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
}
/** Sets the theme.
*/
function updateColourScheme() {
const theme = getPreferredTheme();
console.debug(`updateColourScheme theme->${theme}`);
document.documentElement.setAttribute("data-bs-theme", theme);
}
updateColourScheme();
window.matchMedia("(prefers-color-scheme: light)").addEventListener("change", updateColourScheme);
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", updateColourScheme);
document.body.addEventListener("htmx:afterOnLoad", updateColourScheme);

View file

@ -13,7 +13,7 @@
(% match app %)
(% when AppLink::Oauth2 with { name, display_name, redirect_url, has_image }
%)
<a href="(( redirect_url ))" class="link-dark stretched-link mt-2">
<a href="(( redirect_url ))" class="link-emphasis stretched-link mt-2">
(% if has_image %)
<img src="/ui/images/oauth2/(( name ))" class="oauth2-img"
alt="((display_name)) icon" id="(( name ))">

View file

@ -15,6 +15,9 @@
<script
src="/pkg/external/bootstrap.bundle.min.js?v=((crate::https::cache_buster::get_cache_buster_key()))"
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"></script>
<script
src="/pkg/style.js?v=((crate::https::cache_buster::get_cache_buster_key()))"
defer></script>
<link rel="stylesheet"
href="/pkg/style.css?v=((crate::https::cache_buster::get_cache_buster_key()))" />
@ -22,7 +25,7 @@
</head>
<body class="flex-column d-flex h-100">
(% block body %)(% endblock %)
<footer class="footer mt-auto py-3 bg-light text-end">
<footer class="footer mt-auto py-3 bs-secondary-bg text-end">
<div class="container">
<span class="text-muted">Powered by <a
href="https://kanidm.com">Kanidm</a></span>

View file

@ -19,6 +19,9 @@
<script
src="/pkg/external/htmx.min.1.9.12.js?v=((crate::https::cache_buster::get_cache_buster_key()))"
integrity="sha384-ujb1lZYygJmzgSwoxRggbCHcjc0rB2XoQrxeTUQyRjrOnlCoYta87iKBWq3EsdM2"></script>
<script
src="/pkg/style.js?v=((crate::https::cache_buster::get_cache_buster_key()))"
defer></script>
<link rel="stylesheet"
href="/pkg/style.css?v=((crate::https::cache_buster::get_cache_buster_key()))" />
@ -27,7 +30,7 @@
<body hx-boost="true" class="flex-column d-flex h-100">
(% block nav %)(% endblock %)
(% block body %)(% endblock %)
<footer class="footer mt-auto py-3 bg-light text-end">
<footer class="footer mt-auto py-3 bs-secondary-bg text-end">
<div class="container">
<span class="text-muted">Powered by <a
href="https://kanidm.com">Kanidm</a></span>

View file

@ -131,7 +131,7 @@
(% endmatch %)
<hr class="my-4" />
<div id="cred-update-commit-bar" class="toast">
<div id="cred-update-commit-bar" class="toast bs-emphasis-color bs-secondary-bg">
<div class="toast-body">
<span class="d-flex align-items-center">
<div>

View file

@ -58,7 +58,7 @@
<div class="input-group mb-3 justify-content-md-center">
<button
type="submit"
class="btn btn-dark"
class="btn btn-primary"
>Begin</button>
</div>
</form>

View file

@ -17,7 +17,7 @@
<div class="input-group mb-3 justify-content-md-center">
<button
type="submit"
class="btn btn-dark"
class="btn btn-primary"
>Submit</button>
</div>
</form>

View file

@ -13,7 +13,7 @@
<button
(% if mech.autofocus %)autofocus(% endif %)
type="submit"
class="btn btn-dark"
class="btn btn-primary"
>(( mech.name ))</button>
</form>
</li>

View file

@ -18,7 +18,7 @@
<div class="input-group mb-3 justify-content-md-center">
<button
type="submit"
class="btn btn-dark"
class="btn btn-primary"
>Submit</button>
</div>
</form>

View file

@ -36,7 +36,7 @@
<div class="input-group mb-3 justify-content-md-center">
<button
type="submit"
class="btn btn-dark"
class="btn btn-primary"
>Submit</button>
</div>
</form>

View file

@ -16,13 +16,13 @@
(% if passkey %)
<form id="cred-form" action="/ui/login/passkey" method="POST">
<input hidden="hidden" name="cred" id="cred">
<button hx-disable type="button" autofocus class="btn btn-dark"
<button hx-disable type="button" autofocus class="btn btn-primary"
id="start-passkey-button">Use Passkey</button>
</form>
(% else %)
<form id="cred-form" action="/ui/login/seckey" method="POST">
<input hidden="hidden" name="cred" id="cred">
<button hx-disable type="button" autofocus class="btn btn-dark"
<button hx-disable type="button" autofocus class="btn btn-primary"
id="start-seckey-button">Use Security Key</button>
</form>
(% endif %)

View file

@ -1,4 +1,4 @@
<nav class="navbar navbar-expand-md navbar-dark bg-dark mb-4">
<nav class="navbar navbar-expand-md kanidm_navbar mb-4">
<div class="container-lg">
<a class="navbar-brand d-flex align-items-center" href="/ui/apps">
(% if navbar_ctx.domain_info.image().is_some() %)

View file

@ -27,7 +27,7 @@
<div class="input-group mb-3 justify-content-md-center">
<button
type="submit"
class="btn btn-dark">Continue</button>
class="btn btn-primary">Continue</button>
</div>
</form>
</center>

View file

@ -2,7 +2,7 @@
<li>
<a hx-select="main" hx-target="main" hx-swap="outerHTML show:false"
href="(( href ))"
class="side-menu-item d-flex rounded link-dark(% if menu_active_item == menu_item %) active(% endif %)">
class="side-menu-item d-flex rounded link-emphasis(% if menu_active_item == menu_item %) active(% endif %)">
<div class="icon-container align-items-center justify-content-center d-flex me-2">
<img class="text-body-secondary"
src="/pkg/img/icons/(( icon_name )).svg?v=((crate::https::cache_buster::get_cache_buster_key()))"