This commit is contained in:
Kelsey Jackson
2025-05-27 15:36:26 -05:00
7 changed files with 62 additions and 23 deletions

View File

@@ -58,6 +58,8 @@
"exportmaps",
"exportparts",
"fieldsets",
"focusin",
"focusout",
"fontawesome",
"formaction",
"formdata",

View File

@@ -35,8 +35,8 @@ const globalData = {
export default function (eleventyConfig) {
/**
* If you plan to add or remove any of these extensions, make sure to let either Konnor or Cory know as these passthrough extensions
* will also need to be updated in the Web Awesome App.
* If you plan to add or remove any of these extensions, make sure to let either Konnor or Cory know as these
* passthrough extensions will also need to be updated in the Web Awesome App.
*/
const passThroughExtensions = ['js', 'css', 'png', 'svg', 'jpg', 'mp4'];
@@ -44,11 +44,11 @@ export default function (eleventyConfig) {
const passThrough = [...passThroughExtensions.map(ext => path.join(baseDir, '**/*.' + ext))];
/**
* This is the guard we use for now to make sure our final built files dont need a 2nd pass by the server. This keeps us able to still deploy the bare HTML files on Vercel until the app is ready.
* This is the guard we use for now to make sure our final built files don't need a 2nd pass by the server. This keeps
* us able to still deploy the bare HTML files on Vercel until the app is ready.
*/
const serverBuild = process.env.WEBAWESOME_SERVER === 'true';
// Add template data
for (let name in globalData) {
eleventyConfig.addGlobalData(name, globalData[name]);
}
@@ -135,6 +135,10 @@ export default function (eleventyConfig) {
// Various text replacements
eleventyConfig.addPlugin(
replaceTextPlugin([
{
replace: /\[version\]/gs,
replaceWith: packageData.version,
},
// Replace [issue:1234] with a link to the issue on GitHub
{
replace: /\[pr:([0-9]+)\]/gs,

View File

@@ -1,5 +1,6 @@
import { parse } from 'node-html-parser';
import { v4 as uuid } from 'uuid';
import { markdown } from '../_utils/markdown.js';
/**
* Eleventy plugin to turn `<code class="example">` blocks into live examples.
@@ -24,6 +25,7 @@ export function codeExamplesPlugin(options = {}) {
const pre = code.closest('pre');
const hasButtons = !code.classList.contains('no-buttons');
const isOpen = code.classList.contains('open') || !hasButtons;
const isViewportDemo = code.classList.contains('viewport');
const noEdit = code.classList.contains('no-edit');
const id = `code-example-${uuid().slice(-12)}`;
let preview = pre.textContent;
@@ -33,10 +35,29 @@ export function codeExamplesPlugin(options = {}) {
root.querySelectorAll('script').forEach(script => script.setAttribute('type', 'module'));
preview = root.toString();
const escapedHtml = markdown.utils.escapeHtml(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Awesome Demo</title>
<link rel="stylesheet" href="https://early.webawesome.com/webawesome@[version]/dist/styles/themes/default.css" />
<link rel="stylesheet" href="https://early.webawesome.com/webawesome@[version]/dist/styles/webawesome.css" />
<script type="module" src="https://early.webawesome.com/webawesome@[version]/dist/webawesome.loader.js"></script>
</head>
<body>
${preview}
</body>
</html>
`);
const codeExample = parse(`
<div class="code-example ${isOpen ? 'open' : ''}">
<div class="code-example ${isOpen ? 'open' : ''} ${isViewportDemo ? 'is-viewport-demo' : ''}">
<div class="code-example-preview">
${preview}
${isViewportDemo ? ` <wa-viewport-demo><iframe srcdoc="${escapedHtml}"></iframe></wa-viewport-demo>` : preview}
<div class="code-example-resizer" aria-hidden="true">
<wa-icon name="grip-lines-vertical"></wa-icon>
</div>

View File

@@ -92,10 +92,22 @@ const colorScheme = new ThemeAspect({
let dark = this.computedValue === 'dark';
document.documentElement.classList.toggle(`wa-dark`, dark);
document.documentElement.dispatchEvent(new CustomEvent('wa-color-scheme-change', { detail: { dark } }));
syncViewportDemoColorSchemes();
});
},
});
function syncViewportDemoColorSchemes() {
const isDark = document.documentElement.classList.contains('wa-dark');
// Update viewport demo color schemes in code examples
document.querySelectorAll('.code-example.is-viewport-demo wa-viewport-demo').forEach(demo => {
demo.querySelectorAll('iframe').forEach(iframe => {
iframe.contentWindow.document.documentElement?.classList?.toggle('wa-dark', isDark);
});
});
}
// Update the color scheme when the preference changes
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => colorScheme.set());
@@ -109,3 +121,12 @@ document.addEventListener('keydown', event => {
colorScheme.set(colorScheme.get() === 'dark' ? 'light' : 'dark');
}
});
// When rendering a code example with a viewport demo, set the theme to match initially
document.querySelectorAll('.code-example.is-viewport-demo wa-viewport-demo iframe').forEach(iframe => {
const isDark = document.documentElement.classList.contains('wa-dark');
iframe.addEventListener('load', () => {
iframe.contentWindow.document.documentElement?.classList?.toggle('wa-dark', isDark);
});
});

View File

@@ -31,7 +31,7 @@ tags: blog-news
## Modal
```html {.example viewport}
```html {.example .viewport}
<wa-dialog without-header label="Subscribe or continue with ads" class="dialog-deny-close" style="--width: 90ch;" open>
<div class="wa-stack wa-gap-xl">
<h2 class="wa-heading-m">Want to subscribe or continue using our Products for free with ads?</h2>
@@ -74,7 +74,7 @@ tags: blog-news
## Footer
```html {.example viewport}
```html {.example .viewport}
<wa-drawer
without-header
label="Free article limit reached"

View File

@@ -201,8 +201,8 @@ isPro: true
## Drawer
```html {.example viewport}
<wa-drawer label="Shopping Cart" id="shopping-card-drawer">
```html {.example .viewport}
<wa-drawer label="Shopping Cart" open>
<div class="wa-stack">
<article class="wa-flank" style="--flank-size: 6rem">
<div class="wa-frame wa-border-radius-m">

View File

@@ -36,7 +36,7 @@
/* Style frame like a window */
border: var(--viewport-bezel-width) solid transparent;
border-radius: calc(var(--wa-border-radius-m));
border-radius: var(--wa-border-radius-m);
/* Window-like frame styling */
--button-params: 0.4em / 0.5em 0.5em border-box;
@@ -49,14 +49,13 @@
var(--button-params),
var(--wa-color-gray-95);
background-repeat: no-repeat;
box-shadow:
0 0 0 1px var(--wa-color-gray-90),
var(--wa-shadow-m);
&.resized {
aspect-ratio: var(--iframe-manual-aspect-ratio);
}
background-color: var(--wa-color-neutral-fill-normal);
/* User has not yet resized the viewport */
&:not(.resized) ::slotted(iframe),
&:not(.resized) slot {
@@ -79,6 +78,7 @@ slot {
scale: var(--zoom);
transform-origin: top left;
resize: var(--viewport-resize);
border-radius: var(--wa-border-radius-m);
overflow: auto;
/* The width and height specified here are only applied if the iframe is not manually resized */
@@ -91,7 +91,6 @@ slot {
/* Divide with var(--zoom) to get lengths that stay constant regardless of zoom level */
border: calc(1px / var(--zoom)) solid var(--wa-color-gray-90);
background: var(--viewport-background-color);
}
[part~='controls'] {
@@ -120,14 +119,9 @@ slot {
display: none;
vertical-align: -0.1em;
font-size: 85%;
color: var(--wa-color-gray-70);
}
wa-icon-button {
&:not(:hover, :focus) {
opacity: 0.5;
}
&::part(base) {
padding: 0;
}
@@ -137,9 +131,6 @@ slot {
display: flex;
align-items: center;
gap: 0.3em;
font-weight: 600;
color: var(--wa-color-text-quiet);
opacity: 80%;
}
[part~='zoom-in'],