Skip to content
Snippets Groups Projects
Verified Commit e36422dd authored by Lauri Timmanee's avatar Lauri Timmanee
Browse files

Issue #3355381 by catch, drewcking, stewest, bnjmnm, lmoeni, fngatia,...

Issue #3355381 by catch, drewcking, stewest, bnjmnm, lmoeni, fngatia, kevinquillen, Danny Englander, Ambient.Impact, gapple, manikandank03, lucasvm: Investigate better ways to add anti-flicker JS

(cherry picked from commit 56e2560a)
parent 19f1dbc0
Branches
Tags
19 merge requests!11628Update file MediaLibraryWidget.php,!7564Revert "Issue #3364773 by roshnichordiya, Chris Matthews, thakurnishant_06,...,!5752Issue #3275828 by joachim, quietone, bradjones1, Berdir: document the reason...,!5627Issue #3261805: Field not saved when change of 0 on string start,!5427Issue #3338518: send credentials in ajax if configured in CORS settings.,!5395Issue #3387916 by fjgarlin, Spokje: Each GitLab job exposes user email,!5217Issue #3386607 by alexpott: Improve spell checking in commit-code-check.sh,!5064Issue #3379522 by finnsky, Gauravvvv, kostyashupenko, smustgrave, Chi: Revert...,!5040SDC ComponentElement: Transform slots scalar values to #plain_text instead of throwing an exception,!4958Issue #3392147: Whitelist IP for a Ban module.,!4894Issue #3280279: Add API to allow sites to opt in to upload SVG images in CKEditor 5,!4857Issue #3336994: StringFormatter always displays links to entity even if the user in context does not have access,!4856Issue #3336994: StringFormatter always displays links to entity even if the user in context does not have access,!4788Issue #3272985: RSS Feed header reverts to text/html when cached,!4716Issue #3362929: Improve 400 responses for broken/invalid image style routes,!3679Issue #115801: Allow password on registration without disabling e-mail verification,!3106Issue #3017548: "Filtered HTML" text format does not support manual teaser break (<!--break-->),!925Issue #2339235: Remove taxonomy hard dependency on node module,!872Draft: Issue #3221319: Race condition when creating menu links and editing content deletes menu links
/**
* @file
* Prevents flicker of the toolbar on page load.
*/
(() => {
const toolbarState = sessionStorage.getItem('Drupal.toolbar.toolbarState')
? JSON.parse(sessionStorage.getItem('Drupal.toolbar.toolbarState'))
: false;
// These are classes that toolbar typically adds to <body>, but this code
// executes before the first paint, when <body> is not yet present. The
// classes are added to <html> so styling immediately reflects the current
// toolbar state. The classes are removed after the toolbar completes
// initialization.
const classesToAdd = ['toolbar-loading', 'toolbar-anti-flicker'];
if (toolbarState) {
const {
orientation,
hasActiveTab,
isFixed,
activeTray,
activeTabId,
isOriented,
userButtonMinWidth,
} = toolbarState;
classesToAdd.push(
orientation ? `toolbar-${orientation}` : 'toolbar-horizontal',
);
if (hasActiveTab !== false) {
classesToAdd.push('toolbar-tray-open');
}
if (isFixed) {
classesToAdd.push('toolbar-fixed');
}
if (isOriented) {
classesToAdd.push('toolbar-oriented');
}
if (activeTray) {
// These styles are added so the active tab/tray styles are present
// immediately instead of "flickering" on as the toolbar initializes. In
// instances where a tray is lazy loaded, these styles facilitate the
// lazy loaded tray appearing gracefully and without reflow.
const styleContent = `
.toolbar-loading #${activeTabId} {
background-image: linear-gradient(rgba(255, 255, 255, 0.25) 20%, transparent 200%);
}
.toolbar-loading #${activeTabId}-tray {
display: block; box-shadow: -1px 0 5px 2px rgb(0 0 0 / 33%);
border-right: 1px solid #aaa; background-color: #f5f5f5;
z-index: 0;
}
.toolbar-loading.toolbar-vertical.toolbar-tray-open #${activeTabId}-tray {
width: 15rem; height: 100vh;
}
.toolbar-loading.toolbar-horizontal :not(#${activeTray}) > .toolbar-lining {opacity: 0}`;
const style = document.createElement('style');
style.textContent = styleContent;
style.setAttribute('data-toolbar-anti-flicker-loading', true);
document.querySelector('head').appendChild(style);
if (userButtonMinWidth) {
const userButtonStyle = document.createElement('style');
userButtonStyle.textContent = `
#toolbar-item-user {min-width: ${userButtonMinWidth}.px;}`;
document.querySelector('head').appendChild(userButtonStyle);
}
}
}
document.querySelector('html').classList.add(...classesToAdd);
})();
......@@ -28,6 +28,7 @@ toolbar:
- core/once
- core/drupal.displace
- toolbar/toolbar.menu
- toolbar/toolbar.anti-flicker
toolbar.menu:
version: VERSION
......@@ -50,3 +51,9 @@ toolbar.escapeAdmin:
- core/drupal
- core/drupalSettings
- core/once
toolbar.anti-flicker:
# Block the page from being loaded until anti-flicker is initialized.
version: VERSION
header: true
js:
js/toolbar.anti-flicker.js: {}
......@@ -7,7 +7,6 @@
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\Markup;
use Drupal\Core\Render\RenderContext;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Template\Attribute;
......@@ -49,101 +48,6 @@ function toolbar_theme($existing, $type, $theme, $path) {
return $items;
}
/**
* Implements hook_page_attachments().
*/
function toolbar_page_attachments(array &$page) {
// This JavaScript code provides temporary styles while the toolbar loads, so
// it better visually resembles the appearance it will have once fully loaded.
// @todo investigate potential alternatives to this approach in
// https://www.drupal.org/i/3355381
$anti_flicker_js = <<<JS
(function() {
const toolbarState = sessionStorage.getItem('Drupal.toolbar.toolbarState')
? JSON.parse(sessionStorage.getItem('Drupal.toolbar.toolbarState'))
: false;
// These are classes that toolbar typically adds to <body>, but this code
// executes before the first paint, when <body> is not yet present. The
// classes are added to <html> so styling immediately reflects the current
// toolbar state. The classes are removed after the toolbar completes
// initialization.
const classesToAdd = ['toolbar-loading', 'toolbar-anti-flicker'];
if (toolbarState) {
const {
orientation,
hasActiveTab,
isFixed,
activeTray,
activeTabId,
isOriented,
userButtonMinWidth
} = toolbarState;
classesToAdd.push(
orientation ? `toolbar-` + orientation + `` : 'toolbar-horizontal',
);
if (hasActiveTab !== false) {
classesToAdd.push('toolbar-tray-open');
}
if (isFixed) {
classesToAdd.push('toolbar-fixed');
}
if (isOriented) {
classesToAdd.push('toolbar-oriented');
}
if (activeTray) {
// These styles are added so the active tab/tray styles are present
// immediately instead of "flickering" on as the toolbar initializes. In
// instances where a tray is lazy loaded, these styles facilitate the
// lazy loaded tray appearing gracefully and without reflow.
const styleContent = `
.toolbar-loading #` + activeTabId + ` {
background-image: linear-gradient(rgba(255, 255, 255, 0.25) 20%, transparent 200%);
}
.toolbar-loading #` + activeTabId + `-tray {
display: block; box-shadow: -1px 0 5px 2px rgb(0 0 0 / 33%);
border-right: 1px solid #aaa; background-color: #f5f5f5;
z-index: 0;
}
.toolbar-loading.toolbar-vertical.toolbar-tray-open #` + activeTabId + `-tray {
width: 15rem; height: 100vh;
}
.toolbar-loading.toolbar-horizontal :not(#` + activeTray + `) > .toolbar-lining {opacity: 0}`;
const style = document.createElement('style');
style.textContent = styleContent;
style.setAttribute('data-toolbar-anti-flicker-loading', true);
document.querySelector('head').appendChild(style);
if (userButtonMinWidth) {
const userButtonStyle = document.createElement('style');
userButtonStyle.textContent = `#toolbar-item-user {min-width: ` + userButtonMinWidth +`px;}`
document.querySelector('head').appendChild(userButtonStyle);
}
}
}
document.querySelector('html').classList.add(...classesToAdd);
})();
JS;
// The anti flicker javascript is added as an inline tag so it is executed
// as early as possible. This enables it to add classes that prevent
// flickering before the first paint.
$page['#attached']['html_head'][] = [
[
'#tag' => 'script',
'#attributes' => [
'type' => 'text/javascript',
'data-toolbar-anti-flicker-loading' => TRUE,
],
// Process through Markup to prevent character escaping.
'#value' => Markup::create($anti_flicker_js),
],
'anti_flicker_js',
];
}
/**
* Implements hook_page_top().
*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment