feat(core): add pure black mode for dark theme

This commit is contained in:
alistair3149 2024-04-25 15:45:24 -04:00
parent 405eef0b9a
commit 5768ccc25b
No known key found for this signature in database
10 changed files with 127 additions and 69 deletions

View file

@ -53,5 +53,10 @@
"citizen-theme-day-label": "Light", "citizen-theme-day-label": "Light",
"citizen-theme-night-label": "Dark", "citizen-theme-night-label": "Dark",
"citizen-theme-os-label": "Auto", "citizen-theme-os-label": "Auto",
"citizen-theme-exclusion-notice": "This page is always in light mode." "citizen-theme-exclusion-notice": "This page is always in light mode.",
"citizen-feature-pure-black-name": "Pure black mode",
"citizen-feature-pure-black-description": "Pure black mode",
"citizen-feature-pure-black-0-label": "Off",
"citizen-feature-pure-black-1-label": "On"
} }

View file

@ -55,5 +55,9 @@
"citizen-theme-day-label": "Label for light/day theme.", "citizen-theme-day-label": "Label for light/day theme.",
"citizen-theme-night-label": "Label for dark/night theme.", "citizen-theme-night-label": "Label for dark/night theme.",
"citizen-theme-os-label": "Label for automatic theme (which respects any operating system setting).", "citizen-theme-os-label": "Label for automatic theme (which respects any operating system setting).",
"citizen-theme-exclusion-notice": "Text that informs you that the page is always in light/day mode." "citizen-theme-exclusion-notice": "Text that informs you that the page is always in light/day mode.",
"citizen-feature-pure-black-name": "Pure black mode",
"citizen-feature-pure-black-description": "Pure black mode",
"citizen-feature-pure-black-0-label": "Off",
"citizen-feature-pure-black-1-label": "On"
} }

View file

@ -148,7 +148,8 @@ class SkinCitizen extends SkinMustache {
* @param array &$options * @param array &$options
*/ */
private function buildSkinFeatures( array &$options ) { private function buildSkinFeatures( array &$options ) {
$title = $this->getOutput()->getTitle(); $out = $this->getOutput();
$title = $out->getTitle();
$metadata = new Metadata( $this ); $metadata = new Metadata( $this );
$skinTheme = new Theme( $this ); $skinTheme = new Theme( $this );
@ -162,6 +163,9 @@ class SkinCitizen extends SkinMustache {
// Disable default ToC since it is handled by Citizen // Disable default ToC since it is handled by Citizen
$options['toc'] = false; $options['toc'] = false;
// Clientprefs feature handling
$out->addHtmlClasses( 'citizen-feature-pure-black-clientpref-0' );
// Collapsible sections // Collapsible sections
// Load in content pages // Load in content pages
if ( $title !== null && $title->isContentPage() ) { if ( $title !== null && $title->isContentPage() ) {

View file

@ -2,5 +2,9 @@
"skin-theme": { "skin-theme": {
"options": [ "os", "day", "night" ], "options": [ "os", "day", "night" ],
"preferenceKey": "citizen-theme" "preferenceKey": "citizen-theme"
},
"citizen-feature-pure-black": {
"options": [ "0", "1" ],
"preferenceKey": "citizen-pure-black"
} }
} }

View file

@ -98,6 +98,18 @@
// New clientPrefs styles // New clientPrefs styles
.citizen-client-prefs { .citizen-client-prefs {
display: flex;
flex-direction: column;
gap: var( --space-xs );
form {
display: grid;
// This is not the best because it does not adapt to the text length but will revisit later
grid-template-columns: 1fr 1fr;
gap: var( --space-xxs );
text-align: center;
}
&-radio { &-radio {
&__input { &__input {
// Hide radio button because we use label as button // Hide radio button because we use label as button
@ -138,15 +150,7 @@
} }
#skin-client-prefs-skin-theme { #skin-client-prefs-skin-theme {
form { .citizen-client-prefs-radio__label {
display: grid;
// This is not the best because it does not adapt to the text length but will revisit later
grid-template-columns: 1fr 1fr;
gap: var( --space-xxs );
text-align: center;
}
label {
background: var( --color-surface-0 ); background: var( --color-surface-0 );
&[ for='skin-client-pref-skin-theme-value-day' ] { &[ for='skin-client-pref-skin-theme-value-day' ] {
@ -165,6 +169,25 @@
} }
} }
#skin-client-prefs-citizen-feature-pure-black {
display: none;
// Display on dark theme
.skin-theme-clientpref-night & {
display: block;
}
@media ( prefers-color-scheme: dark ) {
.skin-theme-clientpref-os & {
display: block;
}
}
.citizen-client-prefs-radio__label[ for='skin-client-pref-citizen-feature-pure-black-value-1' ] {
background-color: #000;
}
}
@media ( hover: hover ) { @media ( hover: hover ) {
.citizen-pref:hover .citizen-pref__button .citizen-ui-icon::before { .citizen-pref:hover .citizen-pref__button .citizen-ui-icon::before {
transform: rotate3d( 0, 0, 1, 90deg ); transform: rotate3d( 0, 0, 1, 90deg );

View file

@ -11,7 +11,7 @@
<aside id="citizen-pref-panel" class="citizen-pref-panel"> <aside id="citizen-pref-panel" class="citizen-pref-panel">
<header id="citizen-pref-header">{{msg-preferences}}</header> <header id="citizen-pref-header">{{msg-preferences}}</header>
<div id="citizen-client-prefs"></div> <div class="citizen-client-prefs" id="citizen-client-prefs"></div>
<form id="citizen-pref-form"> <form id="citizen-pref-form">
{{! Font size }} {{! Font size }}
<fieldset class="citizen-pref-item" id="citizen-pref-fontsize"> <fieldset class="citizen-pref-item" id="citizen-pref-fontsize">

View file

@ -0,0 +1,11 @@
.citizen-feature-pure-black-clientpref-1 {
:root.skin-theme-clientpref-night& {
--color-surface-0: #000;
}
@media ( prefers-color-scheme: dark ) {
:root.skin-theme-clientpref-os& {
--color-surface-0: #000;
}
}
}

View file

@ -1,3 +1,49 @@
/**
* Dark theme mixin
* Dark theme needs a mixin because it is being used by the auto theme as well
*/
.theme-dark() {
--color-primary__l: 60%;
--color-surface-0: ~'hsl( var( --color-primary__h ), 20%, 10% )';
--color-surface-1: ~'hsl( var( --color-primary__h ), 25%, 12% )';
--color-surface-2: ~'hsl( var( --color-primary__h ), 25%, 15% )';
--color-surface-3: ~'hsl( var( --color-primary__h ), 15%, 20% )';
--color-surface-4: ~'hsl( var( --color-primary__h ), 15%, 25% )';
--color-base--emphasized: ~'hsl( var( --color-primary__h ), 80%, 95% )';
--color-base: ~'hsl( var( --color-primary__h ), 25%, 80% )';
--color-base--subtle: ~'hsl( var( --color-primary__h ), 25%, 65% )';
--background-color-primary--hover: ~'hsl( var( --color-primary__h ), var( --color-primary__s ), 15% )';
--background-color-primary--active: ~'hsl( var( --color-primary__h ), var( --color-primary__s ), 20% )';
--background-color-overlay: ~'hsla( var( --color-primary__h ), 20%, 10%, 0.95 )';
--background-color-overlay--lighter: ~'hsla( var( --color-primary__h ), 20%, 10%, 0.6 )';
--color-surface-2--hover: ~'hsl( var( --color-primary__h ), 30%, 19% )';
--color-surface-2--active: ~'hsl( var( --color-primary__h ), 30%, 11% )';
--border-color-base: rgba( 255, 255, 255, 0.05 );
--border-color-subtle: rgba( 255, 255, 255, 0.02 );
--border-color-interactive: rgba( 255, 255, 255, 0.08 );
--surface-shadow: var( --color-primary__h ), 50%, 3%;
--shadow-strength: 0.8;
--filter-invert: invert( 1 ) hue-rotate( 180deg );
--font-grade: -25;
// FIXME: Browsers seem to treat GRAD differently, disabling for now
// Dark theme usually have an illusion of thicker fonts
// So we have to tune it back
// font-variation-settings: 'GRAD' -90;
color-scheme: dark;
}
/** /**
* Base/light theme * Base/light theme
*/ */
@ -47,6 +93,18 @@
--shadow-strength: 0.02; --shadow-strength: 0.02;
--font-grade: 0; --font-grade: 0;
// Dark theme
&.skin-theme-clientpref-night {
.theme-dark();
}
// Auto theme
@media ( prefers-color-scheme: dark ) {
&.skin-theme-clientpref-os {
.theme-dark();
}
}
} }
a { a {
@ -54,58 +112,3 @@ a {
--color-link--hover: ~'var( --color-primary--hover )'; --color-link--hover: ~'var( --color-primary--hover )';
--color-link--active: ~'var( --color-primary--active )'; --color-link--active: ~'var( --color-primary--active )';
} }
/**
* Dark theme
* Dark theme needs a mixin because it is being used by the auto theme as well
*/
.theme-dark() {
--color-primary__l: 60%;
--color-surface-0: ~'hsl( var( --color-primary__h ), 20%, 10% )';
--color-surface-1: ~'hsl( var( --color-primary__h ), 25%, 12% )';
--color-surface-2: ~'hsl( var( --color-primary__h ), 25%, 15% )';
--color-surface-3: ~'hsl( var( --color-primary__h ), 15%, 20% )';
--color-surface-4: ~'hsl( var( --color-primary__h ), 15%, 25% )';
--color-base--emphasized: ~'hsl( var( --color-primary__h ), 80%, 95% )';
--color-base: ~'hsl( var( --color-primary__h ), 25%, 80% )';
--color-base--subtle: ~'hsl( var( --color-primary__h ), 25%, 65% )';
--background-color-primary--hover: ~'hsl( var( --color-primary__h ), var( --color-primary__s ), 15% )';
--background-color-primary--active: ~'hsl( var( --color-primary__h ), var( --color-primary__s ), 20% )';
--background-color-overlay: ~'hsla( var( --color-primary__h ), 20%, 10%, 0.95 )';
--background-color-overlay--lighter: ~'hsla( var( --color-primary__h ), 20%, 10%, 0.6 )';
--color-surface-2--hover: ~'hsl( var( --color-primary__h ), 30%, 19% )';
--color-surface-2--active: ~'hsl( var( --color-primary__h ), 30%, 11% )';
--border-color-base: rgba( 255, 255, 255, 0.05 );
--border-color-subtle: rgba( 255, 255, 255, 0.02 );
--border-color-interactive: rgba( 255, 255, 255, 0.08 );
--surface-shadow: var( --color-primary__h ), 50%, 3%;
--shadow-strength: 0.8;
--filter-invert: invert( 1 ) hue-rotate( 180deg );
--font-grade: -25;
// FIXME: Browsers seem to treat GRAD differently, disabling for now
// Dark theme usually have an illusion of thicker fonts
// So we have to tune it back
// font-variation-settings: 'GRAD' -90;
color-scheme: dark;
}
:root.skin-theme-clientpref-night {
.theme-dark();
}
@media ( prefers-color-scheme: dark ) {
:root.skin-theme-clientpref-os {
.theme-dark();
}
}

View file

@ -18,6 +18,7 @@
@media screen { @media screen {
@import 'layout.less'; @import 'layout.less';
@import 'common/theme.less'; @import 'common/theme.less';
@import 'common/features.less';
@import 'common/common.less'; @import 'common/common.less';
@import 'common/content.less'; @import 'common/content.less';
@import 'common/scrollbar.less'; @import 'common/scrollbar.less';

View file

@ -246,7 +246,10 @@
"citizen-theme-day-label", "citizen-theme-day-label",
"citizen-theme-night-label", "citizen-theme-night-label",
"citizen-theme-os-label", "citizen-theme-os-label",
"citizen-theme-exclusion-notice" "citizen-theme-exclusion-notice",
"citizen-feature-pure-black-name",
"citizen-feature-pure-black-0-label",
"citizen-feature-pure-black-1-label"
], ],
"dependencies": [ "dependencies": [
"mediawiki.storage", "mediawiki.storage",