Skip to content

Commit

Permalink
feat: add theme toggle button to error overlay (#5884)
Browse files Browse the repository at this point in the history
* feat: add theme toggle button for error overlay

* add changeset

* simplify toggling logic

Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>

* redesign toggle

* code figma design

* style: remove code indent

* add `aria-hidden` to svgs

Co-authored-by: Yan Thomas <61414485+Yan-Thomas@users.noreply.github.com>

* apply Yan a11y suggestions

Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
Co-authored-by: Yan Thomas <61414485+Yan-Thomas@users.noreply.github.com>
  • Loading branch information
3 people committed Jan 18, 2023
1 parent 64b8082 commit ce5c5db
Show file tree
Hide file tree
Showing 2 changed files with 198 additions and 49 deletions.
5 changes: 5 additions & 0 deletions .changeset/few-rice-report.md
@@ -0,0 +1,5 @@
---
'astro': patch
---

Add a theme toggle button to the error overlay
242 changes: 193 additions & 49 deletions packages/astro/src/core/errors/overlay.ts
Expand Up @@ -59,7 +59,14 @@ const style = /* css */ `
rgba(255, 255, 255, 0.96449) 78.38%,
rgba(255, 255, 255, 0.991353) 84.11%,
#ffffff 89.84%
);
);
/* Theme toggle */
--toggle-ball-color: var(--accent);
--toggle-tabel-background: var(--background);
--sun-icon-color: #ffffff;
--moon-icon-color: #a3acc8;
--toggle-border-color: #C3CADB;
/* Syntax Highlighting */
--shiki-color-text: #000000;
Expand All @@ -74,54 +81,145 @@ const style = /* css */ `
--shiki-token-link: #ee0000;
}
@media (prefers-color-scheme: dark) {
:host {
--background: #090b11;
--error-text: #f49090;
--error-text-hover: #ffaaaa;
--title-text: #ffffff;
--box-background: #141925;
--box-background-hover: #2e333f;
--hint-text: #a3acc8;
--hint-text-hover: #bdc6e2;
--border: #283044;
--accent: #c490f4;
--accent-hover: #deaaff;
--stack-text: #c3cadb;
--misc-text: #8490b5;
--houston-overlay: linear-gradient(
180deg,
rgba(9, 11, 17, 0) 3.95%,
rgba(9, 11, 17, 0.0086472) 9.68%,
rgba(9, 11, 17, 0.03551) 15.4%,
rgba(9, 11, 17, 0.0816599) 21.13%,
rgba(9, 11, 17, 0.147411) 26.86%,
rgba(9, 11, 17, 0.231775) 32.58%,
rgba(9, 11, 17, 0.331884) 38.31%,
rgba(9, 11, 17, 0.442691) 44.03%,
rgba(9, 11, 17, 0.557309) 49.76%,
rgba(9, 11, 17, 0.668116) 55.48%,
rgba(9, 11, 17, 0.768225) 61.21%,
rgba(9, 11, 17, 0.852589) 66.93%,
rgba(9, 11, 17, 0.91834) 72.66%,
rgba(9, 11, 17, 0.96449) 78.38%,
rgba(9, 11, 17, 0.991353) 84.11%,
#090b11 89.84%
);
:host(.astro-dark) {
--background: #090b11;
--error-text: #f49090;
--error-text-hover: #ffaaaa;
--title-text: #ffffff;
--box-background: #141925;
--box-background-hover: #2e333f;
--hint-text: #a3acc8;
--hint-text-hover: #bdc6e2;
--border: #283044;
--accent: #c490f4;
--accent-hover: #deaaff;
--stack-text: #c3cadb;
--misc-text: #8490b5;
/* Syntax Highlighting */
--shiki-color-text: #ffffff;
--shiki-token-constant: #90f4e3;
--shiki-token-string: #f4cf90;
--shiki-token-comment: #8490b5;
--shiki-token-keyword: var(--accent);
--shiki-token-parameter: #aa0000;
--shiki-token-function: #90f4e3;
--shiki-token-string-expression: #f4cf90;
--shiki-token-punctuation: #ffffff;
--shiki-token-link: #ee0000;
}
--houston-overlay: linear-gradient(
180deg,
rgba(9, 11, 17, 0) 3.95%,
rgba(9, 11, 17, 0.0086472) 9.68%,
rgba(9, 11, 17, 0.03551) 15.4%,
rgba(9, 11, 17, 0.0816599) 21.13%,
rgba(9, 11, 17, 0.147411) 26.86%,
rgba(9, 11, 17, 0.231775) 32.58%,
rgba(9, 11, 17, 0.331884) 38.31%,
rgba(9, 11, 17, 0.442691) 44.03%,
rgba(9, 11, 17, 0.557309) 49.76%,
rgba(9, 11, 17, 0.668116) 55.48%,
rgba(9, 11, 17, 0.768225) 61.21%,
rgba(9, 11, 17, 0.852589) 66.93%,
rgba(9, 11, 17, 0.91834) 72.66%,
rgba(9, 11, 17, 0.96449) 78.38%,
rgba(9, 11, 17, 0.991353) 84.11%,
#090b11 89.84%
);
/* Theme toggle */
--sun-icon-color: #505D84;
--moon-icon-color: #090B11;
--toggle-border-color: #3D4663;
/* Syntax Highlighting */
--shiki-color-text: #ffffff;
--shiki-token-constant: #90f4e3;
--shiki-token-string: #f4cf90;
--shiki-token-comment: #8490b5;
--shiki-token-keyword: var(--accent);
--shiki-token-parameter: #aa0000;
--shiki-token-function: #90f4e3;
--shiki-token-string-expression: #f4cf90;
--shiki-token-punctuation: #ffffff;
--shiki-token-link: #ee0000;
}
#theme-toggle-wrapper{
position: relative;
display: inline-block
}
#theme-toggle-wrapper > div{
position: absolute;
right: 3px;
margin-top: 3px;
}
.theme-toggle-checkbox {
opacity: 0;
position: absolute;
}
#theme-toggle-label {
background-color: var(--toggle-tabel-background);
border-radius: 50px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: space-between;
padding: 7.5px;
position: relative;
width: 66px;
height: 30px;
transform: scale(1.2);
box-shadow: 0 0 0 1px var(--toggle-border-color);
outline: 1px solid transparent;
}
.theme-toggle-checkbox:focus ~ #theme-toggle-label {
outline: 2px solid var(--toggle-border-color);
outline-offset: 4px;
}
#theme-toggle-label #theme-toggle-ball {
background-color: var(--accent);
border-radius: 50%;
position: absolute;
height: 30px;
width: 30px;
transform: translateX(-7.5px);
transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0ms;
}
@media (forced-colors: active) {
#theme-toggle-label {
--moon-icon-color: CanvasText;
--sun-icon-color: CanvasText;
}
#theme-toggle-label #theme-toggle-ball {
background-color: SelectedItem;
}
}
.theme-toggle-checkbox:checked + #theme-toggle-label #theme-toggle-ball {
transform: translateX(28.5px);
}
.sr-only {
border: 0 !important;
clip: rect(1px, 1px, 1px, 1px) !important;
-webkit-clip-path: inset(50%) !important;
clip-path: inset(50%) !important;
height: 1px !important;
margin: -1px !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
width: 1px !important;
white-space: nowrap !important;
}
.icon-tabler{
transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0ms;
z-index: 10;
}
.icon-tabler-moon {
color: var(--moon-icon-color);
}
.icon-tabler-sun {
color: var(--sun-icon-color);
}
#backdrop {
Expand All @@ -138,6 +236,7 @@ const style = /* css */ `
#layout {
max-width: min(100%, 1280px);
position: relative;
width: 1280px;
margin: 0 auto;
padding: 40px;
Expand All @@ -151,6 +250,12 @@ const style = /* css */ `
padding: 12px;
margin-top: 12px;
}
#theme-toggle-wrapper > div{
position: absolute;
right: 22px;
margin-top: 47px;
}
#layout {
padding: 0;
Expand All @@ -172,6 +277,7 @@ const style = /* css */ `
#header-left {
min-height: 63px;
display: flex;
align-items: flex-start;
flex-direction: column;
justify-content: end;
}
Expand Down Expand Up @@ -390,14 +496,33 @@ ${style.trim()}
</style>
<div id="backdrop">
<div id="layout">
<div id="theme-toggle-wrapper">
<div>
<input type="checkbox" class="theme-toggle-checkbox" id="chk" />
<label id="theme-toggle-label" for="chk">
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="icon-tabler icon-tabler-sun" width="15px" height="15px" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<circle cx="12" cy="12" r="4" />
<path d="M3 12h1m8 -9v1m8 8h1m-9 8v1m-6.4 -15.4l.7 .7m12.1 -.7l-.7 .7m0 11.4l.7 .7m-12.1 -.7l-.7 .7" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="icon-tabler icon-tabler-moon" width="15" height="15" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z" />
</svg>
<div id="theme-toggle-ball">
<span class="sr-only">Use dark theme</span>
</div>
</label>
</div>
</div>
<header id="header">
<section id="header-left">
<h2 id="name"></h2>
<h1 id="title">An error occurred.</h1>
</section>
<div id="houston-overlay"></div>
<div id="houston">
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="175" height="131" fill="none"><path fill="currentColor" d="M55.977 81.512c0 8.038-6.516 14.555-14.555 14.555S26.866 89.55 26.866 81.512c0-8.04 6.517-14.556 14.556-14.556 8.039 0 14.555 6.517 14.555 14.556Zm24.745-5.822c0-.804.651-1.456 1.455-1.456h11.645c.804 0 1.455.652 1.455 1.455v11.645c0 .804-.651 1.455-1.455 1.455H82.177a1.456 1.456 0 0 1-1.455-1.455V75.689Zm68.411 5.822c0 8.038-6.517 14.555-14.556 14.555-8.039 0-14.556-6.517-14.556-14.555 0-8.04 6.517-14.556 14.556-14.556 8.039 0 14.556 6.517 14.556 14.556Z"/><rect width="168.667" height="125" x="3.667" y="3" stroke="currentColor" stroke-width="4" rx="20.289"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="175" height="131" fill="none"><path fill="currentColor" d="M55.977 81.512c0 8.038-6.516 14.555-14.555 14.555S26.866 89.55 26.866 81.512c0-8.04 6.517-14.556 14.556-14.556 8.039 0 14.555 6.517 14.555 14.556Zm24.745-5.822c0-.804.651-1.456 1.455-1.456h11.645c.804 0 1.455.652 1.455 1.455v11.645c0 .804-.651 1.455-1.455 1.455H82.177a1.456 1.456 0 0 1-1.455-1.455V75.689Zm68.411 5.822c0 8.038-6.517 14.555-14.556 14.555-8.039 0-14.556-6.517-14.556-14.555 0-8.04 6.517-14.556 14.556-14.556 8.039 0 14.556 6.517 14.556 14.556Z"/><rect width="168.667" height="125" x="3.667" y="3" stroke="currentColor" stroke-width="4" rx="20.289"/></svg>
</div>
</header>
Expand Down Expand Up @@ -445,6 +570,25 @@ class ErrorOverlay extends HTMLElement {
this.root = this.attachShadow({ mode: 'open' });
this.root.innerHTML = overlayTemplate;

// theme toggle logic
const themeToggle = this.root.querySelector<HTMLInputElement>('.theme-toggle-checkbox');
if (
localStorage.astroErrorOverlayTheme === 'dark' ||
(!('astroErrorOverlayTheme' in localStorage) &&
window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
this?.classList.add('astro-dark');
themeToggle!.checked = true;
} else {
this?.classList.remove('astro-dark');
themeToggle!.checked = false;
}
themeToggle?.addEventListener('click', () => {
const isDark = localStorage.astroErrorOverlayTheme === 'dark';
this?.classList.toggle('astro-dark', !isDark);
localStorage.astroErrorOverlayTheme = isDark ? 'light' : 'dark';
});

this.text('#name', err.name);
this.text('#title', err.title);
this.text('#message-content', err.message, true);
Expand Down

0 comments on commit ce5c5db

Please sign in to comment.