Refactored theme variable storage to use a cookie

This commit is contained in:
Chris Kankiewicz
2021-06-19 23:03:34 -07:00
parent 8229e10a2a
commit 8d40ef905e
5 changed files with 59 additions and 9 deletions

View File

@@ -24,6 +24,7 @@ return [
/** Array of application middlewares */
'middlewares' => function (ContainerInterface $container): array {
return [
Middlewares\ThemeMiddleware::class,
Middlewares\WhoopsMiddleware::class,
new HttpMiddlewares\Expires($container->get('http_expires')),
];

View File

@@ -1,12 +1,21 @@
export default () => ({
theme: 'light',
loading: true,
init() {
this.theme = localStorage.theme || (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark');
const [cookie, theme] = document.cookie.match(/theme=(dark|light)/) || [null, null];
this.theme = theme || (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark');
if (cookie === undefined) {
storeThemeCookie(this.theme);
}
},
toggleTheme() {
this.theme = this.theme == 'light' ? 'dark' : 'light';
},
storeThemeCookie(theme) {
document.cookie = `theme=${theme}; expires=Fri, 31 Dec 9999 23:59:59 GMT; SameSite=Lax`;
}
});

View File

@@ -0,0 +1,44 @@
<?php
namespace App\Middlewares;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Views\Twig;
class ThemeMiddleware
{
/** Array of valid theme strings. */
private const VALID_THEMES = ['dark', 'light'];
/** @var Twig Twig templating component */
protected $view;
public function __construct(Twig $view)
{
$this->view = $view;
}
/** Invoke the ThemeMiddleware class. */
public function __invoke(Request $request, RequestHandler $handler): ResponseInterface
{
$this->view->getEnvironment()->addGlobal('theme', $this->getThemeFromRequest($request));
return $handler->handle($request);
}
/** Determine the theme from the request. */
private function getThemeFromRequest(Request $request): string
{
if (! isset($request->getCookieParams()['theme'])) {
return 'light';
}
if (! in_array($request->getCookieParams()['theme'], self::VALID_THEMES)) {
return 'light';
}
return $request->getCookieParams()['theme'];
}
}

View File

@@ -1,5 +1,5 @@
<div class="flex flex-col justify-center items-center bg-gray-900 bg-opacity-30 rounded-full cursor-pointer w-4 h-8" title="{{ translate('toggle_theme') }}" @click="toggleTheme()">
<div class="flex justify-center items-center bg-white w-5 h-5 rounded-full shadow-md transform duration-300 ease-in-out" :class="{ '-translate-y-2': theme === 'light', 'translate-y-2': theme === 'dark' }" x-cloak>
<i class="fas fa-lightbulb fa-xs" :class="{ 'text-gray-600': theme === 'dark', 'text-yellow-400': theme === 'light' }"></i>
<div class="flex justify-center items-center bg-white w-5 h-5 rounded-full shadow-md transform duration-300 ease-in-out -translate-y-2 dark:translate-y-2">
<i class="fas fa-lightbulb fa-xs text-yellow-400 dark:text-gray-600"></i>
</div>
</div>

View File

@@ -21,12 +21,8 @@
<title>{{ title }} &bull; {{ config('site_title') }}</title>
<div x-data="application" x-init="loading = false" x-effect="localStorage.setItem('theme', theme)" :class="{ 'dark': theme === 'dark' }">
<div class="{{ theme }}" x-data="application" x-effect="storeThemeCookie(theme)" :class="{ 'dark': theme === 'dark' }">
<div class="flex flex-col min-h-screen font-sans dark:bg-gray-800">
{% block content %}{% endblock %}
</div>
<div class="fixed inset-0 flex items-center justify-center bg-gray-600 p-4 z-50" x-show="loading">
<i class="fas fa-spinner fa-pulse fa-5x text-white"></i>
</div>
</div>