Skip to content

Commit

Permalink
Add UI
Browse files Browse the repository at this point in the history
  • Loading branch information
tireymorris committed Jun 22, 2024
1 parent 1b2f570 commit 52322eb
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 125 deletions.
58 changes: 32 additions & 26 deletions public/styles/uno.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,60 +21,66 @@

/* layer: default */
.m-0{margin:0;}
.m-auto{margin:auto;}
.mr-4{margin-right:1rem;}
.mt-4{margin-top:1rem;}
.hidden{display:none;}
.h-1\/4{height:25%;}
.h-16{height:4rem;}
.h-5{height:1.25rem;}
.h-8{height:2rem;}
.h-full{height:100%;}
.min-h-screen{min-height:100vh;}
.w-16{width:4rem;}
.w-5{width:1.25rem;}
.w-full{width:100%;}
.flex{display:flex;}
.flex-col{flex-direction:column;}
@keyframes spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}
.animate-spin{animation:spin 1s linear infinite;}
.cursor-pointer{cursor:pointer;}
.items-center{align-items:center;}
.justify-center{justify-content:center;}
.gap-3{gap:0.75rem;}
.gap-8{gap:2rem;}
.gap-4{gap:1rem;}
.border{border-width:1px;}
.border-b{border-bottom-width:1px;}
.border-gray-2{--un-border-opacity:1;border-color:rgb(229 231 235 / var(--un-border-opacity));}
.focus\:border-blue-200:focus{--un-border-opacity:1;border-color:rgb(191 219 254 / var(--un-border-opacity));}
.rounded{border-radius:0.25rem;}
.rounded-md{border-radius:0.375rem;}
.border-none{border-style:none;}
.border-solid{border-style:solid;}
.bg-blue-200{--un-bg-opacity:1;background-color:rgb(191 219 254 / var(--un-bg-opacity));}
.bg-blue-300{--un-bg-opacity:1;background-color:rgb(147 197 253 / var(--un-bg-opacity));}
.bg-gray-300{--un-bg-opacity:1;background-color:rgb(209 213 219 / var(--un-bg-opacity));}
.bg-indigo-200{--un-bg-opacity:1;background-color:rgb(199 210 254 / var(--un-bg-opacity));}
.bg-transparent{background-color:transparent;}
.bg-white{--un-bg-opacity:1;background-color:rgb(255 255 255 / var(--un-bg-opacity));}
.dark .dark\:bg-blue-600{--un-bg-opacity:1;background-color:rgb(37 99 235 / var(--un-bg-opacity));}
.dark .dark\:bg-gray-700{--un-bg-opacity:1;background-color:rgb(55 65 81 / var(--un-bg-opacity));}
.dark .dark\:bg-gray-900{--un-bg-opacity:1;background-color:rgb(17 24 39 / var(--un-bg-opacity));}
.dark .dark\:bg-indigo-600{--un-bg-opacity:1;background-color:rgb(79 70 229 / var(--un-bg-opacity));}
.bg-white,
[bg-white=""]{--un-bg-opacity:1;background-color:rgb(255 255 255 / var(--un-bg-opacity));}
.dark .dark\:bg-gray-900,
.dark [dark\:bg-gray-900=""]{--un-bg-opacity:1;background-color:rgb(17 24 39 / var(--un-bg-opacity));}
.hover\:bg-blue-400:hover{--un-bg-opacity:1;background-color:rgb(96 165 250 / var(--un-bg-opacity));}
.from-blue-500{--un-gradient-from-position:0%;--un-gradient-from:rgb(59 130 246 / var(--un-from-opacity, 1)) var(--un-gradient-from-position);--un-gradient-to-position:100%;--un-gradient-to:rgb(59 130 246 / 0) var(--un-gradient-to-position);--un-gradient-stops:var(--un-gradient-from), var(--un-gradient-to);}
.to-purple-500{--un-gradient-to-position:100%;--un-gradient-to:rgb(168 85 247 / var(--un-to-opacity, 1)) var(--un-gradient-to-position);}
.bg-gradient-to-r{--un-gradient-shape:to right;--un-gradient:var(--un-gradient-shape), var(--un-gradient-stops);background-image:linear-gradient(var(--un-gradient));}
.p-0{padding:0;}
.px-10{padding-left:2.5rem;padding-right:2.5rem;}
.px-2{padding-left:0.5rem;padding-right:0.5rem;}
.p-4{padding:1rem;}
.px-4{padding-left:1rem;padding-right:1rem;}
.px-6{padding-left:1.5rem;padding-right:1.5rem;}
.py-1{padding-top:0.25rem;padding-bottom:0.25rem;}
.py-2{padding-top:0.5rem;padding-bottom:0.5rem;}
.py-3{padding-top:0.75rem;padding-bottom:0.75rem;}
.py-8{padding-top:2rem;padding-bottom:2rem;}
.pl-3{padding-left:0.75rem;}
.pr-10{padding-right:2.5rem;}
.text-center{text-align:center;}
.text-5xl{font-size:3rem;line-height:1;}
.text-4xl{font-size:2.25rem;line-height:2.5rem;}
.text-base{font-size:1rem;line-height:1.5rem;}
.text-sm{font-size:0.875rem;line-height:1.25rem;}
.dark .dark\:text-white{--un-text-opacity:1;color:rgb(255 255 255 / var(--un-text-opacity));}
.text-xl{font-size:1.25rem;line-height:1.75rem;}
.dark .dark\:text-white,
.dark [dark\:text-white=""],
.text-white{--un-text-opacity:1;color:rgb(255 255 255 / var(--un-text-opacity));}
.text-black{--un-text-opacity:1;color:rgb(0 0 0 / var(--un-text-opacity));}
.text-blue-500{--un-text-opacity:1;color:rgb(59 130 246 / var(--un-text-opacity));}
.text-neutral-500{--un-text-opacity:1;color:rgb(115 115 115 / var(--un-text-opacity));}
.text-slate-900{--un-text-opacity:1;color:rgb(15 23 42 / var(--un-text-opacity));}
.dark .dark\:hover\:text-yellow-300:hover{--un-text-opacity:1;color:rgb(253 224 71 / var(--un-text-opacity));}
.hover\:text-yellow-600:hover{--un-text-opacity:1;color:rgb(202 138 4 / var(--un-text-opacity));}
.font-bold{font-weight:700;}
.font-extrabold{font-weight:800;}
.font-lato{font-family:"Lato";}
.underline{text-decoration-line:underline;}
.shadow-lg{--un-shadow:var(--un-shadow-inset) 0 10px 15px -3px var(--un-shadow-color, rgb(0 0 0 / 0.1)),var(--un-shadow-inset) 0 4px 6px -4px var(--un-shadow-color, rgb(0 0 0 / 0.1));box-shadow:var(--un-ring-offset-shadow), var(--un-ring-shadow), var(--un-shadow);}
.hover\:underline:hover{text-decoration-line:underline;}
.opacity-25{opacity:0.25;}
.opacity-75{opacity:0.75;}
.shadow-md{--un-shadow:var(--un-shadow-inset) 0 4px 6px -1px var(--un-shadow-color, rgb(0 0 0 / 0.1)),var(--un-shadow-inset) 0 2px 4px -2px var(--un-shadow-color, rgb(0 0 0 / 0.1));box-shadow:var(--un-ring-offset-shadow), var(--un-ring-shadow), var(--un-shadow);}
.outline{outline-style:solid;}
.drop-shadow-lg{--un-drop-shadow:drop-shadow(0 10px 8px var(--un-drop-shadow-color, rgb(0 0 0 / 0.04))) drop-shadow(0 4px 3px var(--un-drop-shadow-color, rgb(0 0 0 / 0.1)));filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia);}
.outline{outline-style:solid;}
115 changes: 91 additions & 24 deletions src/server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,106 @@ import { Hono } from "hono";
import { serveStatic } from "hono/bun";
import { logger } from "hono/logger";
import Layout from "./components/Layout.tsx";
import { fetchAllArticles } from "./util/api";
import db from "./util/db";
import { Article } from "./types.ts";
import shuffle from "./util/shuffle.ts";

const app = new Hono();

app.use("/styles/*", serveStatic({ root: "./public/" }));
app.use("*", logger());

app.get("/", (c) =>
c.html(
app.get("/", async (c) => {
await fetchAllArticles();

return c.html(
<Layout title="hyperwave">
<main class="m-auto flex h-full flex-col items-center gap-8 px-10 py-8 text-center">
<h1 class="text-5xl font-extrabold text-black dark:text-white drop-shadow-lg">
🌊 hyperwave
</h1>
<pre class="rounded-md bg-indigo-200 dark:bg-indigo-600 px-6 py-3 text-black dark:text-white shadow-lg">
⌨️ edit&nbsp;
<code class="bg-gray-300 dark:bg-gray-700 text-black dark:text-white rounded px-2 py-1">
src/server.tsx
</code>
</pre>
<pre class="rounded-md bg-blue-200 dark:bg-blue-600 px-6 py-3 text-black dark:text-white shadow-lg">
📚 read the&nbsp;
<a
href="https://github.com/tireymorris/hyperwave?tab=readme-ov-file#hyperwave-"
class="underline hover:text-yellow-600 dark:hover:text-yellow-300"
<div class="flex flex-col items-center gap-4 p-4 min-h-screen">
<header class="w-full h-1/4 flex items-center justify-center bg-gradient-to-r from-blue-500 to-purple-500 text-white">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
class="w-16 h-16 mr-4"
>
friendly manual
</a>
!
</pre>
</main>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M19 10c0-1.988-1.291-3.676-3.051-4.358C15.609 3.529 13.877 2 12 2S8.391 3.529 8.051 5.642C6.291 6.324 5 8.012 5 10c0 3.019 1.736 5.463 4.207 6.572.157.069.32.119.487.138C9.99 18.025 9.352 19.109 8 19.481V20h8v-.519c-1.352-.372-1.99-1.456-1.694-2.771a1.75 1.75 0 00.487-.138C17.264 15.463 19 13.019 19 10z"
/>
</svg>
<h1 class="text-4xl font-bold">Top Stories</h1>
</header>
<div
id="articles"
hx-get="/articles?page=1"
hx-trigger="load"
hx-swap="beforeend"
hx-indicator="#loading-indicator"
class="w-full"
></div>
<div id="loading-indicator" class="mt-4 text-center hidden">
<svg
class="animate-spin h-5 w-5 text-blue-500"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
class="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zM12 16a4 4 0 100-8 4 4 0 000 8z"
></path>
</svg>
</div>
</div>
</Layout>,
),
);
);
});

app.get("/articles", async (c) => {
const page = parseInt(c.req.query("page") || "1");
const articlesPerPage = 5;
const offset = (page - 1) * articlesPerPage;

const articles = db
.prepare("SELECT * FROM articles ORDER BY RANDOM() DESC LIMIT ? OFFSET ?")
.all(articlesPerPage, offset) as Article[];

const nextPage = page + 1;

return c.html(
<>
{articles.map((article) => (
<div key={article.id} class="article-item p-4 border-b">
<a href={article.link} class="text-blue-500 hover:underline text-xl">
{article.title} [{article.source}]
</a>
</div>
))}
{articles.length > 0 && (
<div
hx-get={`/articles?page=${nextPage}`}
hx-trigger="intersect once"
hx-swap="beforeend"
class="mt-4"
hx-indicator="#loading-indicator"
></div>
)}
</>,
);
});

export default {
port: process.env.PORT || 1234,
Expand Down
1 change: 0 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@ export interface Article {
title: string;
link: string;
source: string;
page: number;
created_at: string;
}
Loading

0 comments on commit 52322eb

Please sign in to comment.