@@ -559,6 +567,19 @@ 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) => {
+ app.eventTarget.dispatchEvent(
+ new CustomEvent('placement-updated', {
+ detail: {
+ placement: newPlacement,
+ },
+ })
+ );
+ });
+ }
}
export class DevToolbarCanvas extends HTMLElement {
diff --git a/packages/astro/src/runtime/client/dev-toolbar/ui-library/index.ts b/packages/astro/src/runtime/client/dev-toolbar/ui-library/index.ts
index c515dccfc721..7b1197ab70c2 100644
--- a/packages/astro/src/runtime/client/dev-toolbar/ui-library/index.ts
+++ b/packages/astro/src/runtime/client/dev-toolbar/ui-library/index.ts
@@ -3,6 +3,7 @@ export { DevToolbarButton } from './button.js';
export { DevToolbarCard } from './card.js';
export { DevToolbarHighlight } from './highlight.js';
export { DevToolbarIcon } from './icon.js';
+export { DevToolbarSelect } from './select.js';
export { DevToolbarToggle } from './toggle.js';
export { DevToolbarTooltip } from './tooltip.js';
export { DevToolbarWindow } from './window.js';
diff --git a/packages/astro/src/runtime/client/dev-toolbar/ui-library/select.ts b/packages/astro/src/runtime/client/dev-toolbar/ui-library/select.ts
new file mode 100644
index 000000000000..ee56f3cb0796
--- /dev/null
+++ b/packages/astro/src/runtime/client/dev-toolbar/ui-library/select.ts
@@ -0,0 +1,108 @@
+import { settings } from '../settings.js';
+
+const styles = ['purple', 'gray', 'red', 'green', 'yellow', 'blue'] as const;
+
+type SelectStyle = (typeof styles)[number];
+
+export class DevToolbarSelect extends HTMLElement {
+ shadowRoot: ShadowRoot;
+ element: HTMLSelectElement;
+ _selectStyle: SelectStyle = 'gray';
+
+ get selectStyle() {
+ return this._selectStyle;
+ }
+ set selectStyle(value) {
+ if (!styles.includes(value)) {
+ settings.logger.error(`Invalid style: ${value}, expected one of ${styles.join(', ')}.`);
+ return;
+ }
+ this._selectStyle = value;
+ this.updateStyle();
+ }
+
+ static observedAttributes = ['select-style'];
+
+ constructor() {
+ super();
+ this.shadowRoot = this.attachShadow({ mode: 'open' });
+ this.shadowRoot.innerHTML = `
+
+
+
+ `;
+ this.element = document.createElement('select');
+ this.shadowRoot.addEventListener('slotchange', (event) => {
+ if (event.target instanceof HTMLSlotElement) {
+ // Manually add slotted elements to