summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Erika <3019731+Princesseuh@users.noreply.github.com> 2023-11-13 13:09:32 +0100
committerGravatar GitHub <noreply@github.com> 2023-11-13 13:09:32 +0100
commit5ef89ef33e0dc4621db947b6889b3c563eb56a78 (patch)
treebf751c202c022a36ac14cd97c52592437805e993
parenta7f8123ba45359e3d4db71089c6db5d50ac2088c (diff)
downloadastro-5ef89ef33e0dc4621db947b6889b3c563eb56a78.tar.gz
astro-5ef89ef33e0dc4621db947b6889b3c563eb56a78.tar.zst
astro-5ef89ef33e0dc4621db947b6889b3c563eb56a78.zip
feat(overlay): Add a settings panel (#9058)
-rw-r--r--.changeset/six-chefs-flash.md5
-rw-r--r--packages/astro/e2e/dev-overlay.test.js19
-rw-r--r--packages/astro/src/@types/astro.ts2
-rw-r--r--packages/astro/src/runtime/client/dev-overlay/entrypoint.ts14
-rw-r--r--packages/astro/src/runtime/client/dev-overlay/overlay.ts26
-rw-r--r--packages/astro/src/runtime/client/dev-overlay/plugins/astro.ts50
-rw-r--r--packages/astro/src/runtime/client/dev-overlay/plugins/settings.ts106
-rw-r--r--packages/astro/src/runtime/client/dev-overlay/plugins/utils/window.ts56
-rw-r--r--packages/astro/src/runtime/client/dev-overlay/settings.ts32
-rw-r--r--packages/astro/src/runtime/client/dev-overlay/ui-library/icons.ts1
-rw-r--r--packages/astro/src/runtime/client/dev-overlay/ui-library/toggle.ts52
-rw-r--r--packages/astro/src/runtime/client/dev-overlay/ui-library/window.ts45
12 files changed, 349 insertions, 59 deletions
diff --git a/.changeset/six-chefs-flash.md b/.changeset/six-chefs-flash.md
new file mode 100644
index 000000000..3de93b983
--- /dev/null
+++ b/.changeset/six-chefs-flash.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Add a new settings panel to the dev overlay
diff --git a/packages/astro/e2e/dev-overlay.test.js b/packages/astro/e2e/dev-overlay.test.js
index 3e8c6662c..1a358487c 100644
--- a/packages/astro/e2e/dev-overlay.test.js
+++ b/packages/astro/e2e/dev-overlay.test.js
@@ -98,4 +98,23 @@ test.describe('Dev Overlay', () => {
await expect(auditHighlight).not.toBeVisible();
await expect(auditHighlightTooltip).not.toBeVisible();
});
+
+ test('can open Settings plugin', async ({ page, astro }) => {
+ await page.goto(astro.resolveUrl('/'));
+
+ const overlay = page.locator('astro-dev-overlay');
+ const pluginButton = overlay.locator('button[data-plugin-id="astro:settings"]');
+ await pluginButton.click();
+
+ const settingsPluginCanvas = overlay.locator(
+ 'astro-dev-overlay-plugin-canvas[data-plugin-id="astro:settings"]'
+ );
+ const settingsWindow = settingsPluginCanvas.locator('astro-dev-overlay-window');
+ await expect(settingsWindow).toHaveCount(1);
+ await expect(settingsWindow).toBeVisible();
+
+ // Toggle plugin off
+ await pluginButton.click();
+ await expect(settingsWindow).not.toBeVisible();
+ });
});
diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts
index faa2df03e..e517a0424 100644
--- a/packages/astro/src/@types/astro.ts
+++ b/packages/astro/src/@types/astro.ts
@@ -24,6 +24,7 @@ import type { AstroIntegrationLogger, Logger, LoggerLevel } from '../core/logger
import type { AstroDevOverlay, DevOverlayCanvas } from '../runtime/client/dev-overlay/overlay.js';
import type { DevOverlayHighlight } from '../runtime/client/dev-overlay/ui-library/highlight.js';
import type { Icon } from '../runtime/client/dev-overlay/ui-library/icons.js';
+import type { DevOverlayToggle } from '../runtime/client/dev-overlay/ui-library/toggle.js';
import type { DevOverlayTooltip } from '../runtime/client/dev-overlay/ui-library/tooltip.js';
import type { DevOverlayWindow } from '../runtime/client/dev-overlay/ui-library/window.js';
import type { AstroComponentFactory, AstroComponentInstance } from '../runtime/server/index.js';
@@ -2578,5 +2579,6 @@ declare global {
'astro-dev-overlay-plugin-canvas': DevOverlayCanvas;
'astro-dev-overlay-tooltip': DevOverlayTooltip;
'astro-dev-overlay-highlight': DevOverlayHighlight;
+ 'astro-dev-overlay-toggle': DevOverlayToggle;
}
}
diff --git a/packages/astro/src/runtime/client/dev-overlay/entrypoint.ts b/packages/astro/src/runtime/client/dev-overlay/entrypoint.ts
index 7336f9d06..887449c37 100644
--- a/packages/astro/src/runtime/client/dev-overlay/entrypoint.ts
+++ b/packages/astro/src/runtime/client/dev-overlay/entrypoint.ts
@@ -1,5 +1,6 @@
import type { DevOverlayPlugin as DevOverlayPluginDefinition } from '../../../@types/astro.js';
import { type AstroDevOverlay, type DevOverlayPlugin } from './overlay.js';
+import { settings } from './settings.js';
let overlay: AstroDevOverlay;
@@ -9,22 +10,26 @@ document.addEventListener('DOMContentLoaded', async () => {
{ default: astroDevToolPlugin },
{ default: astroAuditPlugin },
{ default: astroXrayPlugin },
+ { default: astroSettingsPlugin },
{ AstroDevOverlay, DevOverlayCanvas },
{ DevOverlayCard },
{ DevOverlayHighlight },
{ DevOverlayTooltip },
{ DevOverlayWindow },
+ { DevOverlayToggle },
] = await Promise.all([
// @ts-expect-error
import('astro:dev-overlay'),
import('./plugins/astro.js'),
import('./plugins/audit.js'),
import('./plugins/xray.js'),
+ import('./plugins/settings.js'),
import('./overlay.js'),
import('./ui-library/card.js'),
import('./ui-library/highlight.js'),
import('./ui-library/tooltip.js'),
import('./ui-library/window.js'),
+ import('./ui-library/toggle.js'),
]);
// Register custom elements
@@ -34,6 +39,7 @@ document.addEventListener('DOMContentLoaded', async () => {
customElements.define('astro-dev-overlay-tooltip', DevOverlayTooltip);
customElements.define('astro-dev-overlay-highlight', DevOverlayHighlight);
customElements.define('astro-dev-overlay-card', DevOverlayCard);
+ customElements.define('astro-dev-overlay-toggle', DevOverlayToggle);
overlay = document.createElement('astro-dev-overlay');
@@ -60,7 +66,9 @@ document.addEventListener('DOMContentLoaded', async () => {
newState = evt.detail.state ?? true;
}
- target.querySelector('.notification')?.toggleAttribute('data-active', newState);
+ if (settings.config.showPluginNotifications === false) {
+ target.querySelector('.notification')?.toggleAttribute('data-active', newState);
+ }
});
eventTarget.addEventListener('toggle-plugin', async (evt) => {
@@ -77,8 +85,8 @@ document.addEventListener('DOMContentLoaded', async () => {
const customPluginsDefinitions = (await loadDevOverlayPlugins()) as DevOverlayPluginDefinition[];
const plugins: DevOverlayPlugin[] = [
- ...[astroDevToolPlugin, astroXrayPlugin, astroAuditPlugin].map((pluginDef) =>
- preparePlugin(pluginDef, true)
+ ...[astroDevToolPlugin, astroXrayPlugin, astroAuditPlugin, astroSettingsPlugin].map(
+ (pluginDef) => preparePlugin(pluginDef, true)
),
...customPluginsDefinitions.map((pluginDef) => preparePlugin(pluginDef, false)),
];
diff --git a/packages/astro/src/runtime/client/dev-overlay/overlay.ts b/packages/astro/src/runtime/client/dev-overlay/overlay.ts
index e0ab02e48..70d957269 100644
--- a/packages/astro/src/runtime/client/dev-overlay/overlay.ts
+++ b/packages/astro/src/runtime/client/dev-overlay/overlay.ts
@@ -1,5 +1,6 @@
/* eslint-disable no-console */
import type { DevOverlayPlugin as DevOverlayPluginDefinition } from '../../../@types/astro.js';
+import { settings } from './settings.js';
import { getIconElement, isDefinedIcon, type Icon } from './ui-library/icons.js';
export type DevOverlayPlugin = DevOverlayPluginDefinition & {
@@ -235,14 +236,21 @@ export class AstroDevOverlay extends HTMLElement {
<div id="dev-bar">
<div id="bar-container">
${this.plugins
- .filter((plugin) => plugin.builtIn)
+ .filter((plugin) => plugin.builtIn && plugin.id !== 'astro:settings')
.map((plugin) => this.getPluginTemplate(plugin))
.join('')}
+ ${
+ this.plugins.filter((plugin) => !plugin.builtIn).length > 0
+ ? `<div class="separator"></div>${this.plugins
+ .filter((plugin) => !plugin.builtIn)
+ .map((plugin) => this.getPluginTemplate(plugin))
+ .join('')}`
+ : ''
+ }
<div class="separator"></div>
- ${this.plugins
- .filter((plugin) => !plugin.builtIn)
- .map((plugin) => this.getPluginTemplate(plugin))
- .join('')}
+ ${this.getPluginTemplate(
+ this.plugins.find((plugin) => plugin.builtIn && plugin.id === 'astro:settings')!
+ )}
</div>
</div>
<button id="minimize-button">${getIconElement('arrow-down')?.outerHTML}</button>
@@ -254,7 +262,8 @@ export class AstroDevOverlay extends HTMLElement {
// Create plugin canvases
this.plugins.forEach(async (plugin) => {
if (!this.hasBeenInitialized) {
- console.log(`Creating plugin canvas for ${plugin.id}`);
+ if (settings.config.verbose) console.log(`Creating plugin canvas for ${plugin.id}`);
+
const pluginCanvas = document.createElement('astro-dev-overlay-plugin-canvas');
pluginCanvas.dataset.pluginId = plugin.id;
this.shadowRoot?.append(pluginCanvas);
@@ -321,7 +330,7 @@ export class AstroDevOverlay extends HTMLElement {
if (this.isHidden()) {
this.hoverTimeout = window.setTimeout(() => {
this.toggleOverlay(true);
- }, this.HOVER_DELAY);
+ }, this.HOVER_DELAY + 200); // Slightly higher delay here to prevent users opening the overlay by accident
} else {
this.hoverTimeout = window.setTimeout(() => {
this.toggleMinimizeButton(true);
@@ -374,7 +383,8 @@ export class AstroDevOverlay extends HTMLElement {
const shadowRoot = this.getPluginCanvasById(plugin.id)!.shadowRoot!;
try {
- console.info(`Initializing plugin ${plugin.id}`);
+ if (settings.config.verbose) console.info(`Initializing plugin ${plugin.id}`);
+
await plugin.init?.(shadowRoot, plugin.eventTarget);
plugin.status = 'ready';
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 ea3b7f26f..352a018e1 100644
--- a/packages/astro/src/runtime/client/dev-overlay/plugins/astro.ts
+++ b/packages/astro/src/runtime/client/dev-overlay/plugins/astro.ts
@@ -1,4 +1,5 @@
import type { DevOverlayPlugin } from '../../../../@types/astro.js';
+import { createWindowWithTransition, waitForTransition } from './utils/window.js';
export default {
id: 'astro',
@@ -10,38 +11,10 @@ export default {
document.addEventListener('astro:after-swap', createWindow);
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 = `
- <style>
+ const window = createWindowWithTransition(
+ 'Astro',
+ 'astro:logo',
+ `<style>
#buttons-container {
display: flex;
gap: 16px;
@@ -91,18 +64,13 @@ export default {
<a href="https://astro.build" target="_blank">Visit the Astro website</a>
</footer>
</div>
- `;
+ `
+ );
- canvas.append(astroWindow);
+ canvas.append(window);
}
},
async beforeTogglingOff(canvas) {
- canvas.host?.removeAttribute('data-active');
-
- await new Promise((resolve) => {
- canvas.host.addEventListener('transitionend', resolve);
- });
-
- return true;
+ return await waitForTransition(canvas);
},
} satisfies DevOverlayPlugin;
diff --git a/packages/astro/src/runtime/client/dev-overlay/plugins/settings.ts b/packages/astro/src/runtime/client/dev-overlay/plugins/settings.ts
new file mode 100644
index 000000000..c4202c5c1
--- /dev/null
+++ b/packages/astro/src/runtime/client/dev-overlay/plugins/settings.ts
@@ -0,0 +1,106 @@
+import type { DevOverlayPlugin } from '../../../../@types/astro.js';
+import { settings, type Settings } from '../settings.js';
+import { createWindowWithTransition, waitForTransition } from './utils/window.js';
+
+interface SettingRow {
+ name: string;
+ description: string;
+ input: 'checkbox' | 'text' | 'number' | 'select';
+ settingKey: keyof Settings;
+ changeEvent: (evt: Event) => void;
+}
+
+const settingsRows = [
+ {
+ name: 'Disable notifications',
+ description: 'Notification bubbles will not be shown when this is enabled.',
+ input: 'checkbox',
+ settingKey: 'showPluginNotifications',
+ changeEvent: (evt: Event) => {
+ if (evt.currentTarget instanceof HTMLInputElement) {
+ settings.updateSetting('showPluginNotifications', evt.currentTarget.checked);
+ }
+ },
+ },
+ {
+ name: 'Verbose logging',
+ description: 'Log additional information to the console.',
+ input: 'checkbox',
+ settingKey: 'verbose',
+ changeEvent: (evt: Event) => {
+ if (evt.currentTarget instanceof HTMLInputElement) {
+ settings.updateSetting('verbose', evt.currentTarget.checked);
+ }
+ },
+ },
+] satisfies SettingRow[];
+
+export default {
+ id: 'astro:settings',
+ name: 'Overlay settings',
+ icon: 'gear',
+ init(canvas) {
+ createSettingsWindow();
+
+ document.addEventListener('astro:after-swap', createSettingsWindow);
+
+ function createSettingsWindow() {
+ const window = createWindowWithTransition(
+ 'Settings',
+ 'gear',
+ `<style>
+ h2, h3 {
+ margin-top: 0;
+ }
+
+ .setting-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+
+ h3 {
+ font-size: 16px;
+ font-weight: 400;
+ color: white;
+ margin-bottom: 0;
+ }
+
+ label {
+ font-size: 15px;
+ line-height: 1.5rem;
+ }
+ </style>
+ <h2>General</h2>
+ `,
+ settingsRows.flatMap((setting) => [
+ getElementForSettingAsString(setting),
+ document.createElement('hr'),
+ ])
+ );
+ canvas.append(window);
+
+ function getElementForSettingAsString(setting: SettingRow) {
+ const label = document.createElement('label');
+ label.classList.add('setting-row');
+ const section = document.createElement('section');
+ section.innerHTML = `<h3>${setting.name}</h3>${setting.description}`;
+ label.append(section);
+
+ switch (setting.input) {
+ case 'checkbox': {
+ const astroToggle = document.createElement('astro-dev-overlay-toggle');
+ astroToggle.input.addEventListener('change', setting.changeEvent);
+ astroToggle.input.checked = settings.config[setting.settingKey];
+ label.append(astroToggle);
+ }
+ }
+
+ return label;
+ }
+ }
+ },
+ async beforeTogglingOff(canvas) {
+ return await waitForTransition(canvas);
+ },
+} satisfies DevOverlayPlugin;
diff --git a/packages/astro/src/runtime/client/dev-overlay/plugins/utils/window.ts b/packages/astro/src/runtime/client/dev-overlay/plugins/utils/window.ts
new file mode 100644
index 000000000..04f09d6e6
--- /dev/null
+++ b/packages/astro/src/runtime/client/dev-overlay/plugins/utils/window.ts
@@ -0,0 +1,56 @@
+import type { Icon } from '../../ui-library/icons.js';
+
+export function createWindowWithTransition(
+ title: string,
+ icon: Icon,
+ windowContent: string,
+ addedNodes: Node[] = []
+): DocumentFragment {
+ const fragment = document.createDocumentFragment();
+
+ 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%);
+ }
+ }
+ `;
+ fragment.append(style);
+
+ const window = document.createElement('astro-dev-overlay-window');
+ window.windowTitle = title;
+ window.windowIcon = icon;
+ window.innerHTML = windowContent;
+
+ window.append(...addedNodes);
+
+ fragment.append(window);
+
+ return fragment;
+}
+
+export async function waitForTransition(canvas: ShadowRoot): Promise<boolean> {
+ canvas.host?.removeAttribute('data-active');
+
+ await new Promise((resolve) => {
+ canvas.host.addEventListener('transitionend', resolve);
+ });
+
+ return true;
+}
diff --git a/packages/astro/src/runtime/client/dev-overlay/settings.ts b/packages/astro/src/runtime/client/dev-overlay/settings.ts
new file mode 100644
index 000000000..a6c086d2c
--- /dev/null
+++ b/packages/astro/src/runtime/client/dev-overlay/settings.ts
@@ -0,0 +1,32 @@
+export interface Settings {
+ showPluginNotifications: boolean;
+ verbose: boolean;
+}
+
+export const defaultSettings = {
+ showPluginNotifications: true,
+ verbose: false,
+} satisfies Settings;
+
+export const settings = getSettings();
+
+function getSettings() {
+ let _settings: Settings = { ...defaultSettings };
+ const overlaySettings = localStorage.getItem('astro:dev-overlay:settings');
+
+ if (overlaySettings) {
+ _settings = { ..._settings, ...JSON.parse(overlaySettings) };
+ }
+
+ function updateSetting(key: keyof Settings, value: Settings[typeof key]) {
+ _settings[key] = value;
+ localStorage.setItem('astro:dev-overlay:settings', JSON.stringify(_settings));
+ }
+
+ return {
+ get config() {
+ return _settings;
+ },
+ updateSetting,
+ };
+}
diff --git a/packages/astro/src/runtime/client/dev-overlay/ui-library/icons.ts b/packages/astro/src/runtime/client/dev-overlay/ui-library/icons.ts
index 10f33cad1..7a0236900 100644
--- a/packages/astro/src/runtime/client/dev-overlay/ui-library/icons.ts
+++ b/packages/astro/src/runtime/client/dev-overlay/ui-library/icons.ts
@@ -30,4 +30,5 @@ const icons = {
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 25 24"><path fill="#CCCED8" d="m20.6293 7.455-5.25-5.25c-.1045-.10461-.2285-.1876-.3651-.24422-.1366-.05662-.283-.08577-.4308-.08578H5.58337c-.49728 0-.97419.19754-1.32582.54917-.35163.35164-.54918.82855-.54918 1.32583v16.5c0 .4973.19755.9742.54918 1.3258.35163.3517.82854.5492 1.32582.5492H19.0834c.4973 0 .9742-.1975 1.3258-.5492.3516-.3516.5492-.8285.5492-1.3258v-12c0-.29813-.1184-.58407-.3291-.795Zm-3.1397.045h-2.1562V5.34375L17.4896 7.5ZM5.95837 19.875V4.125h7.12503v4.5c0 .29837.1185.58452.3295.7955.211.21097.4971.3295.7955.3295h4.5v10.125H5.95837Zm9.04503-4.5459c.3426-.7185.4202-1.5349.2192-2.3051-.2011-.7702-.6679-1.4445-1.3179-1.9038-.65-.4594-1.4415-.6742-2.2346-.6066-.7931.0677-1.5368.4135-2.0996.9763-.56283.5629-.90863 1.3065-.9763 2.0996-.06766.7931.14716 1.5846.60651 2.2346.45936.6501 1.13369 1.1169 1.90389 1.3179.7701.201 1.5866.1234 2.305-.2192l1.125 1.125c.2114.2114.498.3301.7969.3301.2989 0 .5855-.1187.7969-.3301.2113-.2113.3301-.498.3301-.7969 0-.2988-.1188-.5855-.3301-.7968l-1.125-1.125Zm-4.17-1.4541c0-.2225.066-.44.1896-.625.1236-.185.2993-.3292.5049-.4144.2055-.0851.4317-.1074.65-.064.2182.0434.4186.1506.576.3079.1573.1573.2644.3578.3079.576.0434.2183.0211.4445-.0641.65-.0851.2056-.2293.3813-.4143.5049-.185.1236-.4025.1896-.625.1896-.2984 0-.5845-.1185-.7955-.3295-.211-.211-.3295-.4971-.3295-.7955Z"/></svg>',
'check-circle':
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M10.0306 4.96938c.0699.06967.1254.15247.1633.24363.0378.09116.0573.1889.0573.28762 0 .09871-.0195.19645-.0573.28761-.0379.09116-.0934.17396-.1633.24364L6.53063 9.53187c-.06968.06992-.15247.1254-.24364.16326-.09116.03785-.1889.05734-.28761.05734-.09871 0-.19645-.01949-.28762-.05734-.09116-.03786-.17395-.09334-.24363-.16326l-1.5-1.5c-.06977-.06976-.12511-.15258-.16286-.24373-.03776-.09116-.05719-.18885-.05719-.28752 0-.09866.01943-.19635.05719-.28751.03775-.09115.09309-.17397.16286-.24373.06976-.06977.15259-.12511.24374-.16287.09115-.03775.18885-.05719.28751-.05719s.19636.01944.28751.05719c.09115.03776.17397.0931.24374.16287L6 7.9375l2.96938-2.97c.06978-.06961.15259-.12478.24371-.16237.09111-.03758.18874-.05683.2873-.05666.09856.00018.19612.01978.28711.05768.09098.0379.1736.09337.2431.16323ZM13.75 7c0 1.33502-.3959 2.64007-1.1376 3.7501-.7417 1.11-1.7959 1.9752-3.02928 2.4861-1.23341.5109-2.5906.6446-3.89998.3841-1.30937-.2605-2.5121-.9033-3.45611-1.8473-.944-.944-1.586877-2.14677-1.847328-3.45614-.26045-1.30937-.126777-2.66657.384114-3.89997C1.27471 3.18349 2.13987 2.12928 3.2499 1.38758 4.35994.645881 5.66498.25 7 .25c1.78961.001985 3.5053.713781 4.7708 1.97922C13.0362 3.49466 13.748 5.2104 13.75 7Zm-1.5 0c0-1.03835-.3079-2.05339-.8848-2.91674-.5769-.86336-1.3968-1.53627-2.35611-1.93363-.95931-.39736-2.01491-.50133-3.03331-.29875-1.0184.20257-1.95386.70258-2.68809 1.43681-.73422.73422-1.23424 1.66969-1.43681 2.68809-.20257 1.0184-.0986 2.074.29876 3.03331.39736.95931 1.07026 1.77921 1.93362 2.35611.86336.5769 1.87839.8848 2.91674.8848 1.39193-.0015 2.72643-.5551 3.7107-1.5393C11.6949 9.72642 12.2485 8.39193 12.25 7Z"/></svg>',
+ gear: '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 22 22"><path fill="#fff" d="M11 6.12507c-.9642 0-1.90671.28592-2.7084.82159-.80169.53567-1.42653 1.29704-1.79551 2.18783-.36898.89081-.46552 1.87101-.27742 2.81661.18811.9457.6524 1.8143 1.33419 2.4961.68178.6818 1.55042 1.1461 2.49604 1.3342.9457.1881 1.9259.0916 2.8167-.2774s1.6521-.9938 2.1878-1.7955c.5357-.8017.8216-1.7442.8216-2.7084-.0015-1.2925-.5156-2.53161-1.4295-3.44553-.9139-.91392-2.153-1.42801-3.4455-1.4295Zm0 7.50003c-.5192 0-1.02669-.154-1.45837-.4424-.43168-.2885-.76813-.6984-.96681-1.1781-.19868-.4796-.25067-1.0074-.14938-1.5166.10129-.50924.35129-.97697.71841-1.34408.36711-.36712.83484-.61712 1.34405-.71841.5092-.10129 1.037-.0493 1.5166.14938.4797.19868.8897.53513 1.1781.96681.2884.43168.4424.9392.4424 1.4584 0 .6962-.2766 1.3638-.7688 1.8561-.4923.4923-1.16.7689-1.8562.7689Zm8.625-2.551v-.1481l1.3125-1.64155c.1102-.13755.1865-.29905.2228-.4715s.0316-.35102-.0137-.52131c-.2369-.89334-.5909-1.75142-1.0528-2.55188-.089-.15264-.2127-.28218-.3611-.37811-.1484-.09594-.3173-.15557-.493-.17408l-2.0888-.23437-.104-.10406-.2344-2.08969c-.0186-.17556-.0783-.34426-.1743-.49247-.0959-.1482-.2254-.27175-.3779-.36066-.8005-.46341-1.6589-.81869-2.5528-1.056559-.1704-.044683-.349-.048704-.5213-.01174-.1723.036965-.3335.113881-.4706.224549l-1.6415 1.3125h-.1482l-1.64152-1.3125C9.14683.9524 8.98532.87608 8.81288.839767c-.17245-.036314-.35102-.031606-.52132.013744-.89357.238319-1.75165.593909-2.55187 1.057499-.15205.08854-.28121.2115-.37712.35901-.0959.14752-.15586.31547-.17507.49037l-.23437 2.08875-.10407.10406-2.08968.23437c-.17556.01865-.34426.07835-.49247.17428-.14821.09593-.27176.22539-.36066.37791-.46211.80072-.81613 1.65912-1.052812 2.55281-.045195.17016-.049823.34855-.013512.52082.03631.17227.112546.33362.222574.47106L2.375 10.926v.1481l-1.3125 1.6416c-.110173.1375-.186492.299-.222806.4715-.036313.1724-.031605.351.013744.5213.238622.8936.594522 1.7517 1.058442 2.5519.08844.1519.21126.281.3586.3769.14734.0959.3151.1559.48983.1753l2.08875.2325.10407.104.23437 2.0916c.01865.1756.07835.3443.17428.4925.09592.1482.22538.2717.37791.3606.80052.4634 1.65893.8187 2.55281 1.0566.17045.0447.349.0487.52129.0117.17228-.0369.33347-.1139.47059-.2245l1.64152-1.3125h.1482l1.6415 1.3125c.1376.1101.2991.1865.4715.2228.1725.0363.351.0316.5213-.0138.8934-.2368 1.7514-.5908 2.5519-1.0528.1524-.0883.2819-.2112.3782-.3587.0962-.1475.1565-.3156.1759-.4907l.2325-2.0887.104-.1041 2.0897-.239c.1751-.0194.3432-.0797.4907-.1759.1475-.0963.2704-.2258.3587-.3782.4634-.8005.8187-1.6589 1.0566-2.5528.0448-.1699.0493-.3479.013-.5198-.0363-.172-.1124-.333-.2221-.4702l-1.3125-1.6416Zm-2.2612-.4584c.015.256.015.5127 0 .7687-.0168.2784.0704.553.2446.7707l1.2038 1.5047c-.1136.3363-.2492.6648-.406.9834l-1.9153.2128c-.2773.0317-.5329.1654-.7171.375-.1704.1919-.3519.3735-.5438.5438-.2096.1842-.3433.4398-.375.7171l-.2119 1.9144c-.3185.1574-.647.2936-.9834.4078l-1.5047-1.2047c-.1997-.1593-.4477-.2459-.7031-.2456h-.0675c-.2561.015-.5127.015-.7688 0-.2781-.0165-.5525.0703-.7706.2438l-1.50469 1.2047c-.33634-.1137-.66486-.2493-.98343-.406l-.21282-1.9153c-.0317-.2773-.16536-.5329-.375-.7172-.19187-.1703-.37344-.3519-.54375-.5437-.18426-.2097-.43988-.3433-.71718-.375l-1.91438-.2119c-.15734-.3185-.29357-.647-.40781-.9834l1.20375-1.5047c.17424-.2177.26144-.4923.24469-.7707-.01501-.256-.01501-.5127 0-.7687.01675-.2783-.07045-.553-.24469-.77063L3.18781 8.34038c.11364-.33634.24924-.66486.40594-.98343l1.91531-.21281c.27731-.03171.53292-.16537.71719-.375.17031-.19188.35188-.37345.54375-.54375.20964-.18427.3433-.43989.375-.71719l.21188-1.91438c.31852-.15734.64704-.29357.98343-.40781L9.845 4.3907c.2181.17343.4925.26023.7706.24375.2561-.015.5127-.015.7688 0 .2782.01701.5528-.06985.7706-.24375l1.5047-1.20469c.3364.11424.6649.25047.9834.40781l.2128 1.91532c.0317.2773.1654.53292.375.71718.1919.17031.3735.35188.5438.54375.1843.20964.4399.3433.7172.375l1.9143.21188c.1574.31852.2936.64704.4079.98343l-1.2038 1.50469c-.1749.21743-.2628.49203-.2465.77063Z"/></svg>',
} as const;
diff --git a/packages/astro/src/runtime/client/dev-overlay/ui-library/toggle.ts b/packages/astro/src/runtime/client/dev-overlay/ui-library/toggle.ts
new file mode 100644
index 000000000..5ff21fd18
--- /dev/null
+++ b/packages/astro/src/runtime/client/dev-overlay/ui-library/toggle.ts
@@ -0,0 +1,52 @@
+export class DevOverlayToggle extends HTMLElement {
+ shadowRoot: ShadowRoot;
+ input: HTMLInputElement;
+
+ constructor() {
+ super();
+ this.shadowRoot = this.attachShadow({ mode: 'open' });
+
+ this.shadowRoot.innerHTML = `
+ <style>
+ input {
+ appearance: none;
+ width: 32px;
+ height: 20px;
+ border: 1px solid rgba(145, 152, 173, 1);
+ transition: background-color 0.2s ease, border-color 0.2s ease;
+ border-radius: 9999px;
+ }
+
+ input::after {
+ content: '';
+ width: 16px;
+ display: inline-block;
+ height: 16px;
+ background-color: rgba(145, 152, 173, 1);
+ border-radius: 9999px;
+ transition: transform 0.2s ease, background-color 0.2s ease;
+ top: 1px;
+ left: 1px;
+ position: relative;
+ }
+
+ input:checked {
+ border: 1px solid rgba(213, 249, 196, 1);
+ background-color: rgba(61, 125, 31, 1);
+ }
+
+ input:checked::after {
+ transform: translateX(12px);
+ background: rgba(213, 249, 196, 1);
+ }
+ </style>
+ `;
+
+ this.input = document.createElement('input');
+ }
+
+ connectedCallback() {
+ this.input.type = 'checkbox';
+ this.shadowRoot.append(this.input);
+ }
+}
diff --git a/packages/astro/src/runtime/client/dev-overlay/ui-library/window.ts b/packages/astro/src/runtime/client/dev-overlay/ui-library/window.ts
index 64bf58076..18b515429 100644
--- a/packages/astro/src/runtime/client/dev-overlay/ui-library/window.ts
+++ b/packages/astro/src/runtime/client/dev-overlay/ui-library/window.ts
@@ -19,11 +19,12 @@ export class DevOverlayWindow extends HTMLElement {
this.shadowRoot.innerHTML = `
<style>
:host {
+ box-sizing: border-box;
display: flex;
flex-direction: column;
background: linear-gradient(0deg, #13151A, #13151A), linear-gradient(0deg, #343841, #343841);
border: 1px solid rgba(52, 56, 65, 1);
- width: 640px;
+ width: min(640px, 100%);
height: 480px;
border-radius: 12px;
padding: 24px;
@@ -37,24 +38,54 @@ export class DevOverlayWindow extends HTMLElement {
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);
}
- h1 {
- margin: 0;
+ ::slotted(h1), ::slotted(h2), ::slotted(h3), ::slotted(h4), ::slotted(h5) {
font-weight: 600;
color: #fff;
}
- h1 svg {
- vertical-align: text-bottom;
+ #window-title {
+ display: flex;
+ align-items: center;
+ font-weight: 600;
+ color: #fff;
+ margin: 0;
+ font-size: 22px;
+ }
+
+ ::slotted(h1) {
+ font-size: 22px;
+ }
+
+ ::slotted(h2) {
+ font-size: 20px;
+ }
+
+ ::slotted(h3) {
+ font-size: 18px;
+ }
+
+ ::slotted(h4) {
+ font-size: 16px;
+ }
+
+ ::slotted(h5) {
+ font-size: 14px;
+ }
+
+ #window-title svg {
margin-right: 8px;
+ height: 1em;
}
- hr {
+ hr, ::slotted(hr) {
border: 1px solid rgba(27, 30, 36, 1);
margin: 1em 0;
}
</style>
- <h1>${this.windowIcon ? this.getElementForIcon(this.windowIcon) : ''}${this.windowTitle ?? ''}</h1>
+ <h1 id="window-title">${this.windowIcon ? this.getElementForIcon(this.windowIcon) : ''}${
+ this.windowTitle ?? ''
+ }</h1>
<hr />
<slot />
`;