Business Affiliates Stories — Canary Refactoring Specification
Specification for refactoring the Business Affiliates use case stories
(src/use-cases/reference/business-affiliates/) to use canary components from
src/components/canary/. The existing stories use hand-rolled UI for grids,
drawers, dialogs, search, pagination, and column visibility. Canary equivalents
now exist for most of these, proven by the Items and General Behaviors stories.
The refactoring preserves the existing directory structure, use-case IDs (BA-0001 through BA-0005, BR-0002), sidebar titles, MSW handlers, and mock data. Each story is updated in place — not duplicated alongside a “(Canary)” variant.
Entry Conditions
Section titled “Entry Conditions”The following must be verified before implementation begins.
- Canary components available. All canary components referenced in the
Component Sourcing table are implemented and
rendering in the Storybook build on
main. - Existing checks green. Lint, TypeScript, Storybook build, and all unit tests pass on the working branch.
- Existing canary variants reviewed. The two proof-of-concept canary
stories already in the codebase
(
view-suppliers-list-canary.stories.tsxandsupplier-details-canary.stories.tsx) have been reviewed for patterns and lessons learned. These files are removed as part of this project since the primary stories will be refactored directly.
Component Sourcing
Section titled “Component Sourcing”Stories must follow a strict sourcing hierarchy:
- Canary components (
@/components/canary/) — preferred. - Story-local composition — hand-rolled markup within the story file for behaviors that have no canary equivalent.
- Vendored components (
@frontend/) — prohibited. All vendored imports in BA stories are replaced by canary equivalents.
Canary Coverage
Section titled “Canary Coverage”The following canary components replace hand-rolled BA equivalents:
| Hand-Rolled Component | Canary Replacement | Import Path |
|---|---|---|
SuppliersPage (grid, search, pagination, column toggle) |
createEntityDataGrid() factory |
@/components/canary/organisms/shared/entity-data-grid/create-entity-data-grid |
App shell: SidebarProvider + SidebarInset + AppSidebar |
Sidebar, SidebarHeader, SidebarNav, SidebarNavItem, SidebarUserMenu, AppHeader |
@/components/canary/organisms/sidebar/, molecules/sidebar/, organisms/app-header/, primitives/sidebar |
SupplierDrawer (view mode — read-only fields) |
Drawer + ArdaFieldList |
@/components/canary/atoms/drawer/, @/components/canary/molecules/field-list/ |
SupplierDrawer (create/edit mode — form shell) |
Drawer (DrawerHeader, DrawerBody, DrawerFooter) |
@/components/canary/atoms/drawer/ |
ArdaConfirmDialog (focus trap, escape, backdrop) |
AlertDialog primitive |
@/components/canary/primitives/alert-dialog |
ColumnVisibilityDropdown |
DropdownMenu primitive |
@/components/canary/primitives/dropdown-menu |
SelectAllHeaderComponent + SelectionCheckboxCell |
Built into createEntityDataGrid() row selection |
(included in entity-data-grid factory) |
Vendored Button |
Canary Button |
@/components/canary/atoms/button/button |
Vendored Collapsible / CollapsibleTrigger / CollapsibleContent |
Canary Collapsible primitive |
@/components/canary/primitives/collapsible |
Vendored ArdaGrid |
Canary DataGrid (via createEntityDataGrid) |
@/components/canary/molecules/data-grid/ |
| Custom search input (300ms debounce) | Built into createEntityDataGrid() search |
(included in entity-data-grid factory) |
| Custom pagination (prev/next buttons) | Built into createEntityDataGrid() pagination |
(included in entity-data-grid factory) |
| Selection-driven action bar | OverflowToolbar |
@/components/canary/molecules/overflow-toolbar/ |
Components That Remain Story-Local
Section titled “Components That Remain Story-Local”The following behaviors have no canary equivalent and remain hand-rolled within story files. They are not vendored imports — they are story-local composition using canary primitives and atoms.
| Behavior | Reason | Canary Atoms Used |
|---|---|---|
| Create form body (identity, contact, address, legal, notes fields) | No canary form component exists | Drawer shell, Button, Collapsible, HTML form elements |
| Edit form body (pre-populated fields, dirty tracking) | No canary form component exists | Drawer shell, Button, Collapsible, HTML form elements |
AffiliateTypeahead (lookup + create-on-the-fly) |
No canary standalone typeahead exists (only grid cell editor) | Button, HTML input/listbox. Wrapped in canary app shell for stories. |
| Role badge rendering in grid cells | Simple inline cell renderer; canary Badge can be used for styling |
Badge atom (optional) |
Deliverables per Story
Section titled “Deliverables per Story”Each refactored story produces an updated *.stories.tsx file. No new
directories or MDX files are created — the existing structure is
preserved.
Refactored stories must:
- Replace all vendored imports (
@frontend/) with canary equivalents. - Remove the hand-rolled
SuppliersPageand compose fromcreateEntityDataGrid()+ canary app shell. - Replace
SupplierDrawerview mode withDrawer+ArdaFieldList. - Replace
SupplierDrawercreate/edit mode shell with canaryDrawer(DrawerHeader/DrawerBody/DrawerFooter), keeping form body markup. - Replace
ArdaConfirmDialogwith canaryAlertDialogprimitive. - Preserve all existing
playfunctions, updating selectors as needed for the new DOM structure. - Preserve all existing story exports and sidebar titles.
Shared Module Changes (_shared/)
Section titled “Shared Module Changes (_shared/)”| File | Action |
|---|---|
suppliers-page.tsx |
Rewrite. Replace with a canary-composed page using createEntityDataGrid(), Sidebar, AppHeader. Export a SuppliersCanaryPage component. Existing column definitions move to inline factory config or a local column-defs.ts. |
supplier-drawer.tsx |
Rewrite. Replace with canary Drawer composition. View mode uses ArdaFieldList. Create/edit modes use DrawerBody with hand-rolled form markup. |
confirm-dialog.tsx |
Remove. Replace all usages with canary AlertDialog primitive. |
grid-cell-renderers.tsx |
Remove. SelectAllHeaderComponent and SelectionCheckboxCell are handled by createEntityDataGrid() row selection. Role badge renderer moves inline or uses canary Badge atom. |
column-defs.tsx |
Update. Adapt column definitions for createEntityDataGrid ColDef format. Remove references to custom cell renderers. |
suppliers-sidebar.tsx |
Remove. Replaced by canary Sidebar organism + molecules composed in the page wrapper. |
affiliate-typeahead.tsx |
Keep. No canary standalone typeahead exists. Minor updates: replace any vendored imports with canary atoms. |
mock-data.ts |
Keep. No changes needed. |
msw-handlers.ts |
Keep. No changes needed. |
types.ts |
Keep. No changes needed. |
story-step-delay.ts |
Keep. No changes needed. |
Proof-of-Concept Canary Variants
Section titled “Proof-of-Concept Canary Variants”The following files are removed after their patterns have been absorbed into the primary stories:
browse-and-search/view-suppliers-list-canary.stories.tsxview-details/supplier-details-canary.stories.tsx
Impact on Existing Stories
Section titled “Impact on Existing Stories”This is a refactoring project — every existing story is modified in place. The sidebar hierarchy, use-case IDs, and story export names are preserved. Visual output changes are expected (canary styling differs from vendored) but behavioral coverage must remain equivalent.
Verification per Story
Section titled “Verification per Story”After refactoring, each story must:
- Render without errors in Storybook.
- Pass its existing
playfunction (with selector updates as needed). - Maintain the same sidebar title and position.
- Demonstrate the same user-visible behavior as before.
Conventions
Section titled “Conventions”Composition Pattern
Section titled “Composition Pattern”All refactored stories follow the full-app context composition pattern established by the Items canary stories:
Sidebar (organism) ├── SidebarHeader (molecule) ├── SidebarNav (molecule) │ └── SidebarNavItem[] (molecule) └── SidebarUserMenu (molecule) content={ SidebarInset (primitive) ├── AppHeader (organism) ├── Main content area │ └── EntityDataGrid (from factory) └── Drawer (atom) ← detail/create/edit panel }Entity Data Grid Factory Usage
Section titled “Entity Data Grid Factory Usage”The createEntityDataGrid<SupplierEntity>() factory replaces the hand-rolled
SuppliersPage grid, search, pagination, and column visibility. Configuration:
displayName:'SupplierGrid'persistenceKeyPrefix:'ba-supplier-grid'columnDefs: adapted from existingcolumn-defs.tsxgetEntityId:(s) => s.id(maps tobusinessAffiliateEntityId)searchConfig.fields:['name', 'contact', 'email', 'city']- Row selection enabled for delete flows
onRowClickcallback for detail drawer
Drawer Composition
Section titled “Drawer Composition”View mode:
Drawer ├── DrawerHeader → supplier name + close button ├── DrawerBody → ArdaFieldList with supplier fields └── DrawerFooter → action buttons (Edit, Delete)Create/edit mode:
Drawer ├── DrawerHeader → mode title + close button ├── DrawerBody → hand-rolled form (Collapsible sections) └── DrawerFooter → Save/Cancel buttonsConfirm Dialog Replacement
Section titled “Confirm Dialog Replacement”The hand-rolled ArdaConfirmDialog is replaced by the canary AlertDialog
primitive, which provides equivalent functionality:
- Focus trap (built into Radix AlertDialog)
- Escape key dismissal
- Backdrop click dismissal (configurable)
AlertDialogAction(confirm) +AlertDialogCancel(cancel) buttons
Play Function Updates
Section titled “Play Function Updates”Existing play functions are preserved with minimal selector changes. Common
adjustments:
- Search input:
canvas.getByRole('searchbox')(entity-data-grid usesrole="searchbox") - Grid rows:
[role="gridcell"]selectors remain compatible - Drawer: use
screen.getAllByRole('dialog')for Radix portal-rendered content (same pattern as canary variant stories) - Confirm dialog:
screen.getByRole('alertdialog')for AlertDialog
Mock Strategy
Section titled “Mock Strategy”All stories continue to use mock data only via MSW handlers. The existing
_shared/msw-handlers.ts and _shared/mock-data.ts are unchanged. The
entity-data-grid factory receives data via props — MSW handlers are
used in stories that demonstrate server interaction (create, edit, delete).
Sidebar Title Convention
Section titled “Sidebar Title Convention”Existing sidebar titles are preserved exactly:
Use Cases/Reference/Business Affiliates/BA-0001 Browse and Search/{story}Use Cases/Reference/Business Affiliates/BA-0002 View Details/{story}Use Cases/Reference/Business Affiliates/BA-0003 Create Supplier/{story}Use Cases/Reference/Business Affiliates/BA-0004 Edit Supplier/{story}Use Cases/Reference/Business Affiliates/BA-0005 Delete Supplier/{story}Use Cases/Reference/Business Affiliates/BR-0002 Affiliate Typeahead/{story}Story Inventory
Section titled “Story Inventory”BA-0001 — Browse and Search
Section titled “BA-0001 — Browse and Search”Directory: browse-and-search/
The core SuppliersPage is replaced by createEntityDataGrid() + canary app
shell. Search, pagination, column visibility, and row selection are handled by
the factory.
| Story File | Sidebar Title | Refactoring Scope |
|---|---|---|
view-suppliers-list.stories.tsx |
0001 View Suppliers List | Replace SuppliersPage with canary page wrapper. Grid renders via createEntityDataGrid. Update play function selectors for entity-data-grid DOM. |
search-by-name.stories.tsx |
0002 Search by Name | Search is now built into entity-data-grid. Story demonstrates the same behavior via factory search config. Update play function to use role="searchbox". |
toggle-columns.stories.tsx |
0003 Toggle Columns | Column visibility handled by entity-data-grid or composed via DropdownMenu primitive. Update play function selectors. |
select-multiple.stories.tsx |
0005 Select Multiple | Row selection built into entity-data-grid. Selection toolbar composed with OverflowToolbar. Update play function for new selection UI. |
pagination.stories.tsx |
0006 Pagination | Pagination built into entity-data-grid. Story demonstrates the same page nav behavior. Update play function selectors. |
deep-link.stories.tsx |
0007 Deep Link | Deep-link behavior (auto-open drawer on load) must be preserved via onRowClick + initial selection logic in the page wrapper. |
Removed: view-suppliers-list-canary.stories.tsx (proof-of-concept
absorbed into primary story).
BA-0002 — View Details
Section titled “BA-0002 — View Details”Directory: view-details/
The SupplierDrawer in view mode is replaced by canary Drawer +
ArdaFieldList. The supplier field mapping function converts entity data to
FieldDef[].
| Story File | Sidebar Title | Refactoring Scope |
|---|---|---|
supplier-details-panel.stories.tsx |
0001 Supplier Details Panel (Default, MinimalData, CloseDrawer, SectionCollapse) | Replace SupplierDrawer view mode with Drawer + ArdaFieldList. Collapsible sections use canary Collapsible primitive. Multiple story exports preserved. Update play function for Radix portal selectors. |
Removed: supplier-details-canary.stories.tsx (proof-of-concept
absorbed into primary story).
BA-0003 — Create Supplier
Section titled “BA-0003 — Create Supplier”Directory: create-supplier/
The drawer shell is replaced by canary Drawer atoms. The multi-step form
body (identity, contact, address/legal, notes) remains hand-rolled inside
DrawerBody. The createUseCaseStories framework is preserved.
| Story File | Sidebar Title | Refactoring Scope |
|---|---|---|
happy-path.stories.tsx |
Happy Path (Interactive / Stepwise / Automated) | Replace drawer shell with canary Drawer. Form body stays hand-rolled inside DrawerBody. Replace vendored Button with canary. Framework stories preserved. Update play function selectors. |
validation-errors.stories.tsx |
0002 Validation Errors | Same drawer shell replacement. Error display markup may use canary styling. Update selectors. |
experimental-wizard.stories.tsx |
0003 [Experimental] Wizard | Same drawer shell replacement. Wizard step logic stays hand-rolled. Framework stories preserved. |
BA-0004 — Edit Supplier
Section titled “BA-0004 — Edit Supplier”Directory: edit-supplier/
The drawer transitions between view mode (ArdaFieldList) and edit mode
(hand-rolled form in DrawerBody). The createUseCaseStories framework is
preserved for the happy path.
| Story File | Sidebar Title | Refactoring Scope |
|---|---|---|
happy-path.stories.tsx |
Happy Path (Interactive / Stepwise / Automated) | View mode → canary Drawer + ArdaFieldList. Edit mode → canary Drawer shell + hand-rolled form. Mode toggle logic preserved. Framework stories preserved. Update play function selectors. |
validation-errors.stories.tsx |
0002 Validation Errors | Same pattern. Error display and cancel-discard behavior preserved. Update selectors. |
BA-0005 — Delete Supplier
Section titled “BA-0005 — Delete Supplier”Directory: delete-supplier/
The hand-rolled ArdaConfirmDialog is replaced by canary AlertDialog
primitive. The grid uses createEntityDataGrid() with row selection.
| Story File | Sidebar Title | Refactoring Scope |
|---|---|---|
delete-from-list.stories.tsx |
0001 Delete from List | Grid selection via entity-data-grid. Confirm dialog → canary AlertDialog. Selection toolbar via OverflowToolbar. Update play function for alertdialog role. |
delete-from-panel.stories.tsx |
0002 Delete from Detail Panel | Detail drawer via canary Drawer + ArdaFieldList. Delete button triggers AlertDialog. Update play function selectors. |
delete-error.stories.tsx |
0003 Delete Error | Same AlertDialog replacement. Server error handling (MSW 500 response) preserved. Update selectors. |
BR-0002 — Affiliate Typeahead
Section titled “BR-0002 — Affiliate Typeahead”Directory: affiliate-typeahead/
The AffiliateTypeahead component has no canary equivalent and stays
hand-rolled. The stories are updated to use the canary app shell and replace
any vendored atom imports.
| Story File | Sidebar Title | Refactoring Scope |
|---|---|---|
create-on-the-fly.stories.tsx |
0002 Create on the Fly (SelectExisting, CreateNew, LoadingState, EmptySearch, KeyboardNav, EscapeDismiss) | Replace vendored Button with canary. Wrap in canary app shell if not already. Typeahead component itself unchanged. Update play function selectors if atoms change. |
Pages (Support Stories)
Section titled “Pages (Support Stories)”Directory: pages/
| Story File | Sidebar Title | Refactoring Scope |
|---|---|---|
suppliers-list-view.stories.tsx |
Ignore/Pages/Suppliers List View | Composite story. Replace with canary-composed full page. This story combines browse, select, drawer, and delete in one view. Refactored to compose all canary replacements together. |
Story Count Summary
Section titled “Story Count Summary”| Use Case | Story Files | Stories Modified | Stories Removed |
|---|---|---|---|
| BA-0001 Browse and Search | 6 | 6 | 1 (canary variant) |
| BA-0002 View Details | 1 | 1 | 1 (canary variant) |
| BA-0003 Create Supplier | 3 | 3 | 0 |
| BA-0004 Edit Supplier | 2 | 2 | 0 |
| BA-0005 Delete Supplier | 3 | 3 | 0 |
| BR-0002 Affiliate Typeahead | 1 | 1 | 0 |
| Pages (support) | 1 | 1 | 0 |
| Total | 17 | 17 | 2 |
Plus shared module changes: 4 files rewritten, 2 files removed, 1 file updated, 4 files unchanged.
Directory Structure
Section titled “Directory Structure”The existing directory structure is preserved. Files marked with ❌ are removed; files marked with ✎ are modified.
src/use-cases/reference/business-affiliates/├── _shared/│ ├── affiliate-typeahead.tsx ✏ minor vendored import updates│ ├── column-defs.tsx ✏ adapt for createEntityDataGrid│ ├── confirm-dialog.tsx ✘ removed (replaced by AlertDialog)│ ├── grid-cell-renderers.tsx ✘ removed (handled by factory)│ ├── mock-data.ts (unchanged)│ ├── msw-handlers.ts (unchanged)│ ├── story-step-delay.ts (unchanged)│ ├── supplier-drawer.tsx ✏ rewrite: canary Drawer composition│ ├── suppliers-page.tsx ✏ rewrite: canary app shell + factory│ ├── suppliers-sidebar.tsx ✘ removed (replaced by Sidebar organism)│ └── types.ts (unchanged)├── affiliate-typeahead/│ ├── affiliate-typeahead.mdx (unchanged)│ └── create-on-the-fly.stories.tsx ✏ canary atom imports├── browse-and-search/│ ├── browse-and-search.mdx (unchanged)│ ├── deep-link.stories.tsx ✏ canary page wrapper│ ├── pagination.stories.tsx ✏ canary page wrapper│ ├── search-by-name.stories.tsx ✏ canary page wrapper│ ├── select-multiple.stories.tsx ✏ canary page wrapper + OverflowToolbar│ ├── toggle-columns.stories.tsx ✏ canary page wrapper + DropdownMenu│ ├── view-suppliers-list.stories.tsx ✏ canary page wrapper│ └── view-suppliers-list-canary.stories.tsx ✘ removed├── create-supplier/│ ├── create-supplier.mdx (unchanged)│ ├── experimental-wizard.stories.tsx ✏ canary Drawer shell│ ├── happy-path.stories.tsx ✏ canary Drawer shell│ └── validation-errors.stories.tsx ✏ canary Drawer shell├── delete-supplier/│ ├── delete-error.stories.tsx ✏ AlertDialog + canary page│ ├── delete-from-list.stories.tsx ✏ AlertDialog + canary page│ ├── delete-from-panel.stories.tsx ✏ AlertDialog + canary Drawer│ ├── delete-supplier.mdx (unchanged)│ ├── deletable-suppliers-page.tsx ✏ rewrite: canary composition│ └── panel-deletable-suppliers-page.tsx ✏ rewrite: canary composition├── edit-supplier/│ ├── editable-suppliers-page.tsx ✏ rewrite: canary composition│ ├── edit-supplier.mdx (unchanged)│ ├── happy-path.stories.tsx ✏ canary Drawer (view + edit modes)│ └── validation-errors.stories.tsx ✏ canary Drawer├── pages/│ ├── import-suppliers-modal.tsx ✏ canary Dialog if applicable│ └── suppliers-list-view.stories.tsx ✏ full canary rewrite├── view-details/│ ├── supplier-details-panel.stories.tsx ✏ canary Drawer + ArdaFieldList│ ├── supplier-details-canary.stories.tsx ✘ removed│ └── view-details.mdx (unchanged)├── business-affiliates.mdx (unchanged)├── mock-data.ts (unchanged)├── msw-handlers.ts (unchanged)└── types.ts (unchanged)Implementation Waves
Section titled “Implementation Waves”Stories are ordered by dependency: the shared module must be refactored first, then stories that depend only on the grid, then stories that also depend on the drawer, and finally stories that combine grid + drawer + dialog.
Wave 1 — Shared Module Refactoring
Section titled “Wave 1 — Shared Module Refactoring”Rewrite the shared components that all stories depend on.
Scope:
- Rewrite
_shared/suppliers-page.tsx→ canary app shell +createEntityDataGrid() - Rewrite
_shared/supplier-drawer.tsx→ canaryDrawercomposition (view/create/edit modes) - Update
_shared/column-defs.tsxfor entity-data-grid format - Remove
_shared/confirm-dialog.tsx,_shared/grid-cell-renderers.tsx,_shared/suppliers-sidebar.tsx - Update
_shared/affiliate-typeahead.tsxvendored imports
Gate: npm run lint, npx tsc --noEmit pass. No stories need to render
yet (they will be updated in subsequent waves).
Wave 2 — Browse and Search Stories (BA-0001)
Section titled “Wave 2 — Browse and Search Stories (BA-0001)”Refactor the grid-focused stories that depend on the shared page wrapper.
Scope:
- Refactor all 6 stories in
browse-and-search/ - Remove
view-suppliers-list-canary.stories.tsx - Update play functions for entity-data-grid selectors
Gate: Storybook builds. All BA-0001 stories render. All play functions pass.
Wave 3 — View Details and Edit Stories (BA-0002, BA-0004)
Section titled “Wave 3 — View Details and Edit Stories (BA-0002, BA-0004)”Refactor stories that depend on the drawer in view and edit modes.
Scope:
- Refactor
view-details/supplier-details-panel.stories.tsx - Remove
view-details/supplier-details-canary.stories.tsx - Refactor
edit-supplier/happy-path.stories.tsxandedit-supplier/validation-errors.stories.tsx - Refactor
edit-supplier/editable-suppliers-page.tsx
Gate: Storybook builds. All BA-0002 and BA-0004 stories render. All play functions pass.
Wave 4 — Create and Delete Stories (BA-0003, BA-0005)
Section titled “Wave 4 — Create and Delete Stories (BA-0003, BA-0005)”Refactor stories that use the drawer in create mode and the confirm dialog.
Scope:
- Refactor all 3 stories in
create-supplier/ - Refactor all 3 stories in
delete-supplier/+ wrapper pages - Refactor
pages/suppliers-list-view.stories.tsx - Refactor
pages/import-suppliers-modal.tsxif applicable
Gate: Storybook builds. All BA-0003, BA-0005, and Pages stories render. All play functions pass.
Wave 5 — Typeahead and Final Verification
Section titled “Wave 5 — Typeahead and Final Verification”Refactor the typeahead stories and perform final verification.
Scope:
- Refactor
affiliate-typeahead/create-on-the-fly.stories.tsx - Full regression: all BA stories render, all play functions pass
- VRT check: run VRT tests, evaluate visual diffs, retake baselines if acceptable
Gate: All checks pass: npm run lint, npx tsc --noEmit,
npm run build-storybook, npm run test, VRT tests.
Wave Gate Protocol
Section titled “Wave Gate Protocol”At the end of each wave:
- Dead code sweep. Verify no orphaned imports, unused exports, or unreferenced files remain from the refactoring. Remove any pre-existing dead code discovered during the wave.
npm run lintpasses (catches unused imports/variables).npx tsc --noEmitpasses (catches dangling references to removed files).npm run build-storybookcompletes without errors.- All unit tests pass (
npm run test). - All story
playfunctions in the wave scope pass in the Storybook test runner. - VRT check (Wave 5 only). Run VRT tests
(
npx playwright test --project=vrt). Evaluate visual diffs — canary styling differs from vendored, so diffs are expected. Retake baselines (./tools/generate-vrt-baselines.sh) for acceptable changes. - Changes are committed locally before proceeding to the next wave.
Component–Story Traceability
Section titled “Component–Story Traceability”| Canary Component | Stories That Use It |
|---|---|
createEntityDataGrid() |
All BA-0001 stories, BA-0005 (delete from list), Pages composite |
Sidebar + molecules |
All stories (app shell) |
AppHeader |
All stories (app shell) |
Drawer + atoms |
BA-0002 (view), BA-0003 (create), BA-0004 (edit), BA-0005 (delete from panel) |
ArdaFieldList |
BA-0002 (view mode), BA-0004 (view mode before edit) |
AlertDialog |
BA-0005 (all delete stories) |
OverflowToolbar |
BA-0001 select-multiple, BA-0005 delete-from-list |
DropdownMenu |
BA-0001 toggle-columns |
Button |
All stories |
Collapsible |
BA-0002 (section collapse), BA-0003/BA-0004 (form sections) |
Dead Code Removal
Section titled “Dead Code Removal”Each wave includes a dead code sweep. Code is considered dead if it is:
- Unreferenced — no import or usage anywhere in the BA story tree after refactoring.
- Superseded — replaced by a canary component (e.g., vendored imports that were the sole reason a utility existed).
- Pre-existing dead code — code that was already unused before the refactoring began.
Removal Targets
Section titled “Removal Targets”| Category | Examples | Wave |
|---|---|---|
| Deleted shared files | confirm-dialog.tsx, grid-cell-renderers.tsx, suppliers-sidebar.tsx |
Wave 1 |
| Deleted canary variant stories | view-suppliers-list-canary.stories.tsx, supplier-details-canary.stories.tsx |
Wave 2, Wave 3 |
| Orphaned imports and type aliases | Vendored component imports, unused type re-exports, stale interface fields | Each wave (during refactoring) |
| Unused helper functions | Functions in shared modules that lose all callers after refactoring | Each wave (during refactoring) |
| Duplicate files at root level | business-affiliates/mock-data.ts and business-affiliates/msw-handlers.ts (duplicates of _shared/ versions — verify and remove if unused) |
Wave 1 |
| Pre-existing dead code | Any unreferenced exports, unused variables, or commented-out blocks found during refactoring | Each wave (opportunistic) |
Verification
Section titled “Verification”After each wave, run npx tsc --noEmit to confirm no dangling references.
ESLint no-unused-vars and no-unused-imports rules catch orphaned imports.
If a removed file is still referenced, the TypeScript build will fail at the
wave gate.
Out of Scope
Section titled “Out of Scope”The following are explicitly excluded from this specification:
- New canary component creation. No new atoms, molecules, or organisms are created. Only existing canary components are used.
- Form component. No canary form field/layout components exist. Create and edit form bodies remain hand-rolled.
- Standalone typeahead component. The
AffiliateTypeaheadstays hand-rolled. A canary typeahead atom/molecule would be a separate project. - MDX documentation changes. Existing
.mdxfiles are not modified. - Mock data or MSW handler changes. Existing mocks are preserved as-is.
- New stories. No new story files are created. This is a refactoring of existing stories only.
- Use-case ID or directory restructuring. The existing hierarchy is preserved exactly.
Copyright: (c) Arda Systems 2025-2026, All rights reserved
Copyright: © Arda Systems 2025-2026, All rights reserved