Skip to content

Commit a81c2e2

Browse files
feat(#2609): add data-grid component
1 parent 39df355 commit a81c2e2

File tree

116 files changed

+4845
-675
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+4845
-675
lines changed

apps/prs/angular/src/app/app.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
<a href="/features/2730">2730</a>
6262
<a href="/features/2829">2829</a>
6363
<a href="/features/3102">3102</a>
64+
<a href="/features/2609">2609</a>
6465
</goab-side-menu-group>
6566
</goab-side-menu>
6667
</section>

apps/prs/angular/src/app/app.routes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import { Feat2722Component } from "../routes/features/feat2722/feat2722.componen
4444
import { Feat2730Component } from "../routes/features/feat2730/feat2730.component";
4545
import { Feat2829Component } from "../routes/features/feat2829/feat2829.component";
4646
import { Feat3102Component } from "../routes/features/feat3102/feat3102.component";
47+
import { Feat2609Component } from "../routes/features/feat2609/feat2609.component";
4748

4849
export const appRoutes: Route[] = [
4950
{ path: "bugs/2152", component: Bug2152Component },
@@ -90,4 +91,5 @@ export const appRoutes: Route[] = [
9091
{ path: "features/2730", component: Feat2730Component },
9192
{ path: "features/2829", component: Feat2829Component },
9293
{ path: "features/3102", component: Feat3102Component },
94+
{ path: "features/2609", component: Feat2609Component },
9395
];

apps/prs/angular/src/app/everything.component.html

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,40 @@
10061006
{{ paginationState.total / paginationState.perPage | number: "1.0-0" }}
10071007
</goab-text>
10081008
</goab-container>
1009+
<goab-container type="interactive" padding="relaxed">
1010+
<goab-text tag="h3" size="heading-s">Data Grid (Keyboard Navigation)</goab-text>
1011+
<goab-text tag="p" size="body-s" mb="m">
1012+
The data grid wraps a table to enable keyboard navigation. Use arrow keys to move between cells.
1013+
</goab-text>
1014+
<goab-data-grid keyboardNav="table">
1015+
<goab-table width="100%">
1016+
<thead>
1017+
<tr data-grid="row">
1018+
<th data-grid="cell">Name</th>
1019+
<th data-grid="cell-1">Created</th>
1020+
<th data-grid="cell-2">Status</th>
1021+
<th data-grid="cell-3">Progress</th>
1022+
<th data-grid="cell-4">Actions</th>
1023+
</tr>
1024+
</thead>
1025+
<tbody>
1026+
@for (row of pageData; track row.name) {
1027+
<tr data-grid="row">
1028+
<td data-grid="cell">{{ row.name }}</td>
1029+
<td data-grid="cell-1">{{ row.created }}</td>
1030+
<td data-grid="cell-2">
1031+
<goab-badge [type]="row.status === 'Active' ? 'success' : 'important'" [content]="row.status"></goab-badge>
1032+
</td>
1033+
<td data-grid="cell-3">{{ row.progress }}%</td>
1034+
<td data-grid="cell-4">
1035+
<goab-button type="tertiary" size="compact">View</goab-button>
1036+
</td>
1037+
</tr>
1038+
}
1039+
</tbody>
1040+
</goab-table>
1041+
</goab-data-grid>
1042+
</goab-container>
10091043
<goab-container type="interactive" padding="relaxed">
10101044
<goab-text tag="h3" size="heading-s">Site chrome</goab-text>
10111045
<goab-column-layout>

apps/prs/angular/src/app/everything.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
GoabCircularProgress,
1818
GoabColumnLayout,
1919
GoabContainer,
20+
GoabDataGrid,
2021
GoabDatePicker,
2122
GoabDetails,
2223
GoabDivider,
@@ -180,6 +181,7 @@ interface DemoFormValue {
180181
GoabCircularProgress,
181182
GoabColumnLayout,
182183
GoabContainer,
184+
GoabDataGrid,
183185
GoabDatePicker,
184186
GoabDetails,
185187
GoabDivider,
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
<h2>Feature #2609: Data Grid Component</h2>
2+
<p>This feature adds a keyboard-navigable grid wrapper component that provides ARIA-compliant accessibility for tables and grid layouts.</p>
3+
4+
<h3>Table with Dynamic Row Addition (Testing Dropdown Focus Issue)</h3>
5+
6+
<div style="margin-bottom: 1rem;">
7+
<goab-button type="primary" (onClick)="addNewRows()" style="margin-right: 1rem;">
8+
Add 3 New Rows (Simulate Pagination)
9+
</goab-button>
10+
<goab-button type="secondary" (onClick)="removeLastRows()">
11+
Remove Last 3 Rows
12+
</goab-button>
13+
<span style="margin-left: 1rem;">Total rows: {{ users.length }}</span>
14+
</div>
15+
16+
<p style="color: #FF6B6B; margin-bottom: 1rem;">
17+
<strong>Test Instructions:</strong>
18+
1. Navigate to a cell with a dropdown (Approver column) using arrow keys.
19+
2. Click "Add 3 New Rows" button.
20+
3. Navigate to a cell with a dropdown again.
21+
4. Try to navigate away with arrow keys - it should take only 1 press, not 3.
22+
</p>
23+
24+
<goab-data-grid keyboardNav="table">
25+
<goab-table width="100%" mb="xl" (onSort)="handleSort($event)">
26+
<thead>
27+
<tr data-grid="row">
28+
<th style="padding-bottom:0" data-grid="cell"><goab-checkbox mt="2" (onChange)="selectAll($event)" [checked]="isSelectedAll"></goab-checkbox></th>
29+
<th data-grid="cell-1"><goab-table-sort-header name="idNumber">ID</goab-table-sort-header></th>
30+
<th data-grid="cell-2"><goab-table-sort-header name="nameOfChild">Name</goab-table-sort-header></th>
31+
<th data-grid="cell-3"><goab-table-sort-header name="status">Status</goab-table-sort-header></th>
32+
<th data-grid="cell-4">Approver (Dropdown)</th>
33+
<th data-grid="cell-5">Actions</th>
34+
</tr>
35+
</thead>
36+
<tbody>
37+
@for (user of users; track user.idNumber) {
38+
<tr data-grid="row">
39+
<td data-grid="cell"><goab-checkbox [checked]="isSelected(user.idNumber)" (onChange)="toggleSelection(user.idNumber, $event)"></goab-checkbox></td>
40+
<td data-grid="cell-1">{{ user.idNumber }}</td>
41+
<td data-grid="cell-2">{{ user.nameOfChild }}</td>
42+
<td data-grid="cell-3"><goab-badge [type]="getStatusBadgeType(user.status)" [content]="user.status"></goab-badge></td>
43+
<td data-grid="cell-4">
44+
<goab-dropdown [value]="user.approver" (onChange)="onApproverChange(user.idNumber, $event)">
45+
<goab-dropdown-item value="Sarah Ellis">Sarah Ellis</goab-dropdown-item>
46+
<goab-dropdown-item value="John Doe">John Doe</goab-dropdown-item>
47+
<goab-dropdown-item value="Jane Smith">Jane Smith</goab-dropdown-item>
48+
</goab-dropdown>
49+
</td>
50+
<td data-grid="cell-5">
51+
<goab-button type="tertiary" (onClick)="onOpen(user.idNumber)">
52+
Open
53+
</goab-button>
54+
</td>
55+
</tr>
56+
}
57+
</tbody>
58+
</goab-table>
59+
</goab-data-grid>
60+
61+
<h3>Containers (Layout Mode)</h3>
62+
<p>Layout mode allows arrow keys to wrap between rows when reaching the edge.</p>
63+
<goab-data-grid keyboardNav="layout">
64+
@for (user of users; track user.idNumber) {
65+
<goab-container mt="l" data-grid="row">
66+
<goab-block direction="row" gap="m" alignment="start">
67+
<goab-checkbox data-grid="cell-0" [checked]="isSelected(user.idNumber)" (onChange)="toggleSelection(user.idNumber, $event)"></goab-checkbox>
68+
69+
<goab-block direction="column" gap="s" alignment="start" style="flex: 1;">
70+
<goab-block direction="row" gap="s" alignment="center">
71+
<strong data-grid="cell-1">{{ user.nameOfChild }}</strong>
72+
<goab-block data-grid="cell-2">
73+
<goab-badge [type]="getStatusBadgeType(user.status)" [content]="user.status"></goab-badge>
74+
</goab-block>
75+
</goab-block>
76+
77+
<goab-block direction="row" gap="xl" alignment="start">
78+
<goab-block direction="column" gap="s" alignment="start">
79+
<goab-block direction="column" gap="xs" data-grid="cell-4">
80+
<strong>Updated</strong>
81+
<span>{{ user.updated }}</span>
82+
</goab-block>
83+
<goab-block direction="column" gap="xs" data-grid="cell-7">
84+
<strong>Program ID</strong>
85+
<span>{{ user.programId }}</span>
86+
</goab-block>
87+
</goab-block>
88+
89+
<goab-block direction="column" gap="s" alignment="start">
90+
<goab-block direction="column" gap="xs" data-grid="cell-5">
91+
<strong>Email</strong>
92+
<span>{{ user.email }}</span>
93+
</goab-block>
94+
<goab-block direction="column" gap="xs" data-grid="cell-8">
95+
<strong>Service access</strong>
96+
<span>{{ user.serviceAccess }}</span>
97+
</goab-block>
98+
</goab-block>
99+
100+
<goab-block direction="column" gap="s" alignment="start">
101+
<goab-block direction="column" gap="xs" data-grid="cell-6">
102+
<strong>Program</strong>
103+
<span>{{ user.program }}</span>
104+
</goab-block>
105+
<goab-block direction="column" gap="xs" data-grid="cell-9">
106+
<strong>Approver</strong>
107+
<goab-dropdown [value]="user.approver" (onChange)="onApproverChange(user.idNumber, $event)">
108+
<goab-dropdown-item value="Sarah Ellis">Sarah Ellis</goab-dropdown-item>
109+
<goab-dropdown-item value="John Doe">John Doe</goab-dropdown-item>
110+
<goab-dropdown-item value="Jane Smith">Jane Smith</goab-dropdown-item>
111+
</goab-dropdown>
112+
</goab-block>
113+
</goab-block>
114+
</goab-block>
115+
</goab-block>
116+
117+
<goab-button type="tertiary" data-grid="cell-3" (onClick)="onOpen(user.idNumber)">
118+
Open
119+
</goab-button>
120+
</goab-block>
121+
</goab-container>
122+
}
123+
</goab-data-grid>
124+
125+
<h3>Table with Colspan and Different Column Counts</h3>
126+
<p>This table tests navigation with varying column counts and colspan attributes. Use arrow keys to navigate and observe focus behavior.</p>
127+
<goab-data-grid keyboardNav="table">
128+
<goab-table width="100%" mb="xl">
129+
<thead>
130+
<tr data-grid="row">
131+
<th data-grid="cell">Column 1</th>
132+
<th data-grid="cell-1">Column 2</th>
133+
<th data-grid="cell-2">Column 3</th>
134+
<th data-grid="cell-3">Column 4</th>
135+
<th data-grid="cell-4">Column 5</th>
136+
</tr>
137+
</thead>
138+
<tbody>
139+
<tr data-grid="row">
140+
<td data-grid="cell">Row 1, Cell 1</td>
141+
<td data-grid="cell-1">Row 1, Cell 2</td>
142+
<td data-grid="cell-2">Row 1, Cell 3</td>
143+
<td data-grid="cell-3">Row 1, Cell 4</td>
144+
<td data-grid="cell-4">Row 1, Cell 5</td>
145+
</tr>
146+
<tr data-grid="row">
147+
<td data-grid="cell">Row 2, Cell 1</td>
148+
<td data-grid="cell-1" colspan="2">Row 2, Cell 2 (spans 2 cols)</td>
149+
<td data-grid="cell-2" colspan="2">Row 2, Cell 3 (spans 2 cols)</td>
150+
</tr>
151+
<tr data-grid="row">
152+
<td data-grid="cell" colspan="3">Row 3, Cell 1 (spans 3 cols)</td>
153+
<td data-grid="cell-1" colspan="2">Row 3, Cell 2 (spans 2 cols)</td>
154+
</tr>
155+
<tr data-grid="row">
156+
<td data-grid="cell">Row 4, Cell 1</td>
157+
<td data-grid="cell-1">Row 4, Cell 2</td>
158+
<td data-grid="cell-2">Row 4, Cell 3</td>
159+
<td data-grid="cell-3">Row 4, Cell 4</td>
160+
<td data-grid="cell-4">Row 4, Cell 5</td>
161+
</tr>
162+
<tr data-grid="row">
163+
<td data-grid="cell" colspan="5">Row 5, Single Cell (spans all 5 cols)</td>
164+
</tr>
165+
</tbody>
166+
</goab-table>
167+
</goab-data-grid>
168+
169+
<h3>Related Documents (Links with Hidden Keyboard Icon)</h3>
170+
<goab-data-grid keyboardNav="layout" [keyboardIcon]="false">
171+
<goab-block data-grid="row">
172+
<goab-link data-grid="cell"><a href="https://www.w3.org/TR/wai-aria-1.1/">ARIA 1.1 Specification</a></goab-link>
173+
<goab-link data-grid="cell-1"><a href="https://www.w3.org/TR/core-aam-1.1/">Core Accessibility API Mappings 1.1</a></goab-link>
174+
<goab-link data-grid="cell-2"><a href="https://www.w3.org/WAI/intro/aria.php">WAI-ARIA Overview</a></goab-link>
175+
<goab-link data-grid="cell-3"><a href="https://www.w3.org/WAI/intro/wcag">WCAG Overview</a></goab-link>
176+
</goab-block>
177+
</goab-data-grid>

0 commit comments

Comments
 (0)