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}