0
Fork 0
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:
Erika 2023-11-13 13:09:32 +01:00 committed by GitHub
parent a7f8123ba4
commit 5ef89ef33e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 350 additions and 60 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Add a new settings panel to the dev overlay

View file

@ -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();
});
});

View file

@ -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;
}
}

View file

@ -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)),
];

View file

@ -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';

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View 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,
};
}

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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 />
`;