@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.
- package/CHANGELOG.md +33 -0
- package/dist/cn.d.mts +2 -0
- package/dist/cn.mjs +21 -1
- package/dist/components/alert-dialog/alert-dialog.mjs +2 -2
- package/dist/components/app-shell/app-shell.mjs +2 -2
- package/dist/components/avatar/avatar.mjs +1 -1
- package/dist/components/button/button-split.mjs +2 -2
- package/dist/components/button/button.mjs +2 -2
- package/dist/components/choice-list/choice-list.recipe.mjs +1 -1
- package/dist/components/code-block/code-block.recipe.mjs +2 -2
- package/dist/components/combobox/combobox.mjs +1 -1
- package/dist/components/combobox-select/combobox-select.css +1 -1
- package/dist/components/comment/comment.recipe.mjs +2 -2
- package/dist/components/composer/composer-attachment.recipe.mjs +5 -5
- package/dist/components/composer/composer-drop-overlay.mjs +2 -2
- package/dist/components/composer/composer-drop-overlay.recipe.mjs +1 -1
- package/dist/components/composer/sortable-composer-attachments.mjs +1 -1
- package/dist/components/context-menu/context-menu.mjs +1 -1
- package/dist/components/conversation-panel/conversation-panel-empty-state.mjs +1 -1
- package/dist/components/dialog/dialog.mjs +4 -4
- package/dist/components/drag/drag-lift.d.mts +3 -2
- package/dist/components/drag/drag-lift.mjs +3 -2
- package/dist/components/drag/drag.recipe.mjs +1 -1
- package/dist/components/drawer/drawer.recipe.mjs +4 -4
- package/dist/components/dropdown-menu/dropdown-menu.mjs +1 -1
- package/dist/components/file-preview/file-preview.recipe.mjs +1 -1
- package/dist/components/fit-toolbar/fit-toolbar.d.mts +78 -2
- package/dist/components/fit-toolbar/fit-toolbar.mjs +331 -14
- package/dist/components/fit-toolbar/fit-toolbar.recipe.mjs +30 -4
- package/dist/components/fit-toolbar/index.d.mts +2 -2
- package/dist/components/inbox-item/inbox-item.recipe.mjs +7 -7
- package/dist/components/lightbox/lightbox.d.mts +2 -2
- package/dist/components/lightbox/lightbox.mjs +7 -7
- package/dist/components/message-attachment/message-image-gallery.recipe.mjs +1 -1
- package/dist/components/message-item/message-item.recipe.mjs +2 -2
- package/dist/components/message-list/message-list.recipe.mjs +2 -2
- package/dist/components/mobile-nav/mobile-nav.mjs +2 -2
- package/dist/components/notification-center/notification-center.mjs +1 -1
- package/dist/components/panel/panel-header.recipe.mjs +1 -1
- package/dist/components/panel/panel-split-action.recipe.mjs +2 -2
- package/dist/components/popover/popover.mjs +1 -1
- package/dist/components/preview-card/preview-card.mjs +1 -1
- package/dist/components/pull-to-refresh/pull-to-refresh-indicator.mjs +1 -1
- package/dist/components/resizable/resizable.recipe.mjs +1 -1
- package/dist/components/scroll-area/scroll-area.css +1 -0
- package/dist/components/select/select.mjs +2 -2
- package/dist/components/selection-toolbar/selection-toolbar.d.mts +1 -1
- package/dist/components/selection-toolbar/selection-toolbar.recipe.mjs +1 -1
- package/dist/components/sidebar/sidebar.recipe.mjs +1 -1
- package/dist/components/tabs/tabs.mjs +4 -4
- package/dist/components/task-dnd/task-dnd.recipe.mjs +2 -2
- package/dist/components/thread-panel/thread-panel.recipe.mjs +1 -1
- package/dist/components/toast/toast.mjs +5 -5
- package/dist/components/tooltip/tooltip.mjs +2 -2
- package/dist/lib/list-cell.mjs +1 -1
- package/dist/lint/no-raw-z-index.mjs +142 -0
- package/dist/lint/prefer-scroll-area.mjs +1 -1
- package/dist/lint/recommended.json +2 -1
- package/dist/lint.d.mts +8 -2
- package/dist/lint.mjs +16 -3
- package/dist/styles.css +28 -0
- package/dist/wip.d.mts +2 -2
- package/dist/wip.mjs +2 -2
- package/package.json +1 -1
- 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-
|
|
16
|
+
overlay: ["fixed inset-0 z-dialog bg-layer-backdrop"],
|
|
17
17
|
content: [
|
|
18
|
-
"fixed top-1/2 left-1/2 z-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
42
|
-
loadingIndicator: "pointer-events-none absolute inset-0 z-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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))]",
|
|
@@ -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
|
+
"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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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 ?
|
|
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-
|
|
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-
|
|
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-
|
|
25
|
+
overlay: ["fixed inset-0 z-dialog bg-layer-backdrop"],
|
|
26
26
|
content: [
|
|
27
|
-
"fixed top-1/2 left-1/2 z-
|
|
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-
|
|
87
|
-
content: ["z-
|
|
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
|
-
*
|
|
53
|
-
*
|
|
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
|
-
*
|
|
113
|
-
*
|
|
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-
|
|
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-
|
|
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-
|
|
73
|
+
viewport: ["pointer-events-none fixed inset-0 z-dialog select-none"],
|
|
74
74
|
popup: [
|
|
75
|
-
"group/drawer-popup pointer-events-auto fixed z-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|