You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 80a01f0
Browse filesBrowse the repository at this point in the historyBrowse files
Sandboxes, MCP tools, and MCP servers each modeled their list rows and
detail headers differently. Collapse them — and the surfaces they drifted
from — onto one set of primitives.
SettingsResourceRow now owns the row entirely: tile, title/subtitle tokens,
padding and bleed, hover band, hit area, focus ring, and the one navigation
chevron. Adds onClick/href (a stretched overlay, so interactive trailing
controls keep their clicks), navigable, iconVariant='custom', and a badge
slot for decoration that must not swallow row clicks.
Rows that open a detail page get a chevron and a whole-row click; flat
records keep the "..." menu. Delete moves to the detail header as a
destructive chip behind a confirm modal — sandboxes previously deleted with
no confirmation at all.
Also folds in SettingsField (new), SettingsEmptyState tone='error',
RESOURCE_LIST_STACK/GRID, RESOURCE_TILE_PLAIN, and a shared MemberAvatar;
deletes DetailIconTile (byte-identical to ResourceTile); and standardizes
on the emcn ArrowRight, which is a visibly different glyph from lucide's.
or `<div className='py-4 text-center …'>`. It owns the `--text-muted` + `text-sm`
156
-
tokens, so it also keeps these messages consistent across pages.
212
+
muted status message, for empty lists, "no results", loading gates, **and
213
+
failed loads** (`tone='error'`). `variant='fill'` (default) centers in the
214
+
available height; `variant='inline'` sits in flow. Never hand-roll
215
+
`<div className='flex h-full items-center justify-center …'>` or
216
+
`<div className='py-4 text-center …'>`.
157
217
-**`RowActionsMenu`** (`…/components/row-actions-menu`) — the trailing `...`
158
218
actions menu for a list row. Pass `label` (aria-label) and
159
219
`actions: RowAction[]` (`{ label, onSelect, destructive?, disabled? }`); the
160
220
component renders the canonical flush `...` trigger + `DropdownMenuContent`.
161
221
Conditional items become array spreads: `...(canManage ? [{…}] : [])`. Never
162
222
hand-roll the `<DropdownMenu>` + `<MoreHorizontal>` trigger per page.
223
+
-**`RESOURCE_TILE_BASE`** + one of `RESOURCE_TILE_FILL` / `RESOURCE_TILE_PLAIN`
224
+
(`…/components/resource-tile`) — the 36px tile chrome, for the rare tile
225
+
outside a row (a detail heading). `ResourceTile` wraps the filled pairing.
226
+
-**`MemberAvatar`** (`@/components/permissions/member-avatar`) — the one avatar
227
+
for any member row.
228
+
229
+
## Deleting a resource
230
+
231
+
Delete lives in the **detail header**, as
232
+
`{ text: 'Delete', variant: 'destructive', onSelect: … }` behind a
233
+
`ChipConfirmModal` — never `textTone: 'error'`, never a bare `Chip`, and never
234
+
unconfirmed. A list row does not carry Delete when the resource has a detail page.
163
235
164
236
## Save / Discard + unsaved-changes guard
165
237
@@ -246,4 +318,9 @@ A settings page is design-system-clean when:
246
318
-[ ] If it has editable state: Save/Discard go through `SaveDiscardActions`, dirty is wired via `useSettingsUnsavedGuard` (called before any early-return gate), and there is **no** hand-rolled Save button / `beforeunload` / "Unsaved changes" modal.
247
319
-[ ] No business logic, handlers, or conditional rendering changed by the migration.
248
320
-[ ] No literal `text-[Npx]` classes — named scale tokens only (see "Text-scale tokens" above).
321
+
-[ ] Every **resource** list row (a thing with an identity — a tool, a server, a key, a credential) is a `SettingsResourceRow` in a `RESOURCE_LIST_STACK`/`RESOURCE_LIST_GRID` — no wrapper `<button>`/`<Link>`, no hand-passed arrow, no re-derived title/subtitle spans. Rows with a genuinely different shape stay bespoke: multi-line bodies (inbox tasks), tabular columns (billing invoices, credit usage), and grids (secrets).
322
+
-[ ] Rows that open a detail page use `navigable` + `clickLabel`; flat records use `RowActionsMenu`. Not both.
323
+
-[ ] Decorative trailing content is in `badge`, not `trailing`.
324
+
-[ ] Labeled sections use `SettingsSection`; read-only fields use `SettingsField`; empty/loading/error use `SettingsEmptyState`.
325
+
-[ ] Delete is a `destructive` header action behind a `ChipConfirmModal`.
0 commit comments