@comet/agent-features 9.1.0-canary-20260709070153 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comet/agent-features",
3
- "version": "9.1.0-canary-20260709070153",
3
+ "version": "9.1.0",
4
4
  "description": "Agent features (skills and rules) for Comet projects",
5
5
  "repository": {
6
6
  "directory": "packages/agent-features",
@@ -226,3 +226,142 @@ hand-built format.
226
226
  <FormattedDate value={date} year="numeric" month="long" day="numeric" />;
227
227
  <FormattedTime value={date} />;
228
228
  ```
229
+
230
+ ## Layout
231
+
232
+ ### Arranging elements: `Stack` and `Grid`, not `Box` with margins
233
+
234
+ To arrange children and the space between them, use MUI's `Stack` (one-dimensional flow with a
235
+ `spacing` prop) and `Grid` (responsive columns with `spacing` and `size`), imported from
236
+ `@mui/material`. Both apply spacing from the theme through props, so you never hand-write the
237
+ gaps. Use `Box` with manual `margin` only when neither fits.
238
+
239
+ Pure layout — arranging children and the gaps between them — is fine inline through these props
240
+ and needs no `styled()`. Anything beyond that (padding inside an element, background, borders,
241
+ and other visual styling) goes through the theme and `styled()`, as in the styling section
242
+ above.
243
+
244
+ ```tsx
245
+ // Avoid — Box with hand-written margins between children
246
+ <Box>
247
+ <Widget />
248
+ <Box sx={{ marginTop: 16 }}>
249
+ <Widget />
250
+ </Box>
251
+ <Box sx={{ marginTop: 16 }}>
252
+ <Widget />
253
+ </Box>
254
+ </Box>;
255
+
256
+ // Prefer — Stack with spacing from the theme
257
+ <Stack spacing={4}>
258
+ <Widget />
259
+ <Widget />
260
+ <Widget />
261
+ </Stack>;
262
+ ```
263
+
264
+ ```tsx
265
+ // Avoid — manual flex and width math for a responsive two-column layout
266
+ <Box sx={{ display: "flex", flexWrap: "wrap" }}>
267
+ <Box sx={{ width: "50%" }}>
268
+ <Widget />
269
+ </Box>
270
+ <Box sx={{ width: "50%" }}>
271
+ <Widget />
272
+ </Box>
273
+ </Box>;
274
+
275
+ // Prefer — Grid with responsive size and spacing from the theme
276
+ <Grid container spacing={4}>
277
+ <Grid size={{ xs: 12, md: 6 }}>
278
+ <Widget />
279
+ </Grid>
280
+ <Grid size={{ xs: 12, md: 6 }}>
281
+ <Widget />
282
+ </Grid>
283
+ </Grid>;
284
+ ```
285
+
286
+ For responsive behaviour, pass a per-breakpoint object to these props (`size` on `Grid`,
287
+ `direction` on `Stack`); inside a `styled()` component, use `theme.breakpoints` for media
288
+ queries.
289
+
290
+ Don't use `Grid` or `Stack` to lay out form fields: Comet stacks them vertically at full width,
291
+ grouped with `FieldSet` or `FormSection`.
292
+
293
+ `sx` is fine for an occasional layout property that no `Stack` or `Grid` prop covers, such as
294
+ `flexGrow`. It is not for visual styling — that goes through `styled()`.
295
+
296
+ ### Page structure: `MainContent`, `Toolbar`, and their parts
297
+
298
+ Wrap a page's body in `MainContent` rather than a hand-padded `Box` — it applies the standard
299
+ page padding and can fill the height with `fullHeight`. Build the action bar from `Toolbar` and
300
+ its parts instead of assembling one from a flex row:
301
+
302
+ - `ToolbarTitleItem` holds the page title, `ToolbarActions` the action buttons; `ToolbarItem` is
303
+ the generic slot for anything else.
304
+ - `FillSpace` is a flexbox spacer that fills the free space, moving the elements after it to the
305
+ end.
306
+
307
+ ```tsx
308
+ // Avoid — hand-built toolbar and padded container
309
+ <Box sx={{ display: "flex", padding: 16 }}>
310
+ <Typography variant="h4">{title}</Typography>
311
+ <Box sx={{ marginLeft: "auto" }}>
312
+ <Button>{addLabel}</Button>
313
+ </Box>
314
+ </Box>;
315
+
316
+ // Prefer — Toolbar parts and MainContent
317
+ <Toolbar>
318
+ <ToolbarTitleItem>{title}</ToolbarTitleItem>
319
+ <FillSpace />
320
+ <ToolbarActions>
321
+ <Button>{addLabel}</Button>
322
+ </ToolbarActions>
323
+ </Toolbar>;
324
+ <MainContent>{children}</MainContent>;
325
+ ```
326
+
327
+ When a page is rendered inside a Comet navigation `Stack` (nested master–detail views), use the
328
+ `StackMainContent` and `StackToolbar` variants instead: they render only for the active stack
329
+ level, so nested pages don't show duplicate toolbars.
330
+
331
+ ### Full-height content: `fullHeight` and `FullHeightContent`
332
+
333
+ Content that should fill the viewport and scroll inside itself — most often a `DataGrid` — needs
334
+ a height-bounded parent, or it grows the whole page instead of scrolling. Set that height through
335
+ the page structure, not a hand-written `height` that has to track the header and toolbar offset:
336
+
337
+ - When the grid is the page's direct content, add `fullHeight` to `MainContent` or
338
+ `StackMainContent`.
339
+ - When the grid is nested inside `RouterTabs` or other content rather than placed directly in
340
+ `MainContent`, wrap it in `FullHeightContent`, which bounds the height at that level.
341
+ - When the grid holds few rows, give the `DataGrid` the `autoHeight` prop instead and skip
342
+ `fullHeight`.
343
+
344
+ ```tsx
345
+ // Avoid — a hand-set height that has to track the header and toolbar offset
346
+ <MainContent>
347
+ <Box sx={{ height: "calc(100vh - 200px)" }}>
348
+ <DataGrid />
349
+ </Box>
350
+ </MainContent>;
351
+
352
+ // Prefer — fullHeight for a grid that is the page's direct content
353
+ <StackMainContent fullHeight>
354
+ <DataGrid />
355
+ </StackMainContent>;
356
+
357
+ // Prefer — FullHeightContent for a grid nested inside tabs
358
+ <MainContent>
359
+ <RouterTabs>
360
+ <RouterTab path="" label={label}>
361
+ <FullHeightContent>
362
+ <DataGrid />
363
+ </FullHeightContent>
364
+ </RouterTab>
365
+ </RouterTabs>
366
+ </MainContent>;
367
+ ```