docs: add Step Library and Procedural Custom Steps design/plan docs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
175
docs/plans/2026-02-24-step-library-page-design.md
Normal file
175
docs/plans/2026-02-24-step-library-page-design.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# Step Library Page — Design
|
||||
|
||||
> **Date:** February 24, 2026
|
||||
> **Status:** Approved
|
||||
> **Phase:** 2.5 — Feature 1 of 3
|
||||
|
||||
---
|
||||
|
||||
## What We're Building
|
||||
|
||||
Replace the "Coming Soon" stub in `StepLibraryPage` with a fully functional standalone Step Library. Users can browse, search, create, edit, delete, preview, and save steps to their own library.
|
||||
|
||||
All backend endpoints and frontend components are already built. This is primarily a wiring and UX integration task.
|
||||
|
||||
---
|
||||
|
||||
## Scope
|
||||
|
||||
**In scope:**
|
||||
- Full-page Step Library with header, filters, grouped results
|
||||
- Create step flow (modal with `StepForm`)
|
||||
- Edit step flow (same modal, pre-filled)
|
||||
- Delete step with confirmation
|
||||
- "Save to My Library" for steps you don't own (copies step as private)
|
||||
- Preview via `StepDetailModal`
|
||||
- `StepCard` actions adapted for library context (vs. session insert context)
|
||||
|
||||
**Out of scope:**
|
||||
- Rating/reviewing steps from this page (deferred — will come when steps are used in sessions)
|
||||
- Admin category management (already exists in Admin Panel)
|
||||
- Session custom step insertion (Feature 2 of 3)
|
||||
|
||||
---
|
||||
|
||||
## Card Actions by Context
|
||||
|
||||
| Ownership | Actions |
|
||||
|-----------|---------|
|
||||
| Your own step | Preview · Edit · Delete |
|
||||
| Team or public step | Preview · Save to My Library |
|
||||
|
||||
"Save to My Library" POSTs a new step copying the title, step_type, content, category, and tags — with `visibility: 'private'` and the current user as owner.
|
||||
|
||||
---
|
||||
|
||||
## Page Layout
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Step Library [+ Create Step] │
|
||||
│ Reusable steps you can insert into any flow │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ [Search...] [Category ▼] [Type ▼] [Rating ▼] [Sort▼]│
|
||||
│ Popular Tags: [powershell] [dns] [quick-fix] ... │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ MY STEPS (3) [▲] │
|
||||
│ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ StepCard │ │ StepCard │ (Preview · Edit · Del) │
|
||||
│ └────────────┘ └────────────┘ │
|
||||
│ │
|
||||
│ TEAM STEPS (12) [▲] │
|
||||
│ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ StepCard │ │ StepCard │ (Preview · Save) │
|
||||
│ └────────────┘ └────────────┘ │
|
||||
│ │
|
||||
│ COMMUNITY (47) [▲] │
|
||||
│ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ StepCard │ │ StepCard │ (Preview · Save) │
|
||||
│ └────────────┘ └────────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Component Architecture
|
||||
|
||||
### StepLibraryPage (rewritten)
|
||||
- Owns modal state: `createOpen`, `editingStep`, `deletingStepId`
|
||||
- Renders page header with "+ Create Step" button
|
||||
- Renders `StepLibraryBrowser` with page-context props
|
||||
- Renders `StepFormModal` (create/edit)
|
||||
- Renders delete confirmation dialog
|
||||
|
||||
### StepLibraryBrowser (extend props)
|
||||
Add props:
|
||||
```ts
|
||||
interface StepLibraryBrowserProps {
|
||||
onInsert: (step: Step) => void // existing (used in session context)
|
||||
onEdit?: (step: Step) => void // new — library page only
|
||||
onDelete?: (stepId: string) => void // new — library page only
|
||||
onSave?: (step: Step) => void // new — save to my library
|
||||
onCreateNew?: () => void // existing
|
||||
showCreateButton?: boolean // existing
|
||||
currentUserId?: string // new — to determine ownership
|
||||
}
|
||||
```
|
||||
|
||||
### StepCard (extend props)
|
||||
Add props mirroring the browser:
|
||||
```ts
|
||||
interface StepCardProps {
|
||||
step: StepListItem
|
||||
onPreview: (step: StepListItem) => void
|
||||
onInsert?: (step: StepListItem) => void // optional — session context
|
||||
onEdit?: (step: StepListItem) => void // library context
|
||||
onDelete?: (stepId: string) => void // library context
|
||||
onSave?: (step: StepListItem) => void // library context
|
||||
currentUserId?: string
|
||||
}
|
||||
```
|
||||
|
||||
`StepCard` renders actions based on which callbacks are present and whether `step.created_by === currentUserId`.
|
||||
|
||||
### StepFormModal (new wrapper component)
|
||||
Thin modal shell around the existing `StepForm`:
|
||||
- Fixed header ("Create Step" or "Edit Step")
|
||||
- Scrollable body with `StepForm`
|
||||
- Handles create (`stepsApi.create`) and update (`stepsApi.update`) API calls
|
||||
- Calls `onSuccess(step)` so the browser list can refresh
|
||||
|
||||
---
|
||||
|
||||
## Data Flow
|
||||
|
||||
### Create
|
||||
1. User clicks "+ Create Step"
|
||||
2. `StepFormModal` opens in create mode
|
||||
3. On submit → `stepsApi.create(data)` → `onSuccess` → reload steps
|
||||
|
||||
### Edit
|
||||
1. User clicks Edit on their own step card
|
||||
2. `stepsApi.get(stepId)` fetches full step (need content fields)
|
||||
3. `StepFormModal` opens pre-filled with step data
|
||||
4. On submit → `stepsApi.update(id, data)` → `onSuccess` → reload steps
|
||||
|
||||
### Delete
|
||||
1. User clicks Delete on their own step card
|
||||
2. Confirmation dialog: "Delete '[title]'? This cannot be undone."
|
||||
3. On confirm → `stepsApi.delete(id)` → remove from local state
|
||||
|
||||
### Save to My Library
|
||||
1. User clicks "Save to My Library" on a team/public step
|
||||
2. No confirmation needed — silent copy
|
||||
3. `stepsApi.create({ ...step fields, visibility: 'private' })` → toast "Saved to My Steps"
|
||||
4. Reload steps so the copy appears under "My Steps"
|
||||
|
||||
---
|
||||
|
||||
## Files to Change
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `pages/StepLibraryPage.tsx` | Rewrite — wire up browser + modals |
|
||||
| `components/step-library/StepCard.tsx` | Add `onEdit`, `onDelete`, `onSave`, `currentUserId` props; render contextual buttons |
|
||||
| `components/step-library/StepLibraryBrowser.tsx` | Add `onEdit`, `onDelete`, `onSave`, `currentUserId` props; pass through to cards; expose refresh trigger |
|
||||
| `components/step-library/StepFormModal.tsx` | Create — thin modal wrapper around `StepForm` |
|
||||
|
||||
No backend changes required.
|
||||
|
||||
---
|
||||
|
||||
## StepCard Button Layout
|
||||
|
||||
**Own step:**
|
||||
```
|
||||
[Preview] [Edit] [🗑]
|
||||
```
|
||||
Edit and Preview are full-width-ish buttons; delete is an icon-only button in red on hover.
|
||||
|
||||
**Others' step:**
|
||||
```
|
||||
[Preview] [Save to My Library]
|
||||
```
|
||||
|
||||
Both full-width buttons, same pattern as current Insert layout.
|
||||
Reference in New Issue
Block a user