KQ-1701 · TRIAL/RECAP

Trial Recap

The screen a workspace sees as its trial runs out: what the team did with it beside the plans. The first time it is seen, the days-left ring sweeps to its share on springs.drift while the day count rolls up, the recap's counts roll up on odometer wheels in cascade on springs.glide (each wheel turns only as the one below it rolls over), and the plan that fits the workspace's actual usage rises on glide as its reason chip stamps in on springs.recoil. The plans are a radiogroup with arrow keys and roving focus; the call to action rolls its monthly total on springs.snap, and an expired trial changes the copy and empties the ring.

KQ-1701 · TRIAL/RECAP
FieldlineTrial
Ends Oct 19

Seven days left in your trial

Here is what your team did with the first 7 days.

Day 8 of 14

Ends Oct 19. Nothing is charged until you choose.

Projects createdacross 4 teams
23
Teammates invited14 seats in use
13
Hours savedfrom automations
61

Choose a plan

7 days left · team fits 14 seats

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/trial-recap

Props

usage
TrialUsage
default defaultTrialUsage
What the workspace did: { projects, invited, seats, hoursSaved, teams? }.
plans
TrialPlan[]
default defaultTrialPlans
The plans offered: { id, name, price, seats, projects, blurb } with null for no limit.
now
number
default defaultTrialNow
The moment days are counted from, in ms; never the wall clock.
endsAt
number
default now + 7 days
When the trial ends, in ms; before now the trial reads as expired.
trialDays
number
default 14
How long the trial runs; the ring goes round once for it.
value / defaultValue
string
default — / the plan that fits
The chosen plan's id, controlled or initial.
onValueChange
(planId: string) => void
default —
Fires from the click or key that chose another plan.
onChoosePlan
(plan: TrialPlan, total: number) => void
default —
The call to action was pressed, with the plan and its monthly total for the workspace's seats.
onExtend
() => void
default —
Extend (or, once expired, Ask for more days) was pressed.
onTalk
() => void
default —
Talk to us was pressed.
recommend
(usage, plans) => { planId, reason } | null
default recommendTrialPlan
Picks the plan that fits and the reason it shows; by default the cheapest plan holding your seats and projects, explained by whichever ruled out the plan below.
extendDays
number
default 7
Days an extension asks for.
workspace
string
default "Fieldline"
The workspace's name in the header.
ringStyle
"solid" | "days" | "ticks"
default "solid"
The days-left ring: one round-capped arc, one segment per trial day, or a dial of fine ticks.
density
"compact" | "regular" | "roomy"
default "regular"
Padding, gaps, ring size (112, 136 or 156px) and the size of the numbers.
tone
"calm" | "urgent" | "quiet"
default "calm"
Voice and colour: calm cobalt ("Seven days left in your trial"), urgent amber ("Your trial ends in 7 days"), or quiet graphite ("Trial · 7 days left").
formatPrice
(amount: number) => string
default US dollars
Formats prices and the monthly total; cents only when there are some.
status
"ready" | "loading" | "error"
default "ready"
Whether the recap has arrived: an empty ring and breathing bars while loading, a retry on error.
onRetry
() => void
default —
Try again was pressed after the recap failed to load.
disabled
boolean
default false
Holds the plans and every action.
className
string
default —
Classes for the surface; give it a height and it scrolls inside itself.