Shows how far a workshop has travelled: Designed → Delivered → Synthesized.
When to Use
Use when:
Displaying a saved workshop's position across the Plan → Facilitate → Reflect journey — workshop cards, saved lists, record detail headers. Pass the status derived by getWorkshopRecord() or getWorkshopList().
Don't use when:
You mean the planner's manual doc-bar status (Draft / Ready / Live / Done) — that's a different concept with a different control. For a single state label use Badge via ws_status().
infoThe status is derived, never stored. Designed means a plan row exists; delivered means a completed coaching_sessions row or an ended live session; synthesized means a synthesis_sessions row. Never write a lifecycle value to the database, and never let a caller set it by hand — read it from the Workshop Record.
Variants
Compact (default)
For card footers and list rows. Completed steps fill with very-light red; pending steps stay outlined neutral. State is carried by fill and weight only — never a second hue, which is what keeps it inside Red Unification.
A plan exists. Step 1 complete, steps 2 and 3 pending.
delivered
The session ran — a completed coaching_sessions row with linked_plan_id, or an ended live session. Steps 1–2 complete.
synthesized
A synthesis_sessions row exists for the plan. All three complete.
Per-step
Steps carry .is-complete and .is-current. Complete steps show a check in the dot; the current step gets the weight emphasis.
Unknown status
Falls back to designed. Since the value is derived, an unexpected one means the derivation is wrong — fix it upstream.
No CTA
The full variant renders fine without one. The compact variant ignores cta entirely.
Real-World Usage
A saved-workshop card on MyWorkshopr. getWorkshopList() returns rows under the workshops key, each carrying lifecycle_status — pass it straight through rather than recomputing.
Q3 Planning Offsite
8 activities · 3h 20m
Designed
Delivered
Synthesized
<?php
$record = getWorkshopList($userId); // rows under the `workshops` key
foreach ($record['workshops'] as $w): ?>
<article class="workshop-card">
<h3><?= htmlspecialchars($w['title']) ?></h3>
<?= ws_lifecycle(['status' => $w['lifecycle_status']]) ?>
</article>
<?php endforeach; ?>
The same strip appears on MyWorkshopr, planner/saved.php, and the Synthesize picker — one component so a workshop's stage reads identically wherever it's seen.
Options
Option
Type
Default
Purpose
status
string
'designed'
designed | delivered | synthesized. Always pass a derived value.
variant
string
'compact'
compact | full. Only full emits a modifier class.
cta
array
null
['label' => …, 'href' => …]. Full variant only.
id
string
null
Element ID
class
string
''
Additional CSS classes
attrs
array
[]
Extra HTML attributes
Accessibility
Concern
Behavior
ARIA
Well handled. The strip carries role="img" with a composed aria-label, so a screen reader announces the state as one phrase instead of reading three disconnected dots and labels.
Structure
Steps are an ordered list, so the sequence is conveyed structurally as well as visually.
Colour independence
Completion is carried by a check mark inside the dot and by font weight, not by fill alone — it survives greyscale and colour-blindness. This is the pattern to copy elsewhere.
Keyboard
The compact variant has nothing focusable, which is right for a status display. In the full variant the CTA is a normal link.
CTA text
The label is the link's accessible name — "Synthesize this workshop" works out of context; "Continue" wouldn't.
Contrast
Completed steps pair --phase-learn-very-light with --phase-learn-dark; pending steps use --gray-300 on --bg-surface. Both tested.