Add dropdown menu for opening article in other apps

This commit is contained in:
Râu Cao 2024-10-21 22:58:46 +02:00
parent ffd709d2f9
commit 96254b38be
Signed by: raucao
GPG Key ID: 37036C356E56CC51
4 changed files with 114 additions and 19 deletions

View File

@ -52,7 +52,7 @@ pre code {
main { main {
display: block; display: block;
max-width: 728px; max-width: 728px;
margin: 12rem auto; margin: 12rem auto 24rem auto;
} }
main header { main header {
@ -64,26 +64,65 @@ main header h1 {
margin-bottom: 1.6rem; margin-bottom: 1.6rem;
} }
p.meta { main header .meta {
display: flex; display: flex;
column-gap: 1rem; column-gap: 1rem;
} }
p.meta .content { main header .meta .content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
font-size: 0.875rem; font-size: 0.875rem;
line-height: 1.6rem; line-height: 1.6rem;
} }
p.meta .name a { main header .meta .name a {
text-decoration: none; text-decoration: none;
} }
.article-list .item { main .article-list .item {
margin-bottom: 3rem; margin-bottom: 3rem;
} }
.article-list .item h3 { main .article-list .item h3 {
margin-bottom: 1rem; margin-bottom: 1rem;
} }
main article footer {
margin-top: 5rem;
}
/* Dropdown menu */
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-button {
font-family: "Merriweather", serif;
font-size: 0.875rem;
padding: 0.6rem 1rem;
border: 1px solid;
border-radius: 5px;
cursor: pointer;
}
.dropdown-content {
display: none;
position: absolute;
min-width: 160px;
border-radius: 5px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
}
.dropdown-content a {
padding: 0.6rem 1rem;
text-decoration: none;
display: block;
}
.dropdown:hover .dropdown-content {
display: block;
}

View File

@ -25,10 +25,35 @@ pre code {
color: #ccc; color: #ccc;
} }
p.meta .date { main header .meta .date {
color: #888; color: #888;
} }
p.meta .name a { main header .meta .name a {
color: #3b3a38; color: #3b3a38;
} }
/* Dropdown menu */
.dropdown-button {
background-color: #f5f2eb;
color: #3b3a38;
border-color: #ccc;
}
.dropdown-content {
background-color: #fff;
}
.dropdown-content a {
color: #3b3a38 !important;
}
.dropdown-content a:hover {
background-color: #f1f1f1;
}
.dropdown:hover .dropdown-button {
background-color: #fff;
border-color: #fff;
}

51
html.ts
View File

@ -2,7 +2,7 @@ import { localizeDate } from "./dates.ts";
import Article from "./models/article.ts"; import Article from "./models/article.ts";
import Profile from "./models/profile.ts"; import Profile from "./models/profile.ts";
export function htmlLayout(title: string, body: string, profile: Profile) { function htmlLayout(title: string, body: string, profile: Profile): string {
return ` return `
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
@ -22,29 +22,34 @@ export function htmlLayout(title: string, body: string, profile: Profile) {
`; `;
} }
export function articleHtml(article: Article, profile: Profile) { export function articleHtml(article: Article, profile: Profile): string {
const publishedAtFormatted = localizeDate(article.publishedAt); const publishedAtFormatted = localizeDate(article.publishedAt);
const body = ` const body = `
<main> <main>
<header> <header>
<h1>${article.title}</h1> <h1>${article.title}</h1>
<p class="meta"> <div class="meta">
<img class="avatar" src="${profile.picture}" alt="User Avatar" /> <img class="avatar" src="${profile.picture}" alt="User Avatar" />
<span class="content"> <div class="content">
<span class="name"><a href="/@${profile.username}">${profile.name}</a></span> <span class="name"><a href="/@${profile.username}">${profile.name}</a></span>
<span class="date">${publishedAtFormatted}</span> <span class="date">${publishedAtFormatted}</span>
</span> </div>
</p> </div>
</header> </header>
${article.html} <article>
${article.html}
<footer>
${openWithNostrAppHtml(article.naddr)}
</footer>
</article>
</main> </main>
`; `;
return htmlLayout(article.title, body, profile); return htmlLayout(article.title, body, profile);
} }
function articleListItemHtml(article: Article) { function articleListItemHtml(article: Article): string {
const formattedDate = localizeDate(article.publishedAt); const formattedDate = localizeDate(article.publishedAt);
return ` return `
@ -55,7 +60,7 @@ function articleListItemHtml(article: Article) {
`; `;
} }
export function articleListHtml(articles: Article[]) { export function articleListHtml(articles: Article[]): string {
if (articles.length === 0) return ""; if (articles.length === 0) return "";
let html = ""; let html = "";
@ -71,7 +76,7 @@ export function articleListHtml(articles: Article[]) {
`; `;
} }
export function profilePageHtml(profile: Profile, articles: Article[]) { export function profilePageHtml(profile: Profile, articles: Article[]): string {
const title = `${profile.name} on Nostr`; const title = `${profile.name} on Nostr`;
const body = ` const body = `
@ -91,3 +96,29 @@ export function profilePageHtml(profile: Profile, articles: Article[]) {
return htmlLayout(title, body, profile); return htmlLayout(title, body, profile);
} }
function openWithNostrAppHtml(bech32Id): string {
let linksHtml = "";
const links = [
{ title: "Nostr Link", href: `nostr:${bech32Id}` },
{ title: "Habla", href: `https://habla.news/a/${bech32Id}` },
{
title: "noStrudel",
href: `https://nostrudel.ninja/#/articles/${bech32Id}`,
},
{ title: "Coracle", href: `https://coracle.social/${bech32Id}` }
];
for (const link of links) {
linksHtml += `<a href="${link.href}" target="_blank">${link.title}</a>`;
}
return `
<div class="open-with dropdown">
<button class="dropdown-button">Open with Nostr app</button>
<div class="dropdown-content">
${linksHtml}
</div>
</div>
`;
}

View File

@ -16,7 +16,7 @@ export default class Article {
} }
get url(): string { get url(): string {
return `${config.base_url}/${this.naddr}` return `${config.base_url}/${this.naddr}`;
} }
get title(): string { get title(): string {