Add 'automatic' dark theme, based on browser 'prefers-color-scheme: dark' media query

This commit is contained in:
Timothy Warren 2019-07-12 15:56:24 -04:00
parent 7a529619ed
commit 0153271a62
16 changed files with 366 additions and 579 deletions

View File

@ -6,8 +6,12 @@
<meta http-equiv="cache-control" content="no-store" /> <meta http-equiv="cache-control" content="no-store" />
<meta http-equiv="Content-Security-Policy" content="script-src 'self'" /> <meta http-equiv="Content-Security-Policy" content="script-src 'self'" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=1" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=1" />
<?php if ($config->get('theme') !== 'auto'): ?>
<link rel="stylesheet" href="<?= $urlGenerator->assetUrl('css/app.min.css') ?>" /> <link rel="stylesheet" href="<?= $urlGenerator->assetUrl('css/app.min.css') ?>" />
<link rel="<?= $config->get('dark_theme') ? '' : 'alternate ' ?>stylesheet" title="Dark Theme" href="<?= $urlGenerator->assetUrl('css/dark.min.css') ?>" /> <?php elseif ($config->get('theme') === 'auto'): ?>
<link rel="stylesheet" href="<?= $urlGenerator->assetUrl('css/dark-auto.min.css') ?>" />
<?php endif ?>
<link rel="<?= $config->get('theme') === 'dark' ? '' : 'alternate ' ?>stylesheet" title="Dark Theme" href="<?= $urlGenerator->assetUrl('css/dark.min.css') ?>" />
<link rel="icon" href="<?= $urlGenerator->assetUrl('images/icons/favicon.ico') ?>" /> <link rel="icon" href="<?= $urlGenerator->assetUrl('images/icons/favicon.ico') ?>" />
<link rel="apple-touch-icon" sizes="57x57" href="<?= $urlGenerator->assetUrl('images/icons/apple-icon-57x57.png') ?>"> <link rel="apple-touch-icon" sizes="57x57" href="<?= $urlGenerator->assetUrl('images/icons/apple-icon-57x57.png') ?>">
<link rel="apple-touch-icon" sizes="60x60" href="<?= $urlGenerator->assetUrl('images/icons/apple-icon-60x60.png') ?>"> <link rel="apple-touch-icon" sizes="60x60" href="<?= $urlGenerator->assetUrl('images/icons/apple-icon-60x60.png') ?>">

File diff suppressed because one or more lines are too long

1
public/css/dark-auto.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
a{color:#1978e2;text-shadow:var(--link-shadow)}a:hover{color:#9e34fd}body,legend,nav ul li a{background:#333;color:#eee}nav a:hover,nav li.selected a{border-color:#fff}header button{background:transparent}table{-webkit-box-shadow:none;box-shadow:none}td,th{border-color:#111}thead td,thead th{background:#333;color:#eee}tbody>tr:nth-child(2n){background:#555;color:#eee}tbody>tr:nth-child(odd){background:#333}footer,hr,legend{border-color:#ddd}small{color:#fff}input,input[type],select,textarea{border-color:#bbb;color:#bbb;background:#333;padding:.8em}button{background:#444;background:-webkit-gradient(linear,left top,left bottom,from(#666),color-stop(#555),color-stop(#444),color-stop(#555),to(#666));background:linear-gradient(#666,#555,#444,#555,#666);border-radius:.5em;margin:0;text-transform:none}button,button:hover{border-color:#ddd;color:#ddd}button:hover{background:#222;background:-webkit-gradient(linear,left top,left bottom,from(#444),color-stop(#333),color-stop(#222),color-stop(#333),to(#444));background:linear-gradient(#444,#333,#222,#333,#444)}button:active{background:#333;background:-webkit-gradient(linear,left top,left bottom,from(#333),to(#333));background:linear-gradient(#333,#333)}.media:hover button{background:-webkit-gradient(linear,left top,left bottom,from(#666),color-stop(#555),color-stop(#444),color-stop(#555),to(#666));background:linear-gradient(#666,#555,#444,#555,#666)}.media:hover button:hover{background:-webkit-gradient(linear,left top,left bottom,from(#444),color-stop(#555),color-stop(#666),color-stop(#555),to(#444));background:linear-gradient(#444,#555,#666,#555,#444)}.message,.static-message{text-shadow:var(--white-link-shadow)}.message.success,.static-message.success{background:#1f8454;border-color:#70dda9}.message.error,.static-message.error{border-color:#f3e6e6;background:#924949}.message.info,.static-message.info{border-color:#ffc;background:#bfbe3a}.invisible tbody>tr:nth-child(2n),.invisible tbody>tr:nth-child(odd),.invisible td,.invisible th,.invisible tr{background:transparent}#main-nav{border-bottom:.1rem solid #ddd}.tabs,.vertical-tabs{background:#333}.tabs>label,.vertical-tabs .tab label{background:#222;border:0;color:#eee}.vertical-tabs .tab label{width:100%}.tabs>label:hover,.vertical-tabs .tab>label:hover{background:#888}.tabs>label:active,.vertical-tabs .tab>label:active{background:#999}.tabs>[type=radio]:checked+label,.tabs>[type=radio]:checked+label+.content,.vertical-tabs [type=radio]:checked+label,.vertical-tabs [type=radio]:checked~.content{border:0;background:#666;color:#eee}.vertical-tabs{background:#222;border:1px solid #444}.vertical-tabs .tab{background:#666;border-bottom:1px solid #444}.streaming-logo{-webkit-filter:drop-shadow(0 0 2px #fff);filter:url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg"><filter id="filter"><feGaussianBlur in="SourceAlpha" stdDeviation="2" /><feOffset dx="1" dy="1" result="offsetblur" /><feFlood flood-color="rgba(255,255,255,1)" /><feComposite in2="offsetblur" operator="in" /><feMerge><feMergeNode /><feMergeNode in="SourceGraphic" /></feMerge></filter></svg>#filter');filter:drop-shadow(0 0 2px #fff)} a{color:#1978e2;text-shadow:var(--link-shadow)}a:hover{color:#9e34fd}body,legend,nav ul li a{background:#333;color:#eee}nav a:hover,nav li.selected a{border-color:#fff}header button{background:transparent}table{box-shadow:none}td,th{border-color:#111}thead td,thead th{background:#333;color:#eee}tbody>tr:nth-child(2n){background:#555;color:#eee}tbody>tr:nth-child(odd){background:#333}footer,hr,legend{border-color:#ddd}small{color:#fff}input,input[type],select,textarea{border-color:#bbb;color:#bbb;background:#333;padding:.8em}button{background:#444;background:linear-gradient(#666,#555,#444,#555,#666);border-radius:.5em;margin:0;text-transform:none}button,button:hover{border-color:#ddd;color:#ddd}button:hover{background:#222;background:linear-gradient(#444,#333,#222,#333,#444)}button:active{background:#333;background:linear-gradient(#333,#333)}.media:hover button{background:linear-gradient(#666,#555,#444,#555,#666)}.media:hover button:hover{background:linear-gradient(#444,#555,#666,#555,#444)}.message,.static-message{text-shadow:var(--white-link-shadow)}.message.success,.static-message.success{background:#1f8454;border-color:#70dda9}.message.error,.static-message.error{border-color:#f3e6e6;background:#924949}.message.info,.static-message.info{border-color:#ffc;background:#bfbe3a}.invisible tbody>tr:nth-child(2n),.invisible tbody>tr:nth-child(odd),.invisible td,.invisible th,.invisible tr{background:transparent}#main-nav{border-bottom:.1rem solid #ddd}.tabs,.vertical-tabs{background:#333}.tabs>label,.vertical-tabs .tab label{background:#222;border:0;color:#eee}.vertical-tabs .tab label{width:100%}.tabs>label:hover,.vertical-tabs .tab>label:hover{background:#888}.tabs>label:active,.vertical-tabs .tab>label:active{background:#999}.tabs>[type=radio]:checked+label,.tabs>[type=radio]:checked+label+.content,.vertical-tabs [type=radio]:checked+label,.vertical-tabs [type=radio]:checked~.content{border:0;background:#666;color:#eee}.vertical-tabs{background:#222;border:1px solid #444}.vertical-tabs .tab{background:#666;border-bottom:1px solid #444}.streaming-logo{-webkit-filter:drop-shadow(0 0 2px #fff);filter:drop-shadow(0 0 2px #fff)}

View File

@ -0,0 +1,5 @@
@import './all.css';
@media (prefers-color-scheme: dark) {
@import './dark-override.css';
}

View File

@ -134,3 +134,4 @@
color: #000; color: #000;
} }
} }

View File

@ -10,13 +10,12 @@
}, },
"devDependencies": { "devDependencies": {
"@ampproject/rollup-plugin-closure-compiler": "^0.9.0", "@ampproject/rollup-plugin-closure-compiler": "^0.9.0",
"concurrently": "^4.0.1", "concurrently": "^4.1.1",
"cssnano": "^4.0.5", "cssnano": "^4.1.10",
"postcss-cachify": "^1.3.1", "postcss": "^7.0.17",
"postcss-cssnext": "^3.0.0", "postcss-import": "^12.0.1",
"postcss-import": "^12.0.0", "postcss-preset-env": "^6.7.0",
"rollup": "^1.11.3", "rollup": "^1.16.7",
"rollup-plugin-closure-compiler-js": "^1.0.6",
"watch": "^1.0.2" "watch": "^1.0.2"
} }
} }

View File

@ -4,46 +4,53 @@
const fs = require('fs'); const fs = require('fs');
const postcss = require('postcss'); const postcss = require('postcss');
const atImport = require('postcss-import'); const atImport = require('postcss-import');
const cssNext = require('postcss-cssnext'); const cssNext = require('postcss-preset-env');
const cssNano = require('cssnano'); const cssNano = require('cssnano');
const css = fs.readFileSync('css/all.css', 'utf-8'); const css = fs.readFileSync('css/src/all.css', 'utf-8');
const darkCss = fs.readFileSync('css/dark-override.css', 'utf-8'); const darkCss = fs.readFileSync('css/src/dark-override.css', 'utf-8');
// Basic theme const minOptions = {
postcss()
.use(atImport())
.use(cssNext())
.use(cssNano({
autoprefixer: false, autoprefixer: false,
colormin: false, colormin: false,
minifyFontValues: false, minifyFontValues: false,
options: { options: {
sourcemap: false sourcemap: false
} }
})) };
const processOptions = {
browser: '> 0.5%',
features: {
'custom-properties': true,
},
stage: 0,
};
(async () => {
// Basic theme
const light = await postcss()
.use(atImport())
.use(cssNext(processOptions))
.use(cssNano(minOptions))
.process(css, { .process(css, {
from: 'css/all.css', from: 'css/src/all.css',
to: 'css/app.min.css' to: 'css/app.min.css',
}).then(result => {
fs.writeFileSync('css/app.min.css', result.css);
}); });
fs.writeFileSync('css/app.min.css', light);
// Dark theme // Dark theme
postcss() const dark = await postcss()
.use(atImport()) .use(atImport())
.use(cssNext()) .use(cssNext(processOptions))
.use(cssNano({ .use(cssNano(minOptions))
autoprefixer: false,
colormin: false,
minifyFontValues: false,
options: {
sourcemap: false
}
}))
.process(darkCss, { .process(darkCss, {
from: 'css/dark-override.css', from: 'css/dark-override.css',
to: 'css/dark.min.css' to: 'css/dark.min.css',
}).then(result => {
fs.writeFileSync('css/dark.min.css', result.css);
}); });
fs.writeFileSync('css/dark.min.css', dark);
const autoDarkCss = `${light} @media (prefers-color-scheme: dark) { ${dark} }`
fs.writeFileSync('css/dark-auto.min.css', autoDarkCss)
})();

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@ class Config extends AbstractType {
// Settings in config.toml // Settings in config.toml
public $asset_path; // Path to public folder for urls public $asset_path; // Path to public folder for urls
public $dark_theme; public $dark_theme; /* Deprecated */
public $default_anime_list_path; public $default_anime_list_path;
public $default_list; public $default_list;
public $default_manga_list_path; public $default_manga_list_path;
@ -33,6 +33,7 @@ class Config extends AbstractType {
public $secure_urls = TRUE; public $secure_urls = TRUE;
public $show_anime_collection; public $show_anime_collection;
public $show_manga_collection; public $show_manga_collection;
public $theme;
public $whose_list; public $whose_list;
// Application config // Application config

View File

@ -152,12 +152,23 @@ const SETTINGS_MAP = [
'default' => 'Somebody', 'default' => 'Somebody',
'description' => 'Name of the owner of the list data.', 'description' => 'Name of the owner of the list data.',
], ],
'dark_theme' => [ 'theme' => [
'type' => 'select',
'title' => 'Theme',
'default' => 'auto',
'description' => 'Which color scheme to use?',
'options' => [
'Automatically match OS theme' => 'auto',
'Original Light Theme' => 'light',
'Dark Theme' => 'dark',
]
],
/* 'dark_theme' => [
'type' => 'boolean', 'type' => 'boolean',
'title' => 'Use Dark Theme', 'title' => 'Use Dark Theme',
'default' => FALSE, 'default' => FALSE,
'description' => 'Use a darker background theme?', 'description' => 'Use a darker background theme?',
], ],*/
'show_anime_collection' => [ 'show_anime_collection' => [
'type' => 'boolean', 'type' => 'boolean',
'title' => 'Show Anime Collection', 'title' => 'Show Anime Collection',