web: much nicer tag list styling with flex box

This commit is contained in:
Bill Thiede 2025-01-26 10:54:28 -08:00
parent 6b3567fb1b
commit b2879211e4

View File

@ -53,9 +53,9 @@ pub fn view(model: &Model) -> Node<Msg> {
),
};
div![
C!["flex", "flex-wrap-reverse"],
C!["flex", "flex-wrap-reverse", "bg-black", "text-white"],
div![
C!["w-48", "flex-none", "flex", "flex-col"],
C!["w-full", "lg:w-48", "flex-none", "flex", "flex-col"],
tags(model),
versions(&model.versions)
],
@ -1040,43 +1040,61 @@ fn view_header(query: &str, refresh_request: &RefreshingState) -> Node<Msg> {
}
pub fn tags(model: &Model) -> Node<Msg> {
fn view_tag_li(display_name: &str, indent: usize, t: &Tag, search_unread: bool) -> Node<Msg> {
fn view_tag(display_name: &str, indent: usize, t: &Tag, search_unread: bool) -> Node<Msg> {
// Hacky, but necessary for tailwind to see all the classes we're using
let indent_cls = match indent {
0 => "",
1 => "pl-2",
2 => "pl-4",
3 => "pl-6",
4 => "pl-8",
5 => "pl-10",
_ => "pl-12",
};
let href = if search_unread {
urls::search(&format!("is:unread tag:{}", t.name), 0)
} else {
urls::search(&format!("tag:{}", t.name), 0)
};
li![a![
attrs! {
At::Href => href
},
(0..indent).map(|_| span![C!["pl-4"], ""]),
div![
C!["flex", "flex-row", "flex-nowrap"],
i![
C!["px-1", "fa-solid", "fa-tag"],
C![indent_cls, "pr-1", "fa-solid", "fa-tag"],
style! {
//"--fa-primary-color" => t.fg_color,
St::Color => t.bg_color,
},
],
a![
C!["grow", "truncate"],
attrs! {
At::Href => href
},
display_name,
IF!(t.unread>0 => format!(" ({})", t.unread)),
],
span![
C![
"self-center",
"justify-self-end",
"text-sm",
"text-gray-400"
],
IF!(t.unread>0 => format!("{}", t.unread))
],
ev(Ev::Click, |_| {
// Scroll window to the top when searching for a tag.
info!("scrolling to the top because you clicked a tag");
web_sys::window().unwrap().scroll_to_with_x_and_y(0., 0.);
})
]]
]
}
fn matches(a: &[&str], b: &[&str]) -> usize {
std::iter::zip(a.iter(), b.iter())
.take_while(|(a, b)| a == b)
.count()
}
fn view_tag_list<'a>(
tags: impl Iterator<Item = &'a Tag>,
search_unread: bool,
) -> Vec<Node<Msg>> {
let mut lis = Vec::new();
fn view_tags<'a>(tags: impl Iterator<Item = &'a Tag>, search_unread: bool) -> Vec<Node<Msg>> {
let mut tag_els = Vec::new();
let mut last = Vec::new();
for t in tags {
let parts: Vec<_> = t.name.split('/').collect();
@ -1085,7 +1103,7 @@ pub fn tags(model: &Model) -> Node<Msg> {
// Synthesize fake tags for proper indenting.
for i in n..parts.len() - 1 {
let display_name = parts[n];
lis.push(view_tag_li(
tag_els.push(view_tag(
&display_name,
n,
&Tag {
@ -1099,10 +1117,10 @@ pub fn tags(model: &Model) -> Node<Msg> {
n = parts.len() - 1;
}
let display_name = parts[n];
lis.push(view_tag_li(&display_name, n, t, search_unread));
tag_els.push(view_tag(&display_name, n, t, search_unread));
last = parts;
}
lis
tag_els
}
let unread = model
.tags
@ -1112,9 +1130,11 @@ pub fn tags(model: &Model) -> Node<Msg> {
let tags_open = use_state(|| false);
let force_tags_open = unread.is_empty();
aside![
IF!(!unread.is_empty() => p![ "Unread"]),
IF!(!unread.is_empty() => ul![view_tag_list(unread.into_iter(), true)]),
C!["p-2"],
IF!(!unread.is_empty() => p![C!["uppercase", "font-bold"], "Unread"]),
IF!(!unread.is_empty() => div![C!["flex","flex-col"], view_tags(unread.into_iter(), true)]),
p![
span![C!["uppercase", "font-bold", "pr-2"], "Tags"],
IF!(!force_tags_open =>
i![C![
"fa-solid",
@ -1124,13 +1144,12 @@ pub fn tags(model: &Model) -> Node<Msg> {
"fa-angle-down"
}
]]),
" Tags",
ev(Ev::Click, move |_| {
tags_open.set(!tags_open.get());
})
],
ul![
IF!(force_tags_open||tags_open.get() => model.tags.as_ref().map(|tags| view_tag_list(tags.iter(),false))),
div![
IF!(force_tags_open||tags_open.get() => model.tags.as_ref().map(|tags| view_tags(tags.iter(),false))),
]
]
}