UX: Makes splash dots use theme colors (#17388)

The dots in the splash were previously hard-coded (v1). This PR makes progress towards making them be based on current theme colors.

Note that this is an improvement and not the "final" version. We're going to dynamically generate the splash file and the base64 URL later on.
This commit is contained in:
Joe 2022-07-08 22:30:59 +08:00 committed by GitHub
parent 9408ea4461
commit 2750049333
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 137 additions and 91 deletions

View File

@ -1,5 +1,116 @@
<%- unless customization_disabled? %> <%- unless customization_disabled? %>
<section id="d-splash"> <section id="d-splash">
<template class="splash-svg-template">
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
>
<style>
:root {
--animation-state: paused;
--primary: #<%= ColorScheme.hex_for_name("primary", scheme_id) %>;
--secondary: #<%= ColorScheme.hex_for_name("secondary", scheme_id) %>;
--tertiary: #<%= ColorScheme.hex_for_name("tertiary", scheme_id) %>;
--quaternary: #<%= ColorScheme.hex_for_name("quaternary", scheme_id) %>;
--highlight: #<%= ColorScheme.hex_for_name("highlight", scheme_id) %>;
--success: #<%= ColorScheme.hex_for_name("success", scheme_id) %>;
}
@media (prefers-color-scheme: dark) {
:root {
--animation-state: paused;
--primary: #<%= ColorScheme.hex_for_name("primary", dark_scheme_id) %>;
--secondary: #<%= ColorScheme.hex_for_name(
"secondary",
dark_scheme_id
) %>;
--tertiary: #<%= ColorScheme.hex_for_name(
"tertiary",
dark_scheme_id
) %>;
--quaternary: #<%= ColorScheme.hex_for_name(
"quaternary",
dark_scheme_id
) %>;
--highlight: #<%= ColorScheme.hex_for_name(
"highlight",
dark_scheme_id
) %>;
--success: #<%= ColorScheme.hex_for_name("success", dark_scheme_id) %>;
}
}
/* these styles need to live here because the SVG has a different scope */
.dots {
animation-name: loader;
animation-timing-function: ease-in-out;
animation-duration: 3s;
animation-iteration-count: infinite;
animation-play-state: var(--animation-state);
stroke: #fff;
stroke-width: 0.5px;
transform-origin: center;
opacity: 0;
r: max(1vw, 11px);
cy: 50%;
filter: saturate(2) opacity(0.85);
}
.dots:first-child {
fill: var(--quaternary);
}
.dots:nth-child(2) {
fill: var(--quaternary);
animation-delay: 0.15s;
}
.dots:nth-child(3) {
fill: var(--highlight);
animation-delay: 0.3s;
}
.dots:nth-child(4) {
fill: var(--tertiary);
animation-delay: 0.45s;
}
.dots:nth-child(5) {
fill: var(--tertiary);
animation-delay: 0.6s;
}
@keyframes loader {
0% {
opacity: 0;
transform: scale(1);
}
45% {
opacity: 1;
transform: scale(0.7);
}
65% {
opacity: 1;
transform: scale(0.7);
}
100% {
opacity: 0;
transform: scale(1);
}
}
</style>
<g class="container">
<circle class="dots" cx="30vw" />
<circle class="dots" cx="40vw" />
<circle class="dots" cx="50vw" />
<circle class="dots" cx="60vw" />
<circle class="dots" cx="70vw" />
</g>
</svg>
</template>
<style> <style>
html { html {
overflow-y: hidden !important; overflow-y: hidden !important;
@ -9,7 +120,7 @@
display: grid; display: grid;
place-items: center; place-items: center;
backface-visibility: hidden; backface-visibility: hidden;
background: var(--secondary); background: #<%= ColorScheme.hex_for_name("secondary", scheme_id) %>;
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
@ -30,7 +141,7 @@
animation-delay: 1s; animation-delay: 1s;
animation-fill-mode: forwards; animation-fill-mode: forwards;
animation-play-state: var(--animation-state); animation-play-state: var(--animation-state);
color: var(--primary); color: #<%= ColorScheme.hex_for_name("primary", scheme_id) %>;
margin-bottom: -4em; margin-bottom: -4em;
} }
@ -70,11 +181,20 @@
content: "..."; content: "...";
} }
} }
@media (prefers-color-scheme: dark) {
#d-splash {
background: #<%= ColorScheme.hex_for_name("secondary", dark_scheme_id) %>;
}
#d-splash .preloader-text-wrapper {
color: #<%= ColorScheme.hex_for_name("primary", dark_scheme_id) %>;
}
}
</style> </style>
<img <img
class="preloader-image" class="preloader-image"
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1'%0A%3E%3Cstyle%3E /* these need to be injected dynamicly to match theme colors */ :root %7B --primary: %23222222; --secondary: %23ffffff; --tertiary: %23f15c21; --highlight: %23f0ea88; --quaternary: %2365ccff; --success: %23009900; --animation-state: paused; %7D /* these styles need to live here because the SVG has a different scope */ .dots %7B animation-name: loader; animation-timing-function: ease-in-out; animation-duration: 3s; animation-iteration-count: infinite; animation-play-state: var(--animation-state); stroke: %23fff; stroke-width: 0.5px; transform-origin: center; opacity: 0; r: max(1vw, 11px); cy: 50%25; %7D .dots:first-child %7B fill: var(--tertiary); %7D .dots:nth-child(2) %7B fill: var(--tertiary); animation-delay: 0.15s; %7D .dots:nth-child(3) %7B fill: var(--highlight); animation-delay: 0.3s; %7D .dots:nth-child(4) %7B fill: var(--quaternary); animation-delay: 0.45s; %7D .dots:nth-child(5) %7B fill: var(--quaternary); animation-delay: 0.6s; %7D @keyframes loader %7B 0%25 %7B opacity: 0; transform: scale(1); %7D 45%25 %7B opacity: 1; transform: scale(0.7); %7D 65%25 %7B opacity: 1; transform: scale(0.7); %7D 100%25 %7B opacity: 0; transform: scale(1); %7D %7D %3C/style%3E%3Cg class='container'%3E%3Ccircle class='dots' cx='30vw' /%3E%3Ccircle class='dots' cx='40vw' /%3E%3Ccircle class='dots' cx='50vw' /%3E%3Ccircle class='dots' cx='60vw' /%3E%3Ccircle class='dots' cx='70vw' /%3E%3C/g%3E%3C/svg%3E%0A" src="data:image/svg;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
alt="<%=SiteSetting.title%>" alt="<%=SiteSetting.title%>"
/> />
@ -98,10 +218,19 @@
const DELAY_TARGET = 2000; const DELAY_TARGET = 2000;
const POLLING_INTERVAL = 50; const POLLING_INTERVAL = 50;
const splashSvgTemplate = document.querySelector(".splash-svg-template");
const splashTemplateClone = splashSvgTemplate.content.cloneNode(true);
const svgElement = splashTemplateClone.querySelector("svg");
const svgString = new XMLSerializer().serializeToString(svgElement);
const encodedSvg = btoa(svgString);
const splashWrapper = document.querySelector("#d-splash"); const splashWrapper = document.querySelector("#d-splash");
const splashImage = splashWrapper?.querySelector(".preloader-image"); const splashImage = splashWrapper?.querySelector(".preloader-image");
if (splashImage) { if (splashImage) {
splashImage.src = `data:image/svg+xml;base64,${encodedSvg}`;
const connectStart = performance?.timing?.connectStart || 0; const connectStart = performance?.timing?.connectStart || 0;
const splashDelay = connectStart ? DELAY_TARGET : 0; const splashDelay = connectStart ? DELAY_TARGET : 0;
const targetTime = connectStart + DELAY_TARGET; const targetTime = connectStart + DELAY_TARGET;
@ -111,11 +240,12 @@
const swapSplash = () => { const swapSplash = () => {
splashWrapper?.style.setProperty("--animation-state", "running"); splashWrapper?.style.setProperty("--animation-state", "running");
svgElement?.style.setProperty("--animation-state", "running");
splashImage.src = splashImage.src.replace( const newSvgString = new XMLSerializer().serializeToString(svgElement);
"--animation-state: paused;", const newEncodedSvg = btoa(newSvgString);
"--animation-state: running;"
); splashImage.src = `data:image/svg+xml;base64,${newEncodedSvg}`;
performance.mark("discourse-splash-visible"); performance.mark("discourse-splash-visible");

View File

@ -1,84 +0,0 @@
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
>
<style>
/* these need to be injected dynamicly to match theme colors */
:root {
--primary: #222222;
--secondary: #ffffff;
--tertiary: #f15c21;
--highlight: #f0ea88;
--quaternary: #65ccff;
--success: #009900;
--animation-state: paused;
}
/* these styles need to live here because the SVG has a different scope */
.dots {
animation-name: loader;
animation-timing-function: ease-in-out;
animation-duration: 3s;
animation-iteration-count: infinite;
animation-play-state: var(--animation-state);
stroke: #fff;
stroke-width: 0.5px;
transform-origin: center;
opacity: 0;
r: max(1vw, 11px);
cy: 50%;
}
.dots:first-child {
fill: var(--tertiary);
}
.dots:nth-child(2) {
fill: var(--tertiary);
animation-delay: 0.15s;
}
.dots:nth-child(3) {
fill: var(--highlight);
animation-delay: 0.3s;
}
.dots:nth-child(4) {
fill: var(--quaternary);
animation-delay: 0.45s;
}
.dots:nth-child(5) {
fill: var(--quaternary);
animation-delay: 0.6s;
}
@keyframes loader {
0% {
opacity: 0;
transform: scale(1);
}
45% {
opacity: 1;
transform: scale(0.7);
}
65% {
opacity: 1;
transform: scale(0.7);
}
100% {
opacity: 0;
transform: scale(1);
}
}
</style>
<g class="container">
<circle class="dots" cx="30vw" />
<circle class="dots" cx="40vw" />
<circle class="dots" cx="50vw" />
<circle class="dots" cx="60vw" />
<circle class="dots" cx="70vw" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB