Bladeren bron

Add theme variants

- Use CSS variables instead of inherence
- Rename default theme to "Light - Serif"
- Rename Black theme to "Dark - Serif"
- Rename "Sans-Serif" theme to "Light - Sans Serif"
- Add "System" theme that use system preferences: Dark or Light
- Add Serif and Sans-Serif variants for each color theme
Frédéric Guillot 6 jaren geleden
bovenliggende
commit
afe1faf214

+ 1 - 1
database/migration.go

@@ -12,7 +12,7 @@ import (
 	"miniflux.app/logger"
 )
 
-const schemaVersion = 24
+const schemaVersion = 25
 
 // Migrate executes database migrations.
 func Migrate(db *sql.DB) {

+ 6 - 0
database/sql.go

@@ -148,6 +148,11 @@ create index document_vectors_idx on entries using gin(document_vectors);`,
 	"schema_version_22": `update entries set document_vectors = setweight(to_tsvector(substring(coalesce(title, '') for 1000000)), 'A') || setweight(to_tsvector(substring(coalesce(content, '') for 1000000)), 'B');`,
 	"schema_version_23": `alter table users add column keyboard_shortcuts boolean default 't';`,
 	"schema_version_24": `alter table feeds add column disabled boolean default 'f';`,
+	"schema_version_25": `ALTER TABLE users ALTER COLUMN theme SET DEFAULT 'light_serif';
+UPDATE users SET theme='light_serif' WHERE theme='default';
+UPDATE users SET theme='light_sans_serif' WHERE theme='sansserif';
+UPDATE users SET theme='dark_serif' WHERE theme='black';
+`,
 	"schema_version_3": `create table tokens (
     id text not null,
     value text not null,
@@ -200,6 +205,7 @@ var SqlMapChecksums = map[string]string{
 	"schema_version_22": "51ed5fbcae9877e57274511f0ef8c61d254ebd78dfbcbc043a2acd30f4c93ca3",
 	"schema_version_23": "cb3512d328436447f114e305048c0daa8af7505cfe5eab02778b0de1156081b2",
 	"schema_version_24": "1224754c5b9c6b4038599852bbe72656d21b09cb018d3970bd7c00f0019845bf",
+	"schema_version_25": "5262d2d4c88d637b6603a1fcd4f68ad257bd59bd1adf89c58a18ee87b12050d7",
 	"schema_version_3":  "a54745dbc1c51c000f74d4e5068f1e2f43e83309f023415b1749a47d5c1e0f12",
 	"schema_version_4":  "216ea3a7d3e1704e40c797b5dc47456517c27dbb6ca98bf88812f4f63d74b5d9",
 	"schema_version_5":  "46397e2f5f2c82116786127e9f6a403e975b14d2ca7b652a48cd1ba843e6a27c",

+ 4 - 0
database/sql/schema_version_25.sql

@@ -0,0 +1,4 @@
+ALTER TABLE users ALTER COLUMN theme SET DEFAULT 'light_serif';
+UPDATE users SET theme='light_serif' WHERE theme='default';
+UPDATE users SET theme='light_sans_serif' WHERE theme='sansserif';
+UPDATE users SET theme='dark_serif' WHERE theme='black';

+ 6 - 3
generate.go

@@ -205,9 +205,12 @@ func main() {
 	})
 
 	generateCSSBundle("ui/static/css.go", map[string][]string{
-		"default":   []string{"ui/static/css/common.css"},
-		"black":     []string{"ui/static/css/common.css", "ui/static/css/black.css"},
-		"sansserif": []string{"ui/static/css/common.css", "ui/static/css/sansserif.css"},
+		"light_serif":       []string{"ui/static/css/light.css", "ui/static/css/serif.css", "ui/static/css/common.css"},
+		"light_sans_serif":  []string{"ui/static/css/light.css", "ui/static/css/sans_serif.css", "ui/static/css/common.css"},
+		"dark_serif":        []string{"ui/static/css/dark.css", "ui/static/css/serif.css", "ui/static/css/common.css"},
+		"dark_sans_serif":   []string{"ui/static/css/dark.css", "ui/static/css/sans_serif.css", "ui/static/css/common.css"},
+		"system_serif":      []string{"ui/static/css/system.css", "ui/static/css/serif.css", "ui/static/css/common.css"},
+		"system_sans_serif": []string{"ui/static/css/system.css", "ui/static/css/sans_serif.css", "ui/static/css/common.css"},
 	})
 
 	generateBinaryBundle("ui/static/bin.go", glob("ui/static/bin/*"))

+ 1 - 1
http/request/context.go

@@ -64,7 +64,7 @@ func UserLanguage(r *http.Request) string {
 func UserTheme(r *http.Request) string {
 	theme := getContextStringValue(r, UserThemeContextKey)
 	if theme == "" {
-		theme = "default"
+		theme = "light_serif"
 	}
 	return theme
 }

+ 3 - 3
http/request/context_test.go

@@ -241,18 +241,18 @@ func TestUserTheme(t *testing.T) {
 	r, _ := http.NewRequest("GET", "http://example.org", nil)
 
 	result := UserTheme(r)
-	expected := "default"
+	expected := "light_serif"
 
 	if result != expected {
 		t.Errorf(`Unexpected context value, got %q instead of %q`, result, expected)
 	}
 
 	ctx := r.Context()
-	ctx = context.WithValue(ctx, UserThemeContextKey, "black")
+	ctx = context.WithValue(ctx, UserThemeContextKey, "dark_serif")
 	r = r.WithContext(ctx)
 
 	result = UserTheme(r)
-	expected = "black"
+	expected = "dark_serif"
 
 	if result != expected {
 		t.Errorf(`Unexpected context value, got %q instead of %q`, result, expected)

+ 7 - 4
model/theme.go

@@ -9,9 +9,12 @@ import "miniflux.app/errors"
 // Themes returns the list of available themes.
 func Themes() map[string]string {
 	return map[string]string{
-		"default":   "Default",
-		"black":     "Black",
-		"sansserif": "Sans-Serif",
+		"light_serif":       "Light - Serif",
+		"light_sans_serif":  "Light - Sans Serif",
+		"dark_serif":        "Dark - Serif",
+		"dark_sans_serif":   "Dark - Sans Serif",
+		"system_serif":      "System - Serif",
+		"system_sans_serif": "System - Sans Serif",
 	}
 }
 
@@ -20,7 +23,7 @@ func Themes() map[string]string {
 // https://developers.google.com/web/tools/lighthouse/audits/address-bar
 func ThemeColor(theme string) string {
 	switch theme {
-	case "black":
+	case "dark_serif", "dark_sans_serif":
 		return "#222"
 	default:
 		return "#fff"

+ 1 - 1
model/theme_test.go

@@ -7,7 +7,7 @@ package model // import "miniflux.app/model"
 import "testing"
 
 func TestValidateTheme(t *testing.T) {
-	for _, status := range []string{"default", "black", "sansserif"} {
+	for _, status := range []string{"light_serif", "dark_sans_serif", "system_serif"} {
 		if err := ValidateTheme(status); err != nil {
 			t.Error(`A valid theme should not generate any error`)
 		}

+ 1 - 1
model/user_test.go

@@ -39,7 +39,7 @@ func TestValidateUserModification(t *testing.T) {
 		t.Error(`There is no changes, so we should not have an error`)
 	}
 
-	user = &User{Theme: "default"}
+	user = &User{Theme: "system_serif"}
 	if err := user.ValidateUserModification(); err != nil {
 		t.Error(`A valid theme should not generate any errors`)
 	}

File diff suppressed because it is too large
+ 0 - 0
ui/static/css.go


+ 0 - 233
ui/static/css/black.css

@@ -1,233 +0,0 @@
-/* Layout */
-body {
-    background: #222;
-    color: #efefef;
-}
-
-hr {
-    border-color: #555;
-}
-
-h1, h2, h3 {
-    color: #aaa;
-}
-
-a {
-    color: #aaa;
-}
-
-a:focus,
-a:hover {
-    color: #ddd;
-}
-
-/* Header and main menu */
-.header li {
-    border-color: #333;
-}
-
-.header a {
-    color: #ddd;
-    font-weight: 400;
-}
-
-.header .active a {
-    font-weight: 400;
-    color: #9b9494;
-}
-
-.header a:focus,
-.header a:hover {
-    color: rgba(82, 168, 236, 0.85);
-}
-
-/* Page header */
-.page-header h1 {
-    border-color: #333;
-}
-
-/* Logo */
-.logo a:hover span {
-    color: #555;
-}
-
-/* Tables */
-table, th, td {
-    border: 1px solid #555;
-}
-
-th {
-    background: #333;
-    color: #aaa;
-    font-weight: 400;
-}
-
-tr:hover {
-    background-color: #333;
-    color: #aaa;
-}
-
-/* Forms */
-input[type="search"],
-input[type="url"],
-input[type="password"],
-input[type="text"] {
-    border: 1px solid #555;
-    background: #333;
-    color: #ccc;
-}
-
-input[type="search"]:focus,
-input[type="url"]:focus,
-input[type="password"]:focus,
-input[type="text"]:focus {
-    color: #efefef;
-    border-color: rgba(82, 168, 236, 0.8);
-    box-shadow: 0 0 8px rgba(82, 168, 236, 0.6);
-}
-
-/* Buttons */
-.button-primary {
-    border-color: #444;
-    background: #333;
-    color: #efefef;
-}
-
-.button-primary:hover,
-.button-primary:focus {
-    border-color: #888;
-    background: #555;
-}
-
-/* Alerts */
-.alert,
-.alert-success,
-.alert-error,
-.alert-info,
-.alert-normal {
-    color: #efefef;
-    background-color: #333;
-    border-color: #444;
-}
-
-/* Panel */
-.panel {
-    background: #333;
-    border-color: #555;
-    color: #9b9b9b;
-}
-
-/* Modals */
-#modal-left {
-    background: #333;
-    color: #efefef;
-    box-shadow: 0 0 10px rgba(82, 168, 236, 0.6);
-}
-
-/* Keyboard Shortcuts */
-.keyboard-shortcuts li {
-    color: #9b9b9b;
-}
-
-/* Counters */
-.unread-counter-wrapper,
-.error-feeds-counter-wrapper {
-    color: #bbb;
-}
-
-/* Category label */
-.category {
-    color: #efefef;
-    background-color: #333;
-    border-color: #444;
-}
-
-.category a {
-    color: #999;
-}
-
-.category a:hover,
-.category a:focus {
-    color: #aaa;
-}
-
-/* Pagination */
-.pagination a {
-    color: #aaa;
-}
-
-.pagination-bottom {
-    border-color: #333;
-}
-
-/* List view */
-.item {
-    border-color: #666;
-    padding: 4px;
-}
-
-.item.current-item {
-    border-width: 2px;
-    border-color: rgba(82, 168, 236, 0.8);
-    box-shadow: 0 0 8px rgba(82, 168, 236, 0.6);
-}
-
-.item-title a {
-    font-weight: 400;
-}
-
-.item-status-read .item-title a {
-    color: #666;
-}
-
-.item-status-read .item-title a:focus,
-.item-status-read .item-title a:hover {
-    color: rgba(82, 168, 236, 0.6);
-}
-
-.item-meta a:hover,
-.item-meta a:focus {
-    color: #aaa;
-}
-
-.item-meta li:after {
-    color: #ddd;
-}
-
-/* Feeds list */
-article.feed-parsing-error {
-    background-color: #343434;
-}
-
-.parsing-error {
-    color: #eee;
-}
-
-/* Entry view */
-.entry header {
-    border-color: #333;
-}
-
-.entry header h1 a {
-    color: #bbb;
-}
-
-.entry-content,
-.entry-content p, ul {
-    color: #999;
-}
-
-.entry-content pre,
-.entry-content code {
-    color: #fff;
-    background: #555;
-    border-color: #888;
-}
-
-.entry-content q {
-    color: #777;
-}
-
-.entry-enclosure {
-    border-color: #333;
-}

+ 98 - 70
ui/static/css/common.css

@@ -11,17 +11,23 @@ html {
 }
 
 body {
-    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+    font-family: var(--font-family);
     text-rendering: optimizeLegibility;
+    color: var(--body-color);
+    background: var(--body-background);
 }
 
 hr {
     border: 0;
     height: 0;
-    border-top: 1px dotted #ccc;
+    border-top: 1px dotted var(--hr-border-color);
     padding-bottom: 10px;
 }
 
+h1, h2, h3 {
+    color: var(--title-color);
+}
+
 main {
     padding-left: 5px;
     padding-right: 5px;
@@ -29,18 +35,18 @@ main {
 }
 
 a {
-    color: #3366CC;
+    color: var(--link-color);
 }
 
 a:focus {
     outline: 0;
-    color: red;
+    color: var(--link-focus-color);
     text-decoration: none;
     outline: 1px dotted #aaa;
 }
 
 a:hover {
-    color: #333;
+    color: var(--link-hover-color);
     text-decoration: none;
 }
 
@@ -59,7 +65,7 @@ a:hover {
     padding-left: 10px;
     line-height: 2.1em;
     font-size: 1.2em;
-    border-bottom: 1px dotted #ddd;
+    border-bottom: 1px dotted var(--header-list-border-color);
 }
 
 .header li:hover a {
@@ -68,18 +74,23 @@ a:hover {
 
 .header a {
     font-size: 0.9em;
-    color: #444;
+    color: var(--header-link-color);
     text-decoration: none;
     border: none;
+    font-weight: 400;
 }
 
 .header .active a {
-    font-weight: 600;
+    color: var(--header-active-link-color);
+    font-weight: 500;
+}
+
+.header a:hover {
+    color: var(--header-link-hover-color);
 }
 
-.header a:hover,
 .header a:focus {
-    color: #888;
+    color: var(--header-link-focus-color);
 }
 
 /* Page header and footer*/
@@ -93,7 +104,7 @@ a:hover {
 
 .page-header h1 {
     font-weight: 500;
-    border-bottom: 1px dotted #ddd;
+    border-bottom: 1px dotted var(--page-header-title-border-color);
 }
 
 .page-header ul,
@@ -114,7 +125,7 @@ a:hover {
 }
 
 .logo a {
-    color: #000;
+    color: var(--logo-color);
     letter-spacing: 1px;
 }
 
@@ -127,7 +138,7 @@ a:hover {
 }
 
 .logo a:hover span {
-    color: #000;
+    color: var(--logo-hover-color-span);
 }
 
 /* Search form */
@@ -213,7 +224,7 @@ table {
 }
 
 table, th, td {
-    border: 1px solid #ddd;
+    border: 1px solid var(--table-border-color);
 }
 
 th, td {
@@ -226,11 +237,14 @@ td {
 }
 
 th {
-    background: #fcfcfc;
+    background: var(--table-th-background);
+    color: var(--table-th-color);
+    font-weight: 400;
 }
 
 tr:hover {
-    background-color: #f9f9f9;
+    color: var(--table-tr-hover-color);
+    background-color: var(--table-tr-hover-background-color);
 }
 
 .column-40 {
@@ -278,7 +292,9 @@ input[type="search"],
 input[type="url"],
 input[type="password"],
 input[type="text"] {
-    border: 1px solid #ccc;
+    color: var(--input-color);
+    background: var(--input-background);
+    border: var(--input-border);
     padding: 3px;
     line-height: 20px;
     width: 250px;
@@ -292,10 +308,10 @@ input[type="search"]:focus,
 input[type="url"]:focus,
 input[type="password"]:focus,
 input[type="text"]:focus {
-    color: #000;
-    border-color: rgba(82, 168, 236, 0.8);
+    color: var(--input-focus-color);
+    border-color: var(--input-focus-border-color);
     outline: 0;
-    box-shadow: 0 0 8px rgba(82, 168, 236, 0.6);
+    box-shadow: var(--input-focus-box-shadow);
 }
 
 input[type="checkbox"] {
@@ -347,15 +363,15 @@ a.button {
 }
 
 .button-primary {
-    border-color: #3079ed;
-    background: #4d90fe;
-    color: #fff;
+    border-color: var(--button-primary-border-color);
+    background: var(--button-primary-background);
+    color: var(--button-primary-color);
 }
 
 .button-primary:hover,
 .button-primary:focus {
-    border-color: #2f5bb7;
-    background: #357ae8;
+    border-color: var(--button-primary-focus-border-color);
+    background: var(--button-primary-focus-background);
 }
 
 .button-danger {
@@ -385,9 +401,9 @@ a.button {
 .alert {
     padding: 8px 35px 8px 14px;
     margin-bottom: 20px;
-    color: #c09853;
-    background-color: #fcf8e3;
-    border: 1px solid #fbeed5;
+    color: var(--alert-color);
+    background-color: var(--alert-background-color);
+    border: 1px solid var(--alert-border-color);
     border-radius: 4px;
     overflow: auto;
 }
@@ -398,32 +414,32 @@ a.button {
 }
 
 .alert-success {
-    color: #468847;
-    background-color: #dff0d8;
-    border-color: #d6e9c6;
+    color: var(--alert-success-color);
+    background-color: var(--alert-success-background-color);
+    border-color: var(--alert-success-border-color);
 }
 
 .alert-error {
-    color: #b94a48;
-    background-color: #f2dede;
-    border-color: #eed3d7;
+    color: var(--alert-error-color);
+    background-color: var(--alert-error-background-color);
+    border-color: var(--alert-error-border-color);
 }
 
 .alert-error a {
-    color: #b94a48;
+    color: var(--alert-error-color);
 }
 
 .alert-info {
-    color: #3a87ad;
-    background-color: #d9edf7;
-    border-color: #bce8f1;
+    color: var(--alert-info-color);
+    background-color: var(--alert-info-background-color);
+    border-color: var(--alert-info-border-color);
 }
 
 /* Panel */
 .panel {
-    color: #333;
-    background-color: #fcfcfc;
-    border: 1px solid #ddd;
+    color: var(--panel-color);
+    background-color: var(--panel-background);
+    border: 1px solid var(--panel-border-color);
     border-radius: 5px;
     padding: 10px;
     margin-bottom: 15px;
@@ -447,8 +463,9 @@ a.button {
     bottom: 0;
     width: 360px;
     overflow: auto;
-    background: #f0f0f0;
-    box-shadow: 2px 0 5px 0 #ccc;
+    color: var(--modal-color);
+    background: var(--modal-background);
+    box-shadow: var(--modal-box-shadow);
     padding: 5px;
     padding-top: 30px;
 }
@@ -477,7 +494,7 @@ a.button {
 .keyboard-shortcuts li {
     margin-left: 25px;
     list-style-type: square;
-    color: #333;
+    color: var(--keyboard-shortcuts-li-color);
     font-size: 0.95em;
     line-height: 1.45em;
 }
@@ -497,28 +514,29 @@ a.button {
 .error-feeds-counter-wrapper {
     font-size: 0.9em;
     font-weight: 300;
-    color: #666;
+    color: var(--counter-color);
 }
 
 /* Category label */
 .category {
     font-size: 0.75em;
-    background-color: #fffcd7;
-    border: 1px solid #d5d458;
+    background-color: var(--category-background-color);
+    border: 1px solid var(--category-border-color);
     border-radius: 5px;
     margin-left: 0.25em;
     padding: 1px 0.4em 1px 0.4em;
     white-space: nowrap;
+    color: var(--category-color);
 }
 
 .category a {
-    color: #555;
+    color: var(--category-link-color);
     text-decoration: none;
 }
 
 .category a:hover,
 .category a:focus {
-    color: #000;
+    color: var(--category-link-hover-color);
 }
 
 /* Pagination */
@@ -530,7 +548,7 @@ a.button {
 }
 
 .pagination-bottom {
-    border-top: 1px dotted #ddd;
+    border-top: 1px dotted var(--pagination-border-color);
     margin-bottom: 15px;
     margin-top: 50px;
 }
@@ -552,7 +570,7 @@ a.button {
 }
 
 .pagination a {
-    color: #333;
+    color: var(--pagination-color);
 }
 
 .pagination a:hover,
@@ -562,28 +580,29 @@ a.button {
 
 /* List view */
 .item {
-    border: 1px dotted #ddd;
+    border: 1px dotted var(--item-border-color);
     margin-bottom: 20px;
-    padding: 5px;
+    padding: var(--item-padding);
     overflow: hidden;
 }
 
 .item.current-item {
-    border: 3px solid #bce;
+    border: var(--current-item-border-width) solid var(--current-item-border-color);
     padding: 3px;
+    box-shadow: var(--current-item-box-shadow);
 }
 
 .item-title a {
     text-decoration: none;
-    font-weight: 600;
+    font-weight: var(--item-title-link-font-weight);
 }
 
 .item-status-read .item-title a {
-    color: #777;
+    color: var(--item-status-read-title-link-color);
 }
 
 .item-meta {
-    color: #777;
+    color: var(--item-meta-focus-color);
     font-size: 0.8em;
 }
 
@@ -607,7 +626,7 @@ a.button {
 
 .item-meta li:after {
     content: "|";
-    color: #aaa;
+    color: var(--item-meta-li-color);
 }
 
 .item-meta li:last-child:after {
@@ -624,14 +643,14 @@ a.button {
 
 /* Feeds list */
 article.feed-parsing-error {
-    background-color: #fcf8e3;
+    background-color: var(--feed-parsing-error-background-color);
     border-color: #aaa;
 }
 
 .parsing-error {
     font-size: 0.85em;
     margin-top: 2px;
-    color: #333;
+    color: var(--parsing-error-color);
 }
 
 .parsing-error-count {
@@ -641,7 +660,7 @@ article.feed-parsing-error {
 /* Entry view */
 .entry header {
     padding-bottom: 5px;
-    border-bottom: 1px dotted #ddd;
+    border-bottom: 1px dotted var(--entry-header-border-color);
 }
 
 .entry header h1 {
@@ -652,7 +671,7 @@ article.feed-parsing-error {
 
 .entry header h1 a {
     text-decoration: none;
-    color: #333;
+    color: var(--entry-header-title-link-color);
 }
 
 .entry header h1 a:hover,
@@ -708,8 +727,8 @@ article.feed-parsing-error {
     padding-top: 15px;
     font-size: 1.2em;
     font-weight: 300;
-    font-family: Georgia, 'Times New Roman', Times, serif;
-    color: #555;
+    font-family: var(--entry-content-font-family);
+    color: var(--entry-content-color);
     line-height: 1.4em;
     overflow-wrap: break-word;
 }
@@ -777,12 +796,12 @@ article.feed-parsing-error {
     margin-bottom: 20px;
     color: #888;
     line-height: 1.4em;
-    font-family: Georgia, serif;
+    font-family: var(--entry-content-quote-font-family);
 }
 
 .entry-content q {
-    color: purple;
-    font-family: Georgia, serif;
+    color: var(--entry-content-quote-color);
+    font-family: var(--entry-content-quote-font-family);
     font-style: italic;
 }
 
@@ -796,10 +815,17 @@ article.feed-parsing-error {
 
 .entry-content pre {
     padding: 5px;
-    background: #f0f0f0;
-    border: 1px solid #ddd;
     overflow: auto;
     overflow-wrap: initial;
+    border-width: 1px;
+    border-style: solid;
+}
+
+.entry-content pre,
+.entry-content code {
+    color: var(--entry-content-code-color);
+    background: var(--entry-content-code-background);
+    border-color: var(--entry-content-code-border-color);
 }
 
 .entry-content table {
@@ -810,6 +836,8 @@ article.feed-parsing-error {
 .entry-content ul,
 .entry-content ol {
     margin-left: 30px;
+    margin-top: 15px;
+    margin-bottom: 15px;
 }
 
 .entry-content ul {
@@ -825,7 +853,7 @@ article.feed-parsing-error {
 }
 
 .entry-enclosure {
-    border: 1px dotted #ddd;
+    border: 1px dotted var(--entry-enclosure-border-color);
     padding: 5px;
     margin-top: 10px;
     max-width: 100%;

+ 105 - 0
ui/static/css/dark.css

@@ -0,0 +1,105 @@
+:root {
+    --font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
+    --body-color: #efefef;
+    --body-background: #222;
+    --hr-border-color: #555;
+    --title-color: #aaa;
+    --link-color: #aaa;
+    --link-focus-color: #ddd;
+    --link-hover-color: #ddd;
+
+    --header-list-border-color: #333;
+    --header-link-color: #ddd;
+    --header-link-focus-color: rgba(82, 168, 236, 0.85);
+    --header-link-hover-color: rgba(82, 168, 236, 0.85);
+    --header-active-link-color: #9b9494;
+
+    --page-header-title-border-color: #333;
+
+    --logo-color: #bbb;
+    --logo-hover-color-span: #bbb;
+
+    --table-border-color: #555;
+    --table-th-background: #333;
+    --table-th-color: #aaa;
+    --table-tr-hover-background-color: #333;
+    --table-tr-hover-color: #aaa;
+
+    --button-primary-border-color: #444;
+    --button-primary-background: #333;
+    --button-primary-color: #efefef;
+    --button-primary-focus-border-color: #888;
+    --button-primary-focus-background: #555;
+
+    --input-border: 1px solid #555;
+    --input-background: #333;
+    --input-color: #ccc;
+
+    --input-focus-color: #efefef;
+    --input-focus-border-color: rgba(82, 168, 236, 0.8);
+    --input-focus-box-shadow: 0 0 8px rgba(82, 168, 236, 0.6);
+
+    --alert-color: #efefef;
+    --alert-background-color: #333;
+    --alert-border-color: #444;
+
+    --alert-success-color: #efefef;
+    --alert-success-background-color: #333;
+    --alert-success-border-color: #444;
+
+    --alert-error-color: #efefef;
+    --alert-error-background-color: #333;
+    --alert-error-border-color: #444;
+
+    --alert-info-color: #efefef;
+    --alert-info-background-color: #333;
+    --alert-info-border-color: #444;
+
+    --panel-background: #333;
+    --panel-border-color: #555;
+    --panel-color: #9b9b9b;
+
+    --modal-background: #333;
+    --modal-color: #efefef;
+    --modal-box-shadow: 0 0 10px rgba(82, 168, 236, 0.6);
+
+    --pagination-link-color: #aaa;
+    --pagination-border-color: #333;
+
+    --category-color: #efefef;
+    --category-background-color: #333;
+    --category-border-color: #444;
+    --category-link-color: #999;
+    --category-link-hover-color: #aaa;
+
+    --item-border-color: #666;
+    --item-padding: 4px;
+    --item-title-link-font-weight: 400;
+
+    --item-status-read-title-link-color: #666;
+    --item-status-read-title-focus-color: rgba(82, 168, 236, 0.6);
+
+    --item-meta-focus-color: #aaa;
+    --item-meta-li-color: #ddd;
+
+    --current-item-border-width: 2px;
+    --current-item-border-color: rgba(82, 168, 236, 0.8);
+    --current-item-box-shadow: 0 0 8px rgba(82, 168, 236, 0.6);
+
+    --entry-header-border-color: #333;
+    --entry-header-title-link-color: #bbb;
+    --entry-content-color: #999;
+    --entry-content-code-color: #fff;
+    --entry-content-code-background: #555;
+    --entry-content-code-border-color: #888;
+    --entry-content-quote-color: #777;
+    --entry-content-quote-font-family: Georgia, 'Times New Roman', Times, serif;
+    --entry-enclosure-border-color: #333;
+
+    --parsing-error-color: #eee;
+    --feed-parsing-error-background-color: #343434;
+
+    --keyboard-shortcuts-li-color: #9b9b9b;
+
+    --counter-color: #bbb;
+}

+ 105 - 0
ui/static/css/light.css

@@ -0,0 +1,105 @@
+:root {
+    --font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
+    --body-color: #333;
+    --body-background: #fff;
+    --hr-border-color: #ccc;
+    --title-color: #333;
+    --link-color: #3366CC;
+    --link-focus-color: red;
+    --link-hover-color: #333;
+
+    --header-list-border-color: #ddd;
+    --header-link-color: #444;
+    --header-link-focus-color: #888;
+    --header-link-hover-color: #888;
+    --header-active-link-color: #444;
+
+    --page-header-title-border-color: #333;
+
+    --logo-color: #000;
+    --logo-hover-color-span: #000;
+
+    --table-border-color: #ddd;
+    --table-th-background: #fcfcfc;
+    --table-th-color: #333;
+    --table-tr-hover-background-color: #a3a3a3;
+    --table-tr-hover-color: #333;
+
+    --button-primary-border-color: #3079ed;
+    --button-primary-background: #4d90fe;
+    --button-primary-color: #fff;
+    --button-primary-focus-border-color: #2f5bb7;
+    --button-primary-focus-background: #357ae8;
+
+    --input-border: 1px solid #ccc;
+    --input-background: #fff;
+    --input-color: #333;
+
+    --input-focus-color: #000;
+    --input-focus-border-color: rgba(82, 168, 236, 0.8);
+    --input-focus-box-shadow: 0 0 8px rgba(82, 168, 236, 0.6);
+
+    --alert-color: #c09853;
+    --alert-background-color: #fcf8e3;
+    --alert-border-color: #fbeed5;
+
+    --alert-success-color: #468847;
+    --alert-success-background-color: #dff0d8;
+    --alert-success-border-color: #d6e9c6;
+
+    --alert-error-color: #b94a48;
+    --alert-error-background-color: #f2dede;
+    --alert-error-border-color: #eed3d7;
+
+    --alert-info-color: #3a87ad;
+    --alert-info-background-color: #d9edf7;
+    --alert-info-border-color: #bce8f1;
+
+    --panel-background: #fcfcfc;
+    --panel-border-color: #ddd;
+    --panel-color: #333;
+
+    --modal-background: #f0f0f0;
+    --modal-color: #333;
+    --modal-box-shadow: 2px 0 5px 0 #ccc;
+
+    --pagination-link-color: #333;
+    --pagination-border-color: #ddd;
+
+    --category-color: #333;
+    --category-background-color: #fffcd7;
+    --category-border-color: #d5d458;
+    --category-link-color: #000;
+    --category-link-hover-color: #000;
+
+    --item-border-color: #ddd;
+    --item-padding: 5px;
+    --item-title-link-font-weight: 600;
+
+    --item-status-read-title-link-color: #777;
+    --item-status-read-title-focus-color: #777;
+
+    --item-meta-focus-color: #777;
+    --item-meta-li-color: #aaa;
+
+    --current-item-border-width: 3px;
+    --current-item-border-color: #bce;
+    --current-item-box-shadow: none;
+
+    --entry-header-border-color: #ddd;
+    --entry-header-title-link-color: #333;
+    --entry-content-color: #555;
+    --entry-content-code-color: #333;
+    --entry-content-code-background: #f0f0f0;
+    --entry-content-code-border-color: #ddd;
+    --entry-content-quote-color: #666;
+    --entry-content-quote-font-family: Georgia, 'Times New Roman', Times, serif;
+    --entry-enclosure-border-color: #333;
+
+    --parsing-error-color: #333;
+    --feed-parsing-error-background-color: #fcf8e3;
+
+    --keyboard-shortcuts-li-color: #333;
+
+    --counter-color: #666;
+}

+ 3 - 0
ui/static/css/sans_serif.css

@@ -0,0 +1,3 @@
+:root {
+    --entry-content-font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
+}

+ 0 - 11
ui/static/css/sansserif.css

@@ -1,11 +0,0 @@
-body,
-.entry-content,
-.entry-content blockquote,
-.entry-content q {
-    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
-}
-
-.entry-content {
-    font-size: 1.17em;
-    font-weight: 400;
-}

+ 3 - 0
ui/static/css/serif.css

@@ -0,0 +1,3 @@
+:root {
+    --entry-content-font-family: Georgia, 'Times New Roman', Times, serif;
+}

+ 213 - 0
ui/static/css/system.css

@@ -0,0 +1,213 @@
+:root {
+    --font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
+    --body-color: #333;
+    --body-background: #fff;
+    --hr-border-color: #ccc;
+    --title-color: #333;
+    --link-color: #3366CC;
+    --link-focus-color: red;
+    --link-hover-color: #333;
+
+    --header-list-border-color: #ddd;
+    --header-link-color: #444;
+    --header-link-focus-color: #888;
+    --header-link-hover-color: #888;
+    --header-active-link-color: #444;
+
+    --page-header-title-border-color: #333;
+
+    --logo-color: #000;
+    --logo-hover-color-span: #000;
+
+    --table-border-color: #ddd;
+    --table-th-background: #fcfcfc;
+    --table-th-color: #333;
+    --table-tr-hover-background-color: #a3a3a3;
+    --table-tr-hover-color: #333;
+
+    --button-primary-border-color: #3079ed;
+    --button-primary-background: #4d90fe;
+    --button-primary-color: #fff;
+    --button-primary-focus-border-color: #2f5bb7;
+    --button-primary-focus-background: #357ae8;
+
+    --input-border: 1px solid #ccc;
+    --input-background: #fff;
+    --input-color: #333;
+
+    --input-focus-color: #000;
+    --input-focus-border-color: rgba(82, 168, 236, 0.8);
+    --input-focus-box-shadow: 0 0 8px rgba(82, 168, 236, 0.6);
+
+    --alert-color: #c09853;
+    --alert-background-color: #fcf8e3;
+    --alert-border-color: #fbeed5;
+
+    --alert-success-color: #468847;
+    --alert-success-background-color: #dff0d8;
+    --alert-success-border-color: #d6e9c6;
+
+    --alert-error-color: #b94a48;
+    --alert-error-background-color: #f2dede;
+    --alert-error-border-color: #eed3d7;
+
+    --alert-info-color: #3a87ad;
+    --alert-info-background-color: #d9edf7;
+    --alert-info-border-color: #bce8f1;
+
+    --panel-background: #fcfcfc;
+    --panel-border-color: #ddd;
+    --panel-color: #333;
+
+    --modal-background: #f0f0f0;
+    --modal-color: #333;
+    --modal-box-shadow: 2px 0 5px 0 #ccc;
+
+    --pagination-link-color: #333;
+    --pagination-border-color: #ddd;
+
+    --category-color: #333;
+    --category-background-color: #fffcd7;
+    --category-border-color: #d5d458;
+    --category-link-color: #000;
+    --category-link-hover-color: #000;
+
+    --item-border-color: #ddd;
+    --item-padding: 5px;
+    --item-title-link-font-weight: 600;
+
+    --item-status-read-title-link-color: #777;
+    --item-status-read-title-focus-color: #777;
+
+    --item-meta-focus-color: #777;
+    --item-meta-li-color: #aaa;
+
+    --current-item-border-width: 3px;
+    --current-item-border-color: #bce;
+    --current-item-box-shadow: none;
+
+    --entry-header-border-color: #ddd;
+    --entry-header-title-link-color: #333;
+    --entry-content-color: #555;
+    --entry-content-code-color: #333;
+    --entry-content-code-background: #f0f0f0;
+    --entry-content-code-border-color: #ddd;
+    --entry-content-quote-color: #666;
+    --entry-content-quote-font-family: Georgia, 'Times New Roman', Times, serif;
+    --entry-enclosure-border-color: #333;
+
+    --parsing-error-color: #333;
+    --feed-parsing-error-background-color: #fcf8e3;
+
+    --keyboard-shortcuts-li-color: #333;
+
+    --counter-color: #666;
+}
+
+@media (prefers-color-scheme: dark) {
+    :root {
+        --font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
+        --body-color: #efefef;
+        --body-background: #222;
+        --hr-border-color: #555;
+        --title-color: #aaa;
+        --link-color: #aaa;
+        --link-focus-color: #ddd;
+        --link-hover-color: #ddd;
+
+        --header-list-border-color: #333;
+        --header-link-color: #ddd;
+        --header-link-focus-color: rgba(82, 168, 236, 0.85);
+        --header-link-hover-color: rgba(82, 168, 236, 0.85);
+        --header-active-link-color: #9b9494;
+
+        --page-header-title-border-color: #333;
+
+        --logo-color: #bbb;
+        --logo-hover-color-span: #bbb;
+
+        --table-border-color: #555;
+        --table-th-background: #333;
+        --table-th-color: #aaa;
+        --table-tr-hover-background-color: #333;
+        --table-tr-hover-color: #aaa;
+
+        --button-primary-border-color: #444;
+        --button-primary-background: #333;
+        --button-primary-color: #efefef;
+        --button-primary-focus-border-color: #888;
+        --button-primary-focus-background: #555;
+
+        --input-border: 1px solid #555;
+        --input-background: #333;
+        --input-color: #ccc;
+
+        --input-focus-color: #efefef;
+        --input-focus-border-color: rgba(82, 168, 236, 0.8);
+        --input-focus-box-shadow: 0 0 8px rgba(82, 168, 236, 0.6);
+
+        --alert-color: #efefef;
+        --alert-background-color: #333;
+        --alert-border-color: #444;
+
+        --alert-success-color: #efefef;
+        --alert-success-background-color: #333;
+        --alert-success-border-color: #444;
+
+        --alert-error-color: #efefef;
+        --alert-error-background-color: #333;
+        --alert-error-border-color: #444;
+
+        --alert-info-color: #efefef;
+        --alert-info-background-color: #333;
+        --alert-info-border-color: #444;
+
+        --panel-background: #333;
+        --panel-border-color: #555;
+        --panel-color: #9b9b9b;
+
+        --modal-background: #333;
+        --modal-color: #efefef;
+        --modal-box-shadow: 0 0 10px rgba(82, 168, 236, 0.6);
+
+        --pagination-link-color: #aaa;
+        --pagination-border-color: #333;
+
+        --category-color: #efefef;
+        --category-background-color: #333;
+        --category-border-color: #444;
+        --category-link-color: #999;
+        --category-link-hover-color: #aaa;
+
+        --item-border-color: #666;
+        --item-padding: 4px;
+        --item-title-link-font-weight: 400;
+
+        --item-status-read-title-link-color: #666;
+        --item-status-read-title-focus-color: rgba(82, 168, 236, 0.6);
+
+        --item-meta-focus-color: #aaa;
+        --item-meta-li-color: #ddd;
+
+        --current-item-border-width: 2px;
+        --current-item-border-color: rgba(82, 168, 236, 0.8);
+        --current-item-box-shadow: 0 0 8px rgba(82, 168, 236, 0.6);
+
+        --entry-header-border-color: #333;
+        --entry-header-title-link-color: #bbb;
+        --entry-content-color: #999;
+        --entry-content-code-color: #fff;
+        --entry-content-code-background: #555;
+        --entry-content-code-border-color: #888;
+        --entry-content-quote-color: #777;
+        --entry-content-quote-font-family: Georgia, 'Times New Roman', Times, serif;
+        --entry-enclosure-border-color: #333;
+
+        --parsing-error-color: #eee;
+        --feed-parsing-error-background-color: #343434;
+
+        --keyboard-shortcuts-li-color: #9b9b9b;
+
+        --counter-color: #bbb;
+    }
+}

Some files were not shown because too many files changed in this diff