1036 lines
51 KiB
HTML
1036 lines
51 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>WordPress Blueprints Gallery</title>
|
||
<script type="module">
|
||
import { h, render, Component } from 'https://esm.sh/preact@10.19.3';
|
||
import { useState, useEffect } from 'https://esm.sh/preact@10.19.3/hooks';
|
||
window.h = h;
|
||
window.Component = Component;
|
||
window.useState = useState;
|
||
window.useEffect = useEffect;
|
||
window.render = render;
|
||
</script>
|
||
<script id="blueprint-data" type="application/json">{"blueprints/portfolio-vueo/blueprint.json":{"title":"Art Gallery","description":"An art gallery created with the Vueo theme.","author":"WordPress.com","categories":["Website","Personal"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/portfolio-vueo/screenshot.jpg","featured":true},"blueprints/brewcommerce/blueprint.json":{"title":"Coffee Shop","description":"A stylish WooCommerce coffee shop storefront with custom theme, products, and content.","author":"adamziel","categories":["WooCommerce","Store"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/e3183200f04bac17b650ef303be934a0be5fe957/blueprints/brewcommerce/screenshot.jpg","featured":true},"blueprints/friends-cors/blueprint.json":{"title":"Feed Reader with the Friends Plugin","description":"By using the Friends plugin, you can read feeds from the web in Playground, and even via ActivityPub","author":"akirk","categories":["rss","social web"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/friends-cors/screenshot.jpg","featured":true},"blueprints/news-spiel/blueprint.json":{"title":"Gaming News","description":"A gaming news site created with the Spiel theme.","author":"WordPress.com","categories":["Website","News"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/news-spiel/screenshot.jpg","featured":true},"blueprints/organization-koinonia/blueprint.json":{"title":"Non-profit Organization","description":"A non-profit organization site created with the Koinonia theme.","author":"WordPress.com","categories":["Website","Organization"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/organization-koinonia/screenshot.jpg","featured":true},"blueprints/personal-substrata/blueprint.json":{"title":"Personal Blog","description":"A personal blog site created with the Substrata theme.","author":"WordPress.com","categories":["Website","Personal","Blog"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/personal-substrata/screenshot.jpg","featured":true},"blueprints/personal-readymade/blueprint.json":{"title":"Personal Resume","description":"A resume site created with the Readymade theme.","author":"WordPress.com","categories":["Website","Personal"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/personal-readymade/screenshot.jpg","featured":true},"blueprints/portfolio-grammer/blueprint.json":{"title":"Photography Portfolio","description":"A photography portfolio created with the Grammer theme.","author":"WordPress.com","categories":["Website","Personal","Photography"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/portfolio-grammer/screenshot.jpg","featured":true},"blueprints/news-piel/blueprint.json":{"title":"Skincare Blog","description":"A skincare blog created with the Piel theme.","author":"WordPress.com","categories":["Website","News","Blog"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/news-piel/screenshot.jpg","featured":true},"blueprints/organization-kentwood/blueprint.json":{"title":"University Website","description":"A university website created with the Kentwood theme.","author":"WordPress.com","categories":["Website","Organization","Education"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/organization-kentwood/screenshot.jpg","featured":true},"blueprints/create-block-theme/blueprint.json":{"title":"Create Block Theme","description":"Blueprint to install Create Block Theme and start editing right away","author":"jonathanbossenger","categories":["Editor","theme"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/create-block-theme/screenshot.jpg","featured":false},"blueprints/user-meta/blueprint.json":{"title":"Creating a new user for the blog","description":"This is a simple example to update user meta data","author":"fellyph","categories":["meta"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/user-meta/screenshot.jpg","featured":false},"blueprints/custom-post/blueprint.json":{"title":"Custom Post Type: Books","description":"Blueprint that added a custom post type to playground","author":"bph","categories":["Content","CPT"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/custom-post/screenshot.jpg","featured":false},"blueprints/tt5-demo/blueprint.json":{"title":"Demo of Twenty-Twenty-Five theme","description":"Blueprint with demo content for the Twenty-Twenty-Five default theme","author":"bph","categories":["Themes","default"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/tt5-demo/screenshot.jpg","featured":false},"blueprints/admin-notice/blueprint.json":{"title":"Display Admin Notice","description":"Blueprint to add a tiny mu-plugin and display an admin notice","author":"bph","categories":["Admin","notices"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/admin-notice/screenshot.jpg","featured":false},"blueprints/gb-more-experiments/blueprint.json":{"title":"Enable all three Dataview Experiments in Gutenberg","author":"bph","description":"Blueprint example to enable multiple Experiments within the Gutenberg plugin ","categories":["Gutenberg","Experiments"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/gb-more-experiments/screenshot.jpg","featured":false},"blueprints/fancy-dashboard_widget/blueprint.json":{"title":"Fancy Dashboard Widget","description":"A blueprint to display statistics about users, posts and comments on a WordPress site.","author":"muryamsultana","screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/fancy-dashboard_widget/screenshot.jpg","featured":false},"blueprints/grid-variations/blueprint.json":{"title":"Grid Variations Experiments enabled","author":"bph","description":"Blueprint example to toggle on enable a feature from the Experiments page in Gutenberg plugin","categories":["Gutenberg","Experiments"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/grid-variations/screenshot.jpg","featured":false},"blueprints/theme-starter-content/blueprint.json":{"title":"Import Theme Starter Content","author":"bph","description":"Blueprint to install a theme with starter content, (here: Twenty-Twenty-One)","categories":["Themes","Starter Content"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/theme-starter-content/screenshot.jpg","featured":false},"blueprints/file-starter-content/blueprint.json":{"title":"Import a standalone starter content via a blueprint step","author":"bph","description":"Blueprint to use a stand-alone starter content file and then to import it. Click on 'Subscriptions'","categories":["Themes","Starter Content"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/file-starter-content/screenshot.jpg","featured":false},"blueprints/translations/blueprint.json":{"title":"Install WordPress language packs","author":"adamziel","description":"Installs and activates the latest WordPress Japanese translation pack from https://translate.wordpress.org/ – both for WordPress core and for the friends plugin.","categories":["core"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/translations/screenshot.jpg","featured":false},"blueprints/install-plugin-from-gist/blueprint.json":{"title":"Install plugin from a gist","author":"zieladam","description":"Install and activate a WordPress plugin from a .php file stored in a gist.","categories":["plugins"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/install-plugin-from-gist/screenshot.jpg","featured":false},"blueprints/latest-gutenberg/blueprint.json":{"title":"Latest Gutenberg plugin","author":"zieladam","description":"A preview of the latest version of the Gutenberg plugin.","categories":["plugins"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/latest-gutenberg/screenshot.jpg","featured":false},"blueprints/install-activate-setup-theme-from-gh-repo/blueprint.json":{"title":"Loading, activating, and configuring a theme from a GitHub repository.","description":"This is a good example of typical steps used on a theme's loading, activation and configuration","author":"richtabor","categories":["theme"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/install-activate-setup-theme-from-gh-repo/screenshot.jpg","featured":false},"blueprints/login-as-editor/blueprint.json":{"title":"Login as an editor","description":"Test WordPress functionality as an editor rather than an administrator.","author":"bacoords","categories":["User","Role"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/login-as-editor/screenshot.jpg","featured":false},"blueprints/blocky-formats/blueprint.json":{"title":"Markdown and Trac Syntax Editor","description":"Edit Markdown and Trac formatting in the block editor thanks to the blocky-formats plugin!","author":"adamziel","categories":["block-editor"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/blocky-formats/screenshot.jpg","featured":false},"blueprints/woo-shipping/blueprint.json":{"title":"Minimal WooCommerce Setup with Sample Products, Shipping, and Payment Method","description":"To create a WordPress Playground instance that installs WooCommerce, adds a custom flat rate shipping method via a plugin, imports WooCommerce sample products XML to demonstrate the shipping method on the cart/checkout pages, and enables the Direct Bank Transfer payment method.","author":"calvinrodrigues500","categories":["woocommerce","shipping","flat_rate"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/woo-shipping/screenshot.jpg","featured":false},"blueprints/my-wordpress/blueprint.json":{"title":"My WordPress","description":"A welcome experience for persistent WordPress Playground instances. Lets you personalize your site name and optionally import content from an RSS feed.","author":"Alex Kirk","categories":["Playground","Onboarding"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/caa7ea840c3e6707ee9f70deae73a7c37aa885ae/blueprints/my-wordpress/screenshot.jpg","featured":false},"blueprints/welcome/blueprint.json":{"title":"Playground Welcome Landing Page","description":"Landing page for the WordPress Playground giving a quick overview of the features and capabilities of the platform.","author":"fellyph","categories":["meta"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/welcome/screenshot.jpg","featured":false},"blueprints/use-pretty-permalinks/blueprint.json":{"title":"Pretty permalinks","description":"Set the permalink structure to use pretty permalinks.","author":"bgrgicak","categories":["Settings"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/use-pretty-permalinks/screenshot.jpg","featured":false},"blueprints/reset-data-and-import-content/blueprint.json":{"title":"Reset data and import content (with logs)","description":"It resets default data before importing custom content. It also logs the state of the content after each step.","author":"juanmaguitar","categories":["reset","log","debug","debug","import","content"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/reset-data-and-import-content/screenshot.jpg","featured":false},"blueprints/redirect-upload-requests/blueprint.json":{"title":"Serve media files from another host","description":"Redirect any requests to files within the uploads directory to an external host. This is useful when you have a lot of image attachments in your playground but don’t want to include them all in the blueprint.","author":"ivanblagdan","categories":["Settings"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/redirect-upload-requests/screenshot.jpg","featured":false},"blueprints/set-admin-color-scheme/blueprint.json":{"title":"Set the admin color scheme","description":"Set the admin color scheme to Modern using the updateUserMeta step.","author":"ndiego","categories":["user meta"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/set-admin-color-scheme/screenshot.jpg","featured":false},"blueprints/showcase-plugin-with-media/blueprint.json":{"title":"Showcase plugin","description":"Showcase custom plugin from own server with media files and content imported as WXR. There is a readme file in github repository (https://github.com/Lovor01/blueprints/blob/trunk/blueprints/showcase-plugin-with-media/readme.md) which explains all steps.","author":"Lovor01","categories":["plugin","demo","media","images"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/showcase-plugin-with-media/screenshot.jpg","featured":false},"blueprints/stylish-press/blueprint.json":{"title":"Stylish Press","description":"A Woo store with custom theme, content, and products.","author":"adamziel","categories":["Woocommerce","Site"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/stylish-press/screenshot.jpg","featured":false},"blueprints/theme-a11y-test/blueprint.json":{"title":"Theme Tester","description":"Blueprint example to add content and plugins to explore a theme","author":"bph","categories":["themes","content"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/theme-a11y-test/screenshot.jpg","featured":false},"blueprints/wpgraphql/blueprint.json":{"title":"Use WPGraphQL to query WordPress","description":"Example that loads WordPress with WPGraphQL active and defaults to the WPGraphQL IDE page to allow users to test GraphQL queries and explore the GraphQL Schema.","author":"jasonbahl","categories":["API","wpgraphql"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/wpgraphql/screenshot.jpg","featured":false},"blueprints/posts-via-wp-cli/blueprint.json":{"title":"Use wp-cli command to add posts","description":"Blueprint example to add posts via a wp-cli command.","author":"bph","categories":["Content","wpcli"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/posts-via-wp-cli/screenshot.jpg","featured":false},"blueprints/wpcli-post-with-image/blueprint.json":{"title":"Use wp-cli to add a post with image","description":"Use wp-cli to create a post from text file with block markup and a featured image","author":"bph","categories":["Content","wpcli"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/wpcli-post-with-image/screenshot.jpg","featured":false},"blueprints/pwa-weather-app/blueprint.json":{"title":"Weather Shortcode Plugin","description":"A blueprint to connect weather API and show data as shortcode on a WordPress site. Requires your own OpenWeatherMap API key.","author":"muryamsultana","screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/pwa-weather-app/screenshot.jpg","featured":false},"blueprints/woocommerce-product-feed/blueprint.json":{"title":"WooCommerce product feed","description":"Blueprint to create a WooCommerce product and export an XML/CSV product feed","author":"mujuonly","categories":["WooCommerce","Content"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/woocommerce-product-feed/screenshot.jpg","featured":false},"blueprints/beta-rc/blueprint.json":{"title":"WordPress Beta","description":"Test the latest WordPress Beta or RC release with theme test data and debugging plugins. Only loads the Beta version during the Beta period.","author":"courtneyr-dev","categories":["Testing"],"screenshot_url":"https://raw.githubusercontent.com/wordpress/blueprints/c399585e8578db32a8706af8cfe25caf760c56cc/blueprints/beta-rc/screenshot.jpg","featured":false}}</script>
|
||
<style>
|
||
:root {
|
||
color-scheme: light;
|
||
}
|
||
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
html {
|
||
overflow-y: scroll;
|
||
}
|
||
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||
line-height: 1.6;
|
||
color: #1f2937;
|
||
background: #f3f4f6;
|
||
}
|
||
|
||
a {
|
||
color: inherit;
|
||
}
|
||
|
||
.page {
|
||
min-height: 100vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
background: #f3f4f6;
|
||
}
|
||
|
||
|
||
.hero {
|
||
background: #1f2937;
|
||
color: #f9fafb;
|
||
padding: 3rem 0 2.75rem;
|
||
box-shadow: 0 12px 40px rgba(15, 23, 42, 0.35);
|
||
}
|
||
|
||
.hero-inner {
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
padding: 0 2rem;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 1.25rem;
|
||
}
|
||
|
||
.hero-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 1rem;
|
||
}
|
||
|
||
.hero-logo {
|
||
width: 48px;
|
||
height: 48px;
|
||
}
|
||
|
||
.hero-title {
|
||
font-size: 2.25rem;
|
||
font-weight: 700;
|
||
margin: 0;
|
||
}
|
||
|
||
.hero-subtitle {
|
||
font-size: 1.05rem;
|
||
color: #d1d5db;
|
||
max-width: 820px;
|
||
line-height: 1.7;
|
||
}
|
||
|
||
.hero-link {
|
||
color: #60a5fa;
|
||
text-decoration: none;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.hero-link:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.filters-section {
|
||
background: #f9fafb;
|
||
border-bottom: 1px solid #e5e7eb;
|
||
}
|
||
|
||
.filters-inner {
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
padding: 1.75rem 2rem;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 1.25rem;
|
||
}
|
||
|
||
.tab-list {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 0.75rem;
|
||
}
|
||
|
||
.tab {
|
||
padding: 0.6rem 1.2rem;
|
||
border-radius: 999px;
|
||
border: 1px solid #d1d5db;
|
||
background: #ffffff;
|
||
color: #1f2937;
|
||
font-weight: 600;
|
||
font-size: 0.95rem;
|
||
cursor: pointer;
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
.tab:hover {
|
||
border-color: #94a3b8;
|
||
}
|
||
|
||
.tab.active {
|
||
background: #0f172a;
|
||
border-color: #0f172a;
|
||
color: #f9fafb;
|
||
box-shadow: 0 6px 16px rgba(15, 23, 42, 0.25);
|
||
}
|
||
|
||
.toolbar {
|
||
display: flex;
|
||
gap: 1rem;
|
||
align-items: center;
|
||
}
|
||
|
||
.search-block {
|
||
flex: 1;
|
||
max-width: 500px;
|
||
}
|
||
|
||
.search-field {
|
||
position: relative;
|
||
}
|
||
|
||
.search-field input {
|
||
width: 100%;
|
||
padding: 0.7rem 1rem 0.7rem 2.6rem;
|
||
border-radius: 12px;
|
||
border: 1px solid #d1d5db;
|
||
background: #ffffff;
|
||
font-size: 0.95rem;
|
||
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
||
}
|
||
|
||
.search-field input:focus {
|
||
outline: none;
|
||
border-color: #2563eb;
|
||
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
|
||
}
|
||
|
||
.search-icon {
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 0.9rem;
|
||
transform: translateY(-50%);
|
||
color: #9ca3af;
|
||
font-size: 1.35rem;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.gallery-section {
|
||
flex: 1;
|
||
}
|
||
|
||
.gallery-inner {
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
padding: 2rem 2rem 3rem;
|
||
}
|
||
|
||
.results-summary {
|
||
margin-bottom: 1.5rem;
|
||
color: #6b7280;
|
||
font-size: 0.95rem;
|
||
}
|
||
|
||
.gallery-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||
gap: 1.75rem;
|
||
}
|
||
|
||
.skeleton-grid {
|
||
opacity: 0.9;
|
||
}
|
||
|
||
.pattern-card {
|
||
background: #ffffff;
|
||
border-radius: 4px;
|
||
overflow: hidden;
|
||
border: 1px solid #e5e7eb;
|
||
box-shadow: 0 15px 35px rgba(15, 23, 42, 0.08);
|
||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.pattern-card:hover {
|
||
transform: translateY(-4px);
|
||
box-shadow: 0 22px 45px rgba(15, 23, 42, 0.15);
|
||
}
|
||
|
||
.pattern-card-image {
|
||
display: block;
|
||
width: 100%;
|
||
height: 230px;
|
||
object-fit: cover;
|
||
object-position: center top;
|
||
background: #f3f4f6;
|
||
}
|
||
|
||
.pattern-card-image.placeholder {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
height: 230px;
|
||
font-size: 0.95rem;
|
||
color: #9ca3af;
|
||
}
|
||
|
||
.pattern-card-body {
|
||
padding: 1.25rem 1.5rem 1.4rem;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 0.9rem;
|
||
flex: 1;
|
||
}
|
||
|
||
.pattern-card-header {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: 0.75rem;
|
||
flex-wrap: nowrap;
|
||
}
|
||
|
||
.pattern-card-title {
|
||
margin: 0;
|
||
font-size: 1.05rem;
|
||
font-weight: 600;
|
||
color: #111827;
|
||
flex: 1 1 auto;
|
||
min-width: 0;
|
||
}
|
||
|
||
.pattern-card-description {
|
||
margin: 0;
|
||
font-size: 0.9rem;
|
||
color: #6b7280;
|
||
min-height: 2.4rem;
|
||
}
|
||
|
||
.pattern-card-meta {
|
||
margin: 0;
|
||
font-size: 0.85rem;
|
||
color: #6b7280;
|
||
margin-top: auto;
|
||
}
|
||
|
||
.pattern-card-meta a {
|
||
color: #2563eb;
|
||
text-decoration: none;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.pattern-card-meta a:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.pattern-card-meta .meta-separator {
|
||
color: #d1d5db;
|
||
margin: 0 0.25rem;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.btn-try-it {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
padding: 0.65rem 1.25rem;
|
||
background: #3858e9;
|
||
color: #ffffff;
|
||
border-radius: 8px;
|
||
font-weight: 600;
|
||
font-size: 0.95rem;
|
||
text-decoration: none;
|
||
transition: background 0.2s ease, transform 0.1s ease;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.pattern-card-header .btn-try-it {
|
||
margin-left: auto;
|
||
}
|
||
|
||
.btn-try-it:hover {
|
||
background: #2a44d0;
|
||
transform: translateY(-1px);
|
||
}
|
||
|
||
.btn-try-it .btn-icon {
|
||
width: 18px;
|
||
height: 18px;
|
||
}
|
||
|
||
.btn-view-source {
|
||
color: #6b7280;
|
||
font-weight: 600;
|
||
font-size: 0.9rem;
|
||
text-decoration: none;
|
||
}
|
||
|
||
.btn-view-source:hover {
|
||
color: #2563eb;
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.empty-state {
|
||
margin-top: 3rem;
|
||
text-align: center;
|
||
padding: 3rem;
|
||
background: #ffffff;
|
||
border-radius: 16px;
|
||
border: 1px solid #e5e7eb;
|
||
color: #6b7280;
|
||
box-shadow: 0 15px 35px rgba(15, 23, 42, 0.08);
|
||
}
|
||
|
||
.empty-state h2 {
|
||
font-size: 1.6rem;
|
||
color: #111827;
|
||
margin-bottom: 0.75rem;
|
||
}
|
||
|
||
.placeholder-card {
|
||
background: #ffffff;
|
||
border-radius: 4px;
|
||
border: 1px solid #e5e7eb;
|
||
padding-bottom: 1.25rem;
|
||
box-shadow: 0 10px 25px rgba(15, 23, 42, 0.08);
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 1rem;
|
||
}
|
||
|
||
.placeholder-thumb {
|
||
height: 230px;
|
||
background: #e5e7eb;
|
||
}
|
||
|
||
.placeholder-body {
|
||
padding: 0 1.5rem;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 0.7rem;
|
||
}
|
||
|
||
.placeholder-line {
|
||
height: 12px;
|
||
border-radius: 999px;
|
||
background: #e5e7eb;
|
||
}
|
||
|
||
.placeholder-line.wide {
|
||
width: 70%;
|
||
}
|
||
|
||
.placeholder-line.medium {
|
||
width: 55%;
|
||
}
|
||
|
||
.placeholder-line.short {
|
||
width: 40%;
|
||
}
|
||
|
||
.skeleton-animate {
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.skeleton-animate::after {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.5) 50%, rgba(255,255,255,0) 100%);
|
||
transform: translateX(-100%);
|
||
animation: shimmer 1.4s infinite;
|
||
}
|
||
|
||
@keyframes shimmer {
|
||
100% {
|
||
transform: translateX(100%);
|
||
}
|
||
}
|
||
|
||
.no-results h2 {
|
||
font-size: 1.6rem;
|
||
color: #111827;
|
||
margin-bottom: 0.75rem;
|
||
}
|
||
|
||
.footer {
|
||
background: #f9fafb;
|
||
padding: 3rem 2rem 3.5rem;
|
||
color: #6b7280;
|
||
font-size: 0.9rem;
|
||
text-align: center;
|
||
border-top: 1px solid #e5e7eb;
|
||
}
|
||
|
||
.footer a {
|
||
color: #2563eb;
|
||
text-decoration: none;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.footer a:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
@media (max-width: 960px) {
|
||
.global-nav-inner {
|
||
gap: 1rem;
|
||
}
|
||
|
||
.hero-title {
|
||
font-size: 2.4rem;
|
||
}
|
||
|
||
.toolbar {
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
}
|
||
|
||
.dropdown-group {
|
||
width: 100%;
|
||
justify-content: flex-start;
|
||
}
|
||
|
||
.search-block {
|
||
width: 100%;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 600px) {
|
||
.global-nav-inner {
|
||
padding: 0.65rem 1.25rem;
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
gap: 0.75rem;
|
||
}
|
||
|
||
.hero-inner {
|
||
padding: 0 1.25rem;
|
||
}
|
||
|
||
.filters-inner {
|
||
padding: 1.5rem 1.25rem;
|
||
}
|
||
|
||
.gallery-inner {
|
||
padding: 1.5rem 1.25rem 2.5rem;
|
||
}
|
||
|
||
.tab {
|
||
padding: 0.5rem 1rem;
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.pattern-card-body {
|
||
padding: 1rem 1.1rem 1.1rem;
|
||
}
|
||
|
||
.pattern-card-header {
|
||
align-items: center;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="app"></div>
|
||
|
||
<script type="module">
|
||
const { h, render, useState, useEffect } = window;
|
||
const dataElement = document.getElementById('blueprint-data');
|
||
let embeddedIndex = null;
|
||
if (dataElement) {
|
||
try {
|
||
embeddedIndex = JSON.parse(dataElement.textContent || '{}');
|
||
} catch (error) {
|
||
console.error('Failed to parse embedded blueprint data.', error);
|
||
}
|
||
}
|
||
window.__EMBEDDED_BLUEPRINT_INDEX__ = embeddedIndex;
|
||
|
||
const highlightedBlueprints = [
|
||
'Stylish Press',
|
||
'Feed Reader with the Friends Plugin',
|
||
'Gaming News',
|
||
'Skincare Blog',
|
||
'Non-profit Organization',
|
||
'Personal Resume',
|
||
'Personal Blog',
|
||
'University Website',
|
||
'Photography Portfolio',
|
||
'Art Gallery'
|
||
];
|
||
|
||
function deriveBlueprintData(indexData) {
|
||
if (!indexData) {
|
||
return null;
|
||
}
|
||
|
||
const categoryCount = {};
|
||
const authors = new Set();
|
||
let highlightedTotal = 0;
|
||
|
||
const entries = Object.entries(indexData).map(([path, meta], index) => {
|
||
const categories = meta.categories || [];
|
||
|
||
categories.forEach(cat => {
|
||
categoryCount[cat] = (categoryCount[cat] || 0) + 1;
|
||
});
|
||
|
||
if (meta.author) {
|
||
authors.add(meta.author);
|
||
}
|
||
|
||
const isHighlighted = highlightedBlueprints.includes(meta.title);
|
||
if (isHighlighted) {
|
||
highlightedTotal += 1;
|
||
}
|
||
|
||
return {
|
||
path,
|
||
title: meta.title || 'Untitled Blueprint',
|
||
description: meta.description || '',
|
||
author: meta.author || '',
|
||
categories,
|
||
screenshot_url: meta.screenshot_url || '',
|
||
highlighted: isHighlighted,
|
||
order: index
|
||
};
|
||
});
|
||
|
||
const sortedCategories = Object.entries(categoryCount)
|
||
.sort((a, b) => b[1] - a[1])
|
||
.map(([name]) => name);
|
||
|
||
return {
|
||
entries,
|
||
topCategories: sortedCategories.slice(0, 8),
|
||
allCategories: sortedCategories,
|
||
stats: {
|
||
totalBlueprints: entries.length,
|
||
uniqueCategories: Object.keys(categoryCount).length,
|
||
uniqueAuthors: authors.size,
|
||
highlighted: highlightedTotal
|
||
}
|
||
};
|
||
}
|
||
|
||
const initialBlueprintData = deriveBlueprintData(embeddedIndex);
|
||
|
||
function buildPreviewUrl(path) {
|
||
return `https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/wordpress/blueprints/trunk/${path}`;
|
||
}
|
||
|
||
function buildEditUrl(path) {
|
||
return `https://playground.wordpress.net/builder/builder.html?blueprint-url=https://raw.githubusercontent.com/wordpress/blueprints/trunk/${path}`;
|
||
}
|
||
|
||
function buildSourceUrl(path) {
|
||
return `https://github.com/wordpress/blueprints/blob/trunk/${path}`;
|
||
}
|
||
|
||
function computeFavoriteCount(blueprint) {
|
||
const seed = `${blueprint.title}|${blueprint.path}`;
|
||
const hash = Array.from(seed).reduce((total, char) => total + char.charCodeAt(0), 0);
|
||
return 40 + (hash % 160);
|
||
}
|
||
|
||
function formatNumber(value) {
|
||
return value.toLocaleString('en-US');
|
||
}
|
||
|
||
function normalizeScreenshotSrc(blueprint) {
|
||
const rawPrefix = 'https://raw.githubusercontent.com/wordpress/blueprints/';
|
||
const { screenshot_url: originalSrc = '', path = '' } = blueprint;
|
||
|
||
if (originalSrc.startsWith(rawPrefix)) {
|
||
return originalSrc.replace(/^https:\/\/raw\.githubusercontent\.com\/wordpress\/blueprints\/[^/]+\//, '');
|
||
}
|
||
|
||
if (originalSrc) {
|
||
return originalSrc;
|
||
}
|
||
|
||
if (path) {
|
||
return path.replace(/blueprint\.json$/, 'screenshot.jpg');
|
||
}
|
||
|
||
return '';
|
||
}
|
||
|
||
function BlueprintCard({ blueprint }) {
|
||
const previewUrl = buildPreviewUrl(blueprint.path);
|
||
const sourceUrl = buildSourceUrl(blueprint.path);
|
||
const editUrl = buildEditUrl(blueprint.path);
|
||
const screenshotSrc = normalizeScreenshotSrc(blueprint);
|
||
|
||
const metaChildren = [];
|
||
|
||
if (blueprint.author) {
|
||
metaChildren.push('By ');
|
||
metaChildren.push(h('a', {
|
||
href: `https://github.com/${encodeURIComponent(blueprint.author)}`,
|
||
target: '_blank',
|
||
rel: 'noreferrer noopener'
|
||
}, `@${blueprint.author}`));
|
||
}
|
||
|
||
const sourceLink = h('a', {
|
||
href: sourceUrl,
|
||
target: '_blank',
|
||
rel: 'noreferrer noopener'
|
||
}, 'View source');
|
||
|
||
const editLink = h('a', {
|
||
href: editUrl,
|
||
target: '_blank',
|
||
rel: 'noreferrer noopener'
|
||
}, 'Edit');
|
||
|
||
const addSeparatorIfNeeded = () => {
|
||
if (metaChildren.length > 0) {
|
||
metaChildren.push(' ');
|
||
metaChildren.push(h('span', { className: 'meta-separator' }, '•'));
|
||
metaChildren.push(' ');
|
||
}
|
||
};
|
||
|
||
addSeparatorIfNeeded();
|
||
metaChildren.push(sourceLink);
|
||
addSeparatorIfNeeded();
|
||
metaChildren.push(editLink);
|
||
|
||
const metaLine = h('p', { className: 'pattern-card-meta' }, metaChildren);
|
||
|
||
return h('article', { className: 'pattern-card' },
|
||
screenshotSrc
|
||
? h('img', {
|
||
className: 'pattern-card-image',
|
||
src: screenshotSrc,
|
||
alt: `${blueprint.title} screenshot`,
|
||
onError: (event) => {
|
||
event.target.parentElement.innerHTML = '<div class="pattern-card-image placeholder">No screenshot available</div>';
|
||
}
|
||
})
|
||
: h('div', { className: 'pattern-card-image placeholder' }, 'No screenshot available'),
|
||
h('div', { className: 'pattern-card-body' },
|
||
h('div', { className: 'pattern-card-header' },
|
||
h('h2', { className: 'pattern-card-title' }, blueprint.title),
|
||
h('a', {
|
||
href: previewUrl,
|
||
className: 'btn-try-it',
|
||
target: '_blank',
|
||
rel: 'noreferrer noopener'
|
||
},
|
||
h('img', {
|
||
src: 'playground-icon.png',
|
||
className: 'btn-icon',
|
||
alt: ''
|
||
}),
|
||
'Run'
|
||
)
|
||
),
|
||
blueprint.description && h('p', { className: 'pattern-card-description' }, blueprint.description),
|
||
metaLine
|
||
)
|
||
);
|
||
}
|
||
|
||
function PlaceholderCard() {
|
||
return h('article', { className: 'placeholder-card' },
|
||
h('div', { className: 'placeholder-thumb skeleton-animate' }),
|
||
h('div', { className: 'placeholder-body' },
|
||
h('div', { className: 'placeholder-line wide skeleton-animate' }),
|
||
h('div', { className: 'placeholder-line medium skeleton-animate' }),
|
||
h('div', { className: 'placeholder-line short skeleton-animate' })
|
||
)
|
||
);
|
||
}
|
||
|
||
function App() {
|
||
const blueprintEntries = initialBlueprintData ? initialBlueprintData.entries : [];
|
||
const blueprints = blueprintEntries;
|
||
const topCategories = initialBlueprintData ? initialBlueprintData.topCategories : [];
|
||
const allCategories = initialBlueprintData ? initialBlueprintData.allCategories : [];
|
||
const stats = initialBlueprintData ? initialBlueprintData.stats : {
|
||
totalBlueprints: 0,
|
||
uniqueCategories: 0,
|
||
uniqueAuthors: 0,
|
||
highlighted: 0
|
||
};
|
||
|
||
const [filteredBlueprints, setFilteredBlueprints] = useState(blueprintEntries);
|
||
const [searchTerm, setSearchTerm] = useState('');
|
||
const [activeCategories, setActiveCategories] = useState(new Set());
|
||
const [showFeaturedOnly, setShowFeaturedOnly] = useState(false);
|
||
const [sortMode, setSortMode] = useState('gallery');
|
||
const [selectedFilter, setSelectedFilter] = useState('all');
|
||
const isLoaded = Boolean(initialBlueprintData);
|
||
|
||
useEffect(() => {
|
||
const params = new URLSearchParams(window.location.search);
|
||
const searchParam = params.get('search');
|
||
const categoriesParam = params.get('categories');
|
||
const featuredParam = params.get('featured');
|
||
const sortParam = params.get('sort');
|
||
const filterParam = params.get('filter');
|
||
|
||
if (searchParam) {
|
||
setSearchTerm(searchParam);
|
||
}
|
||
|
||
if (categoriesParam) {
|
||
const categoryList = categoriesParam.split(',').filter(Boolean);
|
||
if (categoryList.length > 0) {
|
||
setActiveCategories(new Set(categoryList));
|
||
setSelectedFilter(categoryList[0]);
|
||
}
|
||
}
|
||
|
||
if (featuredParam === 'true') {
|
||
setShowFeaturedOnly(true);
|
||
setSelectedFilter('featured');
|
||
}
|
||
|
||
if (sortParam) {
|
||
setSortMode(sortParam);
|
||
}
|
||
|
||
if (filterParam) {
|
||
setSelectedFilter(filterParam === 'curated' ? 'all' : filterParam);
|
||
}
|
||
}, []);
|
||
|
||
useEffect(() => {
|
||
if (!initialBlueprintData) {
|
||
console.error('Blueprint index data missing. Rebuild gallery.html to embed it.');
|
||
}
|
||
}, []);
|
||
|
||
useEffect(() => {
|
||
const params = new URLSearchParams();
|
||
|
||
if (searchTerm) {
|
||
params.set('search', searchTerm);
|
||
}
|
||
|
||
if (activeCategories.size > 0) {
|
||
params.set('categories', Array.from(activeCategories).join(','));
|
||
}
|
||
|
||
if (showFeaturedOnly) {
|
||
params.set('featured', 'true');
|
||
}
|
||
|
||
if (sortMode && sortMode !== 'gallery') {
|
||
params.set('sort', sortMode);
|
||
}
|
||
|
||
if (selectedFilter && selectedFilter !== 'all') {
|
||
params.set('filter', selectedFilter);
|
||
}
|
||
|
||
const newUrl = params.toString()
|
||
? `${window.location.pathname}?${params.toString()}`
|
||
: window.location.pathname;
|
||
|
||
window.history.replaceState({}, '', newUrl);
|
||
}, [searchTerm, activeCategories, showFeaturedOnly, sortMode, selectedFilter]);
|
||
|
||
useEffect(() => {
|
||
const term = searchTerm.trim().toLowerCase();
|
||
|
||
const filtered = blueprints.filter(bp => {
|
||
const matchesSearch = !term ||
|
||
bp.title.toLowerCase().includes(term) ||
|
||
bp.description.toLowerCase().includes(term) ||
|
||
bp.author.toLowerCase().includes(term);
|
||
|
||
const matchesCategory = activeCategories.size === 0 ||
|
||
bp.categories.some(cat => activeCategories.has(cat));
|
||
|
||
const matchesFeatured = !showFeaturedOnly || bp.highlighted;
|
||
|
||
return matchesSearch && matchesCategory && matchesFeatured;
|
||
});
|
||
|
||
const sorted = [...filtered];
|
||
|
||
if (sortMode === 'alphabetical') {
|
||
sorted.sort((a, b) => a.title.localeCompare(b.title));
|
||
} else if (sortMode === 'author') {
|
||
sorted.sort((a, b) =>
|
||
(a.author || '').localeCompare(b.author || '') || a.title.localeCompare(b.title)
|
||
);
|
||
} else if (sortMode === 'newest') {
|
||
sorted.sort((a, b) => b.path.localeCompare(a.path));
|
||
} else {
|
||
sorted.sort((a, b) => a.order - b.order);
|
||
}
|
||
|
||
setFilteredBlueprints(sorted);
|
||
}, [searchTerm, activeCategories, blueprints, showFeaturedOnly, sortMode]);
|
||
|
||
const navItems = ['News', 'Showcase', 'Hosting', 'Extend', 'Learn', 'Community', 'About'];
|
||
const baseTabs = ['All', 'Featured'];
|
||
const tabItems = Array.from(new Set([...baseTabs, ...topCategories.slice(0, 6)]));
|
||
|
||
const handleTabClick = (tab) => {
|
||
if (tab === 'All') {
|
||
setActiveCategories(new Set());
|
||
setShowFeaturedOnly(false);
|
||
setSelectedFilter('all');
|
||
return;
|
||
}
|
||
|
||
if (tab === 'Featured') {
|
||
setActiveCategories(new Set());
|
||
setShowFeaturedOnly(true);
|
||
setSelectedFilter('featured');
|
||
return;
|
||
}
|
||
|
||
setActiveCategories(new Set([tab]));
|
||
setShowFeaturedOnly(false);
|
||
setSelectedFilter(tab);
|
||
};
|
||
|
||
const handleFilterChange = (value) => {
|
||
if (value === 'curated' || value === 'all') {
|
||
setSelectedFilter('all');
|
||
setActiveCategories(new Set());
|
||
setShowFeaturedOnly(false);
|
||
return;
|
||
}
|
||
|
||
if (value === 'featured') {
|
||
setSelectedFilter('featured');
|
||
setActiveCategories(new Set());
|
||
setShowFeaturedOnly(true);
|
||
return;
|
||
}
|
||
|
||
setSelectedFilter(value);
|
||
setActiveCategories(new Set([value]));
|
||
setShowFeaturedOnly(false);
|
||
};
|
||
|
||
const handleFeaturedToggle = (event) => {
|
||
const checked = event.target.checked;
|
||
setShowFeaturedOnly(checked);
|
||
|
||
if (checked) {
|
||
setSelectedFilter('featured');
|
||
setActiveCategories(new Set());
|
||
} else if (selectedFilter === 'featured') {
|
||
setSelectedFilter('all');
|
||
}
|
||
};
|
||
|
||
const showingAll = selectedFilter === 'all' &&
|
||
filteredBlueprints.length === blueprints.length &&
|
||
activeCategories.size === 0 &&
|
||
!searchTerm &&
|
||
!showFeaturedOnly;
|
||
|
||
const isTabActive = (tab) => {
|
||
if (tab === 'All') {
|
||
return selectedFilter === 'all';
|
||
}
|
||
if (tab === 'Featured') {
|
||
return selectedFilter === 'featured';
|
||
}
|
||
return activeCategories.has(tab);
|
||
};
|
||
|
||
const resultsMessage = !isLoaded
|
||
? 'Loading blueprints...'
|
||
: showingAll
|
||
? `Showing all ${formatNumber(blueprints.length)} blueprints`
|
||
: `Showing ${formatNumber(filteredBlueprints.length)} of ${formatNumber(blueprints.length)} blueprints`;
|
||
|
||
const filterOptions = [
|
||
{ value: 'all', label: 'All blueprints' },
|
||
{ value: 'featured', label: 'Featured' },
|
||
...allCategories.map(cat => ({ value: cat, label: cat }))
|
||
];
|
||
|
||
const placeholderCards = Array.from({ length: 6 }).map((_, index) =>
|
||
h(PlaceholderCard, { key: `placeholder-${index}` })
|
||
);
|
||
|
||
const shouldShowSkeletons = !isLoaded;
|
||
const showEmptyState = isLoaded && filteredBlueprints.length === 0;
|
||
|
||
const emptyState = h('div', { className: 'empty-state' },
|
||
h('h2', null, 'No blueprints match your filters'),
|
||
h('p', null, 'Try adjusting your search terms or selecting a different category.')
|
||
);
|
||
|
||
const galleryContent = shouldShowSkeletons
|
||
? h('div', { className: 'gallery-grid skeleton-grid' }, placeholderCards)
|
||
: showEmptyState
|
||
? emptyState
|
||
: h('div', { className: 'gallery-grid' },
|
||
filteredBlueprints.map(bp =>
|
||
h(BlueprintCard, {
|
||
blueprint: bp,
|
||
key: bp.path
|
||
})
|
||
)
|
||
);
|
||
|
||
return h('div', { className: 'page' },
|
||
h('section', { className: 'hero' },
|
||
h('div', { className: 'hero-inner' },
|
||
h('div', { className: 'hero-header' },
|
||
h('img', {
|
||
src: 'playground-icon.png',
|
||
alt: 'WordPress Playground',
|
||
className: 'hero-logo'
|
||
}),
|
||
h('h1', { className: 'hero-title' }, 'WordPress Blueprints Gallery')
|
||
),
|
||
h('p', { className: 'hero-subtitle' },
|
||
'Launch ready-made WordPress environments in seconds. Browse community-created ',
|
||
h('a', {
|
||
href: 'https://wordpress.github.io/wordpress-playground/',
|
||
target: '_blank',
|
||
rel: 'noreferrer noopener',
|
||
className: 'hero-link'
|
||
}, 'WordPress Playground'),
|
||
' blueprints and discover pre-configured setups. Learn how to ',
|
||
h('a', {
|
||
href: 'https://wordpress.github.io/wordpress-playground/blueprints/tutorial/',
|
||
target: '_blank',
|
||
rel: 'noreferrer noopener',
|
||
className: 'hero-link'
|
||
}, 'create your own')
|
||
)
|
||
)
|
||
),
|
||
h('section', { className: 'filters-section' },
|
||
h('div', { className: 'filters-inner' },
|
||
h('div', { className: 'tab-list' },
|
||
tabItems.map(tab =>
|
||
h('button', {
|
||
key: tab,
|
||
className: `tab ${isTabActive(tab) ? 'active' : ''}`,
|
||
onClick: () => handleTabClick(tab)
|
||
}, tab)
|
||
)
|
||
),
|
||
h('div', { className: 'toolbar' },
|
||
h('div', { className: 'search-block' },
|
||
h('div', { className: 'search-field' },
|
||
h('span', { className: 'search-icon' }, '⌕'),
|
||
h('input', {
|
||
type: 'search',
|
||
placeholder: 'Search blueprints',
|
||
value: searchTerm,
|
||
onInput: (event) => setSearchTerm(event.target.value)
|
||
})
|
||
)
|
||
)
|
||
)
|
||
)
|
||
),
|
||
h('main', { className: 'gallery-section' },
|
||
h('div', { className: 'gallery-inner' },
|
||
h('div', { className: 'results-summary' }, resultsMessage),
|
||
galleryContent
|
||
)
|
||
),
|
||
h('footer', { className: 'footer' },
|
||
h('p', null,
|
||
'Want to contribute your own blueprint? Check out the ',
|
||
h('a', {
|
||
href: 'https://github.com/wordpress/blueprints/blob/trunk/README.md#contributing-your-blueprint',
|
||
target: '_blank',
|
||
rel: 'noreferrer noopener'
|
||
}, 'contribution guidelines')
|
||
),
|
||
h('p', { style: { marginTop: '1rem' } },
|
||
h('a', { href: 'https://github.com/wordpress/blueprints', target: '_blank' }, 'View on GitHub'),
|
||
' • ',
|
||
h('a', { href: 'https://github.com/wordpress/blueprints/blob/trunk/GALLERY.md', target: '_blank' }, 'View as Markdown')
|
||
)
|
||
)
|
||
);
|
||
}
|
||
|
||
setTimeout(() => {
|
||
if (window.h && window.render) {
|
||
render(h(App), document.getElementById('app'));
|
||
}
|
||
}, 100);
|
||
</script>
|
||
</body>
|
||
</html>
|