From d979b8f0a82c12f2a844c429982207c88fe13ae6 Mon Sep 17 00:00:00 2001 From: Erika <3019731+Princesseuh@users.noreply.github.com> Date: Wed, 8 Nov 2023 08:37:35 +0100 Subject: [PATCH 01/27] feat(overlay): Match the design's animations, shadows and general styling (#9014) --- .changeset/rude-eggs-hunt.md | 5 + packages/astro/src/@types/astro.ts | 1 + .../runtime/client/dev-overlay/entrypoint.ts | 4 +- .../src/runtime/client/dev-overlay/overlay.ts | 80 +++++++---- .../client/dev-overlay/plugins/astro.ts | 58 ++++++-- .../client/dev-overlay/plugins/audit.ts | 124 +++++++++++++++--- .../client/dev-overlay/plugins/xray.ts | 26 ++++ .../client/dev-overlay/ui-library/card.ts | 2 + .../client/dev-overlay/ui-library/icons.ts | 5 + .../client/dev-overlay/ui-library/tooltip.ts | 1 + .../client/dev-overlay/ui-library/window.ts | 1 + 11 files changed, 251 insertions(+), 56 deletions(-) create mode 100644 .changeset/rude-eggs-hunt.md diff --git a/.changeset/rude-eggs-hunt.md b/.changeset/rude-eggs-hunt.md new file mode 100644 index 000000000000..4bbe7c9c9004 --- /dev/null +++ b/.changeset/rude-eggs-hunt.md @@ -0,0 +1,5 @@ +--- +"astro": patch +--- + +Add animations, shadows and general styling tweaks to the Dev Overlay to better match the intended design. diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 4ae5e7138656..dfeb7ee80f68 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -2318,6 +2318,7 @@ export interface DevOverlayPlugin { name: string; icon: Icon; init?(canvas: ShadowRoot, eventTarget: EventTarget): void | Promise; + beforeTogglingOff?(canvas: ShadowRoot): boolean | Promise; } export type DevOverlayMetadata = Window & diff --git a/packages/astro/src/runtime/client/dev-overlay/entrypoint.ts b/packages/astro/src/runtime/client/dev-overlay/entrypoint.ts index 61c5e779bf6c..7336f9d06673 100644 --- a/packages/astro/src/runtime/client/dev-overlay/entrypoint.ts +++ b/packages/astro/src/runtime/client/dev-overlay/entrypoint.ts @@ -63,13 +63,13 @@ document.addEventListener('DOMContentLoaded', async () => { target.querySelector('.notification')?.toggleAttribute('data-active', newState); }); - eventTarget.addEventListener('toggle-plugin', (evt) => { + eventTarget.addEventListener('toggle-plugin', async (evt) => { let newState = undefined; if (evt instanceof CustomEvent) { newState = evt.detail.state ?? true; } - overlay.togglePluginStatus(plugin, newState); + await overlay.togglePluginStatus(plugin, newState); }); return plugin; diff --git a/packages/astro/src/runtime/client/dev-overlay/overlay.ts b/packages/astro/src/runtime/client/dev-overlay/overlay.ts index 50b015ca12bd..e0ab02e481a7 100644 --- a/packages/astro/src/runtime/client/dev-overlay/overlay.ts +++ b/packages/astro/src/runtime/client/dev-overlay/overlay.ts @@ -51,7 +51,7 @@ export class AstroDevOverlay extends HTMLElement { display: flex; gap: 8px; align-items: center; - transition: bottom 0.2s ease-in-out; + transition: bottom 0.35s cubic-bezier(0.485, -0.050, 0.285, 1.505); pointer-events: none; } @@ -72,11 +72,10 @@ export class AstroDevOverlay extends HTMLElement { height: 56px; overflow: hidden; pointer-events: auto; - background: linear-gradient(180deg, #13151A 0%, rgba(19, 21, 26, 0.88) 100%); - box-shadow: 0px 0px 0px 0px #13151A4D; border: 1px solid #343841; border-radius: 9999px; + box-shadow: 0px 0px 0px 0px rgba(19, 21, 26, 0.30), 0px 1px 2px 0px rgba(19, 21, 26, 0.29), 0px 4px 4px 0px rgba(19, 21, 26, 0.26), 0px 10px 6px 0px rgba(19, 21, 26, 0.15), 0px 17px 7px 0px rgba(19, 21, 26, 0.04), 0px 26px 7px 0px rgba(19, 21, 26, 0.01); } #dev-bar .item { @@ -187,16 +186,6 @@ export class AstroDevOverlay extends HTMLElement { width: 1px; } - astro-dev-overlay-plugin-canvas { - position: absolute; - top: 0; - left: 0; - } - - astro-dev-overlay-plugin-canvas:not([data-active]) { - display: none; - } - #minimize-button { width: 32px; height: 32px; @@ -263,7 +252,7 @@ export class AstroDevOverlay extends HTMLElement { } // Create plugin canvases - this.plugins.forEach((plugin) => { + this.plugins.forEach(async (plugin) => { if (!this.hasBeenInitialized) { console.log(`Creating plugin canvas for ${plugin.id}`); const pluginCanvas = document.createElement('astro-dev-overlay-plugin-canvas'); @@ -271,7 +260,7 @@ export class AstroDevOverlay extends HTMLElement { this.shadowRoot?.append(pluginCanvas); } - this.togglePluginStatus(plugin, plugin.active); + await this.togglePluginStatus(plugin, plugin.active); }); // Init plugin lazily - This is safe to do here because only plugins that are not initialized yet will be affected @@ -306,7 +295,7 @@ export class AstroDevOverlay extends HTMLElement { await this.initPlugin(plugin); } - this.togglePluginStatus(plugin); + await this.togglePluginStatus(plugin); }); }); @@ -418,30 +407,52 @@ export class AstroDevOverlay extends HTMLElement { } getPluginCanvasById(id: string) { - return this.shadowRoot.querySelector(`astro-dev-overlay-plugin-canvas[data-plugin-id="${id}"]`); + return this.shadowRoot.querySelector( + `astro-dev-overlay-plugin-canvas[data-plugin-id="${id}"]` + ); } - togglePluginStatus(plugin: DevOverlayPlugin, status?: boolean) { - plugin.active = status ?? !plugin.active; + /** + * @param plugin The plugin to toggle the status of + * @param newStatus Optionally, force the plugin into a specific state + */ + async togglePluginStatus(plugin: DevOverlayPlugin, newStatus?: boolean) { + const pluginCanvas = this.getPluginCanvasById(plugin.id); + if (!pluginCanvas) return; + + if (plugin.active && !newStatus && plugin.beforeTogglingOff) { + const shouldToggleOff = await plugin.beforeTogglingOff(pluginCanvas.shadowRoot!); + + // If the plugin returned false, don't toggle it off, maybe the plugin showed a confirmation dialog or similar + if (!shouldToggleOff) return; + } + + plugin.active = newStatus ?? !plugin.active; const target = this.shadowRoot.querySelector(`[data-plugin-id="${plugin.id}"]`); if (!target) return; target.classList.toggle('active', plugin.active); - this.getPluginCanvasById(plugin.id)?.toggleAttribute('data-active', plugin.active); - - plugin.eventTarget.dispatchEvent( - new CustomEvent('plugin-toggled', { - detail: { - state: plugin.active, - plugin, - }, - }) - ); + pluginCanvas.style.display = plugin.active ? 'block' : 'none'; + + window.requestAnimationFrame(() => { + pluginCanvas.toggleAttribute('data-active', plugin.active); + plugin.eventTarget.dispatchEvent( + new CustomEvent('plugin-toggled', { + detail: { + state: plugin.active, + plugin, + }, + }) + ); + }); if (import.meta.hot) { import.meta.hot.send(`${WS_EVENT_NAME}:${plugin.id}:toggled`, { state: plugin.active }); } } + /** + * @param newStatus Optionally, force the minimize button into a specific state + */ toggleMinimizeButton(newStatus?: boolean) { const minimizeButton = this.shadowRoot.querySelector('#minimize-button'); if (!minimizeButton) return; @@ -493,4 +504,15 @@ export class DevOverlayCanvas extends HTMLElement { super(); this.shadowRoot = this.attachShadow({ mode: 'open' }); } + + connectedCallback() { + this.shadowRoot.innerHTML = ` + `; + } } diff --git a/packages/astro/src/runtime/client/dev-overlay/plugins/astro.ts b/packages/astro/src/runtime/client/dev-overlay/plugins/astro.ts index cc83cbe83931..ea3b7f26fc1f 100644 --- a/packages/astro/src/runtime/client/dev-overlay/plugins/astro.ts +++ b/packages/astro/src/runtime/client/dev-overlay/plugins/astro.ts @@ -5,12 +5,42 @@ export default { name: 'Astro', icon: 'astro:logo', init(canvas) { - const astroWindow = document.createElement('astro-dev-overlay-window'); + createWindow(); - astroWindow.windowTitle = 'Astro'; - astroWindow.windowIcon = 'astro:logo'; + document.addEventListener('astro:after-swap', createWindow); - astroWindow.innerHTML = ` + function createWindow() { + const style = document.createElement('style'); + style.textContent = ` + :host { + opacity: 0; + transition: opacity 0.15s ease-in-out; + } + + :host([data-active]) { + opacity: 1; + } + + @media screen and (prefers-reduced-motion: no-preference) { + :host astro-dev-overlay-window { + transform: translateY(55px) translate(-50%, -50%); + transition: transform 0.15s ease-in-out; + transform-origin: center bottom; + } + + :host([data-active]) astro-dev-overlay-window { + transform: translateY(0) translate(-50%, -50%); + } + } + `; + canvas.append(style); + + const astroWindow = document.createElement('astro-dev-overlay-window'); + + astroWindow.windowTitle = 'Astro'; + astroWindow.windowIcon = 'astro:logo'; + + astroWindow.innerHTML = ` +{ handleForms ? + : + '' +}