@arbor-education/design-system.components 0.10.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agent-memory/blanche-designspert/MEMORY.md +64 -0
- package/.claude/agent-memory/blanche-designspert/token-review-patterns.md +29 -0
- package/.claude/agent-memory/dorothy-fact-checker/MEMORY.md +129 -0
- package/.claude/agent-memory/rose-storybookspert/MEMORY.md +29 -0
- package/.claude/agent-memory/rose-storybookspert/patterns.md +132 -0
- package/.claude/agent-memory/sophia-componentspert/MEMORY.md +14 -0
- package/.claude/agent-memory/sophia-componentspert/components.md +367 -0
- package/.claude/agents/blanche-designspert.md +150 -0
- package/.claude/agents/dorothy-fact-checker.md +145 -0
- package/.claude/agents/rose-storybookspert.md +148 -0
- package/.claude/agents/sophia-componentspert.md +133 -0
- package/.claude/component-library.md +1107 -0
- package/.claude/design-assessment-daily-attendance-2026-04-10.md +566 -0
- package/.claude/figma-assessment-7154-58899.md +404 -0
- package/.claude/figma-assessment-UKQfcxnT4rlHHNuiumt4o1-11086-97537.md +392 -0
- package/.claude/figma-assessment-UKQfcxnT4rlHHNuiumt4o1-551-41974.md +474 -0
- package/.claude/figma-assessment-UKQfcxnT4rlHHNuiumt4o1-551-43094.md +462 -0
- package/.claude/figma-assessment-fcFK4CGzkz2fVyY3koX8ZE-7154-59061.md +440 -0
- package/.claude/migration-report-custom-report-writer-2026-02-19.md +591 -0
- package/.claude/skills/analyze-design/README.md +295 -0
- package/.claude/skills/analyze-design/SKILL.md +741 -0
- package/.claude/skills/create-page/README.md +246 -0
- package/.claude/skills/create-page/SKILL.md +634 -0
- package/.claude/skills/create-page/design-analysis-template.md +333 -0
- package/.claude/skills/create-page/page-template.scss +118 -0
- package/.claude/skills/create-page/page-template.tsx +230 -0
- package/.claude/skills/map-legacy/README.md +87 -0
- package/.claude/skills/map-legacy/SKILL.md +465 -0
- package/.claude/skills/migrate-page/README.md +125 -0
- package/.claude/skills/migrate-page/SKILL.md +374 -0
- package/.github/CODEOWNERS +1 -0
- package/.github/pull_request_template.md +39 -0
- package/CHANGELOG.md +14 -0
- package/CLAUDE.md +31 -0
- package/CONTRIBUTING.md +191 -0
- package/README.md +110 -20
- package/dist/components/table/DSDefaultColDef.js +2 -2
- package/dist/components/table/DSDefaultColDef.js.map +1 -1
- package/dist/components/table/Table.d.ts +5 -29
- package/dist/components/table/Table.d.ts.map +1 -1
- package/dist/components/table/Table.js +12 -22
- package/dist/components/table/Table.js.map +1 -1
- package/dist/components/table/Table.stories.d.ts +4 -0
- package/dist/components/table/Table.stories.d.ts.map +1 -1
- package/dist/components/table/Table.stories.js +163 -28
- package/dist/components/table/Table.stories.js.map +1 -1
- package/dist/components/table/Table.test.js +109 -8
- package/dist/components/table/Table.test.js.map +1 -1
- package/dist/components/table/TableSettingsContext.d.ts +13 -0
- package/dist/components/table/TableSettingsContext.d.ts.map +1 -0
- package/dist/components/table/TableSettingsContext.js +15 -0
- package/dist/components/table/TableSettingsContext.js.map +1 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.d.ts +3 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.d.ts.map +1 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.js +12 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.js.map +1 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.test.d.ts +2 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.test.d.ts.map +1 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.test.js +65 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.test.js.map +1 -0
- package/dist/components/table/tableConsts.d.ts +7 -0
- package/dist/components/table/tableConsts.d.ts.map +1 -0
- package/dist/components/table/tableConsts.js +8 -0
- package/dist/components/table/tableConsts.js.map +1 -0
- package/dist/components/table/{BulkActionsDropdown.d.ts → tableControls/BulkActionsDropdown.d.ts} +1 -1
- package/dist/components/table/tableControls/BulkActionsDropdown.d.ts.map +1 -0
- package/dist/components/table/{BulkActionsDropdown.js → tableControls/BulkActionsDropdown.js} +3 -3
- package/dist/components/table/tableControls/BulkActionsDropdown.js.map +1 -0
- package/dist/components/table/{HideColumnsDropdown.d.ts → tableControls/HideColumnsDropdown.d.ts} +1 -2
- package/dist/components/table/tableControls/HideColumnsDropdown.d.ts.map +1 -0
- package/dist/components/table/{HideColumnsDropdown.js → tableControls/HideColumnsDropdown.js} +2 -2
- package/dist/components/table/tableControls/HideColumnsDropdown.js.map +1 -0
- package/dist/components/table/tableControls/TableControls.d.ts +23 -0
- package/dist/components/table/tableControls/TableControls.d.ts.map +1 -0
- package/dist/components/table/tableControls/TableControls.js +21 -0
- package/dist/components/table/tableControls/TableControls.js.map +1 -0
- package/dist/components/table/tableControls/TableControls.test.d.ts +2 -0
- package/dist/components/table/tableControls/TableControls.test.d.ts.map +1 -0
- package/dist/components/table/tableControls/TableControls.test.js +124 -0
- package/dist/components/table/tableControls/TableControls.test.js.map +1 -0
- package/dist/components/table/tableControls/TableSettingsDropdown.d.ts.map +1 -0
- package/dist/components/table/{TableSettingsDropdown.js → tableControls/TableSettingsDropdown.js} +7 -6
- package/dist/components/table/tableControls/TableSettingsDropdown.js.map +1 -0
- package/dist/components/table/useTableSettings.d.ts +1 -1
- package/dist/components/table/useTableSettings.d.ts.map +1 -1
- package/dist/components/table/useTableSettings.js +1 -1
- package/dist/components/table/useTableSettings.js.map +1 -1
- package/dist/index.css +19 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/setAgGridLicenseKey.js +1 -1
- package/package.json +1 -1
- package/src/components/table/DSDefaultColDef.ts +2 -2
- package/src/components/table/Table.stories.tsx +202 -35
- package/src/components/table/Table.test.tsx +134 -8
- package/src/components/table/Table.tsx +12 -22
- package/src/components/table/TableSettingsContext.ts +15 -0
- package/src/components/table/cellRenderers/CheckboxCellRenderer.test.tsx +74 -0
- package/src/components/table/cellRenderers/CheckboxCellRenderer.tsx +28 -0
- package/src/components/table/table.scss +23 -1
- package/src/components/table/tableConsts.ts +6 -0
- package/src/components/table/{BulkActionsDropdown.tsx → tableControls/BulkActionsDropdown.tsx} +2 -2
- package/src/components/table/{HideColumnsDropdown.tsx → tableControls/HideColumnsDropdown.tsx} +2 -2
- package/src/components/table/tableControls/TableControls.test.tsx +150 -0
- package/src/components/table/tableControls/TableControls.tsx +143 -0
- package/src/components/table/{TableSettingsDropdown.tsx → tableControls/TableSettingsDropdown.tsx} +2 -1
- package/src/components/table/useTableSettings.ts +1 -1
- package/src/index.ts +1 -0
- package/src/utils/setAgGridLicenseKey.ts +1 -1
- package/dist/components/table/BulkActionsDropdown.d.ts.map +0 -1
- package/dist/components/table/BulkActionsDropdown.js.map +0 -1
- package/dist/components/table/HideColumnsDropdown.d.ts.map +0 -1
- package/dist/components/table/HideColumnsDropdown.js.map +0 -1
- package/dist/components/table/TableSettingsDropdown.d.ts.map +0 -1
- package/dist/components/table/TableSettingsDropdown.js.map +0 -1
- /package/dist/components/table/{TableSettingsDropdown.d.ts → tableControls/TableSettingsDropdown.d.ts} +0 -0
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
# Figma Design Feasibility Assessment
|
|
2
|
+
## Design: Node 551:43094 — Daily Attendance Page
|
|
3
|
+
**Written by:** Sophia Petrillo, Componentspert, age none-of-your-business
|
|
4
|
+
**Fact-checked by:** Dorothy Zbornak, QA Expert
|
|
5
|
+
**Date**: 2026-04-10
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What Is This Thing, Anyway?
|
|
10
|
+
|
|
11
|
+
Picture it: Sicily, 1952. My Aunt Lucia was the attendance secretary at the village school. Every morning she stood at the gate with a ledger, ticking off children as they arrived. Messy, slow, and she always smelled of aniseed.
|
|
12
|
+
|
|
13
|
+
THIS is what Arbor built to replace that. The Daily Attendance page is the command centre for tracking which children are in which registers, which lessons they belong to, and whether their marks have been filled. It's a full-desktop layout — 1366px wide — featuring a top navigation bar, a collapsible left sidebar, breadcrumb navigation, a page heading, a filter info bar, and a very large, very capable AG Grid data table. Nineteen distinct UI elements. Some map beautifully to our library. Some do not exist at all. Pull up a chair.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Design Overview
|
|
18
|
+
|
|
19
|
+
**Daily Attendance | Desktop 1366px** — A full application page layout for school attendance management.
|
|
20
|
+
|
|
21
|
+
### UI Elements Identified
|
|
22
|
+
|
|
23
|
+
- Top navigation bar (logo, nav links with dropdowns, global search, Ask Arbor AI button, user avatar dropdown, org logo)
|
|
24
|
+
- Left side navigation panel (collapsible sections, active items, favorites star icons, notification badge)
|
|
25
|
+
- Breadcrumbs (Students / Attendance / Registers / Daily Attendance + link icon)
|
|
26
|
+
- Page heading H1 "Daily Attendance" with right-aligned primary action button
|
|
27
|
+
- Filter info bar (colored square indicators + info text summary + secondary Edit button)
|
|
28
|
+
- Table toolbar: Actions dropdown, Undo/Redo buttons, Hide columns dropdown
|
|
29
|
+
- Table toolbar: Icon-only buttons (search, comment/message, download, settings, expand)
|
|
30
|
+
- AG Grid table: checkbox selection column
|
|
31
|
+
- AG Grid table: column definitions (Time, Lesson/Event, Year Group, Event Type, Teacher, Marks)
|
|
32
|
+
- AG Grid table: marks status indicators cell (✓ count / ⏱ count / ✗ count)
|
|
33
|
+
- AG Grid table: "(No Students)" placeholder text
|
|
34
|
+
- Pagination footer (first/prev/page input/next/last + "Showing X of Y results")
|
|
35
|
+
- Expand table button
|
|
36
|
+
- UserDropdown (top right of nav bar)
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Section 1: What We Already Have — Use These As-Is, Don't Reinvent Them
|
|
41
|
+
|
|
42
|
+
### Page Heading + Right-Aligned Action Button (`src/components/heading/Heading.tsx`)
|
|
43
|
+
|
|
44
|
+
Oh, this one is a gift. `Heading` with TWO `Heading.InnerContainer` children is precisely the flex layout pattern that splits a title left and an action button right. This is not improvisation — this is the component doing exactly what it was built for.
|
|
45
|
+
|
|
46
|
+
**Key features:**
|
|
47
|
+
- `level={1}` → renders as `<h1>`
|
|
48
|
+
- `Heading.InnerContainer` → `<span class="ds-heading__inner-container">`, one per side
|
|
49
|
+
- No custom flex/justify CSS needed — `Heading` handles it
|
|
50
|
+
|
|
51
|
+
**Example:**
|
|
52
|
+
```tsx
|
|
53
|
+
<Heading level={1}>
|
|
54
|
+
<Heading.InnerContainer>Daily Attendance</Heading.InnerContainer>
|
|
55
|
+
<Heading.InnerContainer>
|
|
56
|
+
<Button variant="primary">Button Text</Button>
|
|
57
|
+
</Heading.InnerContainer>
|
|
58
|
+
</Heading>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
### Table — Actions Dropdown (`src/components/table/Table.tsx`)
|
|
64
|
+
|
|
65
|
+
`Table.BulkActionsDropdown` was built for exactly this "Actions (0)" pattern. It reads the selected row count from `GridApiContext` internally and renders a `Button variant="dropdown"` with the count automatically.
|
|
66
|
+
|
|
67
|
+
**Key features:**
|
|
68
|
+
- Must be rendered INSIDE the `Table` component tree (uses `GridApiContext`)
|
|
69
|
+
- Receives an `actions` array of `{ displayName, callback }` objects
|
|
70
|
+
- Pass via `headerContent` prop on `Table`
|
|
71
|
+
|
|
72
|
+
**Example:**
|
|
73
|
+
```tsx
|
|
74
|
+
<Table
|
|
75
|
+
headerContent={
|
|
76
|
+
<Table.BulkActionsDropdown
|
|
77
|
+
actions={[
|
|
78
|
+
{ displayName: 'Mark Present', callback: (api) => { /* ... */ } },
|
|
79
|
+
]}
|
|
80
|
+
/>
|
|
81
|
+
}
|
|
82
|
+
/>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
### Table — Hide Columns Dropdown (`src/components/table/Table.tsx`)
|
|
88
|
+
|
|
89
|
+
`Table.HideColumnsDropdown` is purpose-built. It reads current column state from `GridApiContext` and renders a multi-select dropdown for toggling visibility. Also lives in `headerContent`.
|
|
90
|
+
|
|
91
|
+
**Example:**
|
|
92
|
+
```tsx
|
|
93
|
+
<Table headerContent={<Table.HideColumnsDropdown />} />
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
### Table — Pagination Footer (`src/components/table/Table.tsx`)
|
|
99
|
+
|
|
100
|
+
`Table.PaginationPanel` + `Table.RowCountInfo` in `footerContent`. The "Showing X of Y results" text and all pagination controls are covered.
|
|
101
|
+
|
|
102
|
+
**Key features:**
|
|
103
|
+
- `Table.PaginationPanel` → first/prev/page input/next/last controls
|
|
104
|
+
- `Table.RowCountInfo` → "Showing X of Y results" text
|
|
105
|
+
- All use `GridApiContext` — must be inside `Table`'s tree
|
|
106
|
+
- Enable pagination: `pagination={true}` + `paginationPageSize={100}` on `Table`
|
|
107
|
+
|
|
108
|
+
**Example:**
|
|
109
|
+
```tsx
|
|
110
|
+
<Table
|
|
111
|
+
pagination={true}
|
|
112
|
+
paginationPageSize={100}
|
|
113
|
+
footerContent={
|
|
114
|
+
<>
|
|
115
|
+
<Table.RowCountInfo />
|
|
116
|
+
<Table.PaginationPanel />
|
|
117
|
+
</>
|
|
118
|
+
}
|
|
119
|
+
/>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
### Table — AG Grid Checkbox Selection
|
|
125
|
+
|
|
126
|
+
Native AG Grid. No custom component needed. Pass `checkboxSelection` and `headerCheckboxSelection` in the first column definition:
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
const columnDefs = [
|
|
130
|
+
{
|
|
131
|
+
checkboxSelection: true,
|
|
132
|
+
headerCheckboxSelection: true,
|
|
133
|
+
width: 50,
|
|
134
|
+
pinned: 'left',
|
|
135
|
+
},
|
|
136
|
+
{ field: 'time', headerName: 'Time' },
|
|
137
|
+
// etc.
|
|
138
|
+
];
|
|
139
|
+
<Table rowSelection="multiple" columnDefs={columnDefs} />
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
AG Grid Enterprise handles the indeterminate header state automatically.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
### Table — Empty State "(No Students)"
|
|
147
|
+
|
|
148
|
+
Native AG Grid via `noRowsOverlayComponent`:
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
<Table
|
|
152
|
+
noRowsOverlayComponent={() => (
|
|
153
|
+
<span className="ds-daily-attendance__empty">No Students</span>
|
|
154
|
+
)}
|
|
155
|
+
/>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
### Undo / Redo Toolbar Buttons (`src/components/button/Button.tsx`)
|
|
161
|
+
|
|
162
|
+
`Button variant="secondary" size="S"` with verified icon names. Dorothy confirmed `'undo'` and `'redo'` BOTH exist in the allowed icons set.
|
|
163
|
+
|
|
164
|
+
**Example:**
|
|
165
|
+
```tsx
|
|
166
|
+
<Button variant="secondary" size="S" iconLeftName="undo" iconLeftScreenReaderText="Undo" />
|
|
167
|
+
<Button variant="secondary" size="S" iconLeftName="redo" iconLeftScreenReaderText="Redo" />
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
### Icon-Only Toolbar Buttons (`src/components/button/Button.tsx`)
|
|
173
|
+
|
|
174
|
+
`Button` in icon-only mode (auto-applied when `iconLeftName` is set and `children` is absent). Use `variant="tertiary"` for the toolbar ghost style. ALWAYS wrap in `TooltipWrapper` — icon-only buttons without tooltips fail WCAG 2.1 AA.
|
|
175
|
+
|
|
176
|
+
**Dorothy-verified icon names:**
|
|
177
|
+
- Search: `'search'` ✅
|
|
178
|
+
- Download: `'download'` ✅
|
|
179
|
+
- Settings: use `Table.TableSettingsDropdown` instead (see below)
|
|
180
|
+
- Expand: `'expand'` ✅
|
|
181
|
+
- Comment/Message: `'message-square-more'` ✅ — **`'comment'` does NOT exist**
|
|
182
|
+
|
|
183
|
+
**Example:**
|
|
184
|
+
```tsx
|
|
185
|
+
<TooltipWrapper tooltipContent="Download">
|
|
186
|
+
<Button variant="tertiary" size="S" iconLeftName="download" iconLeftScreenReaderText="Download registers" />
|
|
187
|
+
</TooltipWrapper>
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
### Table — Settings Button (`src/components/table/Table.tsx`)
|
|
193
|
+
|
|
194
|
+
`Table.TableSettingsDropdown` is the right component — not a raw icon button. It provides the settings icon trigger and the full settings panel (row spacing, borders, cell colours).
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
<Table.TableSettingsDropdown onTableSettingsChanged={handleSettingsChange} />
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
### Table — Expand Table Button
|
|
203
|
+
|
|
204
|
+
`Button variant="secondary" size="S"` in the `footerContent` slot:
|
|
205
|
+
|
|
206
|
+
```tsx
|
|
207
|
+
footerContent={
|
|
208
|
+
<>
|
|
209
|
+
<Table.RowCountInfo />
|
|
210
|
+
<div className="ds-daily-attendance__footer-right">
|
|
211
|
+
<Table.PaginationPanel />
|
|
212
|
+
<Button variant="secondary" size="S">Expand table</Button>
|
|
213
|
+
</div>
|
|
214
|
+
</>
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
### UserDropdown — Top Right User Menu (`src/components/userDropdown/UserDropdown.tsx`)
|
|
221
|
+
|
|
222
|
+
`UserDropdown` handles the entire top-right user avatar trigger, name, role, linked apps, and sign-out in one component. Use `variant="dark"` for a dark navigation bar.
|
|
223
|
+
|
|
224
|
+
**Example:**
|
|
225
|
+
```tsx
|
|
226
|
+
<UserDropdown
|
|
227
|
+
variant="dark"
|
|
228
|
+
user={{ name: 'Amee Morris', subtitle: 'Administrator', avatarSrc: '/path/to/avatar.jpg' }}
|
|
229
|
+
onSignOut={handleSignOut}
|
|
230
|
+
logoSrc="/path/to/org-logo.png"
|
|
231
|
+
sections={[
|
|
232
|
+
{
|
|
233
|
+
label: 'Switch product',
|
|
234
|
+
items: [{ label: 'Arbor', href: '...', logo: ArborLogo }],
|
|
235
|
+
},
|
|
236
|
+
]}
|
|
237
|
+
/>
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Section 2: Almost There — Minor Issues or Gotchas
|
|
243
|
+
|
|
244
|
+
### Filter Info Bar
|
|
245
|
+
|
|
246
|
+
**What exists:** No single `FilterInfoBar` component. `Banner` LOOKS superficially similar but is wrong here — it has rigid semantic styling (info/warning/destructive) and an opinionated layout that doesn't match the filter summary pattern.
|
|
247
|
+
|
|
248
|
+
**What's needed:** A horizontal strip with colored square/circle indicators, a text summary, and a secondary action button.
|
|
249
|
+
|
|
250
|
+
**The fix — compose from primitives:**
|
|
251
|
+
```tsx
|
|
252
|
+
<div className="ds-daily-attendance__filter-bar">
|
|
253
|
+
<Tag text="AM" color="blue" dotColour="blue" />
|
|
254
|
+
<Tag text="Internal Exclusions" color="orange" dotColour="orange" />
|
|
255
|
+
<span className="ds-daily-attendance__filter-text">
|
|
256
|
+
Select Date Wed, 05 Feb 2025 AM Showing Attendance Registers...
|
|
257
|
+
</span>
|
|
258
|
+
<Button variant="secondary" size="S" iconLeftName="pencil">Edit</Button>
|
|
259
|
+
</div>
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Note: `Tag dotColour` produces circles. If the design requires literal squares, that's a bespoke `<span>` with CSS. `'pencil'` is the correct icon name — Dorothy confirmed `'edit'` does NOT exist.
|
|
263
|
+
|
|
264
|
+
**Effort:** Low — composable from primitives.
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
### Marks Status Indicators Cell (`src/components/icon/Icon.tsx`)
|
|
269
|
+
|
|
270
|
+
**What exists:** No registered cell renderer handles the "✓ 24 ⏱ 1 ✗ 3" pattern. `dsInlineTextCellRenderer` is text-only. `dsButtonCellRenderer` renders a single button.
|
|
271
|
+
|
|
272
|
+
**What's needed:** A custom `cellRenderer` component for the Marks column. This is expected AG Grid architecture.
|
|
273
|
+
|
|
274
|
+
**The fix:**
|
|
275
|
+
```tsx
|
|
276
|
+
const MarksSummaryCellRenderer = ({ value }) => (
|
|
277
|
+
<span className="ds-daily-attendance__marks-summary">
|
|
278
|
+
<Icon name="check" size={16} color="var(--color-success-500)" />
|
|
279
|
+
<span>{value.present}</span>
|
|
280
|
+
<Icon name="clock" size={16} color="var(--color-caution-500)" />
|
|
281
|
+
<span>{value.pending}</span>
|
|
282
|
+
<Icon name="x" size={16} color="var(--color-destructive-500)" />
|
|
283
|
+
<span>{value.absent}</span>
|
|
284
|
+
</span>
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
// in columnDefs:
|
|
288
|
+
{ field: 'marks', headerName: 'Marks', cellRenderer: MarksSummaryCellRenderer }
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**Not a library gap** — this is correct pluggable AG Grid architecture. **Effort:** Low.
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
### Breadcrumbs
|
|
296
|
+
|
|
297
|
+
**What exists:** No `Breadcrumbs` component. Must be composed from `Button variant="text-link"`, `Separator orientation="vertical"`, and semantic HTML.
|
|
298
|
+
|
|
299
|
+
**The fix:**
|
|
300
|
+
```tsx
|
|
301
|
+
<nav aria-label="Breadcrumb">
|
|
302
|
+
<ol className="ds-daily-attendance__breadcrumbs">
|
|
303
|
+
<li><Button variant="text-link">Students</Button></li>
|
|
304
|
+
<li aria-hidden="true"><Separator orientation="vertical" decorative={true} /></li>
|
|
305
|
+
<li><Button variant="text-link">Attendance</Button></li>
|
|
306
|
+
<li aria-hidden="true"><Separator orientation="vertical" decorative={true} /></li>
|
|
307
|
+
<li><Button variant="text-link">Registers</Button></li>
|
|
308
|
+
<li aria-hidden="true"><Separator orientation="vertical" decorative={true} /></li>
|
|
309
|
+
<li><span aria-current="page">Daily Attendance</span></li>
|
|
310
|
+
</ol>
|
|
311
|
+
</nav>
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**Effort:** Low for this instance. But this pattern appears on every Arbor MIS page — it needs a library component.
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Section 3: Build It From Scratch — These Don't Exist Yet
|
|
319
|
+
|
|
320
|
+
### Top Navigation Bar (Layout Shell)
|
|
321
|
+
|
|
322
|
+
The layout chrome — dark background, logo slot, horizontal nav link row, layout structure — does not exist as a component. The interactive pieces ARE available (`UserDropdown`, `SearchBar`, `Button`, `Icon`) but the container shell is bespoke.
|
|
323
|
+
|
|
324
|
+
**What would need building:** `TopNavigationBar` with logo slot, nav links slot, search slot, right-aligned actions slot. Nav link items are `Button` + `Dropdown` composites.
|
|
325
|
+
|
|
326
|
+
**Effort:** High. Should be a shared library component, not inline page code.
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
### Left Side Navigation Panel
|
|
331
|
+
|
|
332
|
+
No `SideNavigation` or sidebar component exists. The design shows collapsible section groups, individual nav items with active state, favourites (`'favourite-outline'` / `'favourite-filled'` — `'star'` does NOT exist per Dorothy), and notification badges.
|
|
333
|
+
|
|
334
|
+
`Section` is NOT the answer — it's a page-layout card, not a slim sidebar nav item.
|
|
335
|
+
|
|
336
|
+
**What would need building:** `SideNavigation` shell, `SideNavigation.Section` for collapsible groups, `SideNavigation.Item` for individual links.
|
|
337
|
+
|
|
338
|
+
**Effort:** High. Single most impactful missing component for Arbor MIS page fidelity.
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
### Notification Badge
|
|
343
|
+
|
|
344
|
+
The circular count badge overlaying nav items has no library equivalent. `Tag` is rectangular. No `Badge` component exists.
|
|
345
|
+
|
|
346
|
+
**What would need building:** Small circular `Badge` component with count/dot variants and colour options. Absolute overlay or inline positioning.
|
|
347
|
+
|
|
348
|
+
**Effort:** Low. Small, focused, immediately reusable across nav, avatars, icons.
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## Section 4: Tricky Bits — Pay Attention Here
|
|
353
|
+
|
|
354
|
+
### 1. `headerContent` Must Be Truthy for Search/Toolbar to Render
|
|
355
|
+
|
|
356
|
+
Dorothy caught a critical gotcha: `TableHeader` only renders when `headerContent` is truthy. Passing `hasSearch={true}` alone does NOTHING if `headerContent` is `null`. You must pass truthy `headerContent` to get any header (including the search bar). If the design uses a custom toolbar, pass `hasSearch={false}` and wire search state yourself.
|
|
357
|
+
|
|
358
|
+
### 2. `CheckboxInput` is NOT in the Public API
|
|
359
|
+
|
|
360
|
+
Dorothy confirmed `CheckboxInput` and `CheckboxGroup` are NOT exported from `src/index.ts`. Use the Table's native AG Grid `checkboxSelection` for row selection (the correct approach). If standalone checkboxes are needed elsewhere on this page, raise a ticket to export these.
|
|
361
|
+
|
|
362
|
+
### 3. Tooltip Every Icon-Only Button
|
|
363
|
+
|
|
364
|
+
Every icon-only toolbar button MUST be wrapped in `TooltipWrapper`. WCAG 2.1 AA requirement. Not optional.
|
|
365
|
+
|
|
366
|
+
### 4. Verify Icon Names Before Committing
|
|
367
|
+
|
|
368
|
+
Dorothy's caught hallucinations:
|
|
369
|
+
- `'comment'` → **DOES NOT EXIST** → use `'message-square-more'`
|
|
370
|
+
- `'star'` → **DOES NOT EXIST** → use `'favourite-outline'` or `'favourite-filled'`
|
|
371
|
+
- `'edit'` → **DOES NOT EXIST** → use `'pencil'`
|
|
372
|
+
- `'ghost'` → **NOT a Button variant** → use `'tertiary'`
|
|
373
|
+
|
|
374
|
+
TypeScript will catch these at compile time, but verify upfront against `src/components/icon/allowedIcons.tsx`.
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## Section 5: The Verdict
|
|
379
|
+
|
|
380
|
+
Picture it: Sicily, 1967. My cousin Giacomo spent three days building a barn without a blueprint. Half the walls fell down. The other half ended up where the chicken coop was supposed to go. The chickens were confused for months.
|
|
381
|
+
|
|
382
|
+
Don't be Giacomo.
|
|
383
|
+
|
|
384
|
+
### Is It Buildable With Our Existing Components?
|
|
385
|
+
|
|
386
|
+
**Mostly YES. High confidence for the table. Bespoke work required for navigation chrome.**
|
|
387
|
+
|
|
388
|
+
The data table — the heart of this page — maps almost perfectly to our `Table` component and its sub-components. AG Grid Enterprise handles the heavy lifting. Toolbar, pagination, bulk actions, settings, hide columns are all pre-built. The navigation chrome (top nav, side nav) is genuine bespoke work — but if this page lives inside an existing Arbor app shell that already renders navigation, those concerns are already solved at the host application level.
|
|
389
|
+
|
|
390
|
+
### Summary Table
|
|
391
|
+
|
|
392
|
+
| Design Element | Library Component | Status |
|
|
393
|
+
|---|---|---|
|
|
394
|
+
| Page H1 + right button | `Heading` + `Heading.InnerContainer` | ✅ Ready |
|
|
395
|
+
| Actions dropdown | `Table.BulkActionsDropdown` | ✅ Ready |
|
|
396
|
+
| Undo/Redo buttons | `Button` with `iconLeftName="undo/redo"` | ✅ Ready |
|
|
397
|
+
| Hide columns | `Table.HideColumnsDropdown` | ✅ Ready |
|
|
398
|
+
| Settings button | `Table.TableSettingsDropdown` | ✅ Ready |
|
|
399
|
+
| Icon toolbar buttons | `Button` icon-only + `TooltipWrapper` | ✅ Ready |
|
|
400
|
+
| Checkbox column | AG Grid native `checkboxSelection` | ✅ Ready |
|
|
401
|
+
| Column definitions | AG Grid `columnDefs` | ✅ Ready |
|
|
402
|
+
| Empty state "(No Students)" | `noRowsOverlayComponent` prop | ✅ Ready |
|
|
403
|
+
| Pagination | `Table.PaginationPanel` + `Table.RowCountInfo` | ✅ Ready |
|
|
404
|
+
| Expand table button | `Button variant="secondary"` | ✅ Ready |
|
|
405
|
+
| UserDropdown | `UserDropdown variant="dark"` | ✅ Ready |
|
|
406
|
+
| Filter info bar | Compose: `Tag` + `Button` + layout | 🔧 Minor work |
|
|
407
|
+
| Marks status cell | Custom `cellRenderer` with `Icon` | 🔧 Minor work |
|
|
408
|
+
| Breadcrumbs | Compose: `Button text-link` + `Separator` + semantic HTML | 🔧 Minor work |
|
|
409
|
+
| Top navigation bar | `UserDropdown`/`SearchBar`/`Button` for parts; chrome is bespoke | 🆕 New component |
|
|
410
|
+
| Side navigation panel | No equivalent exists | 🆕 New component |
|
|
411
|
+
| Notification badge | No `Badge` component exists | 🆕 New component |
|
|
412
|
+
|
|
413
|
+
### What Actually Needs Work
|
|
414
|
+
|
|
415
|
+
| Item | Where It Lives | Effort |
|
|
416
|
+
|---|---|---|
|
|
417
|
+
| Marks status cell renderer | Page-level component | Low |
|
|
418
|
+
| Breadcrumbs (this instance) | Page-level composition | Low |
|
|
419
|
+
| Filter info bar | Page-level composition | Low |
|
|
420
|
+
| Breadcrumbs (library component) | New library component | Medium |
|
|
421
|
+
| Notification Badge component | New library component | Low |
|
|
422
|
+
| Top Navigation Bar | New library component (or host app) | High |
|
|
423
|
+
| Side Navigation Panel | New library component (or host app) | High |
|
|
424
|
+
|
|
425
|
+
### Summary Verdict
|
|
426
|
+
|
|
427
|
+
**12 out of 18 elements** can be built directly with current library components. 3 elements need minor composition work (filter bar, breadcrumbs instance, marks cell renderer). 3 require new library components (top nav, side nav, notification badge).
|
|
428
|
+
|
|
429
|
+
**Recommendation:** Highly feasible for the table and content area. The data table is essentially already built. The navigation chrome gaps are structural — either build as shared library components (high value, high effort) or deliver inside the host app's existing nav shell.
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## Appendix: Files Referenced in This Assessment
|
|
434
|
+
|
|
435
|
+
*Every file Dorothy read to verify claims. This assessment is grounded in actual source code.*
|
|
436
|
+
|
|
437
|
+
- `src/index.ts`
|
|
438
|
+
- `src/components/table/Table.tsx`
|
|
439
|
+
- `src/components/table/TableHeader.tsx`
|
|
440
|
+
- `src/components/table/useTableSettings.ts`
|
|
441
|
+
- `src/components/table/BulkActionsDropdown.tsx`
|
|
442
|
+
- `src/components/table/HideColumnsDropdown.tsx`
|
|
443
|
+
- `src/components/button/Button.tsx`
|
|
444
|
+
- `src/components/heading/Heading.tsx`
|
|
445
|
+
- `src/components/section/Section.tsx`
|
|
446
|
+
- `src/components/banner/Banner.tsx`
|
|
447
|
+
- `src/components/icon/Icon.tsx`
|
|
448
|
+
- `src/components/icon/allowedIcons.tsx`
|
|
449
|
+
- `src/components/dropdown/Dropdown.tsx`
|
|
450
|
+
- `src/components/dropdown/DropdownTrigger.tsx`
|
|
451
|
+
- `src/components/dropdown/DropdownContent.tsx`
|
|
452
|
+
- `src/components/dropdown/items/DropdownItem.tsx`
|
|
453
|
+
- `src/components/dropdown/items/DropdownSelectItem.tsx`
|
|
454
|
+
- `src/components/dropdown/items/DropdownGroup.tsx`
|
|
455
|
+
- `src/components/searchBar/SearchBar.tsx`
|
|
456
|
+
- `src/components/pill/Pill.tsx`
|
|
457
|
+
- `src/components/tag/Tag.tsx`
|
|
458
|
+
|
|
459
|
+
---
|
|
460
|
+
|
|
461
|
+
*Analysis by Sophia Petrillo, Componentspert 👜, fact-checked by Dorothy Zbornak 🔍*
|
|
462
|
+
*Powered by Claude Code 🐺*
|