web & server: finish initial tailwind rewrite

This commit is contained in:
2025-01-27 14:00:46 -08:00
parent 70fb635eda
commit ee93d725ba
7 changed files with 158 additions and 108 deletions

View File

@@ -13,7 +13,9 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@700&display=swap" rel="stylesheet">
<!-- <link data-trunk rel="css" href="static/site-specific.css" /> -->
<link data-trunk rel="css" href="static/vars.css" />
<link data-trunk rel="tailwind-css" href="./src/tailwind.css" />
<link data-trunk rel="css" href="static/overrides.css" />
</head>
<body>

View File

@@ -86,7 +86,13 @@ pub fn view(model: &Model) -> Node<Msg> {
} => search_results(&query, results.as_slice(), *count, pager, selected_threads),
};
div![
C!["flex", "flex-wrap-reverse", "bg-black", "text-white"],
C![
"flex",
"flex-wrap-reverse",
"bg-black",
"text-white",
"lg:flex-nowrap"
],
div![
C!["w-full", "lg:w-48", "flex-none", "flex", "flex-col"],
tags(model),
@@ -190,6 +196,7 @@ fn set_title(title: &str) {
seed::document().set_title(&format!("lb: {}", title));
}
// TODO: unifiy tags_chiclet, removable_tags_chiclet, and tags inside news_post()
fn tags_chiclet(tags: &[String], is_mobile: bool) -> impl Iterator<Item = Node<Msg>> + '_ {
tags.iter().map(move |tag| {
let hex = compute_color(tag);
@@ -1147,8 +1154,6 @@ pub fn tags(model: &Model) -> Node<Msg> {
]
}
fn news_post(post: &ShowThreadQueryThreadOnNewsPost, content_el: &ElRef<HtmlElement>) -> Node<Msg> {
// TODO remove and replace with CSS styling
let show_icon_text = true;
let subject = &post.title;
set_title(subject);
let read_thread_id = post.thread_id.clone();
@@ -1156,94 +1161,68 @@ fn news_post(post: &ShowThreadQueryThreadOnNewsPost, content_el: &ElRef<HtmlElem
fn tag(tag: String, is_mobile: bool) -> Node<Msg> {
let hex = compute_color(&tag);
let style = style! {St::BackgroundColor=>hex};
let classes = C!["NOTPORTED", "tag", IF!(is_mobile => "is-small")];
let attrs = attrs! {
At::Href => urls::search(&format!("tag:{tag}"), 0)
};
let tag = tag.clone();
div![
C![
"NOTPORTED",
"message-tags",
"field",
"is-grouped",
"is-grouped-multiline"
],
div![
C!["NOTPORTED", "control"],
div![
C!["NOTPORTED", "tags", "has-addons"],
a![
classes,
attrs,
style,
match tag.as_str() {
"attachment" => span!["📎"],
"replied" => span![i![C!["NOTPORTED", "fa-solid", "fa-reply"]]],
_ => span![&tag],
},
ev(Ev::Click, move |_| Msg::FrontPageRequest {
query: format!("tag:{tag}"),
after: None,
before: None,
first: None,
last: None,
})
]
]
]
a![
attrs,
span![C![&tw_classes::TAG], style, &tag],
ev(Ev::Click, move |_| Msg::FrontPageRequest {
query: format!("tag:{tag}"),
after: None,
before: None,
first: None,
last: None,
})
]
}
div![
C!["NOTPORTED", "thread"],
h3![C!["NOTPORTED", "is-size-5"], subject],
tag(format!("News/{}", post.slug), false),
C!["lg:p-4", "max-w-4xl"],
div![
C!["NOTPORTED", "level", "is-mobile"],
C!["p-4", "lg:p-0"],
h3![C!["text-xl"], subject],
span![tag(format!("News/{}", post.slug), false)],
div![
C!["NOTPORTED", "level-item"],
C!["pt-4", "gap-2", "flex", "justify-around"],
div![
C!["NOTPORTED", "buttons", "has-addons"],
button![
C!["NOTPORTED", "button", "mark-read"],
C![&tw_classes::BUTTON, "rounded-r-none"],
attrs! {At::Title => "Mark as read"},
span![
C!["NOTPORTED", "icon", "is-small"],
i![C!["NOTPORTED", "far", "fa-envelope-open"]]
],
IF!(show_icon_text=>span!["Read"]),
span![i![C!["far", "fa-envelope-open"]]],
span![C!["pl-2", "hidden", "md:inline"], "Read"],
ev(Ev::Click, move |_| Msg::MultiMsg(vec![
Msg::SetUnread(read_thread_id, false),
Msg::GoToSearchResults
])),
],
button![
C!["NOTPORTED", "button", "mark-unread"],
C![&tw_classes::BUTTON, "rounded-l-none"],
attrs! {At::Title => "Mark as unread"},
span![
C!["NOTPORTED", "icon", "is-small"],
i![C!["NOTPORTED", "far", "fa-envelope"]]
],
IF!(show_icon_text=>span!["Unread"]),
span![i![C!["far", "fa-envelope"]]],
span![C!["pl-2", "hidden", "md:inline"], "Unread"],
ev(Ev::Click, move |_| Msg::MultiMsg(vec![
Msg::SetUnread(unread_thread_id, true),
Msg::GoToSearchResults
])),
],
],
// Placeholder for symmetry with email view that has Spam button
div![],
],
// This would be the holder for spam buttons on emails, needed to keep layout
// consistent
div![C!["NOTPORTED", "level-item"], div![]]
],
div![
C!["NOTPORTED", "message"],
div![C!["NOTPORTED", "header"], render_news_post_header(&post)],
C!["lg:mt-4"],
div![render_news_post_header(&post)],
div![
C![
"NOTPORTED",
"body",
"bg-white",
"text-black",
"p-4",
"lg:mb-4",
"min-w-full",
"overflow-x-auto",
"news-post",
format!("site-{}", post.slug)
],
@@ -1251,12 +1230,6 @@ fn news_post(post: &ShowThreadQueryThreadOnNewsPost, content_el: &ElRef<HtmlElem
raw![&post.body]
]
],
/* TODO(wathiede): plumb in orignal id
a![
attrs! {At::Href=>api::original(&thread_node.0.as_ref().expect("message missing").id)},
"Original"
],
*/
click_to_top(),
]
}
@@ -1289,7 +1262,7 @@ fn render_news_post_header(post: &ShowThreadQueryThreadOnNewsPost) -> Node<Msg>
],
];
div![
C!["flex", "p-4"],
C!["flex", "p-4", "bg-neutral-800"],
div![favicon],
div![
C!["px-4", "mr-auto"],
@@ -1329,6 +1302,7 @@ fn render_news_post_header(post: &ShowThreadQueryThreadOnNewsPost) -> Node<Msg>
]
}
fn reading_progress(ratio: f64) -> Node<Msg> {
return div![];
let percent = ratio * 100.;
info!("percent {percent}");
div![
@@ -1336,7 +1310,7 @@ fn reading_progress(ratio: f64) -> Node<Msg> {
"fixed",
"top-0",
"left-0",
"w-screen",
"w-full",
"h-1",
"bg-gray-200",
IF!(percent<1. => "hidden")

33
web/static/overrides.css Normal file
View File

@@ -0,0 +1,33 @@
html {
background-color: black;
}
.news-post a {
color: var(--color-link) !important;
text-decoration: underline;
}
.news-post br {
display: block;
margin-top: 1em;
content: " ";
}
.news-post h1,
.news-post h2,
.news-post h3,
.news-post h4 {
margin-top: 1em !important;
margin-bottom: 1em !important;
}
.news-post p {
margin-bottom: 1em;
}
.news-post pre,
.news-post code {
font-family: monospace;
background-color: #eee !important;
padding: 0.5em !important;
}

42
web/static/vars.css Normal file
View File

@@ -0,0 +1,42 @@
:root {
--active-brightness: 0.85;
--border-radius: 5px;
--box-shadow: 2px 2px 10px;
--color-accent: #118bee15;
--color-bg: #fff;
--color-bg-secondary: #e9e9e9;
--color-link: #118bee;
--color-secondary: #920de9;
--color-secondary-accent: #920de90b;
--color-shadow: #f4f4f4;
--color-table: #118bee;
--color-text: #000;
--color-text-secondary: #999;
--color-scrollbar: #cacae8;
--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
--hover-brightness: 1.2;
--justify-important: center;
--justify-normal: left;
--line-height: 1.5;
/*
--width-card: 285px;
--width-card-medium: 460px;
--width-card-wide: 800px;
*/
--width-content: 1080px;
}
@media (prefers-color-scheme: dark) {
:root[color-mode="user"] {
--color-accent: #0097fc4f;
--color-bg: #333;
--color-bg-secondary: #555;
--color-link: #0097fc;
--color-secondary: #e20de9;
--color-secondary-accent: #e20de94f;
--color-shadow: #bbbbbb20;
--color-table: #0097fc;
--color-text: #f7f7f7;
--color-text-secondary: #aaa;
}
}