mirror of
https://github.com/withastro/astro.git
synced 2025-01-06 22:10:10 -05:00
feat(overlay): Add a settings panel (#9058)
This commit is contained in:
parent
a7f8123ba4
commit
5ef89ef33e
12 changed files with 350 additions and 60 deletions
5
.changeset/six-chefs-flash.md
Normal file
5
.changeset/six-chefs-flash.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Add a new settings panel to the dev overlay
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)),
|
||||
];
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
||||
}
|
32
packages/astro/src/runtime/client/dev-overlay/settings.ts
Normal file
32
packages/astro/src/runtime/client/dev-overlay/settings.ts
Normal file
|
@ -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,
|
||||
};
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
margin-right: 8px;
|
||||
#window-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
hr {
|
||||
::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, ::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 />
|
||||
`;
|
||||
|
|
Loading…
Reference in a new issue