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