table_rs/yew/header.rs
1use crate::yew::types::{SortOrder, TableHeaderProps};
2use yew::prelude::*;
3
4/// A table header component that renders column headers with optional sorting functionality.
5///
6/// This component is part of the `table_rs` Yew integration and is responsible for rendering
7/// the `<thead>` section of a table. It supports sortable columns and emits sort events when
8/// a sortable header is clicked.
9///
10/// # Arguments
11/// * `props` - The properties passed to the component.
12/// - `columns` - A list of column definitions (`Vec<Column>`) specifying the headers to render.
13/// - `sort_column` - An `Option<&'static str>` indicating the currently sorted column, if any.
14/// - `sort_order` - A `SortOrder` indicating whether the sort is ascending or descending.
15/// - `on_sort_column` - A `Callback<&'static str>` triggered when a sortable column is clicked.
16/// - `classes` - A `TableClasses` object defining CSS class names for customization.
17///
18/// # Returns
19/// (Html): A rendered `<thead>` element containing the table header row and interactive sorting logic.
20///
21/// # Examples
22/// ```rust
23/// use table_rs::yew::header::TableHeader;
24/// use table_rs::yew::types::{TableHeaderProps, Column, SortOrder, TableClasses};
25/// use yew::prelude::*;
26///
27/// #[function_component(App)]
28/// pub fn app() -> Html {
29/// let columns = vec![
30/// Column { id: "name", header: "Name", sortable: true, ..Default::default() },
31/// Column { id: "email", header: "Email", sortable: false, ..Default::default() },
32/// ];
33///
34/// let sort_order = use_state(|| SortOrder::Asc);
35/// let sort_column = use_state(|| Some("name"));
36///
37/// let props = TableHeaderProps {
38/// columns,
39/// sort_column: sort_column,
40/// sort_order: sort_order,
41/// on_sort_column: Callback::from(|col_id| web_sys::console::log_1(&format!("Sort: {}", col_id).into())),
42/// classes: Default::default(),
43/// };
44///
45/// html! {
46/// <TableHeader ..props />
47/// }
48/// };
49/// ```
50///
51/// # See Also
52/// - [MDN thead Element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/thead)
53#[function_component(TableHeader)]
54pub fn header(props: &TableHeaderProps) -> Html {
55 let TableHeaderProps {
56 columns,
57 sort_column,
58 sort_order,
59 on_sort_column,
60 classes,
61 } = props;
62
63 html! {
64 <thead class={classes.thead}>
65 <tr class={classes.row} role="row">
66 { for columns.iter().map(|col| {
67 let col_id = col.id;
68 let onclick = if col.sortable {
69 let on_sort_column = on_sort_column.clone();
70 Some(Callback::from(move |_| on_sort_column.emit(col_id)))
71 } else { None };
72
73 html! {
74 <th
75 {onclick}
76 role="columnheader"
77 class={format!("{} {}", classes.header_cell, col.class.unwrap_or("")).trim().to_string()}
78 style={col.style.unwrap_or_default()}
79 aria-sort={
80 if Some(col.id) == **sort_column {
81 match **sort_order {
82 SortOrder::Asc => "ascending",
83 SortOrder::Desc => "descending",
84 }
85 } else {
86 "none"
87 }
88 }
89 >
90 { col.header }
91 </th>
92 }
93 }) }
94 </tr>
95 </thead>
96 }
97}