@arbor-education/design-system.components 3.2.0 → 3.2.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.
Files changed (56) hide show
  1. package/.gather/skills/write-stories/README.md +8 -4
  2. package/.gather/skills/write-stories/SKILL.md +59 -5
  3. package/CHANGELOG.md +10 -0
  4. package/dist/components/breadcrumbs/Breadcrumbs.stories.d.ts +1 -0
  5. package/dist/components/breadcrumbs/Breadcrumbs.stories.d.ts.map +1 -1
  6. package/dist/components/breadcrumbs/Breadcrumbs.stories.js +103 -21
  7. package/dist/components/breadcrumbs/Breadcrumbs.stories.js.map +1 -1
  8. package/dist/components/card/Card.stories.d.ts.map +1 -1
  9. package/dist/components/card/Card.stories.js +46 -41
  10. package/dist/components/card/Card.stories.js.map +1 -1
  11. package/dist/components/editableText/EditableText.stories.d.ts.map +1 -1
  12. package/dist/components/editableText/EditableText.stories.js +19 -6
  13. package/dist/components/editableText/EditableText.stories.js.map +1 -1
  14. package/dist/components/formField/fieldset/Fieldset.stories.d.ts.map +1 -1
  15. package/dist/components/formField/fieldset/Fieldset.stories.js +5 -3
  16. package/dist/components/formField/fieldset/Fieldset.stories.js.map +1 -1
  17. package/dist/components/row/Row.stories.d.ts.map +1 -1
  18. package/dist/components/row/Row.stories.js +22 -13
  19. package/dist/components/row/Row.stories.js.map +1 -1
  20. package/dist/components/sidebar/Sidebar.stories.d.ts.map +1 -1
  21. package/dist/components/sidebar/Sidebar.stories.js +19 -24
  22. package/dist/components/sidebar/Sidebar.stories.js.map +1 -1
  23. package/dist/components/table/Table.stories.d.ts.map +1 -1
  24. package/dist/components/table/Table.stories.js +16 -10
  25. package/dist/components/table/Table.stories.js.map +1 -1
  26. package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.d.ts.map +1 -1
  27. package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.js +8 -5
  28. package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.js.map +1 -1
  29. package/dist/components/table/tableControls/TableControls.stories.d.ts +1 -1
  30. package/dist/components/table/tableControls/TableControls.stories.d.ts.map +1 -1
  31. package/dist/components/table/tableControls/TableControls.stories.js +26 -21
  32. package/dist/components/table/tableControls/TableControls.stories.js.map +1 -1
  33. package/dist/components/widget/Widget.stories.d.ts +13 -0
  34. package/dist/components/widget/Widget.stories.d.ts.map +1 -1
  35. package/dist/components/widget/Widget.stories.js +45 -6
  36. package/dist/components/widget/Widget.stories.js.map +1 -1
  37. package/dist/components/widgetCalendar/WidgetCalendar.stories.d.ts +88 -16
  38. package/dist/components/widgetCalendar/WidgetCalendar.stories.d.ts.map +1 -1
  39. package/dist/components/widgetCalendar/WidgetCalendar.stories.js +443 -30
  40. package/dist/components/widgetCalendar/WidgetCalendar.stories.js.map +1 -1
  41. package/dist/index.css +1 -4
  42. package/dist/index.css.map +1 -1
  43. package/package.json +1 -1
  44. package/src/components/breadcrumbs/Breadcrumbs.stories.tsx +112 -21
  45. package/src/components/card/Card.stories.tsx +46 -41
  46. package/src/components/datePicker/datePicker.scss +0 -5
  47. package/src/components/editableText/EditableText.stories.tsx +26 -29
  48. package/src/components/formField/fieldset/Fieldset.stories.tsx +5 -3
  49. package/src/components/row/Row.stories.tsx +20 -14
  50. package/src/components/sidebar/Sidebar.stories.tsx +61 -112
  51. package/src/components/table/Table.stories.tsx +25 -10
  52. package/src/components/table/cellRenderers/SelectDropdownCellRenderer.stories.tsx +8 -5
  53. package/src/components/table/tableControls/TableControls.stories.tsx +26 -21
  54. package/src/components/widget/Widget.stories.tsx +61 -6
  55. package/src/components/widgetCalendar/WidgetCalendar.stories.tsx +547 -74
  56. package/src/tokens.scss +1 -0
@@ -320,13 +320,11 @@ const MixedClickableAndStaticTemplate = () => (
320
320
  <Row
321
321
  label="SEN status"
322
322
  value="SEN Support"
323
- note="Review due May 2026"
324
323
  onClick={() => {}}
325
324
  />
326
325
  <Row
327
326
  label="Attendance (YTD)"
328
327
  value="88.3%"
329
- note="Below 90% threshold"
330
328
  onClick={() => {}}
331
329
  />
332
330
  </Section>
@@ -778,13 +776,11 @@ function PupilDetailSection() {
778
776
  <Row
779
777
  label="SEN status"
780
778
  value="SEN Support"
781
- note="Review due May 2026"
782
779
  onClick={() => navigateToSENRecord()}
783
780
  />
784
781
  <Row
785
782
  label="Attendance (YTD)"
786
783
  value="88.3%"
787
- note="Below 90% threshold"
788
784
  onClick={() => navigateToAttendance()}
789
785
  />
790
786
  </Section>
@@ -832,7 +828,7 @@ export default PersonalDetailsSection;
832
828
  },
833
829
  render: InSectionTemplate,
834
830
  },
835
- 'The canonical real-world usage: `Row` components as children of a `Section`. The `Section` provides the container heading and background; each `Row` handles the label/value layout. Most product uses of `Row` are inside a `Section`.',
831
+ 'The canonical real-world usage: `Row` components as children of a `Section`. The `Section` provides the container heading and background; each `Row` handles the label/value layout. Most product uses of `Row` are inside a `Section` — one row demonstrates a linked value via `href` to show that pattern working inside a realistic panel too.',
836
832
  );
837
833
 
838
834
  export const LongContent: Story = withDescription(
@@ -857,7 +853,6 @@ function LongContentExample() {
857
853
  label="Pupil premium eligibility reason"
858
854
  value="Free school meals — ever 6"
859
855
  note="Verified by LA"
860
- onClick={() => navigateToEligibilityDetail()}
861
856
  />
862
857
  </div>
863
858
  );
@@ -878,7 +873,6 @@ export default LongContentExample;
878
873
  label="Pupil premium eligibility reason"
879
874
  value="Free school meals — ever 6"
880
875
  note="Verified by LA"
881
- onClick={fn()}
882
876
  />
883
877
  </div>
884
878
  ),
@@ -1102,16 +1096,28 @@ export const WithTooltip: Story = withDescription(
1102
1096
  code: `
1103
1097
  import { Row } from '@arbor-education/design-system.components';
1104
1098
 
1105
- function ReadOnlyRow() {
1099
+ function ReadOnlyRows() {
1106
1100
  return (
1107
- <Row
1108
- label="UPN"
1109
- value="A823456789012"
1110
- tooltipText="Unique Pupil Number — assigned by the DfE and cannot be changed here"
1111
- />
1101
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--spacing-small)' }}>
1102
+ <Row
1103
+ label="UPN"
1104
+ value="A823456789012"
1105
+ tooltipText="Unique Pupil Number — assigned by the DfE and cannot be changed here"
1106
+ />
1107
+ <Row
1108
+ label="Admission number"
1109
+ value="001847"
1110
+ tooltipText="Set at admission — contact the office to request a change"
1111
+ />
1112
+ {/* No tooltipText — hovering this row shows nothing */}
1113
+ <Row
1114
+ label="Year group"
1115
+ value="Year 9"
1116
+ />
1117
+ </div>
1112
1118
  );
1113
1119
  }
1114
- export default ReadOnlyRow;
1120
+ export default ReadOnlyRows;
1115
1121
  `.trim(),
1116
1122
  },
1117
1123
  },
@@ -330,98 +330,53 @@ const DefaultTemplate = () => {
330
330
  );
331
331
  };
332
332
 
333
- const WithSeparatorsTemplate = () => {
334
- const [active, setActive] = useState<string>('favourites');
335
-
336
- return (
337
- <div style={storyWrapperStyle}>
338
- <Sidebar ariaLabel="App navigation">
339
- <SidebarItem
340
- aria-label="Favourites"
341
- selected={active === 'favourites'}
342
- onClick={() => setActive('favourites')}
343
- >
344
- <Icon name="favourite-outline" size={24} />
345
- </SidebarItem>
346
- <SidebarItem
347
- aria-label="Notifications"
348
- selected={active === 'notifications'}
349
- onClick={() => setActive('notifications')}
350
- >
351
- <Icon name="message-square-more" size={24} />
352
- </SidebarItem>
353
- <SidebarItem
354
- aria-label="My Calendar"
355
- selected={active === 'calendar'}
356
- onClick={() => setActive('calendar')}
357
- >
358
- <Icon name="date" size={24} />
359
- </SidebarItem>
360
- <Separator orientation="horizontal" decorative />
361
- <SidebarItem
362
- aria-label="Emergency Alerts"
363
- selected={active === 'emergency'}
364
- onClick={() => setActive('emergency')}
365
- >
366
- <Icon name="triangle-alert" size={24} />
367
- </SidebarItem>
368
- <Separator orientation="horizontal" decorative />
369
- <SidebarItem
370
- aria-label="Help & Learn with Arbor"
371
- selected={active === 'help'}
372
- onClick={() => setActive('help')}
373
- >
374
- <Icon name="circle-help" size={24} />
375
- </SidebarItem>
376
- </Sidebar>
377
- </div>
378
- );
379
- };
380
-
381
- const WithBadgeTemplate = () => {
382
- const [active, setActive] = useState<string>('favourites');
333
+ const WithSeparatorsTemplate = () => (
334
+ <div style={storyWrapperStyle}>
335
+ <Sidebar ariaLabel="App navigation">
336
+ <SidebarItem aria-label="Favourites">
337
+ <Icon name="favourite-outline" size={24} />
338
+ </SidebarItem>
339
+ <SidebarItem aria-label="Notifications">
340
+ <Icon name="message-square-more" size={24} />
341
+ </SidebarItem>
342
+ <SidebarItem aria-label="My Calendar">
343
+ <Icon name="date" size={24} />
344
+ </SidebarItem>
345
+ <Separator orientation="horizontal" decorative />
346
+ <SidebarItem aria-label="Emergency Alerts">
347
+ <Icon name="triangle-alert" size={24} />
348
+ </SidebarItem>
349
+ <Separator orientation="horizontal" decorative />
350
+ <SidebarItem aria-label="Help & Learn with Arbor">
351
+ <Icon name="circle-help" size={24} />
352
+ </SidebarItem>
353
+ </Sidebar>
354
+ </div>
355
+ );
383
356
 
384
- return (
385
- <div style={storyWrapperStyle}>
386
- <Sidebar ariaLabel="App navigation">
387
- <SidebarItem
388
- aria-label="Favourites"
389
- selected={active === 'favourites'}
390
- onClick={() => setActive('favourites')}
391
- >
392
- <Icon name="favourite-outline" size={24} />
393
- </SidebarItem>
394
- <SidebarItem
395
- aria-label="Notifications — 6 unread"
396
- selected={active === 'notifications'}
397
- onClick={() => setActive('notifications')}
398
- >
399
- <Icon name="message-square-more" size={24} />
400
- <Badge size="sm" colour="salmon">6</Badge>
401
- </SidebarItem>
402
- <SidebarItem
403
- aria-label="Emergency Alerts — 2 active"
404
- selected={active === 'emergency'}
405
- onClick={() => setActive('emergency')}
406
- >
407
- <Icon name="triangle-alert" size={24} />
408
- <Badge size="sm" colour="yellow">2</Badge>
409
- </SidebarItem>
410
- <SidebarItem
411
- aria-label="My Calendar"
412
- selected={active === 'calendar'}
413
- onClick={() => setActive('calendar')}
414
- >
415
- <Icon name="date" size={24} />
416
- </SidebarItem>
417
- </Sidebar>
418
- </div>
419
- );
420
- };
357
+ const WithBadgeTemplate = () => (
358
+ <div style={storyWrapperStyle}>
359
+ <Sidebar ariaLabel="App navigation">
360
+ <SidebarItem aria-label="Favourites">
361
+ <Icon name="favourite-outline" size={24} />
362
+ </SidebarItem>
363
+ <SidebarItem aria-label="Notifications — 6 unread">
364
+ <Icon name="message-square-more" size={24} />
365
+ <Badge size="sm" colour="salmon">6</Badge>
366
+ </SidebarItem>
367
+ <SidebarItem aria-label="Emergency Alerts — 2 active">
368
+ <Icon name="triangle-alert" size={24} />
369
+ <Badge size="sm" colour="yellow">2</Badge>
370
+ </SidebarItem>
371
+ <SidebarItem aria-label="My Calendar">
372
+ <Icon name="date" size={24} />
373
+ </SidebarItem>
374
+ </Sidebar>
375
+ </div>
376
+ );
421
377
 
422
378
  const WithPanelTemplate = () => {
423
379
  const [open, setOpen] = useState(true);
424
- const [active, setActive] = useState<string>('favourites');
425
380
 
426
381
  return (
427
382
  <div style={storyWrapperStyle}>
@@ -436,18 +391,10 @@ const WithPanelTemplate = () => {
436
391
  <Icon name="menu" size={24} />
437
392
  </SidebarItem>
438
393
  <Separator orientation="horizontal" decorative />
439
- <SidebarItem
440
- aria-label="Favourites"
441
- selected={active === 'favourites'}
442
- onClick={() => setActive('favourites')}
443
- >
394
+ <SidebarItem aria-label="Favourites">
444
395
  <Icon name="favourite-outline" size={24} />
445
396
  </SidebarItem>
446
- <SidebarItem
447
- aria-label="My Calendar"
448
- selected={active === 'calendar'}
449
- onClick={() => setActive('calendar')}
450
- >
397
+ <SidebarItem aria-label="My Calendar">
451
398
  <Icon name="date" size={24} />
452
399
  </SidebarItem>
453
400
  </Sidebar>
@@ -497,30 +444,28 @@ export const WithSeparators: Story = withDescription(
497
444
  language: 'tsx',
498
445
  code: `
499
446
  import { Sidebar, SidebarItem, Separator, Icon } from '@arbor-education/design-system.components';
500
- import { useState } from 'react';
501
447
 
502
448
  function WithSeparatorsExample() {
503
- const [active, setActive] = useState('favourites');
504
449
  return (
505
450
  <Sidebar ariaLabel="App navigation">
506
451
  {/* Primary nav group */}
507
- <SidebarItem aria-label="Favourites" selected={active === 'favourites'} onClick={() => setActive('favourites')}>
452
+ <SidebarItem aria-label="Favourites">
508
453
  <Icon name="favourite-outline" size={24} />
509
454
  </SidebarItem>
510
- <SidebarItem aria-label="Notifications" selected={active === 'notifications'} onClick={() => setActive('notifications')}>
455
+ <SidebarItem aria-label="Notifications">
511
456
  <Icon name="message-square-more" size={24} />
512
457
  </SidebarItem>
513
- <SidebarItem aria-label="My Calendar" selected={active === 'calendar'} onClick={() => setActive('calendar')}>
458
+ <SidebarItem aria-label="My Calendar">
514
459
  <Icon name="date" size={24} />
515
460
  </SidebarItem>
516
461
  <Separator orientation="horizontal" decorative />
517
462
  {/* Alert group */}
518
- <SidebarItem aria-label="Emergency Alerts" selected={active === 'emergency'} onClick={() => setActive('emergency')}>
463
+ <SidebarItem aria-label="Emergency Alerts">
519
464
  <Icon name="triangle-alert" size={24} />
520
465
  </SidebarItem>
521
466
  <Separator orientation="horizontal" decorative />
522
467
  {/* Utility group */}
523
- <SidebarItem aria-label="Help & Learn with Arbor" selected={active === 'help'} onClick={() => setActive('help')}>
468
+ <SidebarItem aria-label="Help & Learn with Arbor">
524
469
  <Icon name="circle-help" size={24} />
525
470
  </SidebarItem>
526
471
  </Sidebar>
@@ -532,7 +477,7 @@ export default WithSeparatorsExample;
532
477
  },
533
478
  },
534
479
  },
535
- 'Three groups divided by `<Separator orientation="horizontal" decorative />`. A common layout: primary nav / alerts / utility items. Click any item to see the active state.',
480
+ 'Three groups divided by `<Separator orientation="horizontal" decorative />`: primary nav (Favourites, Notifications, My Calendar), alerts (Emergency Alerts), and utility (Help & Learn with Arbor).',
536
481
  );
537
482
 
538
483
  export const WithBadge: Story = withDescription(
@@ -545,27 +490,28 @@ export const WithBadge: Story = withDescription(
545
490
  language: 'tsx',
546
491
  code: `
547
492
  import { Sidebar, SidebarItem, Badge, Icon } from '@arbor-education/design-system.components';
548
- import { useState } from 'react';
549
493
 
550
494
  function WithBadgeExample() {
551
- const [active, setActive] = useState('favourites');
552
495
  return (
553
496
  <Sidebar ariaLabel="App navigation">
554
- <SidebarItem aria-label="Favourites" selected={active === 'favourites'} onClick={() => setActive('favourites')}>
497
+ <SidebarItem aria-label="Favourites">
555
498
  <Icon name="favourite-outline" size={24} />
556
499
  </SidebarItem>
557
500
  {/*
558
501
  Badge is automatically positioned top-right by sidebar.scss — no extra styling needed.
559
502
  Include the count in aria-label so screen reader users also receive the total.
560
503
  */}
561
- <SidebarItem aria-label="Notifications — 6 unread" selected={active === 'notifications'} onClick={() => setActive('notifications')}>
504
+ <SidebarItem aria-label="Notifications — 6 unread">
562
505
  <Icon name="message-square-more" size={24} />
563
506
  <Badge size="sm" colour="salmon">6</Badge>
564
507
  </SidebarItem>
565
- <SidebarItem aria-label="Emergency Alerts — 2 active" selected={active === 'emergency'} onClick={() => setActive('emergency')}>
508
+ <SidebarItem aria-label="Emergency Alerts — 2 active">
566
509
  <Icon name="triangle-alert" size={24} />
567
510
  <Badge size="sm" colour="yellow">2</Badge>
568
511
  </SidebarItem>
512
+ <SidebarItem aria-label="My Calendar">
513
+ <Icon name="date" size={24} />
514
+ </SidebarItem>
569
515
  </Sidebar>
570
516
  );
571
517
  }
@@ -607,9 +553,12 @@ function WithPanelExample() {
607
553
  <Icon name="menu" size={24} />
608
554
  </SidebarItem>
609
555
  <Separator orientation="horizontal" decorative />
610
- <SidebarItem aria-label="Favourites" selected={false}>
556
+ <SidebarItem aria-label="Favourites">
611
557
  <Icon name="favourite-outline" size={24} />
612
558
  </SidebarItem>
559
+ <SidebarItem aria-label="My Calendar">
560
+ <Icon name="date" size={24} />
561
+ </SidebarItem>
613
562
  </Sidebar>
614
563
 
615
564
  {/* SideNavigation is a separate companion component — not a sub-component of Sidebar. */}
@@ -614,6 +614,31 @@ export const Default: Story = {
614
614
  rowSelection: ['2', '3'],
615
615
  },
616
616
  cellSelection: true,
617
+ headerContent: (
618
+ <TableControls
619
+ bulkActions={[
620
+ {
621
+ displayName: 'foo',
622
+ callback: (gridApi) => {
623
+ console.log('clicked on the foo action', gridApi);
624
+ },
625
+ },
626
+ {
627
+ displayName: 'bar',
628
+ callback: (gridApi) => {
629
+ console.log('clicked on the bar action', gridApi);
630
+ },
631
+ disabled: true,
632
+ },
633
+ ]}
634
+ showHideColumns
635
+ onDownload={() => console.log('download')}
636
+ showSettings
637
+ onHelp={() => console.log('help')}
638
+ onExpandToggle={expanded => console.log('expand', expanded)}
639
+ />
640
+ ),
641
+ footerContent,
617
642
  },
618
643
  };
619
644
 
@@ -1505,8 +1530,6 @@ export const WithValidation: Story = {
1505
1530
  columnDefs: colDefsWithValidation,
1506
1531
  defaultColDef: defaultColDef,
1507
1532
  domLayout: 'autoHeight',
1508
- rowSelection: { mode: 'multiRow', checkboxes: true },
1509
- cellSelection: true,
1510
1533
  },
1511
1534
  };
1512
1535
 
@@ -1552,8 +1575,6 @@ export const WithValidationClassesAdded: Story = {
1552
1575
  columnDefs: colDefsWithValidationClasses,
1553
1576
  defaultColDef: defaultColDef,
1554
1577
  domLayout: 'autoHeight',
1555
- rowSelection: { mode: 'multiRow', checkboxes: true },
1556
- cellSelection: true,
1557
1578
  },
1558
1579
  };
1559
1580
 
@@ -1719,10 +1740,6 @@ export const TidyTable: Story = {
1719
1740
  groupExpanded: '',
1720
1741
  groupContracted: '',
1721
1742
  },
1722
- rowSelection: {
1723
- mode: 'multiRow',
1724
- groupSelects: 'filteredDescendants',
1725
- },
1726
1743
  autoGroupColumnDef: {
1727
1744
  field: 'name',
1728
1745
  headerName: 'Marksheet Columns',
@@ -1841,7 +1858,6 @@ export const TableWithExplicitColours: Story = {
1841
1858
  ],
1842
1859
  columnDefs: sampleColumnDefs,
1843
1860
  defaultColDef,
1844
- headerContent,
1845
1861
  onCellValueChanged: (e) => {
1846
1862
  const { node, column, oldValue, newValue } = e;
1847
1863
  if (typeof oldValue === 'object' && 'value' in oldValue) {
@@ -1901,7 +1917,6 @@ export const TableWithSemanticColors: Story = {
1901
1917
  ],
1902
1918
  columnDefs: sampleColumnDefs,
1903
1919
  defaultColDef,
1904
- headerContent,
1905
1920
  domLayout: 'autoHeight',
1906
1921
  onCellValueChanged: (e) => {
1907
1922
  const { node, column, oldValue, newValue } = e;
@@ -24,7 +24,7 @@ const DESCRIPTION_INTRO = [
24
24
  'to update the row data in-place.',
25
25
  '',
26
26
  'Register it via `type: \'dsSelectDropdownColumn\'` on the column definition (pre-registered by Arbor\'s `Table`),',
27
- 'via the string key `dsSelectDropdownCellRenderer`, or by importing the component directly.',
27
+ 'via the string key `dsSelectDropdownCellRenderer`, or via `Table.SelectDropdownCellRenderer`.',
28
28
  ].join('\n');
29
29
 
30
30
  const USAGE_GUIDANCE = [
@@ -49,8 +49,9 @@ const DEVELOPER_NOTES = [
49
49
  '',
50
50
  '**`api` is required.**',
51
51
  'The renderer attaches a `cellKeyDown` listener to the Grid API on mount so that pressing Enter',
52
- 'in the focused cell opens the dropdown. Without `api`, the keyboard shortcut is silently skipped',
53
- 'but the dropdown still renders and is clickable.',
52
+ 'in the focused cell opens the dropdown. `api` is used unconditionally with no fallback — rendering',
53
+ 'this component without a live `api` throws on mount. AG Grid always supplies `api` to cell renderers,',
54
+ 'so this only matters if you render `SelectDropdownCellRenderer` outside of `AgGridReact` yourself.',
54
55
  '',
55
56
  '**`options` must be passed via `cellRendererParams`.**',
56
57
  'Options are not part of the cell `value` — configure them in `cellRendererParams`.',
@@ -89,7 +90,9 @@ const DEVELOPER_NOTES = [
89
90
  '### TypeScript types',
90
91
  '',
91
92
  '```ts',
92
- "import { SelectDropdownCellRenderer } from '@arbor-education/design-system.components';",
93
+ "import { Table } from '@arbor-education/design-system.components';",
94
+ '',
95
+ 'type SelectDropdownCellRendererProps = React.ComponentProps<typeof Table.SelectDropdownCellRenderer>;',
93
96
  '```',
94
97
  '',
95
98
  '`SelectDropdownCellRenderer` extends `CustomCellRendererProps` with `SelectDropdownInputProps`.',
@@ -715,7 +718,7 @@ const columnDefs = [
715
718
  />
716
719
  ),
717
720
  },
718
- '(fillCell + colored) Marksheet with grade-driven cell colours. Each cell uses `backgroundColor` (derived per-row from the current grade) and `fillCell: true` so the colour spans the cell edge-to-edge, plus `cellStyle: { padding: 0 }` to strip ag-grid\'s default cell padding. `iconClickOnly: true` is set so cell selection works — click anywhere in a cell to select it (or shift/drag for a range), and only the chevron icon opens the grade picker. Text colour auto-switches between dark and white for legibility against each background.',
721
+ 'Marksheet with grade-driven cell colours. Each cell uses `backgroundColor` (derived per-row from the current grade) and `fillCell: true` so the colour spans the cell edge-to-edge, plus `cellStyle: { padding: 0 }` to strip ag-grid\'s default cell padding. `iconClickOnly: true` is set so cell selection works — click anywhere in a cell to select it (or shift/drag for a range), and only the chevron icon opens the grade picker. Text colour auto-switches between dark and white for legibility against each background.',
719
722
  );
720
723
 
721
724
  export const CustomCloseFocus: Story = withDescription(
@@ -65,7 +65,7 @@ const DEVELOPER_NOTES = [
65
65
  '### Wiring into `<Table />`',
66
66
  '',
67
67
  '```tsx',
68
- "import { Table, TableControls } from '@arbor-education/design-system.components';",
68
+ "import { Table } from '@arbor-education/design-system.components';",
69
69
  '',
70
70
  'function MyTable() {',
71
71
  ' return (',
@@ -73,7 +73,7 @@ const DEVELOPER_NOTES = [
73
73
  ' rowData={rows}',
74
74
  ' columnDefs={colDefs}',
75
75
  ' headerContent={(',
76
- ' <TableControls',
76
+ ' <Table.TableControls',
77
77
  ' bulkActions={[',
78
78
  ' { displayName: "Export selected", callback: api => exportCsv(api) },',
79
79
  ' { displayName: "Delete selected", callback: api => deleteRows(api) },',
@@ -93,16 +93,19 @@ const DEVELOPER_NOTES = [
93
93
  '',
94
94
  '---',
95
95
  '',
96
- '### `BulkAction` type',
96
+ '### `Table.BulkAction` type',
97
97
  '',
98
98
  '```ts',
99
- "import type { BulkAction } from '@arbor-education/design-system.components';",
99
+ "import { Table } from '@arbor-education/design-system.components';",
100
100
  '',
101
- 'type BulkAction = {',
102
- ' displayName: string;',
103
- ' callback: (gridApi: GridApi) => void;',
104
- ' disabled?: boolean;',
105
- '};',
101
+ 'type MyAction = Table.BulkAction;',
102
+ '',
103
+ '// shape:',
104
+ '// {',
105
+ '// displayName: string;',
106
+ '// callback: (gridApi: GridApi) => void;',
107
+ '// disabled?: boolean;',
108
+ '// }',
106
109
  '```',
107
110
  '',
108
111
  '---',
@@ -115,7 +118,7 @@ const DEVELOPER_NOTES = [
115
118
  'prop to supply columns manually:',
116
119
  '',
117
120
  '```tsx',
118
- '<TableControls',
121
+ '<Table.TableControls',
119
122
  ' showHideColumns',
120
123
  ' hideColumnsProps={{',
121
124
  ' columns: myColumns,',
@@ -129,8 +132,10 @@ const DEVELOPER_NOTES = [
129
132
  '### TypeScript types',
130
133
  '',
131
134
  '```ts',
132
- "import { TableControls } from '@arbor-education/design-system.components';",
133
- "import type { TableControlsProps, BulkAction } from '@arbor-education/design-system.components';",
135
+ "import { Table } from '@arbor-education/design-system.components';",
136
+ '',
137
+ 'type MyControlsProps = Table.ControlsProps;',
138
+ 'type MyAction = Table.BulkAction;',
134
139
  '```',
135
140
  ].join('\n');
136
141
 
@@ -317,7 +322,7 @@ export const BulkActionsOnly: Story = withDescription(
317
322
  source: {
318
323
  language: 'tsx',
319
324
  code: `
320
- import { Table, TableControls } from '@arbor-education/design-system.components';
325
+ import { Table } from '@arbor-education/design-system.components';
321
326
 
322
327
  function MyTable() {
323
328
  return (
@@ -326,7 +331,7 @@ function MyTable() {
326
331
  columnDefs={colDefs}
327
332
  rowSelection={{ mode: 'multiRow', checkboxes: true }}
328
333
  headerContent={(
329
- <TableControls
334
+ <Table.TableControls
330
335
  bulkActions={[
331
336
  { displayName: 'Export selected', callback: api => api.exportDataAsCsv() },
332
337
  { displayName: 'Delete selected', callback: handleDelete, disabled: !canDelete },
@@ -355,7 +360,7 @@ export default MyTable;
355
360
  + 'Pass `disabled: true` to a specific action to grey it out (e.g. "Delete selected" when nothing is selected).',
356
361
  );
357
362
 
358
- export const FullToolbar: Story = withDescription(
363
+ export const MaximumStandaloneToolbar: Story = withDescription(
359
364
  {
360
365
  parameters: {
361
366
  controls: { disable: true },
@@ -363,7 +368,7 @@ export const FullToolbar: Story = withDescription(
363
368
  source: {
364
369
  language: 'tsx',
365
370
  code: `
366
- import { Table, TableControls } from '@arbor-education/design-system.components';
371
+ import { Table } from '@arbor-education/design-system.components';
367
372
 
368
373
  function FullTableExample() {
369
374
  return (
@@ -372,7 +377,7 @@ function FullTableExample() {
372
377
  columnDefs={colDefs}
373
378
  rowSelection={{ mode: 'multiRow', checkboxes: true }}
374
379
  headerContent={(
375
- <TableControls
380
+ <Table.TableControls
376
381
  bulkActions={[
377
382
  { displayName: 'Export selected', callback: api => api.exportDataAsCsv() },
378
383
  { displayName: 'Delete selected', callback: handleDelete },
@@ -408,8 +413,8 @@ export default FullTableExample;
408
413
  onExpandToggle: fn(),
409
414
  },
410
415
  },
411
- 'The full toolbar with both groups populated: bulk actions, undo, redo, hide columns, download, settings, help, and expand. '
412
- + 'This is the maximum control density — only include the slots your users actually need. '
413
- + '`showHideColumns` renders a `HideColumnsDropdown` that reads columns from `GridApiContext`; '
414
- + 'in this standalone preview it is disabled since there is no enclosing `<Table />` providing that context.',
416
+ 'Every standalone control except `showHideColumns`: bulk actions, undo, redo, download, settings, help, and expand. '
417
+ + '`showHideColumns` is left `false` here because `HideColumnsDropdown` needs a `GridApiContext` to read column data, '
418
+ + 'and that context is only provided by a real `<Table />` — it cannot be faked in this standalone preview. '
419
+ + 'See [Table](?path=/docs/components-table--docs) for a fully-wired example with `showHideColumns: true` inside an actual `<Table />`.',
415
420
  );