theme-gallery / index.html
freddyaboulton's picture
Improvement
4625bc6
raw
history blame
7 kB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Gradio theme gallery</title>
<meta name="description" content="Discover all gradio themes created by the community." />
<meta property="og:url" content="https://freddyaboulton-gradio-themes-gallery.hf.space/" />
<meta property="og:type" content="website" />
<meta property="og:title" content="Gradio - Theme Gallery" />
<meta property="og:description" content="Discover all gradio themes created by the community." />
<meta property="og:image" content="https://huggingface-projects-diffusers-gallery.hf.space/Fo6vR6JX0AEjbw1.jpeg" />
<meta name="twitter:card" content="player" />
<meta property="twitter:url" content="https://freddyaboulton-gradio-themes-gallery.hf.space/" />
<meta name="twitter:description" content="Discover all gradio themes created by the community." />
<meta name="twitter:site" content="@huggingface" />
<meta name="twitter:title" content="Gradio - Theme Gallery" />
<meta name="twitter:image" content="https://huggingface-projects-diffusers-gallery.hf.space/Fo6vR6JX0AEjbw1.jpeg" />
<meta name="twitter:player" content="https://freddyaboulton-gradio-themes-gallery.hf.space/index.html" />
<meta name="twitter:player:width" content="100%" />
<meta name="twitter:player:height" content="600" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.1/iframeResizer.contentWindow.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<style>
iframe {
display: block;
border: 1px solid transparent;
width: 100%;
height: 500px;
pointer-events: none;
}
.grid-container {
display: grid;
grid-template-columns: repeat(3, minmax(300px, 1fr));
grid-gap: 10px;
margin-top: 3.5rem;
margin-left: 3.5rem;
margin-right: 3.5rem;
}
.grid-item {
position: relative;
overflow-y: hidden;
border-radius: 10px;
}
.grid-item a {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: block;
z-index: 1;
}
</style>
<script type="module">
import Alpine from "https://cdn.skypack.dev/alpinejs";
import Intersect from "https://cdn.skypack.dev/@alpinejs/intersect";
Alpine.plugin(Intersect);
Alpine.data("themesData", () => ({
async init() {
const data = await this.getThemes(this.page, this.sort, this.useTestData);
this.themes = data.themes;
this.totalPages = data.totalPages;
},
themes: [],
filter: "all",
sort: "likes",
page: 1,
totalPages: -1,
useTestData: false,
buttonClass(attr, filter) {
if (this[attr] === filter) {
return "bg-black dark:bg-white shadow-lg text-white dark:text-black hover:bg-black hover:text-white";
}
return "text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-500 hover:text-gray-800";
},
async switchData() {
this.page = 1;
this.useTestData = !this.useTestData;
const data = await this.getThemes(this.page, this.sort, this.useTestData);
this.themes = data.themes;
this.totalPages = data.totalPages;
},
async sortThemes(sort) {
this.sort = sort;
this.page = 1;
const data = await this.getThemes(this.page, this.sort, this.useTestData);
this.themes = data.themes;
this.totalPages = data.totalPages;
},
async getThemes(page, sort, useTestData) {
const filename = useTestData ? "test_data.json" : "subdomains.json"
const res = await fetch(
`https://huggingface.co/datasets/freddyaboulton/gradio-theme-subdomains/resolve/main/${filename}`
);
const data = await res.json();
if(sort === 'likes') {
data.sort((a, b) => (b.likes - a.likes));
}else {
data.sort((a, b) => (new Date(b.lastModified) - new Date(a.lastModified)));
}
const pageThemes = data.slice((page - 1) * 30, page * 30);
console.log(pageThemes);
return {
themes: pageThemes,
totalPages: Math.floor(data.length + 30 - 1, 30)
};
},
async nextPage() {
if (this.page < this.totalPages) {
this.page += 1;
const data = await this.getThemes(this.page, this.filter, this.useTestData);
this.themes = this.themes.concat(data.themes);
this.totalPages = data.totalPages;
}
},
}));
Alpine.start();
</script>
</head>
<body class="pb-10 pt-5 bg-gray-100 dark:bg-gray-900 relative">
<section
x-data="themesData"
>
<section class="container px-6 grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-14 mx-auto relative">
<div class="col-span-2 lg:col-span-1 flex flex-col gap-14 row-start">
<h1 class="text-lg font-semibold dark:text-white whitespace-nowrap">Gradio Themes Gallery</h1>
</div>
<div class="col-span-2 md:col-span-3 flex items-center gap-14 flex flex-wrap lg-auto lg:ml-auto text-sm">
<div class="flex gap-2">
<span class="md:px-3 py-1 dark:text-white text-gray-400">sort by</span>
<button
:class="buttonClass('sort', 'likes')"
class="text-gray-600 hover:bg-gray-200 dark:hover:bg-gray-500 hover:text-gray-800 px-2 md:px-3 py-1 rounded-full"
@click="sortThemes('likes')"
>
Most Likes
</button>
<button
:class="buttonClass('sort', 'recent')"
class="text-gray-600 hover:bg-gray-200 dark:hover:bg-gray-500 hover:text-gray-800 px-2 md:px-3 py-1 rounded-full"
@click="sortThemes('recent')"
>
Recent
</button>
</div>
<div class="flex gap-0">
<input type="checkbox" @click="switchData()" class="rounded">
<span class="md:px-3 py-1 dark:text-white text-gray-400 ml-0">Use Test Data</span>
<!-- <button
:class="buttonClass('useTestData', false)"
class="px-2 md:px-3 py-1 rounded-full"
@click="switchData()"
>
Use Test Data
</button> -->
</div>
</div>
</section>
<div class="grid-container">
<template x-for="theme in themes" :key="theme.id">
<div class="grid-item">
<iframe :src="theme.subdomain" :alt="theme.id" scrolling="no" frameborder="0"></iframe>
<a :href="`https://huggingface.co/spaces/${theme.id}`" target="_blank"></a>
</div>
</template>
</div>
<div class="h-12 relative" x-intersect="nextPage" data-iframe-height></div>
</section>
</body>
</html>