add back theme preview page

This commit is contained in:
Cory LaViska
2025-06-12 12:28:04 -04:00
parent e66eb25867
commit 5bd1774bad
10 changed files with 756 additions and 26 deletions

View File

@@ -161,6 +161,7 @@
"rgba",
"roadmap",
"Roboto",
"rockstar",
"roledescription",
"Sapan",
"saturationl",

View File

@@ -49,18 +49,10 @@ export default async function (eleventyConfig) {
flashes: '',
});
//
// Add free themes to preset themes global data
//
// TODO - let's iterate the directory and grab these. We'll need to figure out how to separate free from pro and
// update the pro config as well.
//
eleventyConfig.addGlobalData('freeThemes', ['default', 'awesome', 'shoelace']);
// Template filters - {{ content | filter }}
eleventyConfig.addFilter('inlineMarkdown', content => markdown.renderInline(content || ''));
eleventyConfig.addFilter('markdown', content => markdown.render(content || ''));
eleventyConfig.addFilter('stripExtension', string => parse(string).name);
eleventyConfig.addFilter('stripExtension', string => parse(string + '').name);
eleventyConfig.addFilter('stripPrefix', content => content.replace(/^wa-/, ''));
// Trims whitespace and pipes from the start and end of a string. Useful for CEM types, which can be pipe-delimited.
// With Prettier 3, this means a leading pipe will exist be present when the line wraps.
@@ -68,7 +60,22 @@ export default async function (eleventyConfig) {
return typeof content === 'string' ? content.replace(/^(\s|\|)/g, '').replace(/(\s|\|)$/g, '') : content;
});
// Custom filter to sort with a priority item first, e.g.
// {{ collection | sortWithFirst('fileSlug', 'default') }} => the item with the fileSlug of 'default' will be first
eleventyConfig.addFilter('sortWithFirst', function (collection, property, firstValue) {
const items = [...collection]; // Create a copy to avoid mutating original
return items.sort((a, b) => {
const aValue = property ? a[property] : a;
const bValue = property ? b[property] : b;
if (aValue === firstValue) return -1;
if (bValue === firstValue) return 1;
return 0;
});
});
//
// Add the componentPages collection
//
eleventyConfig.addCollection('componentPages', function (collectionApi) {
const componentPages = collectionApi.getFilteredByGlob(
path.join(eleventyConfig.directories.input, 'docs/components/**/*.md'),
@@ -91,6 +98,13 @@ export default async function (eleventyConfig) {
});
});
//
// Add the themes collection
//
eleventyConfig.addCollection('themePages', function (collectionApi) {
return collectionApi.getFilteredByGlob(path.join(eleventyConfig.directories.input, 'docs/themes/**/*.md'));
});
// Shortcodes - {% shortCode arg1, arg2 %}
eleventyConfig.addShortcode('cdnUrl', location => {
return `https://early.webawesome.com/webawesome@${packageData.version}/dist/` + (location || '').replace(/^\//, '');

View File

@@ -17,14 +17,7 @@
<link rel="icon" href="/assets/images/webawesome-logo.svg" />
<link rel="apple-touch-icon" href="/assets/images/app-icon.png">
{# Scripts #}
{# Hydration stuff #}
<script src="/assets/scripts/hydration-errors.js"></script>
<link rel="stylesheet" href="/assets/styles/hydration-errors.css">
<link rel="preconnect" href="https://cdn.jsdelivr.net">
{# Web Awesome #}
<script type="module" src="/dist/webawesome.loader.js"></script>
{# Fallback loading when using the free repo #}
@@ -43,7 +36,6 @@
</script>
<link id="theme-stylesheet" rel="stylesheet" href="/dist/styles/themes/default.css" render="blocking" fetchpriority="high" />
<link rel="stylesheet" href="/dist/styles/webawesome.css" />
{# Used by Web Awesome App to inject other assets into the head. #}

View File

@@ -1,14 +1,27 @@
{{ themePages | dump }}
<br><br>
<wa-select appearance="filled" size="small" value="default" pill class="theme-selector">
<wa-icon slot="prefix" name="paintbrush" variant="regular"></wa-icon>
{% for theme in freeThemes %}
<wa-option value="{{ theme }}">{{ theme | title }}</wa-option>
{# Free themes #}
{% for page in collections.themePages %}
{% if not page.data.isPro %}
<wa-option value="{{ page.data.file | stripExtension }}">{{ page.data.title }}</wa-option>
{% endif %}
{% endfor %}
{% if proThemes.length > 0 %}
{# Only show divider if there are pro themes #}
{% if collections.themePages | selectattr('data.isPro') | list | length > 0 %}
<wa-divider></wa-divider>
{% endif %}
{% for theme in proThemes %}
<wa-option value="{{ theme }}">{{ theme | title }}</wa-option>
{# Pro themes #}
{% for page in collections.themePages %}
{% if loop.first %}<wa-divider></wa-divider>{% endif %}
{% if page.data.isPro %}
<wa-option value="{{ page.data.file | stripExtension }}">{{ page.data.title }}</wa-option>
{% endif %}
{% endfor %}
</wa-select>

View File

@@ -0,0 +1,531 @@
<!DOCTYPE html>
<html lang="en" class="wa-cloak" data-fa-kit-code="b10bfbde90">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Awesome: Theme Showcase</title>
<!-- Web Awesome -->
<link id="theme-stylesheet" rel="stylesheet" href="/dist/styles/themes/default.css" render="blocking" fetchpriority="high" />
<link rel="stylesheet" href="/dist/styles/webawesome.css" />
<script type="module" src="/dist/webawesome.loader.js"></script>
<!-- Handle query params to adjust theme and color scheme -->
<script type="module">
const urlParams = new URLSearchParams(window.location.search);
const theme = urlParams.get('theme');
const colorScheme = urlParams.get('color-scheme');
const name = urlParams.get('name');
const description = urlParams.get('description');
const isPro = urlParams.get('isPro');
// Theme
if (theme) {
const themeStylesheet = document.getElementById('theme-stylesheet');
const currentHref = themeStylesheet.href;
const newHref = currentHref.replace('/themes/default.css', `/themes/${theme}.css`);
themeStylesheet.href = newHref;
}
// Color scheme
if (colorScheme === 'dark') {
document.documentElement.classList.add('wa-dark');
} else if (colorScheme === 'light') {
document.documentElement.classList.remove('wa-dark');
}
// Inject content after DOM loads
document.addEventListener('DOMContentLoaded', () => {
const nameElement = document.querySelector('[data-theme-name]');
const descriptionElement = document.querySelector('[data-theme-description]');
const freeBadge = document.querySelector('[data-free-badge]');
const proBadge = document.querySelector('[data-pro-badge]');
if (nameElement && name) {
nameElement.textContent = name;
}
if (descriptionElement && description) {
descriptionElement.textContent = description;
}
freeBadge.hidden = isPro;
proBadge.hidden = !isPro;;
});
</script>
</head>
<body>
<header>
<h2 data-theme-name="name">Theme</h2>
<wa-badge data-free-badge appearance="outlined" variant="neutral" hidden>FREE</wa-badge>
<wa-badge data-pro-badge appearance="accent" hidden>PRO</wa-badge>
<p data-theme-description>Description</p>
</header>
<div class="showcase-examples-wrapper" aria-hidden="true" data-no-outline>
<div class="showcase-examples">
<wa-card>
<div slot="header" class="wa-split">
<h3 class="wa-heading-m">Your Cart</h3>
<wa-button appearance="plain" size="small" tabindex="-1">
<wa-icon name="xmark" label="Close"></wa-icon>
</wa-button>
</div>
<div class="wa-stack wa-gap-xl">
<div class="wa-flank">
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-green-60); --text-color: var(--wa-color-green-95);">
<wa-icon slot="icon" name="sword-laser"></wa-icon>
</wa-avatar>
<div class="wa-stack wa-gap-2xs">
<div class="wa-split wa-gap-2xs">
<strong>Initiate Saber</strong>
<strong>$179.99</strong>
</div>
<div class="wa-split wa-gap-2xs wa-caption-m">
<span>Green</span>
<a href="#" tabindex="-1">Remove</a>
</div>
</div>
</div>
<wa-divider></wa-divider>
<div class="wa-flank">
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-cyan-60); --text-color: var(--wa-color-cyan-95);">
<wa-icon slot="icon" name="robot-astromech"></wa-icon>
</wa-avatar>
<div class="wa-stack wa-gap-2xs">
<div class="wa-split wa-gap-2xs">
<strong>Repair Droid</strong>
<strong>$3,049.99</strong>
</div>
<div class="wa-split wa-gap-2xs wa-caption-m">
<span>R-series</span>
<a href="#" tabindex="-1">Remove</a>
</div>
</div>
</div>
</div>
<div slot="footer" class="wa-stack">
<div class="wa-split">
<strong>Subtotal</strong>
<strong>$3,229.98</strong>
</div>
<span class="wa-caption-m">Shipping and taxes calculated at checkout.</span>
<wa-button tabindex="-1" variant="brand">
<wa-icon slot="start" name="shopping-bag"></wa-icon>
Checkout
</wa-button>
</div>
</wa-card>
<wa-card>
<wa-avatar shape="rounded" style="--size: 1.9lh; float: left; margin-right: var(--wa-space-m);">
<wa-icon slot="icon" name="hat-wizard" style="font-size: 1.75em;"></wa-icon>
</wa-avatar>
<p class="wa-body-l" style="margin: 0;">&ldquo;All we have to decide is what to do with the time that is given to us. There are other forces at work in this world, Frodo, besides the will of evil.&rdquo;</p>
</wa-card>
<wa-card>
<div class="wa-stack">
<h3 class="wa-heading-m">Sign In</h3>
<wa-input tabindex="-1" label="Email" placeholder="ddjarin@mandalore.gov">
<wa-icon slot="start" name="envelope" variant="regular"></wa-icon>
</wa-input>
<wa-input tabindex="-1" label="Password" type="password">
<wa-icon slot="start" name="lock" variant="regular"></wa-icon>
</wa-input>
<wa-button tabindex="-1" variant="brand">Sign In</wa-button>
<a href="#" tabindex="-1" class="wa-body-s">I forgot my password</a>
</div>
</wa-card>
<wa-card>
<div class="wa-stack">
<div class="wa-split">
<h3 class="wa-heading-m">To-Do</h3>
<wa-button appearance="plain" size="small" tabindex="-1">
<wa-icon name="plus" label="Add task"></wa-icon>
</wa-button>
</div>
<wa-checkbox tabindex="-1" checked>Umbrella for Adelard</wa-checkbox>
<wa-checkbox tabindex="-1" checked>Waste-paper basket for Dora</wa-checkbox>
<wa-checkbox tabindex="-1" checked>Pen and ink for Milo</wa-checkbox>
<wa-checkbox tabindex="-1">Mirror for Angelica</wa-checkbox>
<wa-checkbox tabindex="-1">Silver spoons for Lobelia</wa-checkbox>
</div>
<div slot="footer">
<a href="" tabindex="-1">View all completed</a>
</div>
</wa-card>
<wa-card>
<div class="wa-stack">
<div class="wa-frame wa-border-radius-m" style="align-self: center; max-inline-size: 25ch;">
<img src="https://images.unsplash.com/photo-1667514627762-521b1c815a89?q=20" alt="Album art">
</div>
<div class="wa-flank:end wa-align-items-start">
<div class="wa-stack wa-gap-3xs">
<div class="wa-cluster wa-gap-xs" style="height: 2.25em;">
<strong>The Stone Troll</strong>
<small><wa-badge variant="neutral" appearance="filled">E</wa-badge></small>
</div>
<span class="wa-caption-m">Samwise G</span>
</div>
<wa-button appearance="plain" size="small" tabindex="-1">
<wa-icon name="ellipsis" label="Options"></wa-icon>
</wa-button>
</div>
<div class="wa-stack wa-gap-2xs">
<wa-progress-bar value="34" style="height: 0.5em"></wa-progress-bar>
<div class="wa-split">
<span class="wa-caption-xs">1:01</span>
<span class="wa-caption-xs">-1:58</span>
</div>
</div>
<div class="wa-grid wa-align-items-center" style="--min-column-size: 1em; justify-items: center;">
<wa-button appearance="plain" tabindex="-1">
<wa-icon name="backward" label="Skip backward"></wa-icon>
</wa-button>
<wa-button appearance="plain" size="large" tabindex="-1">
<wa-icon name="pause" label="Pause"></wa-icon>
</wa-button>
<wa-button appearance="plain" tabindex="-1">
<wa-icon name="forward" label="Skip forward"></wa-icon>
</wa-button>
</div>
</div>
</wa-card>
<wa-card>
<div class="wa-stack">
<h3 class="wa-heading-m">Chalmun's Spaceport Cantina</h3>
<div class="wa-cluster wa-gap-xs">
<wa-rating value="4.6" readonly tabindex="-1"></wa-rating>
<strong>4.6</strong>
<span>(419 reviews)</span>
</div>
<div class="wa-cluster wa-gap-xs">
<div class="wa-cluster wa-gap-3xs">
<wa-icon name="dollar" style="color: var(--wa-color-green-60);"></wa-icon>
<wa-icon name="dollar" style="color: var(--wa-color-green-60);"></wa-icon>
<wa-icon name="dollar" style="color: var(--wa-color-green-60);"></wa-icon>
</div>
<span class="wa-caption-m">&bull;</span>
<wa-tag size="small">Cocktail Bar</wa-tag>
<wa-tag size="small">Gastropub</wa-tag>
<wa-tag size="small">Local Fare</wa-tag>
<wa-tag size="small">Gluten Free</wa-tag>
</div>
<div class="wa-flank wa-gap-xs">
<wa-icon name="location-dot"></wa-icon>
<a href="#" class="wa-caption-m" tabindex="-1">Mos Eisley, Tatooine</a>
</div>
</div>
</wa-card>
<wa-card>
<div class="wa-stack">
<div class="wa-flank:end">
<h3 id="odds-label" class="wa-heading-m">Tell Me the Odds</h3>
<wa-switch size="large" aria-labelledby="odds-label" tabindex="-1"></wa-switch>
</div>
<p class="wa-body-s">Allow protocol droids to inform you of probabilities, such as the success rate of navigating an asteroid field. We recommend setting this to "Never."</p>
</div>
</wa-card>
<wa-card>
<div class="wa-stack">
<div class="wa-split wa-align-items-start">
<dl class="wa-stack wa-gap-2xs">
<dt class="wa-heading-s">Amount</dt>
<dd class="wa-heading-l">$5,610.00</dd>
</dl>
<wa-badge appearance="filled outlined" variant="success">Paid</wa-badge>
</div>
<wa-divider></wa-divider>
<dl class="wa-stack">
<div class="wa-flank wa-align-items-center">
<dt><wa-icon name="user" label="Name" fixed-width></wa-icon></dt>
<dd>Tom Bombadil</dd>
</div>
<div class="wa-flank wa-align-items-center">
<dt><wa-icon name="calendar-days" label="Date" fixed-width></wa-icon></dt>
<dd><wa-format-date date="2025-03-15"></wa-format-date></dd>
</div>
<div class="wa-flank wa-align-items-center">
<dt><wa-icon name="coin-vertical" fixed-width></wa-icon></dt>
<dd>Paid with copper pennies</dd>
</div>
</dl>
</div>
<div slot="footer">
<a href="" class="wa-cluster wa-gap-2xs" tabindex="-1">
<span>Download Receipt</span>
<wa-icon name="arrow-right"></wa-icon>
</a>
</div>
</wa-card>
<wa-card>
<div class="wa-stack">
<div class="wa-split">
<div class="wa-cluster wa-heading-l">
<wa-icon name="book-sparkles"></wa-icon>
<h3>Fellowship</h3>
</div>
<wa-badge>Most Popular</wa-badge>
</div>
<span class="wa-flank wa-align-items-baseline wa-gap-2xs">
<span class="wa-heading-2xl">$120</span>
<span class="wa-caption-l">per year</span>
</span>
<p class="wa-caption-l">Carry great power (and great responsibility).</p>
<wa-button variant="brand" tabindex="-1">Get this Plan</wa-button>
</div>
<div slot="footer" class="wa-stack wap-gap-s">
<h4 class="wa-heading-s">What You Get</h4>
<div class="wa-stack">
<div class="wa-flank">
<wa-icon name="user" fixed-width></wa-icon>
<span class="wa-caption-m">9 users</span>
</div>
<div class="wa-flank">
<wa-icon name="ring" fixed-width></wa-icon>
<span class="wa-caption-m">1 ring</span>
</div>
<div class="wa-flank">
<wa-icon name="chess-rook" fixed-width></wa-icon>
<span class="wa-caption-m">API access to Isengard</span>
</div>
<div class="wa-flank">
<wa-icon name="feather" fixed-width></wa-icon>
<span class="wa-caption-m">Priority eagle support</span>
</div>
</div>
</div>
</wa-card>
<wa-card with-footer>
<div class="wa-flank:end">
<div class="wa-stack wa-gap-xs">
<div class="wa-cluster wa-gap-xs">
<h3 class="wa-heading-s">Migs Mayfeld</h3 class="wa-heading-s">
<wa-badge pill>Admin</wa-badge>
</div>
<span class="wa-caption-m">Bounty Hunter</span>
</div>
<wa-avatar image="https://images.unsplash.com/photo-1633268335280-a41fbde58707?q=80&w=3348&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" label="Avatar of a man wearing a sci-fi helmet (Photograph by Nandu Vasudevan)"></wa-avatar>
</div>
<div slot="footer" class="wa-grid wa-gap-xs" style="--min-column-size: 10ch;">
<wa-button appearance="outlined" tabindex="-1">
<wa-icon slot="start" name="at"></wa-icon>
Email
</wa-button>
<wa-button appearance="outlined" tabindex="-1">
<wa-icon slot="start" name="phone"></wa-icon>
Phone
</wa-button>
</div>
</wa-card>
<wa-card>
<div class="wa-flank:end">
<a href="" class="wa-flank wa-link-plain" tabindex="-1">
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-yellow-90); --text-color: var(--wa-color-yellow-50)">
<wa-icon slot="icon" name="egg-fried"></wa-icon>
</wa-avatar>
<div class="wa-gap-2xs wa-stack">
<span class="wa-heading-s">Second Breakfast</span>
<span class="wa-caption-m">19 Items</span>
</div>
</a>
<wa-dropdown>
<wa-button id="more-actions-2" slot="trigger" appearance="plain" size="small" tabindex="-1">
<wa-icon name="ellipsis-vertical" label="View menu"></wa-icon>
</wa-button>
<wa-dropdown-item>Copy link</wa-dropdown-item>
<wa-dropdown-item>Rename</wa-dropdown-item>
<wa-dropdown-item>Move to trash</wa-dropdown-item>
</wa-dropdown>
<wa-tooltip for="more-actions-2">View menu</wa-tooltip>
</div>
</wa-card>
<wa-card with-header with-footer>
<div slot="header" class="wa-stack wa-gap-xs">
<h2 class="wa-heading-m">Decks</h2>
</div>
<div class="wa-stack wa-gap-xl">
<p class="wa-caption-m">You haven't created any decks yet. Get started by selecting an aspect that matches your play style.</p>
<div class="wa-grid wa-gap-xl" style="--min-column-size: 30ch;">
<a href="" class="wa-flank wa-align-items-start wa-link-plain" tabindex="-1">
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-blue-90);color: var(--wa-color-blue-50);">
<wa-icon slot="icon" name="shield"></wa-icon>
</wa-avatar>
<div class="wa-stack wa-gap-2xs">
<span class="wa-align-items-center wa-cluster wa-gap-xs wa-heading-s">
Vigilance <wa-icon name="arrow-right"></wa-icon>
</span>
<p class="wa-caption-m">
Protect, defend, and restore as you ready heavy-hitters.
</p>
</div>
</a>
<a href="" class="wa-flank wa-align-items-start wa-link-plain" tabindex="-1">
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-green-90);color: var(--wa-color-green-50);">
<wa-icon slot="icon" name="chevrons-up"></wa-icon>
</wa-avatar>
<div class="wa-stack wa-gap-2xs">
<span class="wa-align-items-center wa-cluster wa-gap-xs wa-heading-s">
Command <wa-icon name="arrow-right"></wa-icon>
</span>
<p class="wa-caption-m">
Build imposing armies and stockpile resources.
</p>
</div>
</a>
<a href=""class="wa-flank wa-align-items-start wa-link-plain" tabindex="-1">
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-red-90);color: var(--wa-color-red-50);">
<wa-icon slot="icon" name="explosion"></wa-icon>
</wa-avatar>
<div class="wa-stack wa-gap-2xs">
<span class="wa-align-items-center wa-cluster wa-gap-xs wa-heading-s">
Aggression <wa-icon name="arrow-right"></wa-icon>
</span>
<p class="wa-caption-m">
Relentlessly deal damage and apply pressure to your opponent.
</p>
</div>
</a>
<a href="" class="wa-flank wa-align-items-start wa-link-plain" tabindex="-1">
<wa-avatar shape="rounded" style="--background-color: var(--wa-color-yellow-90);color: var(--wa-color-yellow-50);">
<wa-icon slot="icon" name="moon-stars"></wa-icon>
</wa-avatar>
<div class="wa-stack wa-gap-2xs">
<span class="wa-align-items-center wa-cluster wa-gap-xs wa-heading-s">
Cunning <wa-icon name="arrow-right"></wa-icon>
</span>
<p class="wa-caption-m">
Disrupt and frustrate your opponent with dastardly tricks.
</p>
</div>
</a>
</div>
</div>
<div slot="footer">
<a href="" class="wa-cluster wa-gap-xs" tabindex="-1">
<span>Or start a deck from scratch</span>
<wa-icon name="arrow-right"></wa-icon>
</a>
</div>
</wa-card>
</div>
</div>
<!-- Page styles -->
<style>
html,
body,
.theme-showcase {
height: 100vh;
overflow: hidden;
background-color: var(--wa-color-surface-lowered);
}
header {
padding: var(--wa-space-xl);
h2 {
margin-block-end: var(--wa-space-2xs);
}
p {
font-size: var(--wa-font-size-s);
margin-block-start: var(--wa-space-s);
}
}
[hidden] {
display: none !important;
}
.showcase-examples-wrapper {
container-type: inline-size;
inline-size: 100%;
min-block-size: 100%;
box-sizing: border-box;
padding: var(--wa-space-xl);
background-color: var(--wa-color-surface-lowered);
}
.showcase-examples {
column-count: 1;
column-gap: var(--wa-space-xl);
& wa-card {
display: inline-block;
width: 100%;
&:has(+ wa-card) {
margin-block-end: var(--wa-space-xl);
}
}
@container (width > 500px) {
column-count: 2;
}
@container (width > 750px) {
column-count: 3;
}
@container (width > 950px) {
column-count: auto;
column-width: 32ch;
}
}
#mix_and_match {
font-weight: var(--wa-font-weight-semibold);
color: var(--wa-color-text-quiet);
margin-block-end: var(--wa-space-xs);
html:not(.is-remixed) {
display: none;
}
wa-icon {
vertical-align: -0.15em;
}
> strong {
margin-inline-end: var(--wa-space-2xs);
}
wa-badge {
> a {
text-decoration: none;
color: inherit;
}
}
}
.theme-showcase {
isolation: isolate;
background-color: var(--wa-color-surface-lowered);
border-radius: var(--wa-border-radius-l);
overflow: hidden;
@media (width < 500px) {
flex-flow: column;
}
header {
min-width: min(25ch, 100vw);
align-self: center;
padding: var(--wa-space-xl);
box-sizing: border-box;
h1 {
margin-bottom: var(--wa-space-2xs);
}
wa-breadcrumb-item:not(:first-of-type, :last-of-type) {
display: none;
}
p:empty {
display: none;
}
}
}
</style>
</body>
</html>

View File

@@ -0,0 +1,179 @@
---
title: Themes
description: Themes galore
layout: docs
isPro: true
---
<div id="theme-viewer">
<wa-radio-group id="theme-picker" label="Theme Selector" value="default" orientation="horizontal">
{% for page in collections.themePages | sortWithFirst('fileSlug', 'default') %}
<wa-radio
class="theme-card"
value="{{ page.fileSlug | stripExtension }}"
data-description="{{ page.data.description }}"
data-title="{{ page.data.title }}"
{% if page.data.isPro %}data-is-pro{% endif %}
>
{{ page.data.title }}
</wa-radio>
{% endfor %}
</wa-radio-group>
</div>
<wa-comparison position="80">
<wa-zoomable-frame
slot="after"
without-controls
without-interaction
></wa-zoomable-frame>
<wa-zoomable-frame
slot="before"
without-controls
without-interaction
></wa-zoomable-frame>
</wa-comparison>
<script type="module">
function init() {
const themePicker = document.getElementById('theme-picker');
const afterFrame = document.querySelector('wa-zoomable-frame[slot="after"]');
const beforeFrame = document.querySelector('wa-zoomable-frame[slot="before"]');
function updateFrames(selectedValue, title, description, isPro) {
const baseUrl = '/assets/examples/themes/showcase.html';
const params = new URLSearchParams();
if (selectedValue !== 'default') {
params.set('theme', selectedValue);
}
if (title) params.set('name', title);
if (description) params.set('description', description);
if (isPro) params.set('isPro', 'true');
const darkParams = new URLSearchParams(params);
darkParams.set('color-scheme', 'dark');
const queryString = params.toString() ? '?' + params.toString() : '';
const darkQueryString = '?' + darkParams.toString();
console.log(queryString);
afterFrame.src = baseUrl + queryString;
beforeFrame.src = baseUrl + darkQueryString;
}
// Set default radio as checked and initialize frames
const defaultRadio = themePicker.querySelector('wa-radio[value="default"]');
if (defaultRadio) {
defaultRadio.checked = true;
const title = defaultRadio.getAttribute('data-title');
const description = defaultRadio.getAttribute('data-description');
const isPro = defaultRadio.hasAttribute('data-is-pro');
updateFrames('default', title, description, isPro);
}
// Listen for radio changes
themePicker.addEventListener('input', function(event) {
const radioGroup = event.target.closest('wa-radio-group');
const selectedRadio = radioGroup.querySelector(':state(checked)');
const selectedValue = event.target.value;
const title = selectedRadio.getAttribute('data-title');
const description = selectedRadio.getAttribute('data-description');
const isPro = selectedRadio.hasAttribute('data-is-pro');
updateFrames(selectedValue, title, description, isPro);
});
}
document.addEventListener('DOMContentLoaded', init);
window.addEventListener('turbo:load', init);
</script>
<style>
wa-page > main {
max-width: 140ch;
margin-inline: auto;
}
wa-zoomable-frame {
aspect-ratio: 8 / 4;
}
#theme-viewer {
#theme-picker {
margin-bottom: var(--wa-space-l);
&::part(form-control-input) {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: var(--wa-space-s);
}
&::part(form-control-label) {
position: absolute;
width: 1px;
height: 1px;
clip: rect(0 0 0 0);
clip-path: inset(50%);
border: none;
overflow: hidden;
white-space: nowrap;
padding: 0;
}
}
.theme-card {
--border-radius: var(--wa-border-radius-m);
--spacing: var(--wa-space-s) var(--wa-space-m);
display: flex;
align-items: center;
justify-content: center;
min-height: var(--wa-space-3xl);
padding: var(--spacing);
border: 1px solid var(--wa-color-surface-border);
border-radius: var(--border-radius);
box-shadow: var(--wa-shadow-s);
cursor: pointer;
transition: all 0.2s ease;
text-align: center;
font-weight: var(--wa-font-weight-action);
text-transform: capitalize;
&:state(checked) {
border-color: var(--wa-color-brand-border-loud);
background-color: var(--wa-color-brand-fill-quiet);
color: var(--wa-color-brand-text-loud);
}
&::part(control) {
display: none;
}
&::part(label) {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
margin: 0;
}
}
}
/* Smaller screens */
@media (max-width: 768px) {
#theme-viewer {
padding: var(--wa-space-m);
#theme-picker::part(form-control-input) {
grid-template-columns: repeat(2, 1fr);
gap: var(--wa-space-xs);
}
.theme-card {
min-height: var(--wa-space-2xl);
font-size: var(--wa-font-size-s);
}
}
}
</style>

View File

@@ -1,7 +1,7 @@
---
title: Awesome
description: Bustling with plenty of luster and shine.
isPro: true
isPro: false
---
TODO

View File

@@ -1,7 +1,7 @@
---
title: Default
description: Your trusty companion, like a perfectly broken-in pair of jeans.
isPro: true
isPro: false
---
TODO

View File

@@ -1,7 +1,7 @@
---
title: Shoelace
description: The original, familiar look you know and love from Shoelace.
isPro: true
isPro: false
---
TODO

View File

@@ -4,7 +4,7 @@
--handle-color: var(--wa-color-neutral-on-quiet);
--handle-size: 2.5rem;
display: inline-block;
display: block;
position: relative;
max-width: 100%;
max-height: 100%;