Skip to main content

tablo_ui/components/primitives/
table.rs

1// SYNC: topcoat-ui-registry@0.10.0 sha256:a6b8a367f9d26d918521375a64e51ef88ca2e3854edd2a091a63ecf0e2cb09d6 — do not hand-edit. Sync via `cargo xtask sync-topcoat-ui` (ADR-0007).
2use topcoat::{
3    Result,
4    view::{Attributes, Child, View, class, component, view},
5};
6
7/// A table inside a horizontally scrollable container.
8///
9/// Pass table sections as children. `attrs` are forwarded to the `<table>`, with extra
10/// classes added to its classes.
11///
12/// ```ignore
13/// view! {
14///     table(
15///         table_header(
16///             table_row(
17///                 table_head("Environment")
18///                 table_head("Status")
19///             )
20///         )
21///         table_body(
22///             table_row(
23///                 table_cell("production")
24///                 table_cell("Live")
25///             )
26///         )
27///     )
28/// }
29/// ```
30#[component]
31pub async fn table(
32    #[default] mut attrs: Attributes,
33    #[default] child: Child<'_>,
34) -> Result<impl View> {
35    Ok(view! {
36        <div class="w-full overflow-x-auto">
37            <table
38                class=(class!(
39                    "w-full caption-bottom border-collapse text-sm",
40                    attrs.remove("class"),
41                ))
42                (attrs)
43            >
44                (child)
45            </table>
46        </div>
47    })
48}
49
50/// The heading section of a [`table`], holding the row of column headers.
51#[component]
52pub async fn table_header(
53    #[default] mut attrs: Attributes,
54    #[default] child: Child<'_>,
55) -> Result<impl View> {
56    Ok(view! {
57        <thead class=(class!("[&_tr]:border-b", attrs.remove("class"))) (attrs)>
58            (child)
59        </thead>
60    })
61}
62
63/// The body of a table, containing data rows.
64#[component]
65pub async fn table_body(
66    #[default] mut attrs: Attributes,
67    #[default] child: Child<'_>,
68) -> Result<impl View> {
69    Ok(view! {
70        <tbody
71            class=(class!("[&_tr:last-child]:border-0", attrs.remove("class")))
72            (attrs)
73        >
74            (child)
75        </tbody>
76    })
77}
78
79/// The closing section of a [`table`], for totals and other summaries.
80#[component]
81pub async fn table_footer(
82    #[default] mut attrs: Attributes,
83    #[default] child: Child<'_>,
84) -> Result<impl View> {
85    Ok(view! {
86        <tfoot
87            class=(class!(
88                "border-t border-border bg-foreground/5 font-medium [&>tr]:last:border-b-0",
89                attrs.remove("class"),
90            ))
91            (attrs)
92        >
93            (child)
94        </tfoot>
95    })
96}
97
98/// A table row with a separator and hover styling.
99#[component]
100pub async fn table_row(
101    #[default] mut attrs: Attributes,
102    #[default] child: Child<'_>,
103) -> Result<impl View> {
104    Ok(view! {
105        <tr
106            class=(class!(
107                "border-b border-border transition-colors hover:bg-foreground/5",
108                attrs.remove("class"),
109            ))
110            (attrs)
111        >
112            (child)
113        </tr>
114    })
115}
116
117/// A column header in a [`table_header`]'s row.
118#[component]
119pub async fn table_head(
120    #[default] mut attrs: Attributes,
121    #[default] child: Child<'_>,
122) -> Result<impl View> {
123    Ok(view! {
124        <th
125            class=(class!(
126                "h-10 px-3 text-left align-middle font-medium whitespace-nowrap \
127                 text-muted-foreground",
128                attrs.remove("class"),
129            ))
130            (attrs)
131        >
132            (child)
133        </th>
134    })
135}
136
137/// One cell of a [`table_row`].
138#[component]
139pub async fn table_cell(
140    #[default] mut attrs: Attributes,
141    #[default] child: Child<'_>,
142) -> Result<impl View> {
143    Ok(view! {
144        <td
145            class=(class!("p-3 align-middle whitespace-nowrap", attrs.remove("class")))
146            (attrs)
147        >
148            (child)
149        </td>
150    })
151}
152
153/// A caption describing the table.
154#[component]
155pub async fn table_caption(
156    #[default] mut attrs: Attributes,
157    #[default] child: Child<'_>,
158) -> Result<impl View> {
159    Ok(view! {
160        <caption
161            class=(class!("mt-4 text-sm text-muted-foreground", attrs.remove("class")))
162            (attrs)
163        >
164            (child)
165        </caption>
166    })
167}