@jobber/components 7.12.0 → 7.12.1

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.
Files changed (2) hide show
  1. package/dist/docs/Menu/Menu.md +151 -173
  2. package/package.json +2 -2
@@ -212,12 +212,13 @@ Minimum menu item height:
212
212
  [Combobox](../Combobox/Combobox.md)
213
213
 
214
214
 
215
- ## Composable Version (Web Only)
215
+ ## Composable Version
216
216
 
217
- The Menu may be invoked with a subcomponent structure enabling a declarative
218
- style, greater customization and composability with other components.
217
+ The composable API is the preferred way to build Menus. It supports a
218
+ declarative structure, richer customization, and adapts automatically between a
219
+ desktop dropdown and a small-screen bottom sheet.
219
220
 
220
- ```
221
+ ```tsx
221
222
  <Menu>
222
223
  <Menu.Trigger>
223
224
  <Button>Trigger</Button>
@@ -228,18 +229,10 @@ style, greater customization and composability with other components.
228
229
  <Menu.ItemIcon name="email" />
229
230
  </Menu.Item>
230
231
 
231
- <PrivacyMask>
232
- <Menu.Item onClick={clickHandler("sensitive")} textValue="Sensitive">
233
- <Menu.ItemLabel>Sensitive</Menu.ItemLabel>
234
- </Menu.Item>
235
- </PrivacyMask>
236
-
237
- <AuthCheck can="viewAdmin">
238
- <Menu.Item onClick={clickHandler("admin")} textValue="Admin">
239
- <Menu.ItemLabel>Admin</Menu.ItemLabel>
240
- <Menu.ItemIcon name="lock" />
241
- </Menu.Item>
242
- </AuthCheck>
232
+ <Menu.Item onClick={clickHandler("text")} textValue="Text message">
233
+ <Menu.ItemLabel>Text message</Menu.ItemLabel>
234
+ <Menu.ItemIcon name="sms" />
235
+ </Menu.Item>
243
236
  </Menu.Content>
244
237
  </Menu>
245
238
  ```
@@ -248,210 +241,195 @@ style, greater customization and composability with other components.
248
241
 
249
242
  ***Menu.Trigger (Required)***
250
243
 
251
- An interactive element that will cause the Menu to open when clicked or
252
- interacted with via keyboard. The open behavior is handled internally, and no
253
- `onClick` is required on the provided component. A provided `Button` is purely
254
- for appearance, however there is still a requirement that whatever is given to
255
- Menu.Trigger must be an element with an interactive role.
256
-
257
- Clicking the trigger again, or clicking anywhere outside the Menu at all will
258
- close the Menu.
259
-
260
- > **NOTICE:** To achieve a full-width Trigger, such as a Button please use UNSAFE\_style or
261
- > UNSAFE\_className to set the desired display. See example below.
244
+ An interactive element that opens the Menu when clicked, tapped, or activated
245
+ with the keyboard. `Menu.Trigger` handles opening and closing the Menu, so the
246
+ trigger content itself does not need its own `onClick` to open it.
262
247
 
263
- ```
264
- <Menu.Trigger UNSAFE_style={{ display: "block" }}>
265
- <Button fullWidth />
266
- </Menu.Trigger>
267
- ```
248
+ `Menu.Trigger` can render a default Atlantis trigger from simple content, accept
249
+ custom children such as a `Button` or `Chip`, or use a `render` prop when you
250
+ need full control over the trigger element. Whatever you provide must still be
251
+ interactive and accessible.
268
252
 
269
253
  ***Menu.Content (Required)***
270
254
 
271
- A structural container element for the Menu's content which should consist of
272
- one or more `Menu.Item`s, and optional additional content.
255
+ A structural container for menu content. It typically contains one or more
256
+ `Menu.Item`s and optional grouping or separation elements such as `Menu.Group`,
257
+ `Menu.GroupLabel`, and `Menu.Separator`.
258
+
259
+ Use `preferredPlacement` to influence desktop dropdown placement when needed.
273
260
 
274
261
  ***Menu.Item (Strongly recommended)***
275
262
 
276
- The interactive, main element of a Menu.
263
+ The primary interactive row in a Menu.
277
264
 
278
- Each item must be provided an `onClick`, or a `href`\*. Provide a `textValue`
279
- for accessibility and typeahead behavior.
265
+ Each item should provide an `onClick` or an `href`. Provide `textValue` when the
266
+ visible content is abbreviated, custom, or otherwise not ideal for type-ahead
267
+ matching.
280
268
 
281
- Menu Items support default subcomponents that plug into the Menu grid:
269
+ `Menu.Item` supports:
282
270
 
283
- * **Menu.ItemLabel**: Renders the action label within a Typography (span)
284
- component. You MUST supply either a string or a fragment/utility component
285
- that renders down to a raw string (e.g. translation helpers). Responds to the
286
- `destructive` variation Menu.Item prop.
287
- * **Menu.ItemIcon**: Renders a leading icon with consistent sizing and spacing.
288
- Responds to the `destructive` variation Menu.Item prop.
271
+ * `variation="destructive"` for destructive actions
272
+ * `closeOnClick` to control whether the Menu closes after selection
273
+ * `href`, `target`, and `rel` for link-style items
289
274
 
290
- These defaults are placed in a strict order and align automatically via the
291
- Menu's parent grid (see “Layout and spacing” below). Using them is the easiest
292
- way to get correct spacing and alignment.
275
+ Default item subcomponents plug into the shared menu row layout:
293
276
 
294
- If it is necessary to also adjust the *styles of the container*, `UNSAFE` props
295
- apply to the *container* element. No access is provided to internal markup due
296
- to accessibility and behavior requirements.
277
+ * `Menu.ItemLabel`: Renders the primary label text.
278
+ * `Menu.ItemIcon`: Renders a leading icon.
279
+ * `Menu.ItemPrefix`: Renders custom leading content.
280
+ * `Menu.ItemSuffix`: Renders custom trailing content.
297
281
 
298
- \*If being used for client side navigation such as TanStack Router, please
299
- consult with us first.
282
+ Use the built-in item pieces when possible. They align automatically across the
283
+ menu and respond to shared row styling such as destructive state.
300
284
 
301
- ***Menu.Section (Optional)***
285
+ If it is necessary to also adjust the *styles of the container*, style props
286
+ apply to the *container* element. No access is provided to internal markup due
287
+ to accessibility and behavior requirements.
302
288
 
303
- A structural/conceptual element to group your related Items together. Provides
304
- some default spacing that can be overriden with `UNSAFE`.
289
+ ***Menu.Group (Optional)***
305
290
 
306
- ***Menu.Header (Optional)***
291
+ A structural grouping element for related menu items. Use it to create scannable
292
+ sections or apply an `ariaLabel` to a related set of actions.
307
293
 
308
- A presentational element primarily used to describe a group/section.
294
+ ***Menu.GroupLabel (Optional)***
309
295
 
310
- For convenience it includes **Menu.HeaderLabel**, the default way to render
311
- header text with our standard menu heading typography.
296
+ A presentational label for a `Menu.Group`. Use it to describe the category of
297
+ actions in that group. Prefer `Menu.GroupLabel` over custom text styling so
298
+ group headings stay consistent across menus.
312
299
 
313
300
  ***Menu.Separator (Optional)***
314
301
 
315
- A presentational element primarily used to create visual separation between the
316
- groups. Can be used with sections, or with a "flat" Menu.
317
-
318
- Comes with a default appearance that can be overriden with `UNSAFE`.
302
+ A visual divider used to separate groups of items or distinct sections of
303
+ content.
319
304
 
320
- ### Layout and spacing (subgrid)
305
+ ***Menu.RadioGroup and Menu.RadioItem (Optional)***
321
306
 
322
- The Menu uses CSS Grid with `subgrid` on `Menu.Content` to control alignment
323
- across all rows. This allows us to reserve a leading column for icons only when
324
- **any item** includes an icon:
307
+ Use radio items for persistent single-select choices such as a view mode,
308
+ sorting option, or filter state.
325
309
 
326
- * If at least one `Menu.Item` uses `Menu.ItemIcon`, the grid creates and aligns
327
- a leading icon column for every item.
328
- * If no items include `Menu.ItemIcon`, the grid collapses that column and all
329
- labels move flush left.
310
+ Radio menus remain open by default after selection. Use `closeOnClick` on a
311
+ `Menu.RadioItem` if your experience should close after choosing an option.
330
312
 
331
- This behavior is why the order of the default subcomponents is predetermined and
332
- why mixing defaults with custom elements can produce unexpected results. This
333
- also means that the order of the provided default `Menu.ItemLabel` and
334
- `Menu.ItemIcon` in the JSX is incosequential. They will be placed where they
335
- belong irrespective of the order.
336
-
337
- ### Custom content (advanced)
338
-
339
- When you need full control over an item's inner content, do not use the default
340
- subcomponents. There are two recommended approaches depending on scope:
313
+ ```tsx
314
+ <Menu.RadioGroup defaultValue="list">
315
+ <Menu.RadioItem value="list" textValue="List view">
316
+ <Menu.ItemLabel>List view</Menu.ItemLabel>
317
+ </Menu.RadioItem>
318
+ <Menu.RadioItem value="board" textValue="Board view">
319
+ <Menu.ItemLabel>Board view</Menu.ItemLabel>
320
+ </Menu.RadioItem>
321
+ </Menu.RadioGroup>
322
+ ```
341
323
 
342
- 1. Per‑item custom layout (easiest)
324
+ ***Menu.Submenu, Menu.SubmenuTrigger, and Menu.SubmenuContent (Optional)***
343
325
 
344
- * Use a text component such as `Typography` directly instead of
345
- `Menu.ItemLabel`.
346
- * Use `Icon` directly instead of `Menu.ItemIcon` (e.g., to place an icon on the
347
- right).
348
- * Apply your layout to the item container using `UNSAFE_style` or
349
- `UNSAFE_className`. A simple, high‑success recipe is flex:
326
+ Use submenus when a related set of actions is better surfaced one level deeper.
327
+ On desktop, submenus open adjacent to the parent menu. On small screens, they
328
+ drill into a nested bottom-sheet view.
350
329
 
351
- ```
352
- <Menu.Item
353
- textValue="Email"
354
- UNSAFE_style={{
355
- display: 'flex',
356
- alignItems: 'center',
357
- justifyContent: 'space-between',
358
- gap: 'var(--space-small)'
359
- }}
360
- >
361
- <Typography element="span" fontWeight="semiBold">Email</Typography>
362
- <StatusIndicator status="critical" />
363
- </Menu.Item>
364
- ```
330
+ Provide a `textValue` on `Menu.SubmenuTrigger` when the submenu label should be
331
+ explicitly defined for typeahead behavior or the small-screen drill-down title.
365
332
 
366
- This breaks the item out of the subgrid layout and lets you arrange content as
367
- desired.
333
+ ### Deprecated wrappers
368
334
 
369
- 2. Whole‑menu custom layout (advanced)
335
+ Older Menu code may use `Menu.Section`, `Menu.Header`, and `Menu.HeaderLabel`.
336
+ These wrappers still work for backward compatibility, but new code should use
337
+ `Menu.Group` and `Menu.GroupLabel` instead:
370
338
 
371
- If every item is custom, override the grid on `Menu.Content` and provide your
372
- own columns. For example, a simple single‑column stack:
339
+ * `Menu.Group` replaces `Menu.Section` as the grouping container.
340
+ * `Menu.GroupLabel` replaces `Menu.Header` as the group heading.
341
+ * Do not use `Menu.HeaderLabel` in new code. Put the heading content directly
342
+ inside `Menu.GroupLabel`.
373
343
 
374
- ```
375
- <Menu.Content UNSAFE_style={{ display: 'grid', gridTemplateColumns: '1fr' }}>
376
- {/* all items use custom content; avoid Menu.ItemLabel/Menu.ItemIcon */}
377
- </Menu.Content>
344
+ ```tsx
345
+ <Menu.Group>
346
+ <Menu.GroupLabel>Sharing</Menu.GroupLabel>
347
+ <Menu.Item onClick={clickHandler("email")} textValue="Email">
348
+ <Menu.ItemLabel>Email</Menu.ItemLabel>
349
+ </Menu.Item>
350
+ </Menu.Group>
378
351
  ```
379
352
 
380
- Notes and caveats
353
+ ## Layout and spacing
381
354
 
382
- > **WARNING:** Avoid mixing default subcomponents with custom content within the same item or
383
- > even menu. The parent grid reserves space based on the presence of default
384
- > elements and can lead to unexpected spacing or alignment when combined with
385
- > custom layouts.
386
- >
387
- > Also remember the mobile bottom‑sheet presentation has different dimensions;
388
- > test custom layouts on small screens.
355
+ Composable menu rows use a shared grid/subgrid model so labels, icons, prefixes,
356
+ suffixes, radio indicators, and submenu chevrons align consistently across rows.
389
357
 
390
- ## Data Hierarchy Version
358
+ If at least one item uses a built-in leading slot such as `Menu.ItemIcon` or
359
+ `Menu.ItemPrefix`, the layout reserves leading space across the menu. If no
360
+ items use a built-in leading slot, the label column shifts flush left.
391
361
 
392
- ```
393
- <Menu
394
- items={[
395
- {
396
- actions: [
397
- {
398
- label: "Edit",
399
- icon: "edit",
400
- onClick: () => {
401
- alert("✏️");
402
- },
403
- },
404
- ],
405
- },
406
- {
407
- header: "Send as...",
408
- actions: [
409
- {
410
- label: "Text message",
411
- icon: "sms",
412
- onClick: () => {
413
- alert("📱");
414
- },
415
- },
416
- {
417
- label: "Email",
418
- icon: "email",
419
- onClick: () => {
420
- alert("📨");
421
- },
422
- },
423
- ],
424
- },
425
- ]}
426
- />
427
- ```
362
+ This is why built-in item slots are the easiest way to get correct alignment and
363
+ spacing.
364
+
365
+ ## Custom content (advanced)
428
366
 
429
- ### Component customization
367
+ Prefer the built-in Menu item pieces whenever possible. They provide the most
368
+ consistent alignment and behavior across menus.
430
369
 
431
- ### UNSAFE\_ props (advanced usage)
370
+ Custom item layouts are an escape hatch for exceptional cases, not a preferred
371
+ authoring pattern.
432
372
 
433
- General information for using `UNSAFE_` props can be found
434
- [here](../customizing-components/customizing-components.md).
373
+ > **WARNING:** Avoid mixing built-in slots with unrelated custom layout patterns unless you
374
+ > have tested carefully. The shared grid reserves space based on the presence of
375
+ > built-in slot content, which can lead to unexpected spacing or alignment. Also
376
+ > test custom layouts on small screens, where the Menu is presented in a bottom
377
+ > sheet.
435
378
 
436
- **Note**: Use of `UNSAFE_` props is **at your own risk** and should be
437
- considered a **last resort**. Future Menu updates may lead to unintended
438
- breakages.
379
+ ## Component customization
439
380
 
440
- Menu has multiple elements that can be targeted with classes or styles:
381
+ For the composable API, prefer `style` and `className` on the specific Menu
382
+ piece you are customizing.
441
383
 
442
- * `menu`: The actual menu element containing the actions
443
- * `header`: The container for each section
444
- * `action`: The container for each individual action
384
+ * Use `Menu.Trigger` to style the trigger wrapper.
385
+ * Use `Menu.Content` to control the menu panel.
386
+ * Use `Menu.Group`, `Menu.GroupLabel`, `Menu.Item`, and related subcomponents to
387
+ style individual structural pieces.
445
388
 
446
- #### UNSAFE\_className (web)
389
+ Deprecated `UNSAFE_*` props still exist for backward compatibility, but should
390
+ not be used in new code.
447
391
 
448
- Use `UNSAFE_className` to apply custom classes to the Menu. This can be useful
449
- for applying styles via CSS Modules.
392
+ ## Deprecated: `items` API
450
393
 
451
- #### UNSAFE\_style (web)
394
+ The `items` API still exists for backward compatibility, but it is deprecated
395
+ and should not be used for new implementations.
452
396
 
453
- The `UNSAFE_style` prop provides granular control over the Menu's appearance
454
- through inline styles.
397
+ ```tsx
398
+ <Menu
399
+ items={[
400
+ {
401
+ actions: [
402
+ {
403
+ label: "Edit",
404
+ icon: "edit",
405
+ onClick: () => {
406
+ alert("edit");
407
+ },
408
+ },
409
+ ],
410
+ },
411
+ {
412
+ header: "Send as...",
413
+ actions: [
414
+ {
415
+ label: "Text message",
416
+ icon: "sms",
417
+ onClick: () => {
418
+ alert("text");
419
+ },
420
+ },
421
+ {
422
+ label: "Email",
423
+ icon: "email",
424
+ onClick: () => {
425
+ alert("email");
426
+ },
427
+ },
428
+ ],
429
+ },
430
+ ]}
431
+ />
432
+ ```
455
433
 
456
434
 
457
435
  ## Props
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components",
3
- "version": "7.12.0",
3
+ "version": "7.12.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -583,5 +583,5 @@
583
583
  "> 1%",
584
584
  "IE 10"
585
585
  ],
586
- "gitHead": "a74a5ff8148ca6a6103aef333e6ed60caae37e6f"
586
+ "gitHead": "64b5115b33b7aa2a3a949a9ae7ad89575adbcb5a"
587
587
  }