@botiverse/raft-ui 0.84.0 → 0.86.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.
Files changed (65) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/cn.d.mts +2 -0
  3. package/dist/cn.mjs +21 -1
  4. package/dist/components/alert-dialog/alert-dialog.mjs +2 -2
  5. package/dist/components/app-shell/app-shell.mjs +2 -2
  6. package/dist/components/avatar/avatar.mjs +1 -1
  7. package/dist/components/button/button-split.mjs +2 -2
  8. package/dist/components/button/button.mjs +2 -2
  9. package/dist/components/choice-list/choice-list.recipe.mjs +1 -1
  10. package/dist/components/code-block/code-block.recipe.mjs +2 -2
  11. package/dist/components/combobox/combobox.mjs +1 -1
  12. package/dist/components/combobox-select/combobox-select.css +1 -1
  13. package/dist/components/comment/comment.recipe.mjs +2 -2
  14. package/dist/components/composer/composer-attachment.recipe.mjs +5 -5
  15. package/dist/components/composer/composer-drop-overlay.mjs +2 -2
  16. package/dist/components/composer/composer-drop-overlay.recipe.mjs +1 -1
  17. package/dist/components/composer/sortable-composer-attachments.mjs +1 -1
  18. package/dist/components/context-menu/context-menu.mjs +1 -1
  19. package/dist/components/conversation-panel/conversation-panel-empty-state.mjs +1 -1
  20. package/dist/components/dialog/dialog.mjs +4 -4
  21. package/dist/components/drag/drag-lift.d.mts +3 -2
  22. package/dist/components/drag/drag-lift.mjs +3 -2
  23. package/dist/components/drag/drag.recipe.mjs +1 -1
  24. package/dist/components/drawer/drawer.recipe.mjs +4 -4
  25. package/dist/components/dropdown-menu/dropdown-menu.mjs +1 -1
  26. package/dist/components/file-preview/file-preview.recipe.mjs +1 -1
  27. package/dist/components/fit-toolbar/fit-toolbar.d.mts +78 -2
  28. package/dist/components/fit-toolbar/fit-toolbar.mjs +331 -14
  29. package/dist/components/fit-toolbar/fit-toolbar.recipe.mjs +30 -4
  30. package/dist/components/fit-toolbar/index.d.mts +2 -2
  31. package/dist/components/inbox-item/inbox-item.recipe.mjs +7 -7
  32. package/dist/components/lightbox/lightbox.d.mts +2 -2
  33. package/dist/components/lightbox/lightbox.mjs +7 -7
  34. package/dist/components/message-attachment/message-image-gallery.recipe.mjs +1 -1
  35. package/dist/components/message-item/message-item.recipe.mjs +2 -2
  36. package/dist/components/message-list/message-list.recipe.mjs +2 -2
  37. package/dist/components/mobile-nav/mobile-nav.mjs +2 -2
  38. package/dist/components/notification-center/notification-center.mjs +1 -1
  39. package/dist/components/panel/panel-header.recipe.mjs +1 -1
  40. package/dist/components/panel/panel-split-action.recipe.mjs +2 -2
  41. package/dist/components/popover/popover.mjs +1 -1
  42. package/dist/components/preview-card/preview-card.mjs +1 -1
  43. package/dist/components/pull-to-refresh/pull-to-refresh-indicator.mjs +1 -1
  44. package/dist/components/resizable/resizable.recipe.mjs +1 -1
  45. package/dist/components/scroll-area/scroll-area.css +1 -0
  46. package/dist/components/select/select.mjs +2 -2
  47. package/dist/components/selection-toolbar/selection-toolbar.d.mts +1 -1
  48. package/dist/components/selection-toolbar/selection-toolbar.recipe.mjs +1 -1
  49. package/dist/components/sidebar/sidebar.recipe.mjs +1 -1
  50. package/dist/components/tabs/tabs.mjs +4 -4
  51. package/dist/components/task-dnd/task-dnd.recipe.mjs +2 -2
  52. package/dist/components/thread-panel/thread-panel.recipe.mjs +1 -1
  53. package/dist/components/toast/toast.mjs +5 -5
  54. package/dist/components/tooltip/tooltip.mjs +2 -2
  55. package/dist/lib/list-cell.mjs +1 -1
  56. package/dist/lint/no-raw-z-index.mjs +142 -0
  57. package/dist/lint/prefer-scroll-area.mjs +1 -1
  58. package/dist/lint/recommended.json +2 -1
  59. package/dist/lint.d.mts +8 -2
  60. package/dist/lint.mjs +16 -3
  61. package/dist/styles.css +28 -0
  62. package/dist/wip.d.mts +2 -2
  63. package/dist/wip.mjs +2 -2
  64. package/package.json +1 -1
  65. package/skills/raft-ui-guide/SKILL.md +1 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,36 @@
1
+ ## [0.86.0](https://github.com/botiverse/raft-design/compare/v0.85.0...v0.86.0) (2026-11-10)
2
+
3
+ ### Added
4
+
5
+ - **FitToolbar follows the list-toolbar rule: one thing fills each line, at most two lines** ([The toolbar over a list](https://raft-design.botiverse.build/patterns/responsive/#the-toolbar-over-a-list)). New, all optional:
6
+ - `FitToolbarSearch`: the search field of a list's toolbar. It fills the rest of its line and keeps at least what its icon and its whole placeholder take (measured in the field's own font, again when fonts load or the placeholder changes; `minWidth` takes a number instead), so the toolbar's other steps come first. From `collapseOrder` on it is a search icon button at the line's start that opens the field in the scope's place, More and the primary action kept at the line's end. A search with text never collapses. Esc empties it, then closes an open field; Esc that ends an input method's composition is the IME's. `clearLabel` adds a clear button that empties it and keeps focus.
7
+ - `FitToolbarGroup` `moreOrder` and `moreItem`: a group of how-to-show controls (sort, grouping, view) moves into More together at that step, each as its `moreItem` (a view switch as a radio choice in the menu).
8
+ - `FitToolbarGroup` `end`: an item pinned at the end of a scrolling group (`overflow="scroll"`), such as a filter line's Clear all ×. Without `overflow="scroll"` it is not rendered, and development warns.
9
+ - `FitToolbarMore` and `FitToolbarMoreItems`: the More (⋯) button, shown only while something is in it, and the items it holds. Its label comes from the page, in the page's language ("More" by default, in English).
10
+ - Why: a list toolbar with nothing at the start of a line left its buttons hanging, and the search was the first thing squeezed out when a page narrowed (stdrc asked Jasper to decide from research, #proj-raft-ui:f9756e85; rule in #1158).
11
+ - Affects: nothing for an existing toolbar. Step names (`label`, `more`, `collapse`, `wrap`, `plus`) and their order are unchanged, and toolbars that use none of the new parts lay out as before. slock's Tasks, Members, Computers, Search and Apps move onto the new parts in their own PR (#proj-raft-ui:#230).
12
+ - Docs: https://raft-design.botiverse.build/components/fit-toolbar/
13
+
14
+ ## [0.85.0](https://github.com/botiverse/raft-design/compare/v0.84.0...v0.85.0) (2026-11-10)
15
+
16
+ ### Added
17
+
18
+ - **Named layers, `z-below` to `z-drag`, and the lint rule `raft-ui/no-raw-z-index`**: every z-index has a name and a place in one order ([Layer order](https://raft-design.botiverse.build/foundations/elevation/#layer-order)). The names are ordinary Tailwind `z-*` utilities from `--z-index-*` theme variables in `styles.css` (`@theme static`, so CSS can always read `var(--z-index-sticky)`): in the page `z-below` -1, `z-base` 0, `z-raised` 1, `z-control` 10, `z-sticky` 20, `z-float` 30, `z-chrome` 35, `z-cover` 40, `z-app` 45, `z-scrollbar` 49; overlays `z-popup` and `z-dialog` 50, `z-dialog-layer` 60, `z-lightbox` 70, `z-toast` 80, `z-drag` 999. They take every variant (`max-md:z-chrome`, `before:z-below`), and `cn` and the recipes merge them with a number an app passes (`z-popup` and `z-40` keep `z-40`). raft-ui's own components use them. The new rule reports a z class with a number or an arbitrary value (`z-10`, `-z-1`, `z-[60]`), a numeric `zIndex` in a style object, a `zIndex={n}` prop and `el.style.zIndex = n`; a number kept on purpose takes a `// raft-ui: z-index <reason>` comment on the line above. `z-index-named.test.ts` holds raft-ui's own code to the same rule, CSS included, with its kept exceptions listed.
19
+ - Why: slock alone writes 186 z-index values, and the same role has up to five numbers (sticky headers at 2, 10, 15, 20 and 30) while one number has up to seven roles; a share lightbox at 100 hides its own toast, and a badge menu at 1000 sits above the drag lift (#proj-raft-ui:#218, step 1, approved by Artea).
20
+ - Affects: nothing on the upgrade for an app that extends `recommended.json`: the rule is `"off"` in it for now, so an app that lints with `--max-warnings=0` (slock) stays green. It turns on there as `"error"` once slock has moved to the names (#218 step 2). An app can opt in early with `"raft-ui/no-raw-z-index": "warn"` or `"error"` in its own `rules`. Map each value with the table in Elevation: a local lift is `z-raised` inside an `isolate` root (there is no third local level: order a third part by DOM order); a popup, menu, dialog, lightbox, toast or drag copy takes raft-ui's component and no z-index of its own. Nothing may sit above the toasts (80) or the drag lift (999). slock's InlineBadgeEditor (1000) and SelectShareLightbox (100) are not exceptions: they move onto `Popover` and `z-lightbox` in step 2.
21
+ - Docs: https://raft-design.botiverse.build/foundations/elevation/#layer-order, https://raft-design.botiverse.build/about/use-raft-ui/#lint-rules
22
+
23
+ ### Changed
24
+
25
+ - **raft-ui's in-page layers take the scale's values**: where a component's z-index moved to a name with another number, it renders the same inside the component, but its number against an app's own layers changes. Overlays keep theirs (50, 60, 70, 80, 999).
26
+ - Raised parts 10 → 1 (`z-raised`): Button's and Toast's label and loading indicator, Avatar's badge, InboxItem's lead, badge, selection, text, trail and corner (its trigger is `z-base`, 0), ChoiceList's control column, Comment's cover and active comment, CodeBlock's actions, ComposerAttachment's veils, FilePreview's corner badge, MessageImageGallery's "+N" veil, MessageItem's trailing meta, MobileNav's icons, Select's scroll arrows, Tabs' tab content and drop placeholder, Tooltip's kbd, Lightbox's arrows, info dock and counter, ConversationPanelEmptyState's illustration. 20 → 1: CodeBlock's corners, ComposerAttachment's progress bar (over the veil by DOM order), ComposerDropOverlay's second icon (and its first, 10 → 1), Lightbox's close, a dragged TaskDraggable. MessageList's end fade 5 → 1.
27
+ - Up: MessageList's jump controls and SelectionToolbar 10 → 30 (`z-float`), the pull-to-refresh indicator 10 → 20 (`z-sticky`), PanelHeader's sticky phone header 30 → 35 (`z-chrome`), ThreadPanel's header 20 → 35 (inside the panel's `isolate`), AppShellOverlaySlot 20 → 40 (`z-cover`).
28
+ - Down: MessageItem's hover toolbar 20 → 10 and ComposerAttachment's remove button 20 → 10 (`z-control`), the composer attachment row's arrows 30 → 10 (outside the row's ScrollArea, so still over it). The sidebar header mask -10 → -1 (`z-below`).
29
+ - Isolation: a tab is now `isolate` instead of `z-10`, and a dragged tab is lifted by `var(--z-index-raised)` instead of 20, all inside the tab list's `isolate`. TaskDraggable is `isolate`, so a card's own parts rank only inside the card, and a dragged card at `z-raised` is above every other card.
30
+ - Why: the scale has one number per role; the old numbers made the same role differ between components and forced slock to workarounds (a day heading at `z-15`, an `isolate` around the artifacts dashboard, `max-md:z-40` beside the phone header) (#proj-raft-ui:#218).
31
+ - Affects: an app layer that sat between the old and the new number of a raft-ui layer it overlaps. In slock, move these in the same upgrade: a cover at `z-30` beside a PanelHeader (MainLayout, ProfilePanel, ChannelSideArea, LegacyTaskPanel, TaskConversationDialog, `index.css`) to `z-cover`, or the header, now 35, is drawn over it; the typing line (`z-6`) to `z-float`, so it stays over the end fade and beside the jump pills; a hit target at `z-10` in a message (MessageItem) to `z-raised`, so the hover toolbar, now 10, stays above it; ThreadsInbox's day heading (`z-15`) and "new" pill (`z-20`) to `z-sticky` and `z-float`, which InboxItem's parts at 1 now allow.
32
+ - Docs: https://raft-design.botiverse.build/foundations/elevation/#in-page-layers
33
+
1
34
  ## [0.84.0](https://github.com/botiverse/raft-design/compare/v0.83.0...v0.84.0) (2026-11-10)
2
35
 
3
36
  ### Added
package/dist/cn.d.mts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { ClassValue } from "cnfast";
2
2
  //#region src/lib/cn.d.ts
3
+ /** The `--z-index-*` names of styles.css, in order (design/foundations/elevation.md#layer-order). */
4
+ export declare const Z_INDEX_NAMES: string[];
3
5
  export declare function cn(...inputs: ClassValue[]): string;
4
6
  //#endregion
5
7
  export type { ClassValue };
package/dist/cn.mjs CHANGED
@@ -1,6 +1,25 @@
1
1
  import { clsx } from "cnfast";
2
2
  import { extendTailwindMerge } from "tailwind-merge";
3
3
  //#region src/lib/cn.ts
4
+ /** The `--z-index-*` names of styles.css, in order (design/foundations/elevation.md#layer-order). */
5
+ const Z_INDEX_NAMES = [
6
+ "below",
7
+ "base",
8
+ "raised",
9
+ "control",
10
+ "sticky",
11
+ "float",
12
+ "chrome",
13
+ "cover",
14
+ "app",
15
+ "scrollbar",
16
+ "popup",
17
+ "dialog",
18
+ "dialog-layer",
19
+ "lightbox",
20
+ "toast",
21
+ "drag"
22
+ ];
4
23
  const twMerge = extendTailwindMerge({ extend: {
5
24
  theme: { spacing: [
6
25
  "control",
@@ -59,6 +78,7 @@ const twMerge = extendTailwindMerge({ extend: {
59
78
  "x"
60
79
  ] }],
61
80
  opacity: [{ opacity: ["dimmed"] }],
81
+ z: [{ z: Z_INDEX_NAMES }],
62
82
  "bg-image": [{ overlay: [
63
83
  "subtle",
64
84
  "medium",
@@ -71,4 +91,4 @@ function cn(...inputs) {
71
91
  return twMerge(clsx(inputs));
72
92
  }
73
93
  //#endregion
74
- export { cn };
94
+ export { Z_INDEX_NAMES, cn };
@@ -13,9 +13,9 @@ import { jsx, jsxs } from "react/jsx-runtime";
13
13
  //#region src/components/alert-dialog/alert-dialog.tsx
14
14
  const alertDialog = tv({
15
15
  slots: {
16
- overlay: ["fixed inset-0 z-50 bg-layer-backdrop"],
16
+ overlay: ["fixed inset-0 z-dialog bg-layer-backdrop"],
17
17
  content: [
18
- "fixed top-1/2 left-1/2 z-50 grid w-[calc(100%-2rem)] -translate-1/2 outline-none",
18
+ "fixed top-1/2 left-1/2 z-dialog grid w-[calc(100%-2rem)] -translate-1/2 outline-none",
19
19
  decisionWidth,
20
20
  "overflow-clip rounded-dialog bg-layer-popover text-foreground",
21
21
  "shadow-float ring-1 ring-line-seam"
@@ -19,7 +19,7 @@ const appShell = tv({
19
19
  sidebarSlot: ["hidden min-h-0 shrink-0 flex-col md:flex"],
20
20
  mainSlot: ["flex min-h-0 min-w-0 flex-1 flex-col"],
21
21
  panelSlot: ["hidden min-h-0 min-w-0 flex-col md:flex"],
22
- overlaySlot: ["absolute inset-0 z-20 flex min-h-0 min-w-0"]
22
+ overlaySlot: ["absolute inset-0 z-cover flex min-h-0 min-w-0"]
23
23
  },
24
24
  variants: { overlay: {
25
25
  false: {},
@@ -135,7 +135,7 @@ function AppShellSidebarSlot({ className, id: idProp, render, ...props }) {
135
135
  id,
136
136
  inert: collapsed ? true : void 0,
137
137
  className: sidebarSlot({ className: cn(className, sidebar?.collapsible && [
138
- "group-data-[state=expanded]/app-shell:relative group-data-[state=expanded]/app-shell:z-1",
138
+ "group-data-[state=expanded]/app-shell:relative group-data-[state=expanded]/app-shell:z-raised",
139
139
  "group-data-[state=collapsed]/app-shell:pointer-events-none",
140
140
  "group-data-[state=collapsed]/app-shell:opacity-0"
141
141
  ]) })
@@ -37,7 +37,7 @@ const avatar = tv({
37
37
  "[[data-size='3xs']>&]:[&>svg]:size-2"
38
38
  ],
39
39
  badge: [
40
- "absolute z-10 select-none",
40
+ "absolute z-raised select-none",
41
41
  "size-[11px] -right-1 -bottom-1 rounded-[2px]",
42
42
  "outline-2 outline-solid outline-layer-canvas",
43
43
  "group-data-[size=xl]/avatar:size-5 group-data-[size=xl]/avatar:-right-2 group-data-[size=xl]/avatar:-bottom-2",
@@ -10,11 +10,11 @@ const buttonSplit = tv({ base: [
10
10
  "data-sticker-edge:ring-[1.5px]",
11
11
  "data-[size=lg]:rounded-(--control-radius)"
12
12
  ] });
13
- const buttonSplitMain = tv({ base: ["rounded-e-none border-e-0", "ring-0 focus-visible:z-1"] });
13
+ const buttonSplitMain = tv({ base: ["rounded-e-none border-e-0", "ring-0 focus-visible:z-raised"] });
14
14
  const buttonSplitMenu = tv({
15
15
  base: [
16
16
  "min-w-0 rounded-s-none px-0",
17
- "ring-0 focus-visible:z-1",
17
+ "ring-0 focus-visible:z-raised",
18
18
  "after:inset-s-0"
19
19
  ],
20
20
  variants: {
@@ -38,8 +38,8 @@ const buttonVariants = tv({
38
38
  "disabled:border-line-hairline disabled:bg-fill-muted disabled:bg-none disabled:text-foreground-disabled disabled:ring-0",
39
39
  "aria-disabled:border-line-hairline aria-disabled:bg-fill-muted aria-disabled:bg-none aria-disabled:text-foreground-disabled aria-disabled:ring-0"
40
40
  ],
41
- content: "relative z-10 inline-flex min-w-0 max-w-full items-center justify-center gap-[inherit] data-[loading=true]:invisible",
42
- loadingIndicator: "pointer-events-none absolute inset-0 z-10 flex items-center justify-center"
41
+ content: "relative z-raised inline-flex min-w-0 max-w-full items-center justify-center gap-[inherit] data-[loading=true]:invisible",
42
+ loadingIndicator: "pointer-events-none absolute inset-0 z-raised flex items-center justify-center"
43
43
  },
44
44
  variants: {
45
45
  variant: {
@@ -24,7 +24,7 @@ const choiceList = tv({
24
24
  description: ["block truncate font-sans text-footnote font-normal text-foreground-muted", "in-data-disabled:text-foreground-disabled"],
25
25
  meta: ["block truncate font-sans text-footnote font-normal text-foreground-muted", "in-data-disabled:text-foreground-disabled"],
26
26
  action: [
27
- "relative z-10 col-start-2 flex h-lh items-center self-start pr-1",
27
+ "relative z-raised col-start-2 flex h-lh items-center self-start pr-1",
28
28
  "mt-option-inset pointer-coarse:mt-[calc((--spacing(11)-1lh)/2)]",
29
29
  "font-sans text-subhead"
30
30
  ],
@@ -16,11 +16,11 @@ const codeBlock = tv({ slots: {
16
16
  actions: [
17
17
  "ml-auto flex items-center gap-1",
18
18
  "[[data-slot=code-block-body]>&]:col-start-2 [[data-slot=code-block-body]>&]:row-start-1",
19
- "[[data-slot=code-block-body]>&]:z-10 [[data-slot=code-block-body]>&]:ml-3",
19
+ "[[data-slot=code-block-body]>&]:z-raised [[data-slot=code-block-body]>&]:ml-3",
20
20
  "[[data-slot=code-block-body]>&]:my-[calc(var(--control-embedded-inset)-0.5rem-1px)] [[data-slot=code-block-body]>&]:mr-[calc(var(--control-embedded-inset)-0.75rem-1px)]"
21
21
  ],
22
22
  corner: [
23
- "pointer-events-none absolute z-20 size-1",
23
+ "pointer-events-none absolute z-raised size-1",
24
24
  "data-[y=top]:top-0 data-[y=bottom]:bottom-0",
25
25
  "data-[x=left]:left-0 data-[x=right]:right-0",
26
26
  "hidden"
@@ -60,7 +60,7 @@ const combobox = tv({
60
60
  "first:rounded-t-container has-focus-visible:keyboard:inset-ring-2 has-focus-visible:keyboard:inset-ring-foreground"
61
61
  ],
62
62
  input: ["w-full outline-none"],
63
- positioner: ["isolate z-50 outline-none"],
63
+ positioner: ["isolate z-popup outline-none"],
64
64
  content: [
65
65
  "h-auto max-h-(--available-height) min-w-[220px] overflow-hidden",
66
66
  "max-w-[min(var(--available-width),max(var(--anchor-width),24rem))]",
@@ -161,7 +161,7 @@
161
161
  box-shadow: inset 0 0 0 2px var(--foreground);
162
162
  }
163
163
  .r-combobox-select__positioner {
164
- z-index: 50;
164
+ z-index: var(--z-index-popup);
165
165
  isolation: isolate;
166
166
  outline: 0;
167
167
  }
@@ -7,7 +7,7 @@ const comment = tv({
7
7
  "absolute inset-x-0 top-0",
8
8
  "data-animate:transition-transform data-animate:duration-150 data-animate:ease-out",
9
9
  "motion-reduce:transition-none",
10
- "data-active:z-10"
10
+ "data-active:z-raised"
11
11
  ],
12
12
  card: [
13
13
  "relative flex min-w-0 flex-col gap-2",
@@ -16,7 +16,7 @@ const comment = tv({
16
16
  "data-active:border-[1.5px] data-active:border-line-strong data-active:p-[11.5px] data-active:shadow-float"
17
17
  ],
18
18
  cardTrigger: [
19
- "absolute -inset-px z-10 cursor-pointer",
19
+ "absolute -inset-px z-raised cursor-pointer",
20
20
  "rounded-container border-0 bg-transparent p-0",
21
21
  "hover:bg-fill-subtle active:bg-fill-medium",
22
22
  "outline-none focus-visible:shadow-focus"
@@ -20,7 +20,7 @@ const composerAttachment = tv({
20
20
  "pe-1.5"
21
21
  ],
22
22
  attachmentsNav: [
23
- "absolute top-1/2 z-30 -translate-y-1/2",
23
+ "absolute top-1/2 z-control -translate-y-1/2",
24
24
  "size-8 rounded-chip shadow-none",
25
25
  "[&_svg:not([class*='size-'])]:size-4.5"
26
26
  ],
@@ -42,26 +42,26 @@ const composerAttachment = tv({
42
42
  attachmentTitle: ["block truncate", "font-sans text-footnote font-semibold text-foreground"],
43
43
  attachmentMeta: ["block w-full truncate", "text-left font-mono text-mono-meta text-foreground-hint"],
44
44
  attachmentUploadingOverlay: [
45
- "absolute inset-0 z-10 flex flex-col items-center justify-center px-1",
45
+ "absolute inset-0 z-raised flex flex-col items-center justify-center px-1",
46
46
  "text-center",
47
47
  "rounded-control bg-layer-veil",
48
48
  "font-mono text-mono-meta font-bold text-foreground"
49
49
  ],
50
50
  attachmentUploadProgressBar: [
51
- "absolute z-20 h-1 overflow-hidden",
51
+ "absolute z-raised h-1 overflow-hidden",
52
52
  "right-1.5 bottom-1.5 left-1.5 w-auto rounded-[2px]",
53
53
  "bg-layer-card"
54
54
  ],
55
55
  attachmentUploadProgressBarIndicator: ["block h-full", "rounded-[inherit] bg-info"],
56
56
  attachmentFailedOverlay: [
57
- "absolute inset-0 z-10 flex flex-col items-center justify-center px-1",
57
+ "absolute inset-0 z-raised flex flex-col items-center justify-center px-1",
58
58
  "[border-width:var(--ca-overlay-border,2px)]",
59
59
  "text-center",
60
60
  "rounded-control border-danger-strong bg-layer-veil",
61
61
  "font-sans text-caption font-semibold text-danger-strong"
62
62
  ],
63
63
  attachmentRemove: [
64
- "absolute z-20 flex items-center justify-center",
64
+ "absolute z-control flex items-center justify-center",
65
65
  "transition-opacity group-hover/composer-attachment:opacity-100",
66
66
  "[@media(hover:none)]:opacity-100",
67
67
  "[&_svg]:shrink-0",
@@ -42,11 +42,11 @@ function ComposerDropOverlayPrompt({ children, ...props }) {
42
42
  children: /* @__PURE__ */ jsx(FileText, { className: "text-foreground-muted" })
43
43
  }),
44
44
  /* @__PURE__ */ jsx("span", {
45
- className: dropOverlayIcon({ className: "absolute z-10" }),
45
+ className: dropOverlayIcon({ className: "absolute z-raised" }),
46
46
  children: /* @__PURE__ */ jsx(Upload, { className: "text-foreground-muted" })
47
47
  }),
48
48
  /* @__PURE__ */ jsx("span", {
49
- className: dropOverlayIcon({ className: "absolute z-20 translate-x-7 translate-y-1 rotate-12" }),
49
+ className: dropOverlayIcon({ className: "absolute z-raised translate-x-7 translate-y-1 rotate-12" }),
50
50
  children: /* @__PURE__ */ jsx(Image, { className: "text-foreground-muted" })
51
51
  })
52
52
  ]
@@ -2,7 +2,7 @@ import { tv } from "../../lib/tv.mjs";
2
2
  //#region src/components/composer/composer-drop-overlay.recipe.ts
3
3
  const composerDropOverlay = tv({ slots: {
4
4
  dropOverlay: [
5
- "absolute inset-0 z-30 flex items-center justify-center",
5
+ "absolute inset-0 z-float flex items-center justify-center",
6
6
  "rounded-container border-[1.5px] border-dashed border-line-seam",
7
7
  "bg-layer-card bg-[linear-gradient(var(--info-soft),var(--info-soft))]"
8
8
  ],
@@ -225,7 +225,7 @@ function SortableComposerAttachment({ id, label, children }) {
225
225
  const style = {
226
226
  transform: isDragging ? void 0 : CSS.Translate.toString(transform),
227
227
  transition: isDragging ? void 0 : transition,
228
- zIndex: isDragging ? 0 : void 0
228
+ zIndex: isDragging ? "var(--z-index-base)" : void 0
229
229
  };
230
230
  const place = isDragging && !home;
231
231
  return /* @__PURE__ */ jsxs("div", {
@@ -7,7 +7,7 @@ import { ContextMenu } from "@base-ui/react";
7
7
  //#region src/components/context-menu/context-menu.tsx
8
8
  const contextMenu = tv({ slots: {
9
9
  trigger: ["select-none"],
10
- positioner: ["isolate z-50 outline-none"],
10
+ positioner: ["isolate z-popup outline-none"],
11
11
  content: [
12
12
  "flex flex-col max-h-(--available-height) overflow-hidden",
13
13
  "outline-none",
@@ -12,7 +12,7 @@ const conversationPanelEmptyState = tv({ slots: {
12
12
  brand: ["shrink-0", "mb-1 inline-flex rounded-none p-0 text-foreground-hint"],
13
13
  brandMark: [
14
14
  "relative flex items-center justify-center",
15
- "[&>svg]:relative [&>svg]:z-10",
15
+ "[&>svg]:relative [&>svg]:z-raised",
16
16
  "size-9 overflow-visible rounded-none",
17
17
  "[&>svg]:size-9 [&>svg]:stroke-2"
18
18
  ]
@@ -22,9 +22,9 @@ import { createPortal } from "react-dom";
22
22
  //#region src/components/dialog/dialog.tsx
23
23
  const dialog = tv({
24
24
  slots: {
25
- overlay: ["fixed inset-0 z-50 bg-layer-backdrop"],
25
+ overlay: ["fixed inset-0 z-dialog bg-layer-backdrop"],
26
26
  content: [
27
- "fixed top-1/2 left-1/2 z-50 flex w-[calc(100%-2rem)] -translate-1/2 flex-col",
27
+ "fixed top-1/2 left-1/2 z-dialog flex w-[calc(100%-2rem)] -translate-1/2 flex-col",
28
28
  "max-h-[calc(100dvh-2rem)] outline-none",
29
29
  "overflow-clip rounded-dialog bg-layer-popover text-foreground",
30
30
  "shadow-float ring-1 ring-line-seam"
@@ -83,8 +83,8 @@ const dialog = tv({
83
83
  content: []
84
84
  },
85
85
  1: {
86
- overlay: ["z-60"],
87
- content: ["z-60"]
86
+ overlay: ["z-dialog-layer"],
87
+ content: ["z-dialog-layer"]
88
88
  }
89
89
  },
90
90
  nested: {
@@ -49,8 +49,9 @@ export declare function keepGrabInside(proxyWidth: number, inset?: number): Modi
49
49
  */
50
50
  export declare function cancelDrag(win?: Window): void;
51
51
  /**
52
- * Above every raft-ui layer (popovers 50, a stacked dialog 60, toasts and the
53
- * lightbox 70) and an app's own top layers, among the layers rendered in
52
+ * `--z-index-drag` (`z-drag`) as a number: above every raft-ui layer (popups
53
+ * and dialogs 50, a `layer={1}` dialog 60, the lightbox 70, toasts 80) and an
54
+ * app's own top layers, among the layers rendered in
54
55
  * `document.body`, where the copy goes by default. dnd-kit's own default.
55
56
  */
56
57
  export declare const DRAG_LIFT_Z_INDEX = 999;
@@ -109,8 +109,9 @@ function cancelDrag(win = window) {
109
109
  win.dispatchEvent(new Event("resize"));
110
110
  }
111
111
  /**
112
- * Above every raft-ui layer (popovers 50, a stacked dialog 60, toasts and the
113
- * lightbox 70) and an app's own top layers, among the layers rendered in
112
+ * `--z-index-drag` (`z-drag`) as a number: above every raft-ui layer (popups
113
+ * and dialogs 50, a `layer={1}` dialog 60, the lightbox 70, toasts 80) and an
114
+ * app's own top layers, among the layers rendered in
114
115
  * `document.body`, where the copy goes by default. dnd-kit's own default.
115
116
  */
116
117
  const DRAG_LIFT_Z_INDEX = 999;
@@ -18,7 +18,7 @@ const drag = tv({
18
18
  "border-[1.5px] border-dashed border-line-strong bg-fill-subtle"
19
19
  ],
20
20
  hint: [
21
- "pointer-events-none fixed top-0 left-0 z-999 max-w-80",
21
+ "pointer-events-none fixed top-0 left-0 z-drag max-w-80",
22
22
  "rounded-chip px-2 py-1",
23
23
  "font-sans text-caption",
24
24
  "bg-layer-hud text-foreground-on-hud shadow-float ring-1 ring-line-seam"
@@ -66,13 +66,13 @@ const drawer = tv({
66
66
  extend: drawerMotion,
67
67
  slots: {
68
68
  overlay: [
69
- "fixed inset-0 z-50 min-h-dvh select-none",
69
+ "fixed inset-0 z-dialog min-h-dvh select-none",
70
70
  "supports-[-webkit-touch-callout:none]:absolute",
71
71
  "bg-layer-backdrop"
72
72
  ],
73
- viewport: ["pointer-events-none fixed inset-0 z-50 select-none"],
73
+ viewport: ["pointer-events-none fixed inset-0 z-dialog select-none"],
74
74
  popup: [
75
- "group/drawer-popup pointer-events-auto fixed z-50 flex h-(--drawer-content-height) flex-col outline-none",
75
+ "group/drawer-popup pointer-events-auto fixed z-dialog flex h-(--drawer-content-height) flex-col outline-none",
76
76
  "[--drawer-inset:12px] [--drawer-content-height:var(--drawer-height,auto)]",
77
77
  "data-nested-drawer-open:overflow-hidden",
78
78
  "bg-layer-popover text-foreground",
@@ -80,7 +80,7 @@ const drawer = tv({
80
80
  ],
81
81
  content: ["flex min-h-0 flex-1 flex-col rounded-[inherit] select-text", "group-data-swiping/drawer-popup:select-none"],
82
82
  swipeHandle: [
83
- "relative z-10 shrink-0 cursor-grab select-none active:cursor-grabbing",
83
+ "relative z-control shrink-0 cursor-grab select-none active:cursor-grabbing",
84
84
  "before:absolute before:content-['']",
85
85
  "before:rounded-full before:bg-line-seam"
86
86
  ],
@@ -9,7 +9,7 @@ import { Menu } from "@base-ui/react/menu";
9
9
  //#region src/components/dropdown-menu/dropdown-menu.tsx
10
10
  const dropdownMenu = tv({ slots: {
11
11
  trigger: ["select-none"],
12
- positioner: ["isolate z-50 outline-none"],
12
+ positioner: ["isolate z-popup outline-none"],
13
13
  content: [
14
14
  "max-h-(--available-height) overflow-hidden",
15
15
  "outline-none",
@@ -30,7 +30,7 @@ const filePreview = tv({
30
30
  media: ["relative h-10 w-8 overflow-hidden rounded-md ring-1", "bg-fill-muted shadow-none ring-line-hairline"]
31
31
  },
32
32
  variants: { placement: {
33
- corner: { badge: "absolute -right-1.5 bottom-0.5 z-10" },
33
+ corner: { badge: "absolute -right-1.5 bottom-0.5 z-raised" },
34
34
  inline: { badge: "inline-flex h-3.5 w-7 shrink-0 items-center justify-center px-0 py-0" }
35
35
  } },
36
36
  defaultVariants: { placement: "corner" }
@@ -1,7 +1,8 @@
1
1
  import { StyledProps } from "../../lib/styled-props.mjs";
2
2
  import { ButtonProps } from "../button/button.mjs";
3
+ import { InputGroupInputProps } from "../input-group/input-group.mjs";
3
4
  import { PickerTriggerButtonProps } from "../picker-trigger-button/picker-trigger-button.mjs";
4
- import { ReactElement, ReactNode, Ref } from "react";
5
+ import { CSSProperties, ReactElement, ReactNode, Ref } from "react";
5
6
  import { Toolbar } from "@base-ui/react/toolbar";
6
7
  //#region src/components/fit-toolbar/fit-toolbar.d.ts
7
8
  /**
@@ -66,6 +67,25 @@ export declare function useFitMore(): {
66
67
  };
67
68
  /** The items in More, in their order, each as its `moreItem`: put it in More's menu. */
68
69
  export declare function FitToolbarMoreItems(): import("react").JSX.Element[] | null;
70
+ export type FitToolbarMoreProps = Omit<ButtonProps, "children" | "size" | "variant" | "render" | "loading" | "loadingLabel"> & {
71
+ /**
72
+ * Its menu's trigger, which opens the menu holding `FitToolbarMoreItems`:
73
+ * `<DropdownMenuTrigger />`. It renders it as a toolbar button.
74
+ */
75
+ trigger: ReactElement<{
76
+ render?: unknown;
77
+ }>;
78
+ /** Its accessible name and tooltip, in the page's language: "More" by default, in English. */
79
+ "aria-label"?: string;
80
+ /** Its icon: ⋯ by default. */
81
+ children?: ReactNode;
82
+ };
83
+ /**
84
+ * The toolbar's More as one toolbar item: a ghost ⋯ icon button, shown only
85
+ * while an item is in More, its name as a tooltip. Put it where the items it
86
+ * holds were: on a list's toolbar, before the primary action.
87
+ */
88
+ export declare function FitToolbarMore({ trigger, "aria-label": label, children, className, ...props }: FitToolbarMoreProps): import("react").JSX.Element;
69
89
  export type FitToolbarGroupProps = StyledProps<Toolbar.Group.Props> & {
70
90
  /** When it moves to a line of its own (the `wrap` step), in a toolbar that allows it. */
71
91
  wrapOrder?: number;
@@ -78,6 +98,21 @@ export type FitToolbarGroupProps = StyledProps<Toolbar.Group.Props> & {
78
98
  wrapLine?: string;
79
99
  /** When it shows `collapsed` instead of its items (the `collapse` step). */
80
100
  collapseOrder?: number;
101
+ /**
102
+ * When the whole group moves into More (the `more` step), its items
103
+ * together: the sort, the grouping and the view switch of a list's toolbar,
104
+ * folded into one menu. Give the group a `moreItem` for More's menu.
105
+ */
106
+ moreOrder?: number;
107
+ /** What the group is in More's menu while it is there (`FitToolbarMoreItems`). */
108
+ moreItem?: ReactNode;
109
+ /**
110
+ * Pinned at the group's end, outside its scroll, with `overflow="scroll"`:
111
+ * Clear all, as ×, at the end of the filters' line. It changes form with
112
+ * the group's items and keeps the form it took once the group wraps, while
113
+ * the items get theirs back.
114
+ */
115
+ end?: ReactNode;
81
116
  /** The group as one button (a Filter button for its filters), shown once it collapses. */
82
117
  collapsed?: ReactNode;
83
118
  /**
@@ -92,7 +127,7 @@ export type FitToolbarGroupProps = StyledProps<Toolbar.Group.Props> & {
92
127
  * between groups, the last first; groups with the same `wrapLine` share a
93
128
  * line, any other takes one of its own.
94
129
  */
95
- export declare function FitToolbarGroup({ className, wrapOrder, firstLine, wrapLine, collapseOrder, collapsed, overflow, children, ref, ...props }: FitToolbarGroupProps & {
130
+ export declare function FitToolbarGroup({ className, wrapOrder, firstLine, wrapLine, collapseOrder, collapsed, moreOrder, moreItem, overflow, end, children, ref, ...props }: FitToolbarGroupProps & {
96
131
  ref?: Ref<HTMLDivElement>;
97
132
  }): import("react").JSX.Element;
98
133
  export type FitToolbarButtonProps = Omit<ButtonProps, "children" | "size"> & {
@@ -162,4 +197,45 @@ export type FitToolbarPickerProps = Omit<PickerTriggerButtonProps, "children" |
162
197
  * as its tooltip.
163
198
  */
164
199
  export declare function FitToolbarPicker({ trigger, icon, children, value, labelOrder, moreOrder, moreItem, className, ...props }: FitToolbarPickerProps): import("react").JSX.Element;
200
+ export type FitToolbarSearchProps = Omit<InputGroupInputProps, "className" | "value" | "defaultValue" | "onValueChange" | "aria-label" | "render"> & {
201
+ /** Its accessible name ("Search tasks"): the field's and, once it is an icon, the button's, and the button's tooltip. */
202
+ "aria-label": string;
203
+ /** The text, when the page holds it. */
204
+ value?: string;
205
+ /** The text it starts with, when it holds its own. */
206
+ defaultValue?: string;
207
+ /** Called with the new text as the person types, clears it or presses Esc. */
208
+ onValueChange?: (value: string) => void;
209
+ /**
210
+ * The least it may be, in px, before the toolbar gives way. By default it
211
+ * is measured: what its search icon and its whole placeholder (or, with
212
+ * none, its `aria-label`) take, in the field's own font, so the empty field
213
+ * always shows what it is for.
214
+ */
215
+ minWidth?: number;
216
+ /**
217
+ * When it shows as a search icon button at the start of its line instead
218
+ * of the field (the `collapse` step): the toolbar's last step. Without it,
219
+ * it never collapses.
220
+ */
221
+ collapseOrder?: number;
222
+ /** The icon at the field's start and on the button: a search icon by default. */
223
+ icon?: ReactNode;
224
+ /** The clear button's accessible name ("Clear search"): with it, the field has one at its end once it has text. */
225
+ clearLabel?: string;
226
+ /** For the field's box (the InputGroup). */
227
+ className?: string;
228
+ style?: CSSProperties;
229
+ };
230
+ /**
231
+ * The search field of a list's toolbar: it fills the rest of its line and
232
+ * keeps at least the room its icon and its whole placeholder take (measured,
233
+ * or `minWidth`), so the toolbar's other steps come before
234
+ * it is squeezed. From `collapseOrder` on it is a search icon button at the
235
+ * start of the line, which opens the field in the scope's place, More and the
236
+ * primary action kept at the line's end; the
237
+ * field closes once it is empty and loses focus, or on Esc. A search with
238
+ * text stays open. Put it straight in the FitToolbar, between its groups.
239
+ */
240
+ export declare function FitToolbarSearch({ "aria-label": label, value, defaultValue, onValueChange, minWidth, collapseOrder, icon, clearLabel, className, style, onKeyDown, disabled, ref, ...props }: FitToolbarSearchProps): import("react").JSX.Element;
165
241
  //#endregion