Skip to content

Commit

Permalink
feat(toolbar): Allow every element to have every color (#10186)
Browse files Browse the repository at this point in the history
* feat(toolbar): Allow every element to have every color

* chore: changeset

* fix: add validatio

* fix: ok but what happened even

* nit: cooler messages

* fix: toggles
  • Loading branch information
Princesseuh authored Mar 8, 2024
1 parent 33616ba commit 959ca5f
Show file tree
Hide file tree
Showing 7 changed files with 413 additions and 99 deletions.
5 changes: 5 additions & 0 deletions .changeset/khaki-elephants-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"astro": minor
---

Adds the ability to set colors on all the included UI elements for dev toolbar apps. Previously, only badge and buttons could be customized.
10 changes: 8 additions & 2 deletions packages/astro/src/runtime/client/dev-toolbar/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ function getSettings() {
localStorage.setItem('astro:dev-toolbar:settings', JSON.stringify(_settings));
}

function log(message: string) {
function log(message: string, level: 'log' | 'warn' | 'error' = 'log') {
// eslint-disable-next-line no-console
console.log(
console[level](
`%cAstro`,
'background: linear-gradient(66.77deg, #D83333 0%, #F041FF 100%); color: white; padding-inline: 4px; border-radius: 2px; font-family: monospace;',
message
Expand All @@ -46,6 +46,12 @@ function getSettings() {
updateSetting,
logger: {
log,
warn: (message: string) => {
log(message, 'warn');
},
error: (message: string) => {
log(message, 'error');
},
verboseLog: (message: string) => {
if (_settings.verbose) {
log(message);
Expand Down
120 changes: 84 additions & 36 deletions packages/astro/src/runtime/client/dev-toolbar/ui-library/badge.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,53 @@
type BadgeSize = 'small' | 'large';
type BadgeStyle = 'purple' | 'gray' | 'red' | 'green' | 'yellow';
import { settings } from '../settings.js';

const sizes = ['small', 'large'] as const;
const styles = ['purple', 'gray', 'red', 'green', 'yellow', 'blue'] as const;

type BadgeSize = (typeof sizes)[number];
type BadgeStyle = (typeof styles)[number];

export class DevToolbarBadge extends HTMLElement {
size: BadgeSize = 'small';
badgeStyle: BadgeStyle = 'purple';
_size: BadgeSize = 'small';
_badgeStyle: BadgeStyle = 'purple';

get size() {
return this._size;
}

set size(value) {
if (!sizes.includes(value)) {
settings.logger.error(
`Invalid size: ${value}, expected one of ${sizes.join(', ')}, got ${value}.`
);
return;
}
this._size = value;
this.updateStyle();
}

get badgeStyle() {
return this._badgeStyle;
}

set badgeStyle(value) {
if (!styles.includes(value)) {
settings.logger.error(
`Invalid style: ${value}, expected one of ${styles.join(', ')}, got ${value}.`
);
return;
}
this._badgeStyle = value;
this.updateStyle();
}

shadowRoot: ShadowRoot;

static observedAttributes = ['badge-style', 'size'];

constructor() {
super();
this.shadowRoot = this.attachShadow({ mode: 'open' });

if (this.hasAttribute('size')) this.size = this.getAttribute('size') as BadgeSize;

if (this.hasAttribute('badge-style'))
this.badgeStyle = this.getAttribute('badge-style') as BadgeStyle;

const classes = [`badge--${this.size}`, `badge--${this.badgeStyle}`];
this.shadowRoot.innerHTML = `
<style>
.badge {
Expand All @@ -25,47 +56,64 @@ export class DevToolbarBadge extends HTMLElement {
border: 1px solid transparent;
padding: 8px;
font-size: 12px;
color: #fff;
height: 20px;
color: var(--text-color);
height: var(--size);
border: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: center;
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
.badge--large {
height: 24px;
}
--purple-text: rgba(224, 204, 250, 1);
--purple-border: rgba(113, 24, 226, 1);
.badge--gray {
color: rgba(191, 193, 201, 1);
border-color: rgba(191, 193, 201, 1);
}
--gray-text: rgba(191, 193, 201, 1);
--gray-border:rgba(191, 193, 201, 1);
.badge--purple {
color: rgba(224, 204, 250, 1);
border-color: rgba(113, 24, 226, 1);
}
--red-text: rgba(249, 196, 215, 1);
--red-border: rgba(179, 62, 102, 1);
.badge--red {
color: rgba(249, 196, 215, 1);
border-color: rgba(179, 62, 102, 1);
}
--green-text: rgba(213, 249, 196, 1);
--green-border: rgba(61, 125, 31, 1);
.badge--green {
color: rgba(213, 249, 196, 1);
border-color: rgba(61, 125, 31, 1);
}
--yellow-text: rgba(249, 233, 196, 1);
--yellow-border: rgba(181, 138, 45, 1);
.badge--yellow {
color: rgba(249, 233, 196, 1);
border-color: rgba(181, 138, 45, 1);
--blue-text: rgba(189, 195, 255, 1);
--blue-border: rgba(54, 69, 217, 1);
--large: 24px;
--small: 20px;
}
</style>
<style id="selected-style"></style>
<div class="badge ${classes.join(' ')}">
<div class="badge">
<slot></slot>
</div>
`;
}

connectedCallback() {
this.updateStyle();
}

attributeChangedCallback() {
if (this.hasAttribute('badge-style'))
this.badgeStyle = this.getAttribute('badge-style') as BadgeStyle;

if (this.hasAttribute('size')) this.size = this.getAttribute('size') as BadgeSize;
}

updateStyle() {
const style = this.shadowRoot.getElementById('selected-style') as HTMLStyleElement;

style.innerHTML = `
.badge {
--text-color: var(--${this.badgeStyle}-text);
--border-color: var(--${this.badgeStyle}-border);
--size: var(--${this.size});
}
`;
}
}
163 changes: 112 additions & 51 deletions packages/astro/src/runtime/client/dev-toolbar/ui-library/button.ts
Original file line number Diff line number Diff line change
@@ -1,75 +1,110 @@
type ButtonSize = 'small' | 'medium' | 'large';
type ButtonStyle = 'ghost' | 'outline' | 'purple' | 'gray' | 'red';
import { settings } from '../settings.js';

const sizes = ['small', 'medium', 'large'] as const;
const styles = ['ghost', 'outline', 'purple', 'gray', 'red', 'green', 'yellow', 'blue'] as const;

type ButtonSize = (typeof sizes)[number];
type ButtonStyle = (typeof styles)[number];

export class DevToolbarButton extends HTMLElement {
size: ButtonSize = 'small';
buttonStyle: ButtonStyle = 'purple';
_size: ButtonSize = 'small';
_buttonStyle: ButtonStyle = 'purple';

get size() {
return this._size;
}

set size(value) {
if (!sizes.includes(value)) {
settings.logger.error(
`Invalid size: ${value}, expected one of ${sizes.join(', ')}, got ${value}.`
);
return;
}
this._size = value;
this.updateStyle();
}

get buttonStyle() {
return this._buttonStyle;
}

set buttonStyle(value) {
if (!styles.includes(value)) {
settings.logger.error(
`Invalid style: ${value}, expected one of ${styles.join(', ')}, got ${value}.`
);
return;
}
this._buttonStyle = value;
this.updateStyle();
}

static observedAttributes = ['button-style', 'size'];

shadowRoot: ShadowRoot;

constructor() {
super();
this.shadowRoot = this.attachShadow({ mode: 'open' });

if (this.hasAttribute('size')) this.size = this.getAttribute('size') as ButtonSize;

if (this.hasAttribute('button-style'))
this.buttonStyle = this.getAttribute('button-style') as ButtonStyle;

const classes = [`button--${this.size}`, `button--${this.buttonStyle}`];

this.shadowRoot.innerHTML = `
<style>
button {
border: 1px solid transparent;
color: #fff;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
}
--purple-background: rgba(113, 24, 226, 1);
--purple-border: rgba(224, 204, 250, 0.33);
--purple-text: #fff;
button:hover {
cursor: pointer;
}
--gray-background: rgba(52, 56, 65, 1);
--gray-border: rgba(71, 78, 94, 1);
--gray-text: #fff;
.button--small {
font-size: 12px;
padding: 4px 8px;
}
--red-background: rgba(179, 62, 102, 1);
--red-border: rgba(249, 196, 215, 0.33);
--red-text: #fff;
.button--medium {
font-size: 14px;
padding: 8px 12px;
}
--green-background: rgba(213, 249, 196, 1);
--green-border: rgba(61, 125, 31, 1);
--green-text: #000;
.button--large {
font-size: 16px;
padding: 12px 16px;
}
--yellow-background: rgba(255, 236, 179, 1);
--yellow-border: rgba(255, 191, 0, 1);
--yellow-text: #000;
.button--ghost {
background: transparent;
}
--blue-background: rgba(54, 69, 217, 1);
--blue-border: rgba(189, 195, 255, 1);
--blue-text: #fff;
.button--outline {
background: transparent;
border-color: #fff;
}
--outline-background: transparent;
--outline-border: #fff;
--outline-text: #fff;
.button--purple {
background: rgba(113, 24, 226, 1);
border-color: rgba(224, 204, 250, 0.33);
}
--ghost-background: transparent;
--ghost-border: transparent;
--ghost-text: #fff;
--large-font-size: 16px;
--medium-font-size: 14px;
--small-font-size: 12px;
--large-padding: 12px 16px;
--medium-padding: 8px 12px;
--small-padding: 4px 8px;
.button--gray {
background: rgba(52, 56, 65, 1);
border-color: rgba(71, 78, 94, 1);
border: 1px solid var(--border);
padding: var(--padding);
font-size: var(--font-size);
background: var(--background);
color: var(--text-color);
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
}
.button--red {
background: rgba(179, 62, 102, 1);
border-color: rgba(249, 196, 215, 0.33);
button:hover {
cursor: pointer;
}
/* TODO: Remove "astro-dev-overlay-icon" in Astro 5.0 */
Expand All @@ -81,10 +116,36 @@ export class DevToolbarButton extends HTMLElement {
margin-left: 0.5em;
}
</style>
<style id="selected-style"></style>
<button class="${classes.join(' ')}">
<button>
<slot></slot>
</button>
`;
}

connectedCallback() {
this.updateStyle();
}

updateStyle() {
const style = this.shadowRoot.getElementById('selected-style') as HTMLStyleElement;

style.innerHTML = `
button {
--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);
}
`;
}

attributeChangedCallback() {
if (this.hasAttribute('size')) this.size = this.getAttribute('size') as ButtonSize;

if (this.hasAttribute('button-style'))
this.buttonStyle = this.getAttribute('button-style') as ButtonStyle;
}
}
Loading

0 comments on commit 959ca5f

Please sign in to comment.