ai-design-system 0.1.98 → 0.1.99

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.
@@ -49,6 +49,8 @@ function getStoryStatusStyle(status?: StoryItem["status"]) {
49
49
 
50
50
  export const StoriesBar = React.forwardRef<HTMLDivElement, StoriesBarProps>(
51
51
  ({ stories, activeStoryId, onStoryClick, defaultIcon = "clapperboard", className, ...props }, ref) => {
52
+ const hasActiveStory = Boolean(activeStoryId);
53
+
52
54
  return (
53
55
  <div
54
56
  ref={ref}
@@ -68,16 +70,19 @@ export const StoriesBar = React.forwardRef<HTMLDivElement, StoriesBarProps>(
68
70
  key={story.id}
69
71
  variant="ghost"
70
72
  onClick={() => onStoryClick(story)}
71
- className="flex flex-col items-center gap-1 h-auto p-0 hover:bg-transparent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring rounded-lg cursor-pointer group shrink-0"
73
+ className={cn(
74
+ "flex flex-col items-center gap-1 h-auto p-0 hover:bg-transparent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring rounded-lg cursor-pointer group shrink-0 transition-all duration-200",
75
+ hasActiveStory && (isActive ? "opacity-100 scale-105" : "opacity-35 hover:opacity-60")
76
+ )}
72
77
  data-testid={`btn-story-${story.id}`}
73
78
  aria-label={`Open story: ${story.title}`}
74
79
  >
75
80
  <div className="relative w-9 h-9 shrink-0 aspect-square rounded-full transition-transform group-hover:scale-105">
76
81
  <div
77
82
  className={cn(
78
- "w-full h-full rounded-full flex items-center justify-center border transition-colors overflow-hidden select-none",
83
+ "w-full h-full rounded-full flex items-center justify-center border transition-all overflow-hidden select-none",
79
84
  isActive
80
- ? "border-primary bg-muted/60"
85
+ ? "border-primary bg-muted/60 ring-2 ring-primary/60 shadow-lg shadow-primary/40"
81
86
  : "border-border/50 bg-muted/40"
82
87
  )}
83
88
  >
@@ -411,4 +411,26 @@ export const WithImageAndAudioAttachments: Story = {
411
411
  },
412
412
  };
413
413
 
414
+ /**
415
+ * Sheet Presentation - Floating bottom-sheet modal overlay
416
+ */
417
+ export const SheetPresentation: Story = {
418
+ args: {
419
+ variant: "sheet",
420
+ messages: inputStateMessages,
421
+ sessionTitle: "Video Generation Session",
422
+ placeholder: "Ask a question or describe a task...",
423
+ onSubmit: (msg: PromptInputMessage) => console.log("Submitted:", msg),
424
+ onClose: () => alert("Close sheet triggered"),
425
+ },
426
+ parameters: {
427
+ docs: {
428
+ description: {
429
+ story:
430
+ "Floating bottom-sheet panel presentation with frosted backdrop blur overlay, elevated surface, and grab handle.",
431
+ },
432
+ },
433
+ },
434
+ };
435
+
414
436
 
@@ -213,6 +213,18 @@ export interface ChatPanelProps {
213
213
  * @default true
214
214
  */
215
215
  showSessionActions?: boolean;
216
+ /**
217
+ * Presentation variant for ChatPanel:
218
+ * - "default": standard full flex-1 panel (default)
219
+ * - "sheet": elevated floating bottom-sheet panel with frosted backdrop blur overlay,
220
+ * rounded surface, shadow, grab handle, and dismiss backdrop click.
221
+ * @default "default"
222
+ */
223
+ variant?: "default" | "sheet";
224
+ /**
225
+ * Callback fired when clicking the backdrop overlay or dismissing the sheet (when variant="sheet")
226
+ */
227
+ onClose?: () => void;
216
228
  }
217
229
 
218
230
  /**
@@ -260,6 +272,8 @@ export const ChatPanel = React.memo<ChatPanelProps>(
260
272
  showHeader = true,
261
273
  sessionTitle,
262
274
  showSessionActions = true,
275
+ variant = "default",
276
+ onClose,
263
277
  }) => {
264
278
  // File change queue state
265
279
  const [fileChangeState, setFileChangeState] = React.useState<
@@ -411,8 +425,8 @@ export const ChatPanel = React.memo<ChatPanelProps>(
411
425
  );
412
426
  }, [loading, messages]);
413
427
 
414
- return (
415
- <div className={`relative flex h-full flex-col ${className || ""}`}>
428
+ const chatContent = (
429
+ <div className={cn("relative flex h-full flex-col", variant !== "sheet" && className)}>
416
430
  {/* Chat Session Header */}
417
431
  {showHeader && (
418
432
  <SessionHeader
@@ -470,6 +484,40 @@ export const ChatPanel = React.memo<ChatPanelProps>(
470
484
  </div>
471
485
  </div>
472
486
  );
487
+
488
+ if (variant === "sheet") {
489
+ return (
490
+ <div
491
+ className="absolute inset-0 z-50 flex flex-col justify-end backdrop-blur-md bg-black/60"
492
+ data-testid="story-chat-head-overlay"
493
+ >
494
+ <div
495
+ className="absolute inset-0 cursor-pointer"
496
+ onClick={onClose}
497
+ data-testid="story-chat-head-backdrop"
498
+ aria-label="Close sheet"
499
+ />
500
+ <div
501
+ className={cn(
502
+ "relative z-10 flex flex-col bg-card rounded-2xl border border-border shadow-2xl h-[85%] mx-4 mb-4 overflow-hidden",
503
+ className
504
+ )}
505
+ data-testid="story-chat-head-popup"
506
+ >
507
+ <div
508
+ className="w-9 h-1 rounded-full bg-muted-foreground/30 mx-auto mt-2.5 mb-1 shrink-0"
509
+ data-testid="story-sheet-handle"
510
+ aria-hidden="true"
511
+ />
512
+ <div className="flex-1 flex flex-col min-h-0">
513
+ {chatContent}
514
+ </div>
515
+ </div>
516
+ </div>
517
+ );
518
+ }
519
+
520
+ return chatContent;
473
521
  }
474
522
  );
475
523
 
package/dist/index.cjs CHANGED
@@ -8042,7 +8042,9 @@ var ChatPanel = React3__namespace.memo(
8042
8042
  enableSpeech = true,
8043
8043
  showHeader = true,
8044
8044
  sessionTitle,
8045
- showSessionActions = true
8045
+ showSessionActions = true,
8046
+ variant = "default",
8047
+ onClose
8046
8048
  }) => {
8047
8049
  const [fileChangeState, setFileChangeState] = React3__namespace.useState("approval-requested");
8048
8050
  const [approval, setApproval] = React3__namespace.useState({});
@@ -8160,7 +8162,7 @@ var ChatPanel = React3__namespace.memo(
8160
8162
  }
8161
8163
  );
8162
8164
  }, [loading, messages]);
8163
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `relative flex h-full flex-col ${className || ""}`, children: [
8165
+ const chatContent = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative flex h-full flex-col", variant !== "sheet" && className), children: [
8164
8166
  showHeader && /* @__PURE__ */ jsxRuntime.jsx(
8165
8167
  SessionHeader,
8166
8168
  {
@@ -8221,6 +8223,48 @@ var ChatPanel = React3__namespace.memo(
8221
8223
  )
8222
8224
  ] })
8223
8225
  ] });
8226
+ if (variant === "sheet") {
8227
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8228
+ "div",
8229
+ {
8230
+ className: "absolute inset-0 z-50 flex flex-col justify-end backdrop-blur-md bg-black/60",
8231
+ "data-testid": "story-chat-head-overlay",
8232
+ children: [
8233
+ /* @__PURE__ */ jsxRuntime.jsx(
8234
+ "div",
8235
+ {
8236
+ className: "absolute inset-0 cursor-pointer",
8237
+ onClick: onClose,
8238
+ "data-testid": "story-chat-head-backdrop",
8239
+ "aria-label": "Close sheet"
8240
+ }
8241
+ ),
8242
+ /* @__PURE__ */ jsxRuntime.jsxs(
8243
+ "div",
8244
+ {
8245
+ className: cn(
8246
+ "relative z-10 flex flex-col bg-card rounded-2xl border border-border shadow-2xl h-[85%] mx-4 mb-4 overflow-hidden",
8247
+ className
8248
+ ),
8249
+ "data-testid": "story-chat-head-popup",
8250
+ children: [
8251
+ /* @__PURE__ */ jsxRuntime.jsx(
8252
+ "div",
8253
+ {
8254
+ className: "w-9 h-1 rounded-full bg-muted-foreground/30 mx-auto mt-2.5 mb-1 shrink-0",
8255
+ "data-testid": "story-sheet-handle",
8256
+ "aria-hidden": "true"
8257
+ }
8258
+ ),
8259
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex flex-col min-h-0", children: chatContent })
8260
+ ]
8261
+ }
8262
+ )
8263
+ ]
8264
+ }
8265
+ );
8266
+ }
8267
+ return chatContent;
8224
8268
  }
8225
8269
  );
8226
8270
  ChatPanel.displayName = "ChatPanel";
@@ -14421,6 +14465,7 @@ function getStoryStatusStyle(status) {
14421
14465
  var StoriesBar = React3__namespace.forwardRef(
14422
14466
  (_a, ref) => {
14423
14467
  var _b = _a, { stories, activeStoryId, onStoryClick, defaultIcon = "clapperboard", className } = _b, props = __objRest(_b, ["stories", "activeStoryId", "onStoryClick", "defaultIcon", "className"]);
14468
+ const hasActiveStory = Boolean(activeStoryId);
14424
14469
  return /* @__PURE__ */ jsxRuntime.jsx(
14425
14470
  "div",
14426
14471
  __spreadProps(__spreadValues({
@@ -14438,7 +14483,10 @@ var StoriesBar = React3__namespace.forwardRef(
14438
14483
  {
14439
14484
  variant: "ghost",
14440
14485
  onClick: () => onStoryClick(story),
14441
- className: "flex flex-col items-center gap-1 h-auto p-0 hover:bg-transparent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring rounded-lg cursor-pointer group shrink-0",
14486
+ className: cn(
14487
+ "flex flex-col items-center gap-1 h-auto p-0 hover:bg-transparent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring rounded-lg cursor-pointer group shrink-0 transition-all duration-200",
14488
+ hasActiveStory && (isActive ? "opacity-100 scale-105" : "opacity-35 hover:opacity-60")
14489
+ ),
14442
14490
  "data-testid": `btn-story-${story.id}`,
14443
14491
  "aria-label": `Open story: ${story.title}`,
14444
14492
  children: [
@@ -14447,8 +14495,8 @@ var StoriesBar = React3__namespace.forwardRef(
14447
14495
  "div",
14448
14496
  {
14449
14497
  className: cn(
14450
- "w-full h-full rounded-full flex items-center justify-center border transition-colors overflow-hidden select-none",
14451
- isActive ? "border-primary bg-muted/60" : "border-border/50 bg-muted/40"
14498
+ "w-full h-full rounded-full flex items-center justify-center border transition-all overflow-hidden select-none",
14499
+ isActive ? "border-primary bg-muted/60 ring-2 ring-primary/60 shadow-lg shadow-primary/40" : "border-border/50 bg-muted/40"
14452
14500
  ),
14453
14501
  children: story.thumbnailUrl ? /* @__PURE__ */ jsxRuntime.jsx(
14454
14502
  "img",