Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(toolbar): allow the user to change the placement #10591

Merged
merged 17 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions packages/astro/e2e/dev-toolbar.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,4 +349,37 @@ test.describe('Dev Toolbar', () => {
await expect(appButton).not.toHaveClass('active');
}
});

test('can adjust the placement', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/audit-no-warning'));

const toolbar = page.locator('astro-dev-toolbar');
const settingsAppButton = toolbar.locator('button[data-app-id="astro:settings"]');
await settingsAppButton.click();

const settingsAppCanvas = toolbar.locator(
'astro-dev-toolbar-app-canvas[data-app-id="astro:settings"]'
);
const settingsWindow = settingsAppCanvas.locator('astro-dev-toolbar-window');
await expect(settingsWindow).toBeVisible();

for (const placement of ['bottom-left', 'bottom-center', 'bottom-right']) {
const select = toolbar.getByLabel('Placement');
await expect(select).toBeVisible();
await select.selectOption(placement);

const toolbarRoot = toolbar.locator('#dev-toolbar-root');
await expect(toolbarRoot).toHaveAttribute('data-placement', placement);

for (const appId of ['astro:home', 'astro:xray', 'astro:settings']) {
const appButton = toolbar.locator(`button[data-app-id="${appId}"]`);
await appButton.click();

const appCanvas = toolbar.locator(`astro-dev-toolbar-app-canvas[data-app-id="${appId}"]`);
const appWindow = appCanvas.locator('astro-dev-toolbar-window');
await expect(appWindow).toBeVisible();
await expect(appWindow).toHaveAttribute('data-placement', placement);
}
}
});
});
61 changes: 59 additions & 2 deletions packages/astro/src/runtime/client/dev-toolbar/apps/settings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import type { DevToolbarApp } from '../../../../@types/astro.js';
import { type Settings, settings } from '../settings.js';
import {
type Placement,
type Settings,
isValidPlacement,
placements,
settings,
} from '../settings.js';
import { closeOnOutsideClick, createWindowElement } from './utils/window.js';

interface SettingRow {
Expand Down Expand Up @@ -43,6 +49,22 @@ const settingsRows = [
}
},
},
{
name: 'Placement',
description: 'Adjust the placement of the dev toolbar.',
input: 'select',
settingKey: 'placement',
changeEvent: (evt: Event) => {
if (evt.currentTarget instanceof HTMLSelectElement) {
const placement = evt.currentTarget.value;
if (isValidPlacement(placement)) {
document.querySelector('astro-dev-toolbar')?.setToolbarPlacement(placement);
settings.updateSetting('placement', placement);
settings.logger.verboseLog(`Placement set to ${placement}`);
}
}
},
},
] satisfies SettingRow[];

export default {
Expand Down Expand Up @@ -128,6 +150,27 @@ export default {
a:hover {
color: #f4ecfd;
}

select {
appearance: none;
text-align-last: center;
display: inline-block;
font-family: inherit;
font-size: 14px;
padding: 4px 24px 4px 8px;
border: 1px solid rgba(145, 152, 173, 1);
border-radius: 4px;
color: rgba(191, 193, 201, 1);
background-color: transparent;
background-image:
linear-gradient(45deg, transparent 50%, rgba(191, 193, 201, 1) 50%),
linear-gradient(135deg, rgba(191, 193, 201, 1) 50%, transparent 50%);
background-position:
calc(100% - 12px) calc(1em - 2px),
calc(100% - 8px) calc(1em - 2px);
background-size: 4px 4px;
background-repeat: no-repeat;
}
Princesseuh marked this conversation as resolved.
Show resolved Hide resolved
</style>
<header>
<h1><astro-dev-toolbar-icon icon="gear"></astro-dev-toolbar-icon> Settings</h1>
Expand Down Expand Up @@ -161,10 +204,24 @@ export default {
case 'checkbox': {
const astroToggle = document.createElement('astro-dev-toolbar-toggle');
astroToggle.input.addEventListener('change', setting.changeEvent);
astroToggle.input.checked = settings.config[setting.settingKey];
astroToggle.input.checked = settings.config[setting.settingKey] as boolean;
label.append(astroToggle);
break;
}
case 'select': {
const select = document.createElement('select');
placements.forEach((placement) => {
const option = document.createElement('option');
option.setAttribute('value', placement);
option.textContent =
`${placement.slice(0, 1).toUpperCase()}${placement.slice(1)}`.replace('-', ' ');
select.append(option);
});
select.value = settings.config[setting.settingKey] as Placement;
select.addEventListener('change', setting.changeEvent);
label.append(select);
break;
}
default:
break;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { settings } from '../../settings.js';

export function createWindowElement(content: string) {
const windowElement = document.createElement('astro-dev-toolbar-window');
windowElement.setAttribute('data-placement', settings.config.placement);
windowElement.innerHTML = content;
return windowElement;
}
Expand Down
10 changes: 9 additions & 1 deletion packages/astro/src/runtime/client/dev-toolbar/settings.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
export const placements = ['bottom-left', 'bottom-center', 'bottom-right'] as const;
export type Placement = (typeof placements)[number];
export function isValidPlacement(value: string): value is Placement {
return placements.map(String).includes(value);
}

export interface Settings {
disableAppNotification: boolean;
verbose: boolean;
placement: Placement;
}

export const defaultSettings = {
disableAppNotification: false,
verbose: false,
placement: 'bottom-center',
} satisfies Settings;

export const settings = getSettings();
Expand All @@ -25,7 +33,7 @@ function getSettings() {
_settings = { ..._settings, ...JSON.parse(toolbarSettings) };
}

function updateSetting(key: keyof Settings, value: Settings[typeof key]) {
function updateSetting<Key extends keyof Settings>(key: Key, value: Settings[Key]) {
_settings[key] = value;
localStorage.setItem('astro:dev-toolbar:settings', JSON.stringify(_settings));
}
Expand Down
28 changes: 22 additions & 6 deletions packages/astro/src/runtime/client/dev-toolbar/toolbar.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable no-console */
import type { DevToolbarApp as DevToolbarAppDefinition } from '../../../@types/astro.js';
import { settings } from './settings.js';
import { type Placement, settings } from './settings.js';
import { type Icon, getIconElement, isDefinedIcon } from './ui-library/icons.js';

export type DevToolbarApp = DevToolbarAppDefinition & {
Expand Down Expand Up @@ -57,8 +57,6 @@ export class AstroDevToolbar extends HTMLElement {
#dev-toolbar-root {
position: fixed;
bottom: 0px;
left: 50%;
transform: translate(-50%, 0%);
z-index: 2000000010;
display: flex;
flex-direction: column;
Expand All @@ -75,6 +73,17 @@ export class AstroDevToolbar extends HTMLElement {
opacity: 0.2;
}

#dev-toolbar-root[data-placement="bottom-left"] {
left: 16px;
}
#dev-toolbar-root[data-placement="bottom-center"] {
left: 50%;
transform: translateX(-50%);
}
#dev-toolbar-root[data-placement="bottom-right"] {
right: 16px;
}

#dev-bar-hitbox-above,
#dev-bar-hitbox-below {
width: 100%;
Expand Down Expand Up @@ -240,9 +249,7 @@ export class AstroDevToolbar extends HTMLElement {
width: 1px;
}
</style>
<div id="dev-toolbar-root" data-hidden ${
settings.config.disableAppNotification ? 'data-no-notification' : ''
}>
<div id="dev-toolbar-root" data-hidden ${settings.config.disableAppNotification ? 'data-no-notification' : ''} data-placement="${settings.config.placement}">
<div id="dev-bar-hitbox-above"></div>
<div id="dev-bar">
<div id="bar-container">
Expand Down Expand Up @@ -553,6 +560,15 @@ export class AstroDevToolbar extends HTMLElement {
?.querySelector('#dropdown')
?.toggleAttribute('data-no-notification', !newStatus);
}

setToolbarPlacement(newPlacement: Placement) {
this.devToolbarContainer?.setAttribute('data-placement', newPlacement);
this.apps.forEach((app) => {
this.getAppCanvasById(app.id)
?.shadowRoot?.querySelector('astro-dev-toolbar-window')
?.setAttribute('data-placement', newPlacement);
});
Princesseuh marked this conversation as resolved.
Show resolved Hide resolved
}
}

export class DevToolbarCanvas extends HTMLElement {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,18 @@ export class DevToolbarWindow extends HTMLElement {
position: fixed;
z-index: 999999999;
bottom: 72px;
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);
}

:host([data-placement="bottom-left"]) {
left: 16px;
}
:host([data-placement="bottom-center"]) {
left: 50%;
transform: translateX(-50%);
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);
}
:host([data-placement="bottom-right"]) {
right: 16px;
}
Princesseuh marked this conversation as resolved.
Show resolved Hide resolved

@media (forced-colors: active) {
Expand Down
Loading