Skip to content

moooon

Motir

Vibe your whole project. Bring an idea — Motir's three AI layers plan it, track it, and ship it, end to end. You're looking at Motir, built in Motir.

  • Vibe Project
  • Open Source
  • AI Agent
  • AI Loop
1
requests
0
upvotes
145
planned
1,361
shipped

Motir · Work items

MOTIR-2463Done

Design amendment — the delete-with-reassign dialog, the cap-reached refusal, the Members picker with custom roles, and the bulk-toggle question

The shipped roles asset already draws most of this story. design/projects/roles-permissions.mock.html + .png and their design-notes.md section ("Roles & permissions — the role list, a role's permissions, and creating one", MOTIR-2259's output) draw panel 3 — the create page at /settings/project/roles/new, its base picker, its ticked-and-greyed base grants, its pinned action bar and the new Checkbox — and panel 2's Edit / Delete / Based on … provenance chip. Do not redraw any of that. This card amends the same asset for the four things it does NOT draw, so no code card in this story has to improvise a surface.

The four amendments

  1. The delete-with-reassign dialog. Delete exists on panel 2 as a button and the flow behind it is undrawn. Draw it as a Modal — the grammar inherited from design/projects/details.mock.html (6.8.3), which this asset already copies in byte-identical and currently marks "inherited but no longer used"; that line changes with this card. It carries: the role name, how many members hold it (the reassign is only mandatory when that count is > 0), a required destination-role picker over the project's other roles, and a destructive confirm. The zero-members case is a plain confirm with no picker. Ground it in WorkflowEditor.tsx's shipped ReassignModal, which is the same flow one domain over.
  2. The cap-reached refusal on Create role. A project holds a bounded number of custom roles. Draw the list screen's Create role at the cap: disabled, with the explanation on it — the visible-but-disabled-with-a-tooltip treatment design-notes.md § Gating affordances (6.4.6) already prescribes for an in-place control, not a hidden button.
  3. The Members role picker with custom roles. design/projects/access-members.mock.html (6.4.1) draws the per-row role select over three built-ins. Amend THAT asset — it owns the role-chip grammar and this one composes it — to show the select with the project's custom roles listed beneath the built-ins, and a member's row wearing a custom role's chip. Reuse the existing tint slots: built-in --el-tint-lavender, custom --el-tint-sky, exactly as the roles asset already pairs them, with the kind also stated in words.
  4. The bulk-toggle question — decide it, then draw the answer. With 28 role-gated permissions under 15 domain headings, a domain heading could carry a grant-all / clear-all control; that affordance is what Jira's named permission bundles amount to on a catalog that is already grouped. The asset today draws no such control and deliberately keeps one grammar for one catalog. Decide it here on the evidence (does the mirror group-toggle? does a 28-row list at 15 headings actually need it?) and either draw it on the heading row with its indeterminate state, or record the rejection in the notes with its reason. Either answer is fine; the code card inventing one is not.

And one correction to the asset's own content — SUPERSEDED, and gone further (Yue, 2026-08-09). The card originally asked to re-cut the illustrative Reporter off a built-in, because panel 0 chained its provenance chip off the custom Contractor. The decision went past that: no base is recorded or drawn at all. Panel 2's Based on Viewer · +2 chip is removed, the Members picker's Custom · based on … line becomes Custom role, and the create page's Start from survives as a pure authoring SEED that is not stored. Provenance that never re-flows is a claim about how a role was once authored rather than a fact about what it is.

Scope boundary

In: the amendments above, inside the existing three-file sets (roles-permissions.mock.html + .png + its design-notes.md section; access-members.mock.html + .png + its section), with the PNG re-exported for every file whose markup changed and a dated revision note per amendment. Out: any re-draw of the create page, the role list or the role detail — they are drawn and shipped; the settings-nav gating rule, which is the permission-gated UI story's; and the product-wide --el-text-faint sweep, which is its own bug — this card only has to keep its own new markup inside the measured rules the asset already records.

Acceptance criteria

  • design/projects/roles-permissions.mock.html gains a panel drawing the delete-with-reassign dialog in both its states (members > 0, with the count and the required destination picker; members = 0, a plain confirm), composed from the inherited Modal block rather than a new one, and the notes' "inherited but no longer used" line is corrected.
  • The same file draws the Create role button at the cap, disabled with its explanation, and the notes state the treatment and cite § Gating affordances (6.4.6).
  • design/projects/access-members.mock.html draws the role select open with custom roles beneath the built-ins and a member row wearing a custom role's chip; both use the existing tint slots and state the kind in words.
  • The bulk grant-all / clear-all control is either drawn (on the domain heading, with its indeterminate state and an aria-label) or explicitly rejected in the notes with the evidence for the rejection — the notes say which, in a sentence a reader cannot mistake for an omission.
  • No asset draws a base. Panel 2 carries no Based on … chip, no role chains off another, the Members picker's custom options read Custom role, and the notes carry a § A role is its name and its set recording the decision, its reason, and its one behaviour consequence (a custom role grants exactly what it lists).
  • Every file whose markup changed has a re-exported same-basename .png, and every new element uses only --el-* element tokens and the shape tokens — no Tier-0 --color-*, no raw rounded-* / p-* / h-* outside the inherited token blocks — verified in both data-theme states.
  • Every new ink is checked against the asset's own measured contrast table: --el-text-faint carries no text WCAG measures, --el-text-muted only on --el-card, and the new containers take --el-card.
  • The notes name, per amendment, which card builds it — the dialog and the cap state are the list-and-detail card's, the picker is the Members card's — so the allocation is readable from the asset.

Context refs

  • design/projects/roles-permissions.mock.html · design/projects/roles-permissions.png — the asset being amended.
  • design/projects/design-notes.md — its section "Roles & permissions — the role list, a role's permissions, and creating one" (the panels, the pinned-bar trap, the measured contrast table, the primitives table), and § Gating affordances (6.4.6) for the disabled-with-tooltip rule.
  • design/projects/access-members.mock.html · .png — the Members surface and the role-chip grammar this composes.
  • design/projects/details.mock.html — the Modal grammar the dialog composes.
  • app/(authed)/settings/project/workflow/_components/WorkflowEditor.tsx — the shipped ReassignModal and its in-use count, the flow this mirrors.
  • The design card that produced the asset and the screens built to it.
  • lib/permissions/catalog.tspermissionsByDomain / PERMISSION_DOMAINS, the grouping any bulk toggle would sit on.