Pages
Teams & Users — Ideas v6

Source: qdash /teams — c67 state machine + component mapping, 2026-08-14

Two clarity moves. First, v5's four states become one template with a switcher — proof the page is a state machine with conditional sections, not four designs that happen to rhyme. Second, an honest audit of the composition against the layer: what maps to existing components, what qdash already wraps, and the three things that exist nowhere. A vocabulary fix rides along: assign is the act, mapped is the state, attributed is the money.

Machine

One template, four states

Everything below is a single markup tree driven by a state config — switch states and watch sections appear, collapse, and change rank. The switcher itself is the layer's UxTabGroup; in the product these states are derived from data, never chosen.

the working state — v4 corrected
Teams & UsersSpend, sensitive-data access, and risk per person — ranked by risk.
2 people and 4 identities need you — felix has an , sofia an , and $306/30d has no owner.
14people
+1 this week — chen
71%mapped
10 of 14 — 4 need assigning
$1,034attributed · 30d
of $1,340 — from /api/costs
2at risk
felix · sofia
3 of 14 people run on consumer keys — credential detail and risk live on /identity
PersonTeamRisk storyIdentityActivitySpend · 30d
f
felixalias
Data1 Critical — undecided egress · Sunconsumer key2 agents · 31m ago$70
s
sofia
Platform1 Elevated — secrets.yaml read · Friorg ✓2 agents · 2h ago$98
p
priya
Paymentsokorg ✓3 agents · 12m ago$169
c
chennew
okconsumer key1 agent · 19m ago$4
+ 10 more, all ok — show →$693
$306/30d unattributed — 4 identities · 3 have suggestions

Teams

Matrix

Section × state

The whole page in one table — what renders when, and what triggers each transition. This is the spec the teams.vue rewrite implements as conditionals.

SectionFirst runAll clearAttentionAt scale (~30+)
Verdict lineonboarding instruction"Nothing needs you"names the work + $counts + workspace link
Summary stripobserved/0%/spend/—all-green subsmapped % ambersame, bigger numbers
Credential notehiddenhidden (0 consumer keys)neutral, → /identityfolds into /identity link
Search + filtershiddenhidden < 30 peoplehidden < 30 peopleprimary, above roster
Rosterhidden — queue is the pagespend-sorted ledger, no story colrisk-sorted, story + identity colsexceptions only, story col, tail → search
Expand rowagents + contexts (v5 design)agents + contexts (v5 design)same
Workspaceexpanded hero + progressone quiet IdP lineband: assign here ▾ / open workspace →band: escalation only (queue > ~8)
Teamsempty statechips, no amberchips + unassigned chiptop 5 + unassigned, tail → Cost Center
transitions: first-run → attention when the first team exists · attention ↔ all-clear on (open stories + unmapped) reaching/leaving zero · scale rules switch on row count, not a separate state — they compose with either attention or all-clear
Vocabulary

One verb per concept

v5 mixed "map", "assign", and "attribute" freely. Fixed grammar, applied throughout the machine above — v5's "map here ▾" is now "assign here ▾".

assign
the act

A human puts an identity on a team. Buttons say it: "assign →", "assign here ▾", "Assign to Data". The only write verb on the page.

mapped
the state

An identity that has an owner. The coverage stat ("71% mapped"), the workspace queue ("needs assigning"), the IdP line ("100% mapped").

attributed
the money

Spend that landed on a mapped identity. The strip, the band ("$306 unattributed"), and Cost Center all use it — never "assigned spend".

"Map identities" survives as the workspace's title — it names the whole job (assigning at volume, merging aliases, archiving) — but every button inside it says what it does: assign, merge, archive.
Components

The composition against the pantry

Audited against the component registry (151 components) and qdash's locals. v5 hand-rolled nearly everything — only UxPageTitle and NavJumpPills were real. The good news: the table, chips, bars, and search all map cleanly. Three things exist nowhere.

ElementMaps toVerdictNotes
Page title + noteqdash PageHeader → UxPageTitleusePageHeader (qdash local) wraps UxPageTitle and adds the subtitle + #note slot the layer lacks. Promote to layer as-is.
Verdict line— nothing existsnewZero "verdict" hits in the layer. Build on UxLink for verbs. Shared need with c68 index landing — extract once, use twice.
Stat tilesqdash StatTile → DataMetric_BaseextendStatTile's sub-line is always muted; the machine needs toned subs (amber/green/red). Add subTone or a sub slot, then promote.
Merged caveatProseCallout (partial)extendProseCallout is left-border only, tones grape/grey/leaf. The caveat needs a boxed sunken variant; qdash attention/Strip is the chip-row cousin.
Roster table + expandDataTable (#details, search, sort)useAlready in the layer ("unifies qdash DataTable + PermissionTable"). Column search covers the scale state. Expand body is the redesigned agent list.
Risk-story cell— cell patternnewseverity + sentence + verb-link in one cell. Candidate for a #story column slot component; derivation fn lives beside userRollups.
Identity chipUxPill tone=greyuseNeutral per the v5 grammar. AgentAvatar/AgentInline cover the agent side in expand rows.
Filter chips (✕)UxTaguseUxTag has the remove affordance; qdash AgentFilterChip shows the routed variant. Wire to useUrlState.
Context chipsUxCodeuseMono chip bg, exactly the top_context treatment in the expand row.
Amber band— nothing existsnewHand-rolled 3× in v5 with identical classes. Strongest extraction on the page — but amber must enter the tone vocabulary first (UxPill stops at warn).
Team chip + share barUxPercentBar (partial)extendUxPercentBar renders fill behind a label — no standalone track. Add a bare track variant, or extract the chip whole (DataSurfacePanel covers the ranked-list cousin).
Onboarding progressUxPercentBar / DataPercentBaruseThe first-run "3 of 8 assigned" line is a compact UxPercentBar + caption.
Adoption deltasqdash Spark / DataMetricTrenduseFolded into stat subs and chip pills (v5 call) — Spark covers it if a trend cell ever returns.
State switcher (mock only)UxTabGroupuseUsed live in the machine above. Product derives state from data — the switcher never ships.
AvatarsUxAvataruseUsed live in the machine above (initials, small). pending prop covers SCIM-day invited rows later.
Extractions

What the layer gains — post-checkpoint

Ranked by reuse breadth. One prerequisite for all of them: amber enters the layer's tone vocabulary — today UxPill stops at warn, ProseCallout at grape/grey/leaf, and the attribution grammar has no token to stand on.

1
amber tone — the prerequisite — attribution-debt tone across pill/callout/band; today the vocabulary stops at warn
layer-wide
2
AttributionBand — dashed amber band — stake, count, actions; collapsed/hero/escalation variants per the matrix
teams · cost · overview
3
VerdictLine — segmented sentence (plain/strong/toned/link-verb) — the page's voice in every state
teams · c68 index
4
StatTile promotion — qdash StatTile → layer, with subTone; replaces the always-muted sub
every qdash page
5
PageHeader promotion — subtitle + #note slots UxPageTitle lacks
every qdash page
6
ShareChip — team chip with standalone track bar — or a bare-track UxPercentBar variant
teams · cost

Qpoint Brand Style Guide