Improve the loading experience of the newsfeed in dark mode
authorTim Düsterhus <duesterhus@woltlab.com>
Thu, 13 Jul 2023 12:59:39 +0000 (14:59 +0200)
committerTim Düsterhus <duesterhus@woltlab.com>
Thu, 13 Jul 2023 13:03:48 +0000 (15:03 +0200)
The default page of an `<iframe>` is `about:blank` which has a light background
color. In case the newsfeed loads slowly or fails to load entirely, there will
be a big white block in a dark mode ACP which looks odd.

Fix this issue by setting the `<iframe>` to be `visibility: hidden` until the
contents are available. Additionally a spinner is shown while the iframe is
hidden.

wcfsetup/install/files/acp/style/layout.scss
wcfsetup/install/files/acp/templates/index.tpl

index d3a549056374e2fd066850dc7a463a7c0e5cc83e..0cb42d13771c204aac1010b5046f5a17742ba83d 100644 (file)
@@ -870,10 +870,24 @@ html[data-color-scheme="dark"] {
        }
 }
 
-#woltlab_newsfeed {
+.woltlabNewsfeed__loading {
+       text-align: center;
+       width: 600px;
+}
+
+.woltlabNewsfeed.loaded .woltlabNewsfeed__loading {
+       display: none;
+}
+
+.woltlabNewsfeed__iframe {
        border: 1px solid var(--wcfContentBorderInner);
        border-radius: var(--wcfBorderRadius);
        height: 100vh;
        max-width: 100%;
+       visibility: hidden;
        width: 600px;
 }
+
+.woltlabNewsfeed.loaded .woltlabNewsfeed__iframe {
+       visibility: visible;
+}
index 7214cb2ef72f13dd8a8fd149e10240ae227a618a..b7b258e9f4d5982778dd31b443f9a4a91dce2aae 100644 (file)
        {if ENABLE_WOLTLAB_NEWS}
                <div id="news" class="hidden tabMenuContent">
                        <div class="section">
-                               <iframe
-                                       id="woltlab_newsfeed"
-                                       referrerpolicy="no-referrer"
-                                       sandbox
-                                       hidden
-                               ></iframe>
+                               <div class="woltlabNewsfeed">
+                                       <div class="woltlabNewsfeed__loading">{icon name='spinner' size=64}</div>
+                                       <iframe
+                                               class="woltlabNewsfeed__iframe"
+                                               referrerpolicy="no-referrer"
+                                               sandbox
+                                       ></iframe>
+                               </div>
+
                                <script data-eager="true">
                                {
                                        const languageCode = "{if $__wcf->language->languageCode === 'de'}de{else}en{/if}";
                                        let colorScheme = document.documentElement.dataset.colorScheme;
-                                       const iframe = document.getElementById("woltlab_newsfeed");
+                                       const container = document.querySelector('.woltlabNewsfeed');
+                                       const iframe = container.querySelector(".woltlabNewsfeed__iframe");
 
                                        const updateColorScheme = () => {
+                                               container.classList.remove('loaded');
                                                iframe.src = `https://newsfeed.woltlab.com/${ languageCode }_${ colorScheme }.html`;
+                                               iframe.addEventListener(
+                                                       'load',
+                                                       () => container.classList.add('loaded'),
+                                                       { once: true }
+                                               );
                                        };
 
                                        const observer = new MutationObserver(() => {
@@ -84,7 +94,6 @@
                                        });
 
                                        updateColorScheme();
-                                       iframe.hidden = false;
                                }
                                </script>
                        </div>