From 030184387fb687f0db7e8586686cb1587faf64f9 Mon Sep 17 00:00:00 2001 From: Bauke Date: Thu, 9 Aug 2018 00:09:42 +0200 Subject: [PATCH] Overhaul theme system This replaces the previous CSS theme system with a new one based around using SCSS map-merge to define different "color sets" that can overwrite the base theme to generate new themes. The original theme system was heavily based around Solarized with only light and dark variants, and other themes weren't able to replace many of the colors (link colors, buttons, alerts, etc.). This new system will make it possible to have themes that are completely unrelated to the Solarized variants. --- tildes/scss/_base.scss | 5 - tildes/scss/_themes.scss | 491 +++++++++++++++++------ tildes/scss/modules/_btn.scss | 21 - tildes/scss/modules/_comment.scss | 15 +- tildes/scss/modules/_form.scss | 4 - tildes/scss/modules/_label.scss | 1 - tildes/scss/modules/_link.scss | 4 - tildes/scss/modules/_logged-in-user.scss | 5 - tildes/scss/modules/_message.scss | 2 +- tildes/scss/modules/_nav.scss | 2 - tildes/scss/modules/_site-header.scss | 1 - tildes/scss/modules/_topic.scss | 11 +- 12 files changed, 384 insertions(+), 178 deletions(-) diff --git a/tildes/scss/_base.scss b/tildes/scss/_base.scss index 3dfc9bd..61bd70a 100644 --- a/tildes/scss/_base.scss +++ b/tildes/scss/_base.scss @@ -9,12 +9,7 @@ html { } a { - color: $blue; text-decoration: none; - - &:visited { - color: $violet; - } } // this is probably unnecessary, but I'm running into specificity conflicts diff --git a/tildes/scss/_themes.scss b/tildes/scss/_themes.scss index 828ed3b..6375cfc 100644 --- a/tildes/scss/_themes.scss +++ b/tildes/scss/_themes.scss @@ -2,130 +2,229 @@ // SPDX-License-Identifier: AGPL-3.0-or-later // This file should only contain rules that need to differ between the -// different themes, defined inside the `theme-dependent` mixin below. +// different themes, defined inside the `use-theme` mixin below. // Note that all rules inside the mixin will be included in the compiled CSS // once for each theme, so they should be kept as minimal as possible. -@mixin specialtag($color, $is-light) { - @if $is-light { - background-color: $color; +// Each theme is defined by a SCSS map and a `body.theme-` selector. +// The `use-theme` mixin is called inside the body.theme and takes the theme's +// map as its only argument, applying each defined color available in the map. +// If a color variable is left undefined in a map, it will use the default's +// `$theme-base` for it instead. + +$theme-base: ( + 'foreground-primary': #333, + 'foreground-secondary': #999, + 'foreground-highlight': #222, + 'foreground-middle': #666, + 'foreground-extreme': #000, + 'background-primary': #fff, + 'background-secondary': #eee, + 'background-input': #f7f7f7, + 'border-primary': #ccc, + 'anchor-normal': $blue, + 'anchor-normal-hover': darken($blue, 5%), + 'anchor-normal-visited': $violet, +); + +$theme-white: $theme-base; + +$theme-light: map-merge($theme-base, ( + 'foreground-primary': $fg-dark, + 'foreground-secondary': $fg-lightest, + 'foreground-highlight': $fg-darkest, + 'foreground-middle': #7c8e92, + 'background-primary': $bg-lightest, + 'background-secondary': $bg-light, + 'background-input': #fefbf1, + 'border-primary': #cbc5b6, +)); + +$theme-dark: map-merge($theme-base, ( + 'foreground-primary': $fg-light, + 'foreground-secondary': $fg-darkest, + 'foreground-highlight': $fg-lightest, + 'foreground-middle': #6e8186, + 'foreground-extreme': #fff, + 'background-primary': $bg-darkest, + 'background-secondary': $bg-dark, + 'background-input': #001f27, + 'border-primary': #33555e, +)); + +$theme-black: map-merge($theme-base, ( + 'foreground-primary': #ccc, + 'foreground-secondary': #888, + 'foreground-highlight': #ddd, + 'foreground-middle': #aaa, + 'foreground-extreme': #fff, + 'background-primary': #000, + 'background-secondary': #222, + 'background-input': #000, + 'border-primary': #444, +)); + +@mixin use-theme($theme) { + $foreground-primary: map-get($theme, 'foreground-primary'); + $foreground-secondary: map-get($theme, 'foreground-secondary'); + $foreground-highlight: map-get($theme, 'foreground-highlight'); + $foreground-middle: map-get($theme, 'foreground-middle'); + $foreground-extreme: map-get($theme, 'foreground-extreme'); + $background-primary: map-get($theme, 'background-primary'); + $background-secondary: map-get($theme, 'background-secondary'); + $background-input: map-get($theme, 'background-input'); + $border-primary: map-get($theme, 'border-primary'); + $anchor-normal: map-get($theme, 'anchor-normal'); + $anchor-normal-hover: map-get($theme, 'anchor-normal-hover'); + $anchor-normal-visited: map-get($theme, 'anchor-normal-visited'); + + color: $foreground-primary; + background-color: $background-secondary; - a { - color: white; + // set $is-light as a bool for whether $background-color seems light or dark + $is-light: lightness($background-primary) > 50; + + a { + color: $anchor-normal; + + &:hover { + color: $anchor-normal-hover; } - } - @else { - background-color: transparent; - color: $color; - border: 1px solid $color; - a { - color: $color; + &:visited { + color: $anchor-normal-visited; } } -} -@mixin theme-dependent($background-color, $background-alt-color, $text-color, $text-highlight-color, $text-secondary-color, $border-color) { - // set $is-light as a bool for whether $background-color seems light or dark - $is-light: lightness($background-color) > 50; + a.link-user, + a.link-group { + &:visited { + color: $anchor-normal; + } + } - $text-mid-color: mix($text-color, $text-secondary-color); - $text-extreme-color: if($is-light, #000, #fff); + a.logged-in-user-alert { + color: $orange; - // if $background-color is light, make the input background even lighter, - // but if it's dark, make input background even darker - $input-background-color: if($is-light, lighten($background-color, 3%), darken($background-color, 3%)); + &:visited { + color: $orange; + } + } - background-color: $background-alt-color; - color: $text-color; + a.logged-in-user-username:visited, + a.site-header-context:visited, + a.site-header-logo:visited { + color: unset; + } @include syntax-highlighting($is-light); blockquote { - background-color: $background-alt-color; - border-color: $text-highlight-color; + border-color: $foreground-highlight; + background-color: $background-secondary; } code, pre { - background-color: $background-alt-color; - color: $text-highlight-color; + color: $foreground-highlight; + background-color: $background-secondary; } fieldset { - border-color: $border-color; + border-color: $border-primary; } figure { - border-color: $border-color; + border-color: $border-primary; } main { - background-color: $background-color; + background-color: $background-primary; } section { - border-color: $border-color; + border-color: $border-primary; } - .tab-listing-order { - border-color: $border-color; + tbody tr:nth-of-type(2n+1) { + background-color: $background-secondary; } - .logged-in-user-username { - color: $text-color; + td { + border-color: $border-primary; } - .sidebar-controls { - background-color: $background-alt-color; + th { + border-color: $foreground-highlight; } - .site-header-context, .site-header-username { - color: $text-color; - } + .btn { + color: $blue; + background-color: transparent; + border-color: $blue; - .site-header-logo { - color: $text-highlight-color; + &:hover { + background-color: rgba($blue, 0.2); + } } - #sidebar { - background-color: $background-color; + .btn-comment-collapse { + color: $foreground-secondary; + border-color: $border-primary; + + &:hover { + color: $anchor-normal; + } } - .btn-comment-collapse { - color: $text-secondary-color; - border-color: $border-color; + .btn-link { + color: $blue; + background-color: transparent; + border-color: transparent; } - .comment { - border-color: $border-color; + .btn-primary { + color: #fff; + background-color: $blue; + border-color: $blue; - header { - background-color: $background-alt-color; - color: $text-highlight-color; + &:hover { + background-color: darken($blue, 10%); + border-color: darken($blue, 10%); + } + + &:visited { + color: #fff; } } - .comment[data-comment-depth="0"] { - border-color: $border-color; + .btn-used { + color: $violet; + border-color: darken($violet, 3%); + + &:hover { + background-color: darken($violet, 3%); + border-color: darken($violet, 8%); + color: #fff; + } } .comment-branch-counter { - color: $text-secondary-color; + color: $foreground-secondary; } - .comment-nav-link { - color: $text-secondary-color; + .comment-nav-link, .comment-nav-link:visited { + color: $foreground-secondary; } - .label-comment-exemplary { @include specialtag($comment-label-exemplary-color, $is-light); } - .label-comment-joke { @include specialtag($comment-label-joke-color, $is-light); } - .label-comment-noise { @include specialtag($comment-label-noise-color, $is-light); } - .label-comment-offtopic { @include specialtag($comment-label-offtopic-color, $is-light); } - .label-comment-malice { @include specialtag($comment-label-malice-color, $is-light); } + .label-comment-exemplary { @include theme-special-label($comment-label-exemplary-color, $is-light); } + .label-comment-joke { @include theme-special-label($comment-label-joke-color, $is-light); } + .label-comment-noise { @include theme-special-label($comment-label-noise-color, $is-light); } + .label-comment-offtopic { @include theme-special-label($comment-label-offtopic-color, $is-light); } + .label-comment-malice { @include theme-special-label($comment-label-malice-color, $is-light); } %collapsed-theme { header { - background-color: $background-color; + background-color: $background-primary; } } @@ -137,78 +236,134 @@ & > .comment-itself { @extend %collapsed-theme; } - } - .is-comment-deleted, .is-comment-removed { - color: $text-secondary-color; + &:hover { + color: #fff; + background-color: $blue; + border-color: $blue; + } } - .is-comment-new { - .comment-text { - color: $text-highlight-color; + .comment { + border-color: $border-primary; + + header { + color: $foreground-highlight; + background-color: $background-secondary; + } + + &[data-comment-depth="0"] { + border-color: $border-primary; } } - .divider { - border-color: $border-color; + .comment:target > .comment-itself { + border-left-color: $yellow; } - .divider[data-content]::after { - color: $text-color; - background-color: $background-color; + .comment-nav-link { + color: $foreground-secondary; + } + + .divider { + border-color: $border-primary; + + &[data-content]::after { + color: $foreground-primary; + background-color: $background-primary; + } } .empty-subtitle { - color: $text-secondary-color; + color: $foreground-secondary; + } + + .foreground-secondary { + color: $foreground-secondary; } .form-input { - background-color: $input-background-color; - color: $text-color; + color: $foreground-primary; + background-color: $background-input; } .form-input:not(:focus) { - border-color: $border-color; + border-color: $border-primary; } .form-select { - border-color: $border-color; - } + border-color: $border-primary; - .form-select:not([multiple]):not([size]) { - background-color: $input-background-color; + &:not([multiple]):not([size]) { + background-color: $background-input; + } } - .message { - border-color: $border-color; + .form-status-error { + color: $red; + } + .is-comment-collapsed { header { - background-color: $background-alt-color; - color: $text-highlight-color; + color: $foreground-secondary; + background-color: $background-primary; + + .link-user { + color: $foreground-secondary; + } } } .label-topic-tag { - color: $text-mid-color; + color: $foreground-middle; - a { - color: $text-mid-color; + a, + a:hover, + a:visited { + color: $foreground-middle; } } .label-topic-tag-nsfw { - @include specialtag($topic-tag-nsfw-color, $is-light); + @include theme-special-label($topic-tag-nsfw-color, $is-light); } .label-topic-tag-spoiler { - @include specialtag($topic-tag-spoiler-color, $is-light); + @include theme-special-label($topic-tag-spoiler-color, $is-light); + } + + .logged-in-user-username { + color: $foreground-primary; + } + + .message { + border-color: $border-primary; + + header { + color: $foreground-highlight; + background-color: $background-secondary; + } + } + + .nav .nav-item { + a { + color: $anchor-normal; + + &:hover { + color: $anchor-normal-hover; + } + } + + &.active a { + color: $anchor-normal; + } } .post-button { - color: $text-secondary-color; + color: $foreground-secondary; &:hover { - color: $text-extreme-color; + color: $foreground-extreme; } } @@ -216,26 +371,49 @@ color: $violet; } - td { - border-color: $border-color; + .sidebar-controls { + background-color: $background-secondary; } - th { - border-color: $text-highlight-color; + #sidebar { + background-color: $background-primary; } - tbody tr:nth-of-type(2n+1) { - background-color: $background-alt-color; + .site-header-context, + .site-header-username { + color: $foreground-primary; + } + + .site-header-logo { + color: $foreground-highlight; + } + + .site-header-sidebar-button.badge[data-badge]::after { + background-color: $orange; + } + + .tab-listing-order { + border-color: $border-primary; + } + + .tab .tab-item { + a { + color: $foreground-primary; + } + + &.active a { + color: $anchor-normal; + } } .text-secondary { - color: $text-secondary-color; + color: $foreground-secondary; } .toast { - background-color: $background-alt-color; - border-color: $border-color; - color: $text-highlight-color; + color: $foreground-highlight; + border-color: $border-primary; + background-color: $background-secondary; } // Toasts should have colored border + text for dark themes, instead of a @@ -248,42 +426,113 @@ } } + .topic { + border-color: $border-primary; + } + .topic-listing { & > li:nth-of-type(2n) { - background-color: mix($background-color, $background-alt-color); - color: mix($text-color, $text-highlight-color); + color: mix($foreground-primary, $foreground-highlight); + background-color: mix($background-primary, $background-secondary); } } - .topic { - border-color: $border-color; - } - .topic-content-metadata { - color: $text-secondary-color; + color: $foreground-secondary; } .topic-full-byline { - color: $text-secondary-color; + color: $foreground-secondary; } .topic-info { - color: $text-mid-color; + color: $foreground-middle; + } + + .topic-info-comments-new { + color: $orange; } .topic-log-entry-time { - color: $text-secondary-color; + color: $foreground-secondary; } .topic-text-excerpt { - color: $text-secondary-color; + color: $foreground-secondary; summary::after { - color: $text-secondary-color; + color: $foreground-secondary; } &[open] { - color: $text-color; + color: $foreground-primary; + } + } + + .topic-voting.btn-used { + border-color: transparent; + + &:hover { + background-color: darken($blue, 3%); + border-color: darken($blue, 8%); + } + } + + .is-comment-deleted, .is-comment-removed { + color: $foreground-secondary; + } + + .is-comment-mine > .comment-itself { + border-left-color: $violet; + } + + .is-comment-new { + & > .comment-itself { + border-left-color: $orange; + } + + .comment-text { + color: $foreground-highlight; + } + } + + .is-comment-exemplary { + & > .comment-itself { + border-left-color: $comment-label-exemplary-color; + } + } + + .is-message-mine, + .is-topic-mine { + border-left-color: $violet; + } + + .is-topic-official { + border-left-color: $orange; + + h1 { + a, a:visited { + color: $orange; + } + } + } +} + +@mixin theme-special-label($color, $is-light) { + @if $is-light { + background-color: $color; + + a { + color: #fff; + } + } + @else { + background-color: transparent; + color: $color; + border: 1px solid $color; + + a { + color: $color; } } } @@ -435,19 +684,19 @@ } body { - @include theme-dependent($background-color: #fff, $background-alt-color: #eee, $text-color: #333, $text-highlight-color: #222, $text-secondary-color: #999, $border-color: #ccc); + @include use-theme($theme-white); } body.theme-light { - @include theme-dependent($background-color: $bg-lightest, $background-alt-color: $bg-light, $text-color: $fg-dark, $text-highlight-color: $fg-darkest, $text-secondary-color: $fg-lightest, $border-color: #cbc5b6); + @include use-theme($theme-light); } body.theme-dark { - @include theme-dependent($background-color: $bg-darkest, $background-alt-color: $bg-dark, $text-color: $fg-light, $text-highlight-color: $fg-lightest, $text-secondary-color: $fg-darkest, $border-color: #33555e); + @include use-theme($theme-dark); } body.theme-black { - @include theme-dependent($background-color: #000, $background-alt-color: #222, $text-color: #ccc, $text-highlight-color: #ddd, $text-secondary-color: #888, $border-color: #444); + @include use-theme($theme-black); } // Note: if you add a new theme, you may also want to add a new theme-color diff --git a/tildes/scss/modules/_btn.scss b/tildes/scss/modules/_btn.scss index 02be2bb..2525fae 100644 --- a/tildes/scss/modules/_btn.scss +++ b/tildes/scss/modules/_btn.scss @@ -10,12 +10,6 @@ font-size: 0.6rem; font-weight: bold; - - background-color: inherit; - - &:hover { - background-color: rgba($blue, 0.2); - } } .btn.btn-sm { @@ -35,17 +29,6 @@ } } -.btn-used { - border-color: darken($violet, 3%); - color: $violet; - - &:hover { - background-color: darken($violet, 3%); - border-color: darken($violet, 8%); - color: #fff; - } -} - .btn-comment-collapse { @include min-touch-size; @@ -60,10 +43,6 @@ margin-right: 0.2rem; min-width: 0.8rem; } - - &:hover { - color: $blue; - } } .btn-comment-label { diff --git a/tildes/scss/modules/_comment.scss b/tildes/scss/modules/_comment.scss index c2d46b3..304f7c8 100644 --- a/tildes/scss/modules/_comment.scss +++ b/tildes/scss/modules/_comment.scss @@ -19,7 +19,7 @@ } &:target > .comment-itself { - border-left: 3px solid $yellow !important; + border-left: 3px solid; } } @@ -148,7 +148,7 @@ .is-comment-by-op { & > .comment-itself { margin-left: -2px; - border-left: 3px solid !important; + border-left: 3px solid; .comment-user-info { font-weight: bold; @@ -212,14 +212,21 @@ .is-comment-mine { & > .comment-itself { margin-left: -2px; - border-left: 3px solid $violet !important; + border-left: 3px solid; } } .is-comment-new { & > .comment-itself { margin-left: -2px; - border-left: 3px solid $orange !important; + border-left: 3px solid; + } +} + +.is-comment-exemplary { + & > .comment-itself { + margin-left: -2px; + border-left: 3px solid; } } diff --git a/tildes/scss/modules/_form.scss b/tildes/scss/modules/_form.scss index 41e400c..96b225f 100644 --- a/tildes/scss/modules/_form.scss +++ b/tildes/scss/modules/_form.scss @@ -53,10 +53,6 @@ textarea.form-input { font-size: 0.6rem; } -.form-status-error { - color: $red; -} - .form-input { max-width: 40rem; } diff --git a/tildes/scss/modules/_label.scss b/tildes/scss/modules/_label.scss index 7f393fb..4f68746 100644 --- a/tildes/scss/modules/_label.scss +++ b/tildes/scss/modules/_label.scss @@ -8,7 +8,6 @@ .label-comment { font-size: 0.5rem; font-weight: bold; - color: #fff; text-transform: capitalize; } diff --git a/tildes/scss/modules/_link.scss b/tildes/scss/modules/_link.scss index 13b1504..e589d51 100644 --- a/tildes/scss/modules/_link.scss +++ b/tildes/scss/modules/_link.scss @@ -3,8 +3,4 @@ a.link-user, a.link-group { white-space: nowrap; - - &:visited { - color: $blue; - } } diff --git a/tildes/scss/modules/_logged-in-user.scss b/tildes/scss/modules/_logged-in-user.scss index 64db3c7..8cd5d3d 100644 --- a/tildes/scss/modules/_logged-in-user.scss +++ b/tildes/scss/modules/_logged-in-user.scss @@ -19,9 +19,4 @@ .logged-in-user-alert { font-weight: bold; font-size: 0.5rem; - color: $orange; - - &:visited { - color: $orange; - } } diff --git a/tildes/scss/modules/_message.scss b/tildes/scss/modules/_message.scss index 2fb347a..bc75f25 100644 --- a/tildes/scss/modules/_message.scss +++ b/tildes/scss/modules/_message.scss @@ -37,5 +37,5 @@ .is-message-mine { margin-left: -2px; - border-left: 3px solid $violet !important; + border-left: 3px solid; } diff --git a/tildes/scss/modules/_nav.scss b/tildes/scss/modules/_nav.scss index fb4f425..ab9fa09 100644 --- a/tildes/scss/modules/_nav.scss +++ b/tildes/scss/modules/_nav.scss @@ -18,14 +18,12 @@ border-bottom: 0; &.active a { - color: $blue; text-decoration: underline; } } } .nav-item a { - color: $blue; cursor: pointer; &:hover { diff --git a/tildes/scss/modules/_site-header.scss b/tildes/scss/modules/_site-header.scss index 0c84b82..d7d88e5 100644 --- a/tildes/scss/modules/_site-header.scss +++ b/tildes/scss/modules/_site-header.scss @@ -51,7 +51,6 @@ &[data-badge]::after { box-shadow: none; - background-color: $orange; font-size: 0.5rem; height: 0.7rem; transform: translate(50%, -40%); diff --git a/tildes/scss/modules/_topic.scss b/tildes/scss/modules/_topic.scss index 418facc..c0443e1 100644 --- a/tildes/scss/modules/_topic.scss +++ b/tildes/scss/modules/_topic.scss @@ -214,7 +214,6 @@ .topic-info-comments-new { white-space: nowrap; - color: $orange; } .topic-full { @@ -262,17 +261,11 @@ } .is-topic-mine { - border-left: 3px solid $violet !important; + border-left: 3px solid; margin-left: -3px; } .is-topic-official { - border-left: 3px solid $orange !important; + border-left: 3px solid; margin-left: -3px; - - h1 { - a, a:visited { - color: $orange; - } - } }