summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/metal-crabs-applaud.md5
-rw-r--r--.changeset/twelve-dolphins-roll.md5
-rw-r--r--packages/astro/src/@types/astro.ts2
-rw-r--r--packages/astro/src/runtime/client/dev-toolbar/entrypoint.ts2
-rw-r--r--packages/astro/src/runtime/client/dev-toolbar/ui-library/button.ts35
-rw-r--r--packages/astro/src/runtime/client/dev-toolbar/ui-library/index.ts1
-rw-r--r--packages/astro/src/runtime/client/dev-toolbar/ui-library/radio-checkbox.ts121
7 files changed, 168 insertions, 3 deletions
diff --git a/.changeset/metal-crabs-applaud.md b/.changeset/metal-crabs-applaud.md
new file mode 100644
index 000000000..c7cb3a26a
--- /dev/null
+++ b/.changeset/metal-crabs-applaud.md
@@ -0,0 +1,5 @@
+---
+"astro": minor
+---
+
+Adds a new radio checkbox component to the dev toolbar UI library (`astro-dev-toolbar-radio-checkbox`)
diff --git a/.changeset/twelve-dolphins-roll.md b/.changeset/twelve-dolphins-roll.md
new file mode 100644
index 000000000..baf944281
--- /dev/null
+++ b/.changeset/twelve-dolphins-roll.md
@@ -0,0 +1,5 @@
+---
+"astro": minor
+---
+
+Adds a new `buttonBorderRadius` property to the `astro-dev-toolbar-button` component for the dev toolbar component library. This property can be useful to make a fully rounded button with an icon in the center.
diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts
index 0cff203cf..af839ae61 100644
--- a/packages/astro/src/@types/astro.ts
+++ b/packages/astro/src/@types/astro.ts
@@ -33,6 +33,7 @@ import type {
DevToolbarCard,
DevToolbarHighlight,
DevToolbarIcon,
+ DevToolbarRadioCheckbox,
DevToolbarSelect,
DevToolbarToggle,
DevToolbarTooltip,
@@ -3087,6 +3088,7 @@ declare global {
'astro-dev-toolbar-icon': DevToolbarIcon;
'astro-dev-toolbar-card': DevToolbarCard;
'astro-dev-toolbar-select': DevToolbarSelect;
+ 'astro-dev-toolbar-radio-checkbox': DevToolbarRadioCheckbox;
// Deprecated names
// TODO: Remove in Astro 5.0
diff --git a/packages/astro/src/runtime/client/dev-toolbar/entrypoint.ts b/packages/astro/src/runtime/client/dev-toolbar/entrypoint.ts
index dc8d043a2..2558a4db2 100644
--- a/packages/astro/src/runtime/client/dev-toolbar/entrypoint.ts
+++ b/packages/astro/src/runtime/client/dev-toolbar/entrypoint.ts
@@ -25,6 +25,7 @@ document.addEventListener('DOMContentLoaded', async () => {
DevToolbarBadge,
DevToolbarIcon,
DevToolbarSelect,
+ DevToolbarRadioCheckbox,
},
] = await Promise.all([
loadDevToolbarApps() as DevToolbarAppDefinition[],
@@ -48,6 +49,7 @@ document.addEventListener('DOMContentLoaded', async () => {
customElements.define('astro-dev-toolbar-badge', DevToolbarBadge);
customElements.define('astro-dev-toolbar-icon', DevToolbarIcon);
customElements.define('astro-dev-toolbar-select', DevToolbarSelect);
+ customElements.define('astro-dev-toolbar-radio-checkbox', DevToolbarRadioCheckbox);
// Add deprecated names
// TODO: Remove in Astro 5.0
diff --git a/packages/astro/src/runtime/client/dev-toolbar/ui-library/button.ts b/packages/astro/src/runtime/client/dev-toolbar/ui-library/button.ts
index 9a3705817..067a1cf2a 100644
--- a/packages/astro/src/runtime/client/dev-toolbar/ui-library/button.ts
+++ b/packages/astro/src/runtime/client/dev-toolbar/ui-library/button.ts
@@ -2,13 +2,16 @@ import { settings } from '../settings.js';
const sizes = ['small', 'medium', 'large'] as const;
const styles = ['ghost', 'outline', 'purple', 'gray', 'red', 'green', 'yellow', 'blue'] as const;
+const borderRadii = ['normal', 'rounded'] as const;
type ButtonSize = (typeof sizes)[number];
type ButtonStyle = (typeof styles)[number];
+type ButtonBorderRadius = (typeof borderRadii)[number];
export class DevToolbarButton extends HTMLElement {
_size: ButtonSize = 'small';
_buttonStyle: ButtonStyle = 'purple';
+ _buttonBorderRadius: ButtonBorderRadius = 'normal';
get size() {
return this._size;
@@ -40,7 +43,22 @@ export class DevToolbarButton extends HTMLElement {
this.updateStyle();
}
- static observedAttributes = ['button-style', 'size'];
+ get buttonBorderRadius() {
+ return this._buttonBorderRadius;
+ }
+
+ set buttonBorderRadius(value) {
+ if (!borderRadii.includes(value)) {
+ settings.logger.error(
+ `Invalid border-radius: ${value}, expected one of ${borderRadii.join(', ')}, got ${value}.`
+ );
+ return;
+ }
+ this._buttonBorderRadius = value;
+ this.updateStyle();
+ }
+
+ static observedAttributes = ['button-style', 'size', 'button-border-radius'];
shadowRoot: ShadowRoot;
@@ -88,8 +106,14 @@ export class DevToolbarButton extends HTMLElement {
--small-font-size: 12px;
--large-padding: 12px 16px;
+ --large-rounded-padding: 12px 12px;
--medium-padding: 8px 12px;
+ --medium-rounded-padding: 8px 8px;
--small-padding: 4px 8px;
+ --small-rounded-padding: 4px 4px;
+
+ --normal-border-radius: 4px;
+ --rounded-border-radius: 9999px;
border: 1px solid var(--border);
padding: var(--padding);
@@ -97,7 +121,7 @@ export class DevToolbarButton extends HTMLElement {
background: var(--background);
color: var(--text-color);
- border-radius: 4px;
+ border-radius: var(--border-radius);
display: flex;
align-items: center;
justify-content: center;
@@ -137,8 +161,13 @@ export class DevToolbarButton extends HTMLElement {
--background: var(--${this.buttonStyle}-background);
--border: var(--${this.buttonStyle}-border);
--font-size: var(--${this.size}-font-size);
- --padding: var(--${this.size}-padding);
--text-color: var(--${this.buttonStyle}-text);
+ ${
+ this.buttonBorderRadius === 'normal'
+ ? '--padding: var(--' + this.size + '-padding);'
+ : '--padding: var(--' + this.size + '-rounded-padding);'
+ }
+ --border-radius: var(--${this.buttonBorderRadius}-border-radius);
}`;
}
}
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 7b1197ab7..56765c4ca 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
@@ -7,3 +7,4 @@ export { DevToolbarSelect } from './select.js';
export { DevToolbarToggle } from './toggle.js';
export { DevToolbarTooltip } from './tooltip.js';
export { DevToolbarWindow } from './window.js';
+export { DevToolbarRadioCheckbox } from './radio-checkbox.js';
diff --git a/packages/astro/src/runtime/client/dev-toolbar/ui-library/radio-checkbox.ts b/packages/astro/src/runtime/client/dev-toolbar/ui-library/radio-checkbox.ts
new file mode 100644
index 000000000..a223bf1a8
--- /dev/null
+++ b/packages/astro/src/runtime/client/dev-toolbar/ui-library/radio-checkbox.ts
@@ -0,0 +1,121 @@
+const styles = ['purple', 'gray', 'red', 'green', 'yellow', 'blue'] as const;
+
+type RadioStyle = (typeof styles)[number];
+
+export class DevToolbarRadioCheckbox extends HTMLElement {
+ private _radioStyle: RadioStyle = 'purple';
+ input: HTMLInputElement;
+
+ shadowRoot: ShadowRoot;
+
+ get radioStyle() {
+ return this._radioStyle;
+ }
+
+ set radioStyle(value) {
+ if (!styles.includes(value)) {
+ console.error(`Invalid style: ${value}, expected one of ${styles.join(', ')}.`);
+ return;
+ }
+ this._radioStyle = value;
+ this.updateStyle();
+ }
+
+ static observedAttributes = ['radio-style', 'checked', 'disabled', 'name', 'value'];
+
+ constructor() {
+ super();
+ this.shadowRoot = this.attachShadow({ mode: 'open' });
+
+ this.shadowRoot.innerHTML = `
+ <style>
+ :host {
+ --purple-unchecked: rgba(224, 204, 250, 0.33);
+ --purple-checked: rgba(224, 204, 250, 1);
+
+ --gray-unchecked: rgba(191, 193, 201, 0.33);
+ --gray-checked: rgba(191, 193, 201, 1);
+
+ --red-unchecked: rgba(249, 196, 215, 0.33);
+ --red-checked: rgba(179, 62, 102, 1);
+
+ --green-unchecked: rgba(213, 249, 196, 0.33);
+ --green-checked: rgba(61, 125, 31, 1);
+
+ --yellow-unchecked: rgba(255, 236, 179, 0.33);
+ --yellow-checked: rgba(181, 138, 45, 1);
+
+ --blue-unchecked: rgba(189, 195, 255, 0.33);
+ --blue-checked: rgba(54, 69, 217, 1);
+ }
+
+ input[type="radio"] {
+ appearance: none;
+ -webkit-appearance: none;
+ display: flex;
+ align-content: center;
+ justify-content: center;
+ border: 2px solid var(--unchecked-color);
+ border-radius: 9999px;
+ width: 16px;
+ height: 16px;
+ }
+
+ input[type="radio"]::before {
+ content: "";
+ background-color: var(--checked-color);
+ width: 8px;
+ height: 8px;
+ border-radius: 9999px;
+ visibility: hidden;
+ margin: 2px;
+ }
+
+ input[type="radio"]:checked {
+ border-color: var(--checked-color);
+ }
+
+ input[type="radio"]:checked::before {
+ visibility: visible;
+ }
+ </style>
+ <style id="selected-style"></style>
+ `;
+ this.input = document.createElement('input');
+ this.input.type = 'radio';
+ this.shadowRoot.append(this.input);
+ }
+
+ connectedCallback() {
+ this.updateInputState();
+ this.updateStyle();
+ }
+
+ updateStyle() {
+ const styleElement = this.shadowRoot.querySelector<HTMLStyleElement>('#selected-style');
+
+ if (styleElement) {
+ styleElement.innerHTML = `
+ :host {
+ --unchecked-color: var(--${this._radioStyle}-unchecked);
+ --checked-color: var(--${this._radioStyle}-checked);
+ }
+ `;
+ }
+ }
+
+ updateInputState() {
+ this.input.checked = this.hasAttribute('checked');
+ this.input.disabled = this.hasAttribute('disabled');
+ this.input.name = this.getAttribute('name') || '';
+ this.input.value = this.getAttribute('value') || '';
+ }
+
+ attributeChangedCallback() {
+ if (this.hasAttribute('radio-style')) {
+ this.radioStyle = this.getAttribute('radio-style') as RadioStyle;
+ }
+
+ this.updateInputState();
+ }
+}