@botiverse/raft-ui 0.82.0 → 0.84.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 (62) hide show
  1. package/CHANGELOG.md +147 -0
  2. package/dist/components/app-link-card/app-link-card.mjs +19 -37
  3. package/dist/components/banner/banner.mjs +15 -2
  4. package/dist/components/dialog/dialog-sheet-context.mjs +7 -2
  5. package/dist/components/dialog/dialog-sheet.d.mts +3 -2
  6. package/dist/components/dialog/dialog-sheet.mjs +29 -43
  7. package/dist/components/dialog/dialog.d.mts +12 -1
  8. package/dist/components/dialog/dialog.mjs +50 -10
  9. package/dist/components/drag/drag.recipe.mjs +1 -1
  10. package/dist/components/fit-toolbar/fit-toolbar.d.mts +165 -0
  11. package/dist/components/fit-toolbar/fit-toolbar.mjs +736 -0
  12. package/dist/components/fit-toolbar/fit-toolbar.recipe.mjs +35 -0
  13. package/dist/components/fit-toolbar/index.d.mts +2 -0
  14. package/dist/components/lightbox/index.d.mts +2 -2
  15. package/dist/components/lightbox/lightbox.d.mts +70 -4
  16. package/dist/components/lightbox/lightbox.mjs +285 -91
  17. package/dist/components/list-row/list-row.d.mts +14 -1
  18. package/dist/components/list-row/list-row.mjs +4 -2
  19. package/dist/components/list-row/list-row.recipe.d.mts +15 -3
  20. package/dist/components/list-row/list-row.recipe.mjs +18 -1
  21. package/dist/components/message-action-card/message-action-card-content.recipe.mjs +3 -3
  22. package/dist/components/message-action-card/message-action-card.mjs +7 -3
  23. package/dist/components/message-action-card/message-action-card.recipe.mjs +2 -6
  24. package/dist/components/message-embed/index.d.mts +2 -1
  25. package/dist/components/message-embed/message-embed.d.mts +8 -1
  26. package/dist/components/message-embed/message-embed.mjs +2 -2
  27. package/dist/components/message-embed/message-embed.recipe.d.mts +160 -0
  28. package/dist/components/message-embed/message-embed.recipe.mjs +49 -10
  29. package/dist/components/message-forwarded-bundle/message-forwarded-bundle.mjs +1 -0
  30. package/dist/components/message-forwarded-bundle/message-forwarded-bundle.recipe.mjs +1 -1
  31. package/dist/components/message-quoted-preview/message-quoted-preview.mjs +2 -0
  32. package/dist/components/message-replies/message-replies.mjs +1 -1
  33. package/dist/components/message-replies/message-replies.recipe.mjs +1 -1
  34. package/dist/components/mobile-nav/mobile-nav-server.d.mts +21 -8
  35. package/dist/components/mobile-nav/mobile-nav-server.mjs +142 -13
  36. package/dist/components/popover/popover.d.mts +11 -2
  37. package/dist/components/popover/popover.mjs +51 -38
  38. package/dist/components/preview-card/preview-card.d.mts +5 -1
  39. package/dist/components/preview-card/preview-card.mjs +24 -27
  40. package/dist/components/save-status/save-status.d.mts +16 -9
  41. package/dist/components/save-status/save-status.mjs +19 -30
  42. package/dist/components/segmented-control/segmented-control.d.mts +1 -1
  43. package/dist/components/segmented-control/segmented-control.mjs +56 -10
  44. package/dist/components/selection-toolbar/index.d.mts +2 -0
  45. package/dist/components/selection-toolbar/selection-toolbar.d.mts +100 -0
  46. package/dist/components/selection-toolbar/selection-toolbar.mjs +217 -0
  47. package/dist/components/selection-toolbar/selection-toolbar.recipe.mjs +42 -0
  48. package/dist/components/task-board/task-board.d.mts +5 -0
  49. package/dist/components/task-board/task-board.mjs +8 -1
  50. package/dist/components/task-dnd/task-dnd.d.mts +10 -1
  51. package/dist/components/task-dnd/task-dnd.mjs +2 -1
  52. package/dist/components/toast/toast.mjs +2 -2
  53. package/dist/index.d.mts +4 -2
  54. package/dist/index.mjs +4 -2
  55. package/dist/lib/label-value-fit.mjs +33 -6
  56. package/dist/lib/laid-out-children.mjs +32 -0
  57. package/dist/lib/stacked-actions.mjs +7 -4
  58. package/dist/lib/use-mobile-viewport.mjs +5 -2
  59. package/dist/lib/use-soft-keyboard.mjs +72 -0
  60. package/dist/wip.d.mts +8 -3
  61. package/dist/wip.mjs +5 -3
  62. package/package.json +1 -1
@@ -5,7 +5,7 @@ export declare const listRow: import("tailwind-variants/lite").TVReturnType<{
5
5
  root: string;
6
6
  };
7
7
  plain: {
8
- root: string;
8
+ root: string[];
9
9
  };
10
10
  entry: {
11
11
  root: string;
@@ -15,6 +15,10 @@ export declare const listRow: import("tailwind-variants/lite").TVReturnType<{
15
15
  true: {};
16
16
  false: {};
17
17
  };
18
+ attached: {
19
+ true: {};
20
+ false: {};
21
+ };
18
22
  cell: {
19
23
  false: {
20
24
  root: string[];
@@ -47,7 +51,7 @@ export declare const listRow: import("tailwind-variants/lite").TVReturnType<{
47
51
  root: string;
48
52
  };
49
53
  plain: {
50
- root: string;
54
+ root: string[];
51
55
  };
52
56
  entry: {
53
57
  root: string;
@@ -57,6 +61,10 @@ export declare const listRow: import("tailwind-variants/lite").TVReturnType<{
57
61
  true: {};
58
62
  false: {};
59
63
  };
64
+ attached: {
65
+ true: {};
66
+ false: {};
67
+ };
60
68
  cell: {
61
69
  false: {
62
70
  root: string[];
@@ -89,7 +97,7 @@ export declare const listRow: import("tailwind-variants/lite").TVReturnType<{
89
97
  root: string;
90
98
  };
91
99
  plain: {
92
- root: string;
100
+ root: string[];
93
101
  };
94
102
  entry: {
95
103
  root: string;
@@ -99,6 +107,10 @@ export declare const listRow: import("tailwind-variants/lite").TVReturnType<{
99
107
  true: {};
100
108
  false: {};
101
109
  };
110
+ attached: {
111
+ true: {};
112
+ false: {};
113
+ };
102
114
  cell: {
103
115
  false: {
104
116
  root: string[];
@@ -34,13 +34,17 @@ const listRow = tv({
34
34
  variants: {
35
35
  variant: {
36
36
  default: { root: "min-h-16 pointer-coarse:min-h-14 pointer-coarse:py-2 [--list-row-rule-start:63px]" },
37
- plain: { root: "py-(--settings-row-inset) [--list-row-rule-start:16px]" },
37
+ plain: { root: ["py-(--settings-row-inset)", "[--list-row-rule-start:16px]"] },
38
38
  entry: { root: "" }
39
39
  },
40
40
  interactive: {
41
41
  true: {},
42
42
  false: {}
43
43
  },
44
+ attached: {
45
+ true: {},
46
+ false: {}
47
+ },
44
48
  cell: {
45
49
  false: { root: [
46
50
  "relative px-4",
@@ -62,6 +66,7 @@ const listRow = tv({
62
66
  compoundVariants: [
63
67
  {
64
68
  cell: false,
69
+ attached: false,
65
70
  variant: ["default", "plain"],
66
71
  class: { root: [
67
72
  "before:pointer-events-none before:absolute before:top-0 before:right-0 before:hidden",
@@ -69,6 +74,17 @@ const listRow = tv({
69
74
  "[[data-slot=list-row]+&]:before:block [li+li>&]:before:block"
70
75
  ] }
71
76
  },
77
+ {
78
+ variant: "plain",
79
+ attached: true,
80
+ class: { root: "pt-0" }
81
+ },
82
+ {
83
+ variant: "plain",
84
+ attached: true,
85
+ interactive: true,
86
+ class: { root: "min-h-control" }
87
+ },
72
88
  {
73
89
  cell: false,
74
90
  interactive: true,
@@ -87,6 +103,7 @@ const listRow = tv({
87
103
  defaultVariants: {
88
104
  variant: "default",
89
105
  interactive: true,
106
+ attached: false,
90
107
  cell: false,
91
108
  wrap: false
92
109
  }
@@ -1,7 +1,7 @@
1
1
  import { tv } from "../../lib/tv.mjs";
2
2
  //#region src/components/message-action-card/message-action-card-content.recipe.ts
3
3
  const messageActionCardContent = tv({ slots: {
4
- root: ["p-3", "flex flex-col gap-2 px-3 pt-0 pb-3"],
4
+ root: ["flex flex-col gap-2 pt-0"],
5
5
  panel: [
6
6
  "h-(--collapsible-panel-height) overflow-hidden",
7
7
  "transition-[height] duration-200 ease-out motion-reduce:transition-none",
@@ -44,8 +44,8 @@ const messageActionCardContent = tv({ slots: {
44
44
  "[&>svg]:mt-[calc((1lh-14px)/2)] [&>svg]:text-foreground-muted"
45
45
  ],
46
46
  completion: ["inline-flex items-center gap-1.5 text-footnote text-foreground-muted", "[&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-foreground"],
47
- actions: ["flex flex-wrap items-center justify-end", "mt-1 gap-2"],
48
- actionsNote: ["min-w-0 flex-1 basis-40", "text-footnote text-foreground-muted"]
47
+ actions: ["mt-1"],
48
+ actionsNote: ["min-w-0 basis-full", "text-footnote text-foreground-muted"]
49
49
  } });
50
50
  //#endregion
51
51
  export { messageActionCardContent };
@@ -1,5 +1,6 @@
1
1
  import { ScrollArea } from "../scroll-area/scroll-area.mjs";
2
2
  import { Badge } from "../badge/badge.mjs";
3
+ import { messageCard } from "../message-embed/message-embed.recipe.mjs";
3
4
  import { useLabelValueFit } from "../../lib/label-value-fit.mjs";
4
5
  import { MessageEmbed, MessageEmbedContent, MessageEmbedHeader } from "../message-embed/message-embed.mjs";
5
6
  import { messageActionCard } from "./message-action-card.recipe.mjs";
@@ -25,6 +26,7 @@ function MessageActionCard({ className, render, open, defaultOpen = true, onOpen
25
26
  defaultOpen,
26
27
  onOpenChange,
27
28
  render: /* @__PURE__ */ jsx(MessageEmbed, {
29
+ size: "item",
28
30
  className: root({ className }),
29
31
  render,
30
32
  ...props
@@ -36,7 +38,7 @@ function MessageActionCardContent({ className, render, ...props }) {
36
38
  return /* @__PURE__ */ jsx(Collapsible.Panel, {
37
39
  className: panel(),
38
40
  children: /* @__PURE__ */ jsx(MessageEmbedContent, {
39
- className: root({ className }),
41
+ className: messageCard().inset({ className: root({ className }) }),
40
42
  render,
41
43
  ...props
42
44
  })
@@ -129,8 +131,9 @@ function MessageActionCardCollapseTrigger({ className, ...props }) {
129
131
  }
130
132
  function MessageActionCardHeader({ className, render, ...props }) {
131
133
  const { header } = messageActionCard();
134
+ const { inset, heading } = messageCard();
132
135
  return /* @__PURE__ */ jsx(MessageEmbedHeader, {
133
- className: header({ className }),
136
+ className: inset({ className: heading({ className: header({ className }) }) }),
134
137
  render,
135
138
  ...props
136
139
  });
@@ -290,10 +293,11 @@ function MessageActionCardCompletion({ className, render, ...props }) {
290
293
  }
291
294
  function MessageActionCardActions({ className, render, ...props }) {
292
295
  const { actions } = messageActionCardContent();
296
+ const { actionRow } = messageCard();
293
297
  return useRender({
294
298
  defaultTagName: "div",
295
299
  render,
296
- props: mergeProps({ className: actions({ className }) }, props),
300
+ props: mergeProps({ className: actionRow({ className: actions({ className }) }) }, props),
297
301
  state: { slot: "message-action-card-actions" }
298
302
  });
299
303
  }
@@ -2,12 +2,8 @@ import { tv } from "../../lib/tv.mjs";
2
2
  //#region src/components/message-action-card/message-action-card.recipe.ts
3
3
  const messageActionCard = tv({
4
4
  slots: {
5
- root: ["w-full", "group/action-card mt-2 max-w-[440px]"],
6
- header: [
7
- "flex items-start",
8
- "gap-2 px-3 pt-3 pb-2 group-data-closed/action-card:pb-3",
9
- "text-subhead font-bold text-foreground"
10
- ],
5
+ root: ["group/action-card mt-2"],
6
+ header: ["flex items-start", "gap-2 pb-2 group-data-closed/action-card:pb-3"],
11
7
  headerIcon: [
12
8
  "flex shrink-0 items-center justify-center",
13
9
  "[&>svg]:shrink-0",
@@ -1,2 +1,3 @@
1
1
  import { MessageEmbed, MessageEmbedContent, MessageEmbedContentProps, MessageEmbedFooter, MessageEmbedFooterProps, MessageEmbedHeader, MessageEmbedHeaderProps, MessageEmbedProps } from "./message-embed.mjs";
2
- export { MessageEmbed, MessageEmbedContent, type MessageEmbedContentProps, MessageEmbedFooter, type MessageEmbedFooterProps, MessageEmbedHeader, type MessageEmbedHeaderProps, type MessageEmbedProps };
2
+ import { messageCard, messageEmbed } from "./message-embed.recipe.mjs";
3
+ export { MessageEmbed, MessageEmbedContent, type MessageEmbedContentProps, MessageEmbedFooter, type MessageEmbedFooterProps, MessageEmbedHeader, type MessageEmbedHeaderProps, type MessageEmbedProps, messageCard, messageEmbed };
@@ -1,7 +1,7 @@
1
1
  import { useRender } from "@base-ui/react/use-render";
2
2
  //#region src/components/message-embed/message-embed.d.ts
3
3
  type DivProps = useRender.ComponentProps<"div">;
4
- export declare function MessageEmbed({ interactive, className, render, ...props }: MessageEmbedProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
4
+ export declare function MessageEmbed({ interactive, size, className, render, ...props }: MessageEmbedProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
5
5
  export declare function MessageEmbedHeader({ className, render, ...props }: DivProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
6
6
  export declare function MessageEmbedContent({ className, render, ...props }: DivProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
7
7
  export declare function MessageEmbedFooter({ className, render, ...props }: DivProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
@@ -13,6 +13,13 @@ export type MessageEmbedProps = DivProps & {
13
13
  * @default false
14
14
  */
15
15
  interactive?: boolean;
16
+ /**
17
+ * The card's width, one of the two a card in a message has
18
+ * (cards-in-messages.md): `item` for a card that opens one thing, at most
19
+ * 400px and the message's width on a phone; `content` for a card that
20
+ * shows other messages, at most 560px. Unset, the card sets no width.
21
+ */
22
+ size?: "item" | "content";
16
23
  };
17
24
  export type MessageEmbedHeaderProps = DivProps;
18
25
  export type MessageEmbedContentProps = DivProps;
@@ -2,8 +2,8 @@ import { messageEmbed } from "./message-embed.recipe.mjs";
2
2
  import { mergeProps } from "@base-ui/react/merge-props";
3
3
  import { useRender } from "@base-ui/react/use-render";
4
4
  //#region src/components/message-embed/message-embed.tsx
5
- function MessageEmbed({ interactive = false, className, render, ...props }) {
6
- const { root } = messageEmbed();
5
+ function MessageEmbed({ interactive = false, size, className, render, ...props }) {
6
+ const { root } = messageEmbed({ size });
7
7
  const defaultProps = {
8
8
  "data-interactive": interactive ? "true" : void 0,
9
9
  className: root({ className })
@@ -0,0 +1,160 @@
1
+ //#region src/components/message-embed/message-embed.recipe.d.ts
2
+ export declare const messageEmbed: import("tailwind-variants/lite").TVReturnType<{
3
+ size: {
4
+ item: {
5
+ root: string[];
6
+ };
7
+ content: {
8
+ root: string[];
9
+ };
10
+ };
11
+ }, {
12
+ root: string[];
13
+ header: string[];
14
+ content: string[];
15
+ footer: string[];
16
+ }, undefined, {
17
+ size: {
18
+ item: {
19
+ root: string[];
20
+ };
21
+ content: {
22
+ root: string[];
23
+ };
24
+ };
25
+ }, {
26
+ root: string[];
27
+ header: string[];
28
+ content: string[];
29
+ footer: string[];
30
+ }, import("tailwind-variants/lite").TVReturnTypeLike<{
31
+ size: {
32
+ item: {
33
+ root: string[];
34
+ };
35
+ content: {
36
+ root: string[];
37
+ };
38
+ };
39
+ }, {
40
+ root: string[];
41
+ header: string[];
42
+ content: string[];
43
+ footer: string[];
44
+ }>>;
45
+ export declare const messageCard: import("tailwind-variants/lite").TVReturnType<{
46
+ [key: string]: {
47
+ [key: string]: {
48
+ actionGroup?: import("tailwind-variants/lite").ClassValue;
49
+ actionRow?: import("tailwind-variants/lite").ClassValue;
50
+ actions?: import("tailwind-variants/lite").ClassValue;
51
+ body?: import("tailwind-variants/lite").ClassValue;
52
+ eyebrow?: import("tailwind-variants/lite").ClassValue;
53
+ heading?: import("tailwind-variants/lite").ClassValue;
54
+ inset?: import("tailwind-variants/lite").ClassValue;
55
+ meta?: import("tailwind-variants/lite").ClassValue;
56
+ popover?: import("tailwind-variants/lite").ClassValue;
57
+ source?: import("tailwind-variants/lite").ClassValue;
58
+ sourceFooter?: import("tailwind-variants/lite").ClassValue;
59
+ sourceHost?: import("tailwind-variants/lite").ClassValue;
60
+ sourceHostText?: import("tailwind-variants/lite").ClassValue;
61
+ sourceIcon?: import("tailwind-variants/lite").ClassValue;
62
+ sourceName?: import("tailwind-variants/lite").ClassValue;
63
+ title?: import("tailwind-variants/lite").ClassValue;
64
+ } | import("tailwind-variants/lite").ClassValue;
65
+ };
66
+ } | {
67
+ [x: string]: {
68
+ [x: string]: {
69
+ actionGroup?: import("tailwind-variants/lite").ClassValue;
70
+ actionRow?: import("tailwind-variants/lite").ClassValue;
71
+ actions?: import("tailwind-variants/lite").ClassValue;
72
+ body?: import("tailwind-variants/lite").ClassValue;
73
+ eyebrow?: import("tailwind-variants/lite").ClassValue;
74
+ heading?: import("tailwind-variants/lite").ClassValue;
75
+ inset?: import("tailwind-variants/lite").ClassValue;
76
+ meta?: import("tailwind-variants/lite").ClassValue;
77
+ popover?: import("tailwind-variants/lite").ClassValue;
78
+ source?: import("tailwind-variants/lite").ClassValue;
79
+ sourceFooter?: import("tailwind-variants/lite").ClassValue;
80
+ sourceHost?: import("tailwind-variants/lite").ClassValue;
81
+ sourceHostText?: import("tailwind-variants/lite").ClassValue;
82
+ sourceIcon?: import("tailwind-variants/lite").ClassValue;
83
+ sourceName?: import("tailwind-variants/lite").ClassValue;
84
+ title?: import("tailwind-variants/lite").ClassValue;
85
+ } | import("tailwind-variants/lite").ClassValue;
86
+ };
87
+ } | {}, {
88
+ source: string[];
89
+ sourceIcon: string[];
90
+ sourceName: string[];
91
+ sourceHost: string[];
92
+ sourceHostText: string[];
93
+ sourceFooter: string[];
94
+ body: string[];
95
+ eyebrow: string[];
96
+ title: string[];
97
+ heading: string[];
98
+ meta: string[];
99
+ actions: string[];
100
+ actionRow: string[];
101
+ actionGroup: string[];
102
+ inset: string[];
103
+ popover: string[];
104
+ }, undefined, {
105
+ [key: string]: {
106
+ [key: string]: {
107
+ actionGroup?: import("tailwind-variants/lite").ClassValue;
108
+ actionRow?: import("tailwind-variants/lite").ClassValue;
109
+ actions?: import("tailwind-variants/lite").ClassValue;
110
+ body?: import("tailwind-variants/lite").ClassValue;
111
+ eyebrow?: import("tailwind-variants/lite").ClassValue;
112
+ heading?: import("tailwind-variants/lite").ClassValue;
113
+ inset?: import("tailwind-variants/lite").ClassValue;
114
+ meta?: import("tailwind-variants/lite").ClassValue;
115
+ popover?: import("tailwind-variants/lite").ClassValue;
116
+ source?: import("tailwind-variants/lite").ClassValue;
117
+ sourceFooter?: import("tailwind-variants/lite").ClassValue;
118
+ sourceHost?: import("tailwind-variants/lite").ClassValue;
119
+ sourceHostText?: import("tailwind-variants/lite").ClassValue;
120
+ sourceIcon?: import("tailwind-variants/lite").ClassValue;
121
+ sourceName?: import("tailwind-variants/lite").ClassValue;
122
+ title?: import("tailwind-variants/lite").ClassValue;
123
+ } | import("tailwind-variants/lite").ClassValue;
124
+ };
125
+ } | {}, {
126
+ source: string[];
127
+ sourceIcon: string[];
128
+ sourceName: string[];
129
+ sourceHost: string[];
130
+ sourceHostText: string[];
131
+ sourceFooter: string[];
132
+ body: string[];
133
+ eyebrow: string[];
134
+ title: string[];
135
+ heading: string[];
136
+ meta: string[];
137
+ actions: string[];
138
+ actionRow: string[];
139
+ actionGroup: string[];
140
+ inset: string[];
141
+ popover: string[];
142
+ }, import("tailwind-variants/lite").TVReturnTypeLike<unknown, {
143
+ source: string[];
144
+ sourceIcon: string[];
145
+ sourceName: string[];
146
+ sourceHost: string[];
147
+ sourceHostText: string[];
148
+ sourceFooter: string[];
149
+ body: string[];
150
+ eyebrow: string[];
151
+ title: string[];
152
+ heading: string[];
153
+ meta: string[];
154
+ actions: string[];
155
+ actionRow: string[];
156
+ actionGroup: string[];
157
+ inset: string[];
158
+ popover: string[];
159
+ }>>;
160
+ //#endregion
@@ -1,15 +1,54 @@
1
1
  import { tv } from "../../lib/tv.mjs";
2
2
  //#region src/components/message-embed/message-embed.recipe.ts
3
- const messageEmbed = tv({ slots: {
4
- root: [
5
- "group block min-w-0 text-left",
6
- "rounded-container border border-line-hairline bg-layer-card",
7
- "outline-none focus-visible:shadow-focus",
8
- "data-[interactive=true]:hover:overlay-subtle data-[interactive=true]:active:overlay-medium"
3
+ const messageEmbed = tv({
4
+ slots: {
5
+ root: [
6
+ "group block min-w-0 text-left",
7
+ "rounded-container border border-line-hairline bg-layer-card",
8
+ "outline-none focus-visible:shadow-focus",
9
+ "data-[interactive=true]:hover:overlay-subtle data-[interactive=true]:active:overlay-medium",
10
+ "not-data-[frame=bar]:*:data-[slot=message-embed-content]:first:rounded-t-[calc(var(--radius-container)-1px)] not-data-[frame=bar]:*:data-[slot=message-embed-content]:first:overflow-clip",
11
+ "not-data-[frame=bar]:*:data-[slot=message-embed-content]:last:rounded-b-[calc(var(--radius-container)-1px)] not-data-[frame=bar]:*:data-[slot=message-embed-content]:last:overflow-clip"
12
+ ],
13
+ header: ["min-w-0", "px-3 py-2"],
14
+ content: ["min-w-0"],
15
+ footer: ["min-w-0", "px-3 py-2"]
16
+ },
17
+ variants: { size: {
18
+ item: { root: ["w-full max-w-[400px] max-md:max-w-none"] },
19
+ content: { root: ["w-full max-w-[560px]"] }
20
+ } }
21
+ });
22
+ const messageCard = tv({ slots: {
23
+ source: [
24
+ "flex min-w-0 items-center gap-1.5",
25
+ "border-b border-line-hairline px-3 py-2",
26
+ "font-sans text-caption text-foreground-muted"
9
27
  ],
10
- header: ["min-w-0", "px-3 py-2"],
11
- content: ["min-w-0"],
12
- footer: ["min-w-0", "px-3 py-2"]
28
+ sourceIcon: ["inline-flex size-4 shrink-0 items-center justify-center", "*:size-full *:shrink-0 [&>img]:rounded-[2px] [&>img]:object-cover"],
29
+ sourceName: ["min-w-0 truncate", "font-semibold text-foreground"],
30
+ sourceHost: ["flex min-w-0 items-baseline", "before:shrink-0 before:pe-1.5 before:content-['·']"],
31
+ sourceHostText: ["min-w-0 truncate"],
32
+ sourceFooter: [
33
+ "m-0 truncate",
34
+ "border-t border-line-hairline px-3 py-2",
35
+ "font-sans text-caption text-foreground-muted"
36
+ ],
37
+ body: ["flex min-w-0 flex-col gap-1.5", "p-3"],
38
+ eyebrow: ["m-0 truncate", "font-mono text-mono-meta text-foreground-muted"],
39
+ title: [
40
+ "m-0 line-clamp-2",
41
+ "font-sans text-subhead font-bold text-foreground",
42
+ "[&_a]:rounded-[2px] [&_a]:decoration-[1.5px] [&_a]:underline-offset-[3px] [&_a]:hover:underline",
43
+ "[&_a]:outline-none [&_a]:focus-visible:shadow-focus"
44
+ ],
45
+ heading: ["font-sans text-subhead font-bold text-foreground"],
46
+ meta: ["flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", "m-0 font-sans text-callout text-foreground-muted"],
47
+ actions: ["flex flex-wrap items-center justify-end gap-2", "px-3 pb-3"],
48
+ actionRow: ["flex flex-wrap items-center justify-end gap-2"],
49
+ actionGroup: ["flex min-w-0 max-w-full flex-wrap items-center justify-end gap-2", "ms-auto"],
50
+ inset: ["p-3"],
51
+ popover: ["w-[400px] max-w-(--available-width)"]
13
52
  } });
14
53
  //#endregion
15
- export { messageEmbed };
54
+ export { messageCard, messageEmbed };
@@ -56,6 +56,7 @@ function MessageForwardedBundle({ className, fullWidth = false, render, ...props
56
56
  return /* @__PURE__ */ jsx(MessageForwardedBundleFoldContext.Provider, {
57
57
  value: fold,
58
58
  children: /* @__PURE__ */ jsx(MessageEmbed, {
59
+ size: fullWidth ? void 0 : "content",
59
60
  className: root({ className }),
60
61
  render,
61
62
  ...props
@@ -2,7 +2,7 @@ import { tv } from "../../lib/tv.mjs";
2
2
  //#region src/components/message-forwarded-bundle/message-forwarded-bundle.recipe.ts
3
3
  const messageForwardedBundle = tv({
4
4
  slots: {
5
- root: ["mt-1 max-w-[min(34rem,100%)]"],
5
+ root: ["mt-1"],
6
6
  header: ["flex flex-wrap items-center justify-between", "gap-2"],
7
7
  headerContent: ["flex min-w-0 items-center", "gap-2"],
8
8
  headerLabel: ["inline-flex shrink-0 items-center", "gap-1 text-footnote font-bold text-foreground-muted [&_svg]:size-3.5"],
@@ -7,6 +7,7 @@ import { useRender } from "@base-ui/react/use-render";
7
7
  function MessageQuotedPreview({ className, render, ...props }) {
8
8
  const { root } = messageQuotedPreview();
9
9
  return /* @__PURE__ */ jsx(MessageEmbed, {
10
+ "data-frame": "bar",
10
11
  className: root({ className }),
11
12
  render,
12
13
  ...props
@@ -126,6 +127,7 @@ function MessageQuotedPreviewAttachment({ className, render, ...props }) {
126
127
  function MessageQuotedPreviewLoading({ className, render, ...props }) {
127
128
  const { loading } = messageQuotedPreview();
128
129
  return /* @__PURE__ */ jsx(MessageEmbed, {
130
+ "data-frame": "bar",
129
131
  className: loading({ className }),
130
132
  render,
131
133
  ...props
@@ -6,7 +6,7 @@ import { useRender } from "@base-ui/react/use-render";
6
6
  //#region src/components/message-replies/message-replies.tsx
7
7
  function MessageReplies({ className, render, ...props }) {
8
8
  const { root } = messageReplies();
9
- const { root: embedRoot } = messageEmbed();
9
+ const { root: embedRoot } = messageEmbed({ size: "content" });
10
10
  const defaultProps = { className: embedRoot({ className: root({ className }) }) };
11
11
  return useRender({
12
12
  defaultTagName: "button",
@@ -4,7 +4,7 @@ const messageReplies = tv({ slots: {
4
4
  root: [
5
5
  "group/message-replies flex min-w-0 w-full flex-col text-left",
6
6
  "transition-colors focus-visible:keyboard:outline-1 focus-visible:keyboard:outline-line-strong",
7
- "mt-2 max-w-[480px] gap-1 rounded-container border-0 px-2.5 py-2",
7
+ "mt-2 gap-1 border-0 px-2.5 py-2",
8
8
  "bg-fill-muted text-foreground-muted hover:overlay-subtle active:overlay-medium",
9
9
  "focus-visible:outline-none focus-visible:shadow-focus"
10
10
  ],
@@ -19,19 +19,32 @@ export declare function MobileNavServerItem({ className, id, ref, onClick, onCon
19
19
  export type MobileNavServerPopoverContentProps = PopoverContentProps;
20
20
  /**
21
21
  * The popover above the tab bar, 8px from each side of it and 8px above it,
22
- * as tall as its content and at most 60% of the screen. It stops below the
23
- * top safe area (a notch in a standalone web app): Base UI's collision padding
24
- * takes only pixels, so the height cap subtracts `env(safe-area-inset-top)`.
25
- * The bottom needs none: the tab bar under the popover already pads the
26
- * bottom safe area. A column:
22
+ * as tall as its content and at most 60% of the screen. The one exception:
23
+ * the list always keeps one whole server row, so where the parts after it
24
+ * leave less, the popover grows past 60% as far as that row needs (the
25
+ * floor, measured from its children into `--mobile-nav-server-popover-floor`).
26
+ * Where even that doesn't fit, the whole popover scrolls, the footer and the
27
+ * pages with it: the children sit in a ScrollArea
28
+ * (`data-slot="mobile-nav-server-popover-scroll"`) inside the popup. It stops below the top safe area (a notch in a standalone
29
+ * web app): Base UI's collision padding takes only pixels, so the height cap
30
+ * subtracts `env(safe-area-inset-top)`. The bottom needs none: the tab bar
31
+ * under the popover already pads the bottom safe area. A column:
27
32
  * `MobileNavServerPopoverList` takes the room left and scrolls, and the
28
33
  * destinations and the footer after it stay in view.
34
+ *
35
+ * Focus on open goes to the current server's row (`aria-current="true"` in
36
+ * the list), which the list has already scrolled into view, so focusing it
37
+ * never scrolls the list back to the top. A touch opens it with focus on the
38
+ * popover itself, without scrolling, so no keyboard comes up. `initialFocus`
39
+ * overrides this.
29
40
  */
30
- export declare function MobileNavServerPopoverContent({ anchor, side, align, sideOffset, collisionPadding, className, ...props }: MobileNavServerPopoverContentProps): import("react").JSX.Element;
41
+ export declare function MobileNavServerPopoverContent({ anchor, side, align, sideOffset, collisionPadding, initialFocus, className, children, ref, ...props }: MobileNavServerPopoverContentProps): import("react").JSX.Element;
31
42
  export type MobileNavServerPopoverListProps = ScrollAreaProps;
32
43
  /** The server list: takes the room left in the popover and scrolls inside it,
33
- * a ScrollArea (a column with no gap, so its gutters move nothing). */
34
- export declare function MobileNavServerPopoverList({ className, ...props }: MobileNavServerPopoverListProps): import("react").JSX.Element;
44
+ * a ScrollArea (a column with no gap, so its gutters move nothing). It is
45
+ * never shorter than one whole two-line row, and it opens scrolled to the
46
+ * current server's row (`aria-current="true"`), with no animation. */
47
+ export declare function MobileNavServerPopoverList({ className, ref, ...props }: MobileNavServerPopoverListProps): import("react").JSX.Element;
35
48
  export type MobileNavServerPopoverGroupProps = ComponentPropsWithRef<"div">;
36
49
  /** Rows that always stay in view, such as the footer actions. */
37
50
  export declare function MobileNavServerPopoverGroup({ className, ...props }: MobileNavServerPopoverGroupProps): import("react").JSX.Element;