dark and light modes

also heading size reduction
This commit is contained in:
rimu 2024-01-13 22:09:02 +13:00
parent 1dad787bc4
commit 60efbe988f
16 changed files with 136 additions and 213 deletions

View file

@ -7,6 +7,7 @@ document.addEventListener("DOMContentLoaded", function () {
setupSubmitOnInputChange(); setupSubmitOnInputChange();
setupTimeTracking(); setupTimeTracking();
setupMobileNav(); setupMobileNav();
setupLightDark();
}); });
@ -23,6 +24,19 @@ function setupMobileNav() {
}); });
} }
function setupLightDark() {
const elem = document.getElementById('light_mode');
elem.addEventListener("click", function(event) {
setTheme('light')
setStoredTheme('light')
});
const elem2 = document.getElementById('dark_mode');
elem2.addEventListener("click", function(event) {
setTheme('dark')
setStoredTheme('dark')
});
}
function toggleClass(elementId, className) { function toggleClass(elementId, className) {
var element = document.getElementById(elementId); var element = document.getElementById(elementId);

View file

@ -5,6 +5,7 @@ $green-hover: #83f188;
$light-grey: #ddd; $light-grey: #ddd;
$grey: #bbb; $grey: #bbb;
$dark-grey: #777; $dark-grey: #777;
$super-dark-grey: #424549;
.red { .red {
color: red; color: red;

View file

@ -222,6 +222,14 @@
content: "\e91f"; content: "\e91f";
} }
.fe-sun::before {
content: "\e9d7";
}
.fe-moon::before {
content: "\e99a";
}
h1 { h1 {
.fe-bell, .fe-no-bell { .fe-bell, .fe-no-bell {
font-size: 18px; font-size: 18px;

View file

@ -250,6 +250,14 @@ nav, etc which are used site-wide */
content: "\e91f"; content: "\e91f";
} }
.fe-sun::before {
content: "\e9d7";
}
.fe-moon::before {
content: "\e99a";
}
h1 .fe-bell, h1 .fe-no-bell { h1 .fe-bell, h1 .fe-no-bell {
font-size: 18px; font-size: 18px;
top: -5px; top: -5px;
@ -610,6 +618,17 @@ fieldset legend {
padding-top: 0; padding-top: 0;
} }
[data-bs-theme=dark] .post_list .post_teaser {
border-bottom: solid 1px #424549;
}
[data-bs-theme=dark] .comments > .comment {
border-top-color: #424549;
}
[data-bs-theme=dark] .downarea-textarea .form-control {
background-color: #424549;
color: whitesmoke;
}
.post_body img { .post_body img {
max-height: 40vh; max-height: 40vh;
max-width: 100%; max-width: 100%;

View file

@ -250,6 +250,24 @@ nav, etc which are used site-wide */
} }
} }
[data-bs-theme=dark] {
.post_list .post_teaser {
border-bottom: solid 1px $super-dark-grey;
}
.comments > .comment {
border-top-color: $super-dark-grey;
}
.downarea-textarea {
.form-control {
background-color: $super-dark-grey;
color: whitesmoke;
}
}
}
.post_body { .post_body {
img { img {
max-height: 40vh; max-height: 40vh;

View file

@ -249,6 +249,14 @@
content: "\e91f"; content: "\e91f";
} }
.fe-sun::before {
content: "\e9d7";
}
.fe-moon::before {
content: "\e99a";
}
h1 .fe-bell, h1 .fe-no-bell { h1 .fe-bell, h1 .fe-no-bell {
font-size: 18px; font-size: 18px;
top: -5px; top: -5px;
@ -383,12 +391,9 @@ fieldset legend {
body { body {
font-size: 0.95rem; font-size: 0.95rem;
background-color: #fbfdfe;
color: #495057;
} }
nav.navbar { nav.navbar {
background-color: #fff !important;
border-bottom: 1px solid rgba(0, 40, 100, 0.12); border-bottom: 1px solid rgba(0, 40, 100, 0.12);
min-height: 60px; min-height: 60px;
} }
@ -398,7 +403,6 @@ nav.navbar {
} }
.navbar-light .navbar-nav .nav-link { .navbar-light .navbar-nav .nav-link {
color: rgba(0, 0, 0, 0.8);
outline-style: none; outline-style: none;
} }
@ -474,7 +478,6 @@ nav.navbar {
.main_pane { .main_pane {
border: solid 1px #ddd; border: solid 1px #ddd;
border-radius: 5px; border-radius: 5px;
background-color: white;
padding-top: 8px; padding-top: 8px;
padding-bottom: 12px; padding-bottom: 12px;
} }
@ -487,6 +490,10 @@ nav.navbar {
height: auto; height: auto;
} }
[data-bs-theme=dark] .main_pane {
border-color: #424549;
}
.community_icon { .community_icon {
width: 20vw; width: 20vw;
height: 20vw; height: 20vw;
@ -627,31 +634,21 @@ nav.navbar {
color: black; color: black;
} }
@media (prefers-color-scheme: dark) { @media (min-width: 992px) {
body { .h1, h1 {
background-color: #777; font-size: 2rem;
} }
}
nav.navbar { @media (min-width: 992px) {
background-color: #eee !important; .h2, h2 {
font-size: 1.8rem;
} }
}
.main_pane, .card { @media (min-width: 992px) {
background-color: #eee; .h3, h3 {
} font-size: 1.6rem;
.btn-outline-secondary {
border-color: #eee;
color: #eee;
}
.main_pane .btn-outline-secondary {
border-color: #777;
color: #777;
}
footer a {
color: #eee;
} }
} }

View file

@ -6,12 +6,9 @@
body { body {
font-size: 0.95rem; font-size: 0.95rem;
background-color: #fbfdfe;
color: #495057;
} }
nav.navbar { nav.navbar {
background-color: #fff!important;
border-bottom: 1px solid rgba(0, 40, 100, 0.12); border-bottom: 1px solid rgba(0, 40, 100, 0.12);
min-height: 60px; min-height: 60px;
} }
@ -22,7 +19,6 @@ nav.navbar {
} }
} }
.navbar-light .navbar-nav .nav-link { .navbar-light .navbar-nav .nav-link {
color: rgba(0,0,0,.8);
outline-style: none; outline-style: none;
} }
@ -98,7 +94,6 @@ nav.navbar {
.main_pane { .main_pane {
border: solid 1px $light-grey; border: solid 1px $light-grey;
border-radius: 5px; border-radius: 5px;
background-color: white;
padding-top: 8px; padding-top: 8px;
padding-bottom: 12px; padding-bottom: 12px;
@ -113,6 +108,10 @@ nav.navbar {
} }
} }
[data-bs-theme=dark] .main_pane {
border-color: $super-dark-grey;
}
.community_icon { .community_icon {
width: 20vw; width: 20vw;
height: 20vw; height: 20vw;
@ -267,35 +266,20 @@ nav.navbar {
color: black; color: black;
} }
@media (prefers-color-scheme: dark) { .h1, h1 {
@include breakpoint(tablet) {
body { font-size: 2rem;
background-color: $dark-grey;
} }
}
nav.navbar { .h2, h2 {
background-color: #eee!important; @include breakpoint(tablet) {
font-size: 1.8rem;
} }
}
.main_pane, .card { .h3, h3 {
background-color: #eee; @include breakpoint(tablet) {
font-size: 1.6rem;
} }
}
.btn-outline-secondary {
border-color: #eee;
color: #eee;
}
.main_pane {
.btn-outline-secondary {
border-color: $dark-grey;
color: $dark-grey;
}
}
footer {
a {
color: #eee;
}
}
}

View file

@ -66,12 +66,34 @@
{% if rss_feed %} {% if rss_feed %}
<link rel="alternate" type="application/rss+xml" title="{{ rss_feed_name }}" href="{{ rss_feed }}" /> <link rel="alternate" type="application/rss+xml" title="{{ rss_feed_name }}" href="{{ rss_feed }}" />
{% endif %} {% endif %}
<script nonce="{{ session['nonce']}}">
const getStoredTheme = () => localStorage.getItem('theme')
const setStoredTheme = theme => localStorage.setItem('theme', theme)
const getPreferredTheme = () => {
const storedTheme = getStoredTheme()
if (storedTheme) {
return storedTheme
}
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}
const setTheme = theme => {
if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.setAttribute('data-bs-theme', 'dark')
} else {
document.documentElement.setAttribute('data-bs-theme', theme)
}
}
setTheme(getPreferredTheme());
</script>
{% endblock %} {% endblock %}
</head> </head>
<body class="d-flex flex-column{{ ' low_bandwidth' if low_bandwidth }}"> <body class="d-flex flex-column{{ ' low_bandwidth' if low_bandwidth }}">
<!-- Page content --> <!-- Page content -->
{% block navbar %} {% block navbar %}
<nav class="navbar navbar-expand-lg navbar-light bg-light"> <nav class="navbar navbar-expand-lg">
<div class="container-lg"> <div class="container-lg">
<a class="navbar-brand" href="/">{% if not low_bandwidth %}<img src="/static/images/logo2.png" alt="Logo" width="50" height="50" />{% endif %}{{ g.site.name }}</a> <a class="navbar-brand" href="/">{% if not low_bandwidth %}<img src="/static/images/logo2.png" alt="Logo" width="50" height="50" />{% endif %}{{ g.site.name }}</a>
{% if current_user.is_authenticated %} {% if current_user.is_authenticated %}
@ -159,6 +181,8 @@
</a> </a>
</li> </li>
{% endif %} {% endif %}
<li class="nav-item"><a class="nav-link" id="light_mode"><span class="fe fe-sun" title="Light mode"></span></a></li>
<li class="nav-item"><a class="nav-link" id="dark_mode"><span class="fe fe-moon" title="Dark mode"></span></a></li>
</ul> </ul>
</div> </div>

View file

@ -103,9 +103,9 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
<form method="get"> <!-- <form method="get">
<input type="search" name="search" class="form-control mt-2" placeholder="{{ _('Search this community') }}" /> <input type="search" name="search" class="form-control mt-2" placeholder="{{ _('Search this community') }}" />
</form> </form> -->
</div> </div>
</div> </div>
<div class="card mt-3"> <div class="card mt-3">

View file

@ -29,13 +29,13 @@
</div> </div>
<div class="col-12 col-md-4 side_pane"> <div class="col-12 col-md-4 side_pane">
<div class="card"> <!-- <div class="card">
<div class="card-body"> <div class="card-body">
<form method="get"> <form method="get">
<input type="search" name="search" class="form-control mt-2" placeholder="{{ _('Search') }}" /> <input type="search" name="search" class="form-control mt-2" placeholder="{{ _('Search') }}" />
</form> </form>
</div> </div>
</div> </div> -->
<div class="card mt-3"> <div class="card mt-3">
<div class="card-header"> <div class="card-header">

View file

@ -1,71 +0,0 @@
{% extends "base.html" %}
{% from 'bootstrap5/form.html' import render_form %}
{% block app_content %}
<div class="row">
<div class="col-12 col-md-8 position-relative main_pane">
{% include "_home_nav.html" %}
<div class="post_list">
{% for post in posts %}
{% include 'post/_post_teaser.html' %}
{% else %}
<p>{{ _('No posts yet.') }}</p>
{% endfor %}
</div>
<nav aria-label="Pagination" class="mt-4">
{% if prev_url %}
<a href="{{ prev_url }}" class="btn btn-primary" rel="nofollow">
<span aria-hidden="true">&larr;</span> {{ _('Previous page') }}
</a>
{% endif %}
{% if next_url %}
<a href="{{ next_url }}" class="btn btn-primary" rel="nofollow">
{{ _('Next page') }} <span aria-hidden="true">&rarr;</span>
</a>
{% endif %}
</nav>
</div>
<div class="col-12 col-md-4 side_pane">
<div class="card">
<div class="card-body">
<form method="get">
<input type="search" name="search" class="form-control mt-2" placeholder="{{ _('Search') }}" />
</form>
</div>
</div>
<div class="card mt-3">
<div class="card-header">
<h2>{{ _('Active communities') }}</h2>
</div>
<div class="card-body">
<ul class="list-group list-group-flush">
{% for community in active_communities %}
<li class="list-group-item">
<a href="/c/{{ community.link() }}"><img src="{{ community.icon_image() }}" class="community_icon rounded-circle" loading="lazy" />
{{ community.display_name() }}
</a>
</li>
{% endfor %}
</ul>
<p class="mt-4"><a class="btn btn-primary" href="/communities">Explore communities</a></p>
</div>
</div>
<div class="card mt-3">
<div class="card-header">
<h2>{{ _('About %(site_name)s', site_name=g.site.name) }}</h2>
</div>
<div class="card-body">
<p><strong>{{ g.site.description|safe }}</strong></p>
<p>{{ g.site.sidebar|safe }}</p>
<p class="mt-4">
<a class="no-underline" href="{{ rss_feed }}" rel="nofollow"><span class="fe fe-rss"></span> RSS feed</a>
</p>
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -46,9 +46,9 @@
<a class="w-100 btn btn-primary" href="/community/{{ post.community.link() }}/submit">{{ _('Create post') }}</a> <a class="w-100 btn btn-primary" href="/community/{{ post.community.link() }}/submit">{{ _('Create post') }}</a>
</div> </div>
</div> </div>
<form method="get"> <!-- <form method="get">
<input type="search" name="search" class="form-control mt-2" placeholder="{{ _('Search this community') }}" /> <input type="search" name="search" class="form-control mt-2" placeholder="{{ _('Search this community') }}" />
</form> </form> -->
</div> </div>
</div> </div>
<div class="card mt-3"> <div class="card mt-3">

View file

@ -73,9 +73,9 @@
<a class="w-100 btn btn-primary" href="/community/{{ post.community.link() }}/submit">{{ _('Create post') }}</a> <a class="w-100 btn btn-primary" href="/community/{{ post.community.link() }}/submit">{{ _('Create post') }}</a>
</div> </div>
</div> </div>
<form method="get"> <!-- <form method="get">
<input type="search" name="search" class="form-control mt-2" placeholder="{{ _('Search this community') }}" /> <input type="search" name="search" class="form-control mt-2" placeholder="{{ _('Search this community') }}" />
</form> </form> -->
</div> </div>
</div> </div>
<div class="card mt-3"> <div class="card mt-3">

View file

@ -166,9 +166,9 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
<form method="get"> <!-- <form method="get">
<input type="search" name="search" class="form-control mt-2" placeholder="{{ _('Search this community') }}" /> <input type="search" name="search" class="form-control mt-2" placeholder="{{ _('Search this community') }}" />
</form> </form> -->
</div> </div>
</div> </div>
<div class="card mt-3"> <div class="card mt-3">

View file

@ -46,9 +46,9 @@
<a class="w-100 btn btn-primary" href="/community/{{ post.community.link() }}/submit">{{ _('Create post') }}</a> <a class="w-100 btn btn-primary" href="/community/{{ post.community.link() }}/submit">{{ _('Create post') }}</a>
</div> </div>
</div> </div>
<form method="get"> <!-- <form method="get">
<input type="search" name="search" class="form-control mt-2" placeholder="{{ _('Search this community') }}" /> <input type="search" name="search" class="form-control mt-2" placeholder="{{ _('Search this community') }}" />
</form> </form> -->
</div> </div>
</div> </div>
<div class="card mt-3"> <div class="card mt-3">

View file

@ -1,71 +0,0 @@
{% extends "base.html" %}
{% from 'bootstrap5/form.html' import render_form %}
{% block app_content %}
<div class="row">
<div class="col-12 col-md-8 position-relative main_pane">
{% include "_home_nav.html" %}
<div class="post_list">
{% for post in posts %}
{% include 'post/_post_teaser.html' %}
{% else %}
<p>{{ _('No posts yet.') }}</p>
{% endfor %}
</div>
<nav aria-label="Pagination" class="mt-4">
{% if prev_url %}
<a href="{{ prev_url }}" class="btn btn-primary" rel="nofollow">
<span aria-hidden="true">&larr;</span> {{ _('Previous page') }}
</a>
{% endif %}
{% if next_url %}
<a href="{{ next_url }}" class="btn btn-primary" rel="nofollow">
{{ _('Next page') }} <span aria-hidden="true">&rarr;</span>
</a>
{% endif %}
</nav>
</div>
<div class="col-12 col-md-4 side_pane">
<div class="card">
<div class="card-body">
<form method="get">
<input type="search" name="search" class="form-control mt-2" placeholder="{{ _('Search') }}" />
</form>
</div>
</div>
<div class="card mt-3">
<div class="card-header">
<h2>{{ _('Active communities') }}</h2>
</div>
<div class="card-body">
<ul class="list-group list-group-flush">
{% for community in active_communities %}
<li class="list-group-item">
<a href="/c/{{ community.link() }}"><img src="{{ community.icon_image() }}" class="community_icon rounded-circle" loading="lazy" />
{{ community.display_name() }}
</a>
</li>
{% endfor %}
</ul>
<p class="mt-4"><a class="btn btn-primary" href="/communities">Explore communities</a></p>
</div>
</div>
<div class="card mt-3">
<div class="card-header">
<h2>{{ _('About %(site_name)s', site_name=g.site.name) }}</h2>
</div>
<div class="card-body">
<p><strong>{{ g.site.description|safe }}</strong></p>
<p>{{ g.site.sidebar|safe }}</p>
<p class="mt-4">
<a class="no-underline" href="{{ rss_feed }}" rel="nofollow"><span class="fe fe-rss"></span> RSS feed</a>
</p>
</div>
</div>
</div>
</div>
{% endblock %}