Skip to content

Commit eea4361

Browse files
gunndabadclaude
andauthored
Add tag helpers for the table component (#563)
* Add tag helpers for the table component The table was the last component with a generator but no tag helpers, so it could only be reached through IComponentGenerator. <govuk-table-caption>, <govuk-table-head> and <govuk-table-row> go directly inside <govuk-table>, in that order, with <govuk-table-head-cell> inside the head and <govuk-table-cell> inside each row. Rows sit straight in the table rather than behind a <govuk-table-body> wrapper, matching the summary list, tabs and accordion, and mapping one-to-one onto TableOptions. Each child also takes a component-specific short name — <table-caption>, <table-head>, <table-head-cell>, <table-row>, <table-cell> — rather than <caption>, <head> and so on, which read as the HTML elements they are named after. Every child has <govuk-table> for its parent, so their spelling cannot be paired up through ParentTag; TableContext checks it alongside the ordering, as DetailsContext does. <thead> and <tr> carry fixed markup in the reference template, so the head and row elements throw rather than silently dropping attributes passed to them. The caption's attributes do have somewhere to go, so TableOptions gains a non-standard CaptionAttributes, as DetailsOptions has for its summary and text. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Let the table's head and rows take attributes <govuk-table-head> and <govuk-table-row> threw for any attribute passed to them, because <thead> and <tr> had nowhere in TableOptions to take one from. Both are elements someone will reasonably want to put a class on, so give them somewhere to go. The head is singular, so its attributes sit flat on TableOptions next to the caption's, and land on <thead> — the element <govuk-table-head> names — rather than the <tr> nested inside it. Rows are a collection, so they need an object each: Rows becomes a collection of TableOptionsRow, holding the cells alongside the row's own attributes, which brings it in line with SummaryListOptions. Neither takes a Classes of its own. That property exists elsewhere to mirror the reference implementation's separate classes parameter, and there is no such parameter here; a class in the collection is combined with the component's own by AttributeCollection.Add, so it needs no separate home. The reference fixtures give a row as a bare array of cells, so reading them into the wrapper needs a converter. Options are only ever deserialized by the fixture tests, so it lives in the test project with the three converters already there rather than shaping the public API around the JSON. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent b43a566 commit eea4361

35 files changed

Lines changed: 1692 additions & 6 deletions

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,25 @@ The library no longer embeds the `govuk-frontend` files or serves them from midd
3333

3434
As per the guidance, the first page, the pages either side of the current page and the last page are shown, with an ellipsis wherever pages have been skipped, plus Previous and Next links where there is a page to go to. Nothing is rendered at all when there is only one page. Child elements cannot be combined with these attributes.
3535

36+
The table component now has tag helpers:
37+
38+
```razor
39+
<govuk-table first-cell-is-header="true">
40+
<table-caption class="govuk-table__caption--m">Dates and amounts</table-caption>
41+
<table-head>
42+
<table-head-cell>Date</table-head-cell>
43+
<table-head-cell format="numeric">Amount</table-head-cell>
44+
</table-head>
45+
<table-row>
46+
<table-cell>First 6 weeks</table-cell>
47+
<table-cell format="numeric">£109.80 per week</table-cell>
48+
</table-row>
49+
</govuk-table>
50+
```
51+
52+
`<govuk-table-caption>`, `<govuk-table-head>` and `<govuk-table-row>` go directly inside `<govuk-table>`, in that order, with `<govuk-table-head-cell>` inside the head and `<govuk-table-cell>` inside each row.
53+
Each of them also has the short tag name shown above.
54+
3655
The checkboxes, radios, date input, text input, textarea, file upload, password input, select, character count, accordion, breadcrumbs, service navigation, fieldset, generic header, footer, notification banner, pagination, phase banner, tabs, error summary, details and cookie banner tag helpers now support short tag name syntax, as the panel and summary list tag helpers already do:
3756

3857
```razor

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ Files the build didn't copy are left alone, since they can change without the `g
317317
- [Service navigation](docs/components/service-navigation.md)
318318
- [Skip link](docs/components/skip-link.md)
319319
- [Summary list](docs/components/summary-list.md)
320+
- [Table](docs/components/table.md)
320321
- [Tabs](docs/components/tabs.md)
321322
- [Tag](docs/components/tag.md)
322323
- [Textarea](docs/components/textarea.md)

docs/components/table.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<!-- Generated from src/GovUk.Frontend.AspNetCore.Docs/Templates/components/table.liquid -->
2+
# Table
3+
4+
[GOV.UK Design System table component](https://design-system.service.gov.uk/components/table/)
5+
6+
7+
## Tag helpers
8+
9+
### Example
10+
<img alt="Table example" src="../images/table-example.png" />
11+
12+
```razor
13+
<govuk-table>
14+
<table-caption class="govuk-table__caption--m">Months and rates</table-caption>
15+
<table-head>
16+
<table-head-cell>Month you apply</table-head-cell>
17+
<table-head-cell format="numeric">Rate for bicycles</table-head-cell>
18+
<table-head-cell format="numeric">Rate for vehicles</table-head-cell>
19+
</table-head>
20+
<table-row>
21+
<table-cell>January</table-cell>
22+
<table-cell format="numeric">£85</table-cell>
23+
<table-cell format="numeric">£95</table-cell>
24+
</table-row>
25+
<table-row>
26+
<table-cell>February</table-cell>
27+
<table-cell format="numeric">£75</table-cell>
28+
<table-cell format="numeric">£55</table-cell>
29+
</table-row>
30+
<table-row>
31+
<table-cell>March</table-cell>
32+
<table-cell format="numeric">£165</table-cell>
33+
<table-cell format="numeric">£125</table-cell>
34+
</table-row>
35+
</govuk-table>
36+
```
37+
38+
39+
### Example with the first cell as a header
40+
<img alt="Table with first cell as header example" src="../images/table-with-first-cell-as-header-example.png" />
41+
42+
```razor
43+
<govuk-table first-cell-is-header="true">
44+
<table-head>
45+
<table-head-cell>Date</table-head-cell>
46+
<table-head-cell>Amount</table-head-cell>
47+
</table-head>
48+
<table-row>
49+
<table-cell>First 6 weeks</table-cell>
50+
<table-cell>£109.80 per week</table-cell>
51+
</table-row>
52+
<table-row>
53+
<table-cell>Next 33 weeks</table-cell>
54+
<table-cell>£109.80 per week</table-cell>
55+
</table-row>
56+
<table-row>
57+
<table-cell>Total estimated pay</table-cell>
58+
<table-cell>£4,282.20</table-cell>
59+
</table-row>
60+
</govuk-table>
61+
```
62+
63+
64+
### Example with long tag names
65+
<img alt="Table with long tag names example" src="../images/table-with-long-tag-names-example.png" />
66+
67+
```razor
68+
<govuk-table>
69+
<govuk-table-caption class="govuk-table__caption--m">Months and rates</govuk-table-caption>
70+
<govuk-table-head>
71+
<govuk-table-head-cell>Month you apply</govuk-table-head-cell>
72+
<govuk-table-head-cell format="numeric">Rate for bicycles</govuk-table-head-cell>
73+
</govuk-table-head>
74+
<govuk-table-row>
75+
<govuk-table-cell>January</govuk-table-cell>
76+
<govuk-table-cell format="numeric">£85</govuk-table-cell>
77+
</govuk-table-row>
78+
<govuk-table-row>
79+
<govuk-table-cell>February</govuk-table-cell>
80+
<govuk-table-cell format="numeric">£75</govuk-table-cell>
81+
</govuk-table-row>
82+
</govuk-table>
83+
```
84+
85+
86+
### API
87+
88+
#### `<govuk-table>`
89+
90+
| Attribute | Type | Description |
91+
| --- | --- | --- |
92+
| `first-cell-is-header` | `bool?` | Whether the first cell in each row is a header cell. The default is `false`. |
93+
94+
95+
#### `<table-caption>` / `<govuk-table-caption>`
96+
97+
The content is the HTML to use within the table caption.
98+
99+
Must be inside a `<govuk-table>` element.
100+
101+
102+
#### `<table-head>` / `<govuk-table-head>`
103+
104+
Must be inside a `<govuk-table>` element.
105+
106+
107+
#### `<table-head-cell>` / `<govuk-table-head-cell>`
108+
109+
The content is the HTML to use within the table head cell.
110+
111+
Must be inside a `<table-head>` or `<govuk-table-head>` element.
112+
113+
| Attribute | Type | Description |
114+
| --- | --- | --- |
115+
| `colspan` | `int?` | The number of columns the cell spans. |
116+
| `format` | `string` | The format of the cell's content. Specify `numeric` to right align the content. |
117+
| `rowspan` | `int?` | The number of rows the cell spans. |
118+
119+
120+
#### `<table-row>` / `<govuk-table-row>`
121+
122+
Must be inside a `<govuk-table>` element.
123+
124+
125+
#### `<table-cell>` / `<govuk-table-cell>`
126+
127+
The content is the HTML to use within the table cell.
128+
129+
Must be inside a `<table-row>` or `<govuk-table-row>` element.
130+
131+
| Attribute | Type | Description |
132+
| --- | --- | --- |
133+
| `colspan` | `int?` | The number of columns the cell spans. |
134+
| `format` | `string` | The format of the cell's content. Specify `numeric` to right align the content. Ignored when the cell is the first in its row and the table has `first-cell-is-header` specified. |
135+
| `rowspan` | `int?` | The number of rows the cell spans. |
136+

docs/images/table-example.png

40.6 KB
Loading
41.5 KB
Loading
30.8 KB
Loading
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
@page
2+
3+
<example>
4+
<govuk-table>
5+
<table-caption class="govuk-table__caption--m">Months and rates</table-caption>
6+
<table-head>
7+
<table-head-cell>Month you apply</table-head-cell>
8+
<table-head-cell format="numeric">Rate for bicycles</table-head-cell>
9+
<table-head-cell format="numeric">Rate for vehicles</table-head-cell>
10+
</table-head>
11+
<table-row>
12+
<table-cell>January</table-cell>
13+
<table-cell format="numeric">£85</table-cell>
14+
<table-cell format="numeric">£95</table-cell>
15+
</table-row>
16+
<table-row>
17+
<table-cell>February</table-cell>
18+
<table-cell format="numeric">£75</table-cell>
19+
<table-cell format="numeric">£55</table-cell>
20+
</table-row>
21+
<table-row>
22+
<table-cell>March</table-cell>
23+
<table-cell format="numeric">£165</table-cell>
24+
<table-cell format="numeric">£125</table-cell>
25+
</table-row>
26+
</govuk-table>
27+
</example>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
@page
2+
3+
<example>
4+
<govuk-table first-cell-is-header="true">
5+
<table-head>
6+
<table-head-cell>Date</table-head-cell>
7+
<table-head-cell>Amount</table-head-cell>
8+
</table-head>
9+
<table-row>
10+
<table-cell>First 6 weeks</table-cell>
11+
<table-cell>£109.80 per week</table-cell>
12+
</table-row>
13+
<table-row>
14+
<table-cell>Next 33 weeks</table-cell>
15+
<table-cell>£109.80 per week</table-cell>
16+
</table-row>
17+
<table-row>
18+
<table-cell>Total estimated pay</table-cell>
19+
<table-cell>£4,282.20</table-cell>
20+
</table-row>
21+
</govuk-table>
22+
</example>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
@page
2+
3+
<example>
4+
<govuk-table>
5+
<govuk-table-caption class="govuk-table__caption--m">Months and rates</govuk-table-caption>
6+
<govuk-table-head>
7+
<govuk-table-head-cell>Month you apply</govuk-table-head-cell>
8+
<govuk-table-head-cell format="numeric">Rate for bicycles</govuk-table-head-cell>
9+
</govuk-table-head>
10+
<govuk-table-row>
11+
<govuk-table-cell>January</govuk-table-cell>
12+
<govuk-table-cell format="numeric">£85</govuk-table-cell>
13+
</govuk-table-row>
14+
<govuk-table-row>
15+
<govuk-table-cell>February</govuk-table-cell>
16+
<govuk-table-cell format="numeric">£75</govuk-table-cell>
17+
</govuk-table-row>
18+
</govuk-table>
19+
</example>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Table
2+
3+
[GOV.UK Design System table component](https://design-system.service.gov.uk/components/table/)
4+
5+
6+
## Tag helpers
7+
8+
### Example
9+
{{ tag_helper_example(
10+
"Examples/Table/TableExample",
11+
"table-example.png",
12+
"Table example") }}
13+
14+
### Example with the first cell as a header
15+
{{ tag_helper_example(
16+
"Examples/Table/TableWithFirstCellAsHeaderExample",
17+
"table-with-first-cell-as-header-example.png",
18+
"Table with first cell as header example") }}
19+
20+
### Example with long tag names
21+
{{ tag_helper_example(
22+
"Examples/Table/TableWithLongTagNamesExample",
23+
"table-with-long-tag-names-example.png",
24+
"Table with long tag names example") }}
25+
26+
### API
27+
28+
{{ tag_helper_api("TableTagHelper") }}
29+
30+
{{ tag_helper_api("TableCaptionTagHelper") }}
31+
32+
{{ tag_helper_api("TableHeadTagHelper") }}
33+
34+
{{ tag_helper_api("TableHeadCellTagHelper") }}
35+
36+
{{ tag_helper_api("TableRowTagHelper") }}
37+
38+
{{ tag_helper_api("TableCellTagHelper") }}

0 commit comments

Comments
 (0)