Add Sample Widget to Dashboard

Medium todo
2026-05-30 agentics feature Medium effort

Ship a reusable SampleWidget component that renders on the main dashboard, supports collapsed/expanded toggle, and persists its state across page refreshes via localStorage .

Implement Read and implement all steps in the plan at docs/plans/add-sample-widget.md — Add Sample Widget to Dashboard. Verify against the plan's Tests, Verification, and Acceptance Criteria before reporting done. If everything passed, mark completion in docs/plans/add-sample-widget.md — tick each step's [x] marker and each criterion's - [x], set status: completed — and re-render the HTML from the spec. If any check failed, leave status: in-progress and say which.
More ways to run this plan — goal & workflow prompts, file path
Pursue as goal — optimize for the outcome
Achieve this goal: Add Sample Widget to Dashboard. The plan at docs/plans/add-sample-widget.md describes one approach — use it as reference, but optimize for the outcome. Verify against the plan's Tests, Verification, and Acceptance Criteria before reporting done. If everything passed, mark completion in docs/plans/add-sample-widget.md — tick each step's [x] marker and each criterion's - [x], set status: completed — and re-render the HTML from the spec. If any check failed, leave status: in-progress and say which.
File add-sample-widget.html
Path docs/plans/add-sample-widget.html
Spec docs/plans/add-sample-widget.md
Definition of done 0 / 5 done

Context

The story behind this plan — what prompted the work and why it matters now.

The dashboard currently has no reusable widget pattern. Each panel is hand-rolled, making it hard to add, remove, or reorder sections. A SampleWidget establishes the canonical widget shape — toggle state, localStorage persistence, typed props — that all future dashboard panels will follow.

This plan is also a smoke-test artifact for the plan-agent v0.8.0 optimization: it verifies the skill writes a valid verb-target.html file directly without entering harness plan mode.

Steps

The step-by-step work, in order — each step says what to do, why it matters, and how to check it worked.

1
todo Create SampleWidget in src/components/widgets/SampleWidget.tsx
Why
A standalone file isolates the widget's state and markup from the dashboard layout, making it independently testable and reusable.
Verify
ls src/components/widgets/SampleWidget.tsx exits 0; npm run build passes with no new type errors.
2
todo Wire SampleWidget into DashboardPage and pass required props
Why
The dashboard is the entry point — wiring here ensures the widget renders inside the correct column layout and receives its data contract.
Verify
Run npm start , navigate to /dashboard , confirm the widget renders in the expected column with correct default state and no console errors.
3
todo Persist collapsed/expanded state to localStorage via a useLocalStorage hook
Why
Without persistence, a page refresh resets the widget — a friction point that erodes trust in dashboard customisation.
Verify
Expand/collapse the widget, then refresh the page — state survives. Confirm in DevTools: localStorage.getItem('widget-sample-expanded') returns the expected boolean string.
4
todo Write unit tests for SampleWidget covering default state, toggle behaviour, and persistence
Why
The localStorage side effect is easy to miss in a refactor; tests catch regressions before they reach production.
Verify
npm test -- --testPathPattern=SampleWidget passes; coverage report shows ≥80% for the component file.

Definition of done

The plan counts as done when every statement below is true — check each one off as you verify it.

Final check

One last pass to confirm the whole change works end to end.

Open a browser at http://localhost:3000/dashboard . Confirm the widget renders. Toggle it twice. Open DevTools → Application → Local Storage and confirm the key widget-sample-expanded exists with the correct value. Refresh — confirm state restores. Run npm run build && npm test in the terminal; both must exit 0 with no new failures.

Wrapping up

Three gates that must all pass before this plan is marked completed.

Required

Completion Report

No items to report — all requirements met.

Next steps

Follow-up ideas that came up along the way — none of them are required to finish this plan.

Add configurable title and body content via props

Paste this prompt into Claude to execute this follow-up:

In src/components/widgets/SampleWidget.tsx, add optional props `title: string` (default: "Sample Widget") and `children: React.ReactNode` so the widget title and body content are configurable at the call site. Update DashboardPage to pass a real title. Add a test for the custom title prop. Bump the component's JSDoc version comment.
Support drag-to-reorder widgets on the dashboard Wish List

Speculative / blue-sky idea — not on the critical path. Paste into Claude when ready to explore:

Paste this prompt into Claude to execute this follow-up:

Investigate adding drag-to-reorder support for dashboard widgets using the HTML5 Drag and Drop API or a library like @dnd-kit/core. The widget order should persist to localStorage keyed by user ID (or a session key if unauthenticated). Produce a spike plan covering: library choice, state shape for widget order, integration points with the existing SampleWidget pattern, and estimated effort. Do not implement yet — deliver a written recommendation only.