ai-design-system 0.1.56 → 0.1.57

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.
@@ -2,6 +2,8 @@ import * as React from "react"
2
2
  import { SidebarTrigger } from "@/components/primitives/Sidebar"
3
3
  import { Separator } from "@/components/primitives/Separator"
4
4
  import { Tabs, TabsList, TabsTrigger } from "@/components/primitives/Tabs"
5
+ import { ChatToggleButton } from "@/components/composites/ChatToggleButton"
6
+ import { WorkflowSwitcher } from "@/components/composites/WorkflowSwitcher"
5
7
  import type { AppHeaderProps } from "./interfaces"
6
8
 
7
9
  export const AppHeader = React.memo<AppHeaderProps>(({
@@ -13,14 +15,16 @@ export const AppHeader = React.memo<AppHeaderProps>(({
13
15
  className,
14
16
  tabsPosition = 'center',
15
17
  showSidebarToggle = true,
16
- showTitle = true
18
+ showTitle = true,
19
+ workflowSwitcherProps,
20
+ chatToggleProps
17
21
  }) => {
18
22
  return (
19
23
  <header className={`flex h-14 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-14 ${className || ""}`}>
20
24
  <div className="grid w-full grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center px-4 lg:px-6">
21
25
  <div className="min-w-0 flex items-center gap-1 lg:gap-2">
22
26
  {showSidebarToggle && <SidebarTrigger className="-ml-1" />}
23
- {showSidebarToggle && showTitle && title && (
27
+ {showSidebarToggle && (showTitle && title || workflowSwitcherProps || chatToggleProps) && (
24
28
  <Separator orientation="vertical" className="mx-2 data-[orientation=vertical]:h-4" />
25
29
  )}
26
30
  {showTitle && title && (
@@ -28,6 +32,8 @@ export const AppHeader = React.memo<AppHeaderProps>(({
28
32
  ? <h1 className="max-w-[28rem] truncate text-base font-medium">{title}</h1>
29
33
  : title
30
34
  )}
35
+ {chatToggleProps && <ChatToggleButton {...chatToggleProps} />}
36
+ {workflowSwitcherProps && <WorkflowSwitcher {...workflowSwitcherProps} />}
31
37
  </div>
32
38
 
33
39
  <div className="justify-self-center">
@@ -1,4 +1,6 @@
1
1
  import type React from "react";
2
+ import type { WorkflowSwitcherProps } from "@/components/composites/WorkflowSwitcher/WorkflowSwitcher";
3
+ import type { ChatToggleButtonProps } from "@/components/composites/ChatToggleButton/ChatToggleButton";
2
4
 
3
5
  export interface TabItem {
4
6
  value: string;
@@ -15,4 +17,6 @@ export interface AppHeaderProps {
15
17
  className?: string;
16
18
  showSidebarToggle?: boolean;
17
19
  showTitle?: boolean;
20
+ workflowSwitcherProps?: WorkflowSwitcherProps;
21
+ chatToggleProps?: ChatToggleButtonProps;
18
22
  }
@@ -0,0 +1,32 @@
1
+ import * as React from "react"
2
+ import type { Meta, StoryObj } from "@storybook/react"
3
+ import { WorkflowSwitcher } from "./WorkflowSwitcher"
4
+
5
+ const meta: Meta<typeof WorkflowSwitcher> = {
6
+ title: "Composites/WorkflowSwitcher",
7
+ component: WorkflowSwitcher,
8
+ parameters: {
9
+ layout: "centered",
10
+ },
11
+ args: {
12
+ workflows: [
13
+ { id: "1", name: "Alpha Workflow" },
14
+ { id: "2", name: "Beta Workflow" },
15
+ { id: "3", name: "Gamma Workflow" },
16
+ ],
17
+ currentWorkflowId: "1",
18
+ onSelectWorkflow: () => {},
19
+ },
20
+ }
21
+
22
+ export default meta
23
+ type Story = StoryObj<typeof WorkflowSwitcher>
24
+
25
+ export const Default: Story = {}
26
+
27
+ export const Empty: Story = {
28
+ args: {
29
+ workflows: [],
30
+ currentWorkflowId: undefined,
31
+ },
32
+ }
@@ -0,0 +1,66 @@
1
+ import * as React from "react"
2
+ import { Button } from "@/components/primitives/Button"
3
+ import {
4
+ DropdownMenu,
5
+ DropdownMenuContent,
6
+ DropdownMenuItem,
7
+ DropdownMenuTrigger,
8
+ } from "@/components/primitives/DropdownMenu"
9
+ import { Icon } from "@/components/primitives/Icon"
10
+
11
+ export interface WorkflowItem {
12
+ id: string
13
+ name: string
14
+ }
15
+
16
+ export interface WorkflowSwitcherProps {
17
+ workflows: WorkflowItem[]
18
+ currentWorkflowId?: string | null
19
+ onSelectWorkflow: (id: string) => void
20
+ className?: string
21
+ }
22
+
23
+ export const WorkflowSwitcher = React.memo<WorkflowSwitcherProps>(
24
+ ({ workflows, currentWorkflowId, onSelectWorkflow, className }) => {
25
+ const currentWorkflow = workflows.find((w) => w.id === currentWorkflowId)
26
+
27
+ return (
28
+ <div className={className}>
29
+ <DropdownMenu>
30
+ <DropdownMenuTrigger asChild>
31
+ <Button
32
+ className="h-9 border hover:bg-black/5 dark:hover:bg-white/5"
33
+ size="sm"
34
+ title="Select workflow"
35
+ variant="secondary"
36
+ >
37
+ <span className="truncate max-w-[150px]">
38
+ {currentWorkflow?.name ?? "Select Workflow"}
39
+ </span>
40
+ <Icon name="chevron-down" size="xs" className="ml-1 opacity-50 shrink-0" />
41
+ </Button>
42
+ </DropdownMenuTrigger>
43
+ <DropdownMenuContent align="start">
44
+ {workflows.map((w) => (
45
+ <DropdownMenuItem
46
+ className="flex items-center justify-between"
47
+ key={w.id}
48
+ onClick={() => onSelectWorkflow(w.id)}
49
+ >
50
+ <span className="truncate pr-4">{w.name}</span>
51
+ {w.id === currentWorkflowId && <Icon name="check" size="sm" className="ml-auto shrink-0" />}
52
+ </DropdownMenuItem>
53
+ ))}
54
+ {workflows.length === 0 && (
55
+ <div className="px-2 py-1.5 text-sm text-muted-foreground text-center">
56
+ No workflows found
57
+ </div>
58
+ )}
59
+ </DropdownMenuContent>
60
+ </DropdownMenu>
61
+ </div>
62
+ )
63
+ }
64
+ )
65
+
66
+ WorkflowSwitcher.displayName = "WorkflowSwitcher"
@@ -0,0 +1 @@
1
+ export * from "./WorkflowSwitcher"
@@ -115,11 +115,16 @@ export function WorkflowToolbar({
115
115
  {/* Left: workflow name text + version dropdown */}
116
116
  <div className="flex items-center gap-2">
117
117
  {/* Plain text title */}
118
- <div className="flex h-9 items-center rounded-md border bg-secondary px-3 text-secondary-foreground">
119
- <span className="truncate font-medium text-sm">
120
- {workflowName || "Untitled Workflow"}
121
- </span>
122
- </div>
118
+ {
119
+ workflowName && (
120
+ <div className="flex h-9 items-center rounded-md border bg-secondary px-3 text-secondary-foreground">
121
+ <span className="truncate font-medium text-sm">
122
+ {workflowName || ""}
123
+ </span>
124
+ </div>
125
+ )
126
+ }
127
+
123
128
 
124
129
  {/* Version selector — only shown when versions are provided */}
125
130
  {versions && versions.length > 0 && (
@@ -190,3 +190,7 @@ export type { PromptInputBlockProps } from './PromptInput'
190
190
  // ChatToggleButton Composite
191
191
  export { ChatToggleButton } from './ChatToggleButton'
192
192
  export type { ChatToggleButtonProps } from './ChatToggleButton'
193
+
194
+ // WorkflowSwitcher Composite
195
+ export { WorkflowSwitcher } from './WorkflowSwitcher'
196
+ export type { WorkflowSwitcherProps, WorkflowItem } from './WorkflowSwitcher'
@@ -22,3 +22,5 @@ export type { ExternalToast, ToastT, ToasterProps } from 'sonner';
22
22
 
23
23
  // Utilities
24
24
  export { cn } from '@/lib/utils';
25
+ export { WorkflowSwitcher } from './composites';
26
+ export type { WorkflowSwitcherProps, WorkflowItem } from './composites';
package/dist/index.cjs CHANGED
@@ -1951,6 +1951,74 @@ var Tabs2 = React3__namespace.forwardRef((props, ref) => {
1951
1951
  return /* @__PURE__ */ jsxRuntime.jsx(Tabs, __spreadValues({}, props));
1952
1952
  });
1953
1953
  Tabs2.displayName = "Tabs";
1954
+ var Button2 = React3__namespace.memo(
1955
+ React3__namespace.forwardRef(
1956
+ (props, ref) => {
1957
+ return /* @__PURE__ */ jsxRuntime.jsx(Button, __spreadValues({ ref }, props));
1958
+ }
1959
+ )
1960
+ );
1961
+ Button2.displayName = "Button";
1962
+ function ChatToggleButton(_a) {
1963
+ var _b = _a, {
1964
+ isOpen = true,
1965
+ label = "Hide Chat",
1966
+ className
1967
+ } = _b, props = __objRest(_b, [
1968
+ "isOpen",
1969
+ "label",
1970
+ "className"
1971
+ ]);
1972
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1973
+ Button2,
1974
+ __spreadProps(__spreadValues({
1975
+ variant: "ghost",
1976
+ className: `-ml-2 h-8 text-muted-foreground hover:text-foreground ${className != null ? className : ""}`
1977
+ }, props), {
1978
+ children: [
1979
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "panel-left", size: "sm" }),
1980
+ label
1981
+ ]
1982
+ })
1983
+ );
1984
+ }
1985
+ var WorkflowSwitcher = React3__namespace.memo(
1986
+ ({ workflows, currentWorkflowId, onSelectWorkflow, className }) => {
1987
+ var _a;
1988
+ const currentWorkflow = workflows.find((w) => w.id === currentWorkflowId);
1989
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu2, { children: [
1990
+ /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
1991
+ Button2,
1992
+ {
1993
+ className: "h-9 border hover:bg-black/5 dark:hover:bg-white/5",
1994
+ size: "sm",
1995
+ title: "Select workflow",
1996
+ variant: "secondary",
1997
+ children: [
1998
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate max-w-[150px]", children: (_a = currentWorkflow == null ? void 0 : currentWorkflow.name) != null ? _a : "Select Workflow" }),
1999
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "chevron-down", size: "xs", className: "ml-1 opacity-50 shrink-0" })
2000
+ ]
2001
+ }
2002
+ ) }),
2003
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuContent, { align: "start", children: [
2004
+ workflows.map((w) => /* @__PURE__ */ jsxRuntime.jsxs(
2005
+ DropdownMenuItem,
2006
+ {
2007
+ className: "flex items-center justify-between",
2008
+ onClick: () => onSelectWorkflow(w.id),
2009
+ children: [
2010
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate pr-4", children: w.name }),
2011
+ w.id === currentWorkflowId && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "check", size: "sm", className: "ml-auto shrink-0" })
2012
+ ]
2013
+ },
2014
+ w.id
2015
+ )),
2016
+ workflows.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 py-1.5 text-sm text-muted-foreground text-center", children: "No workflows found" })
2017
+ ] })
2018
+ ] }) });
2019
+ }
2020
+ );
2021
+ WorkflowSwitcher.displayName = "WorkflowSwitcher";
1954
2022
  var AppHeader = React3__namespace.memo(({
1955
2023
  title,
1956
2024
  actions,
@@ -1960,14 +2028,18 @@ var AppHeader = React3__namespace.memo(({
1960
2028
  className,
1961
2029
  tabsPosition = "center",
1962
2030
  showSidebarToggle = true,
1963
- showTitle = true
2031
+ showTitle = true,
2032
+ workflowSwitcherProps,
2033
+ chatToggleProps
1964
2034
  }) => {
1965
2035
  var _a, _b;
1966
2036
  return /* @__PURE__ */ jsxRuntime.jsx("header", { className: `flex h-14 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-14 ${className || ""}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid w-full grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center px-4 lg:px-6", children: [
1967
2037
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex items-center gap-1 lg:gap-2", children: [
1968
2038
  showSidebarToggle && /* @__PURE__ */ jsxRuntime.jsx(SidebarTrigger2, { className: "-ml-1" }),
1969
- showSidebarToggle && showTitle && title && /* @__PURE__ */ jsxRuntime.jsx(Separator3, { orientation: "vertical", className: "mx-2 data-[orientation=vertical]:h-4" }),
1970
- showTitle && title && (typeof title === "string" ? /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "max-w-[28rem] truncate text-base font-medium", children: title }) : title)
2039
+ showSidebarToggle && (showTitle && title || workflowSwitcherProps || chatToggleProps) && /* @__PURE__ */ jsxRuntime.jsx(Separator3, { orientation: "vertical", className: "mx-2 data-[orientation=vertical]:h-4" }),
2040
+ showTitle && title && (typeof title === "string" ? /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "max-w-[28rem] truncate text-base font-medium", children: title }) : title),
2041
+ chatToggleProps && /* @__PURE__ */ jsxRuntime.jsx(ChatToggleButton, __spreadValues({}, chatToggleProps)),
2042
+ workflowSwitcherProps && /* @__PURE__ */ jsxRuntime.jsx(WorkflowSwitcher, __spreadValues({}, workflowSwitcherProps))
1971
2043
  ] }),
1972
2044
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "justify-self-center", children: tabsPosition === "center" && tabs && tabs.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Tabs2, { defaultValue: defaultTab || ((_a = tabs[0]) == null ? void 0 : _a.value), onValueChange: onTabChange, children: /* @__PURE__ */ jsxRuntime.jsx(TabsList, { children: tabs.map((tab) => /* @__PURE__ */ jsxRuntime.jsx(TabsTrigger, { value: tab.value, children: tab.label }, tab.value)) }) }) }),
1973
2045
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center justify-end gap-2", children: [
@@ -2075,14 +2147,6 @@ var PageContainer = React3__namespace.memo(({ children, className }) => {
2075
2147
  return /* @__PURE__ */ jsxRuntime.jsx(SidebarInset2, { className, children });
2076
2148
  });
2077
2149
  PageContainer.displayName = "PageContainer";
2078
- var Button2 = React3__namespace.memo(
2079
- React3__namespace.forwardRef(
2080
- (props, ref) => {
2081
- return /* @__PURE__ */ jsxRuntime.jsx(Button, __spreadValues({ ref }, props));
2082
- }
2083
- )
2084
- );
2085
- Button2.displayName = "Button";
2086
2150
  function Dialog(_a) {
2087
2151
  var props = __objRest(_a, []);
2088
2152
  return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Root, __spreadValues({ "data-slot": "dialog" }, props));
@@ -2510,29 +2574,6 @@ var ProjectSwitcher = React3__namespace.memo(
2510
2574
  }
2511
2575
  );
2512
2576
  ProjectSwitcher.displayName = "ProjectSwitcher";
2513
- function ChatToggleButton(_a) {
2514
- var _b = _a, {
2515
- isOpen = true,
2516
- label = "Hide Chat",
2517
- className
2518
- } = _b, props = __objRest(_b, [
2519
- "isOpen",
2520
- "label",
2521
- "className"
2522
- ]);
2523
- return /* @__PURE__ */ jsxRuntime.jsxs(
2524
- Button2,
2525
- __spreadProps(__spreadValues({
2526
- variant: "ghost",
2527
- className: `-ml-2 h-8 text-muted-foreground hover:text-foreground ${className != null ? className : ""}`
2528
- }, props), {
2529
- children: [
2530
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "panel-left", size: "sm" }),
2531
- label
2532
- ]
2533
- })
2534
- );
2535
- }
2536
2577
  var EmptyState = React3__namespace.forwardRef(
2537
2578
  ({ title, description, actionLabel, onAction, className }, ref) => {
2538
2579
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -9915,7 +9956,7 @@ function WorkflowToolbar({
9915
9956
  const currentVersion = versions == null ? void 0 : versions.find((v) => v.id === currentVersionId);
9916
9957
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center justify-between gap-4", className), children: [
9917
9958
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
9918
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-9 items-center rounded-md border bg-secondary px-3 text-secondary-foreground", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium text-sm", children: workflowName || "Untitled Workflow" }) }),
9959
+ workflowName && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-9 items-center rounded-md border bg-secondary px-3 text-secondary-foreground", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium text-sm", children: workflowName || "" }) }),
9919
9960
  versions && versions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu2, { children: [
9920
9961
  /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
9921
9962
  Button2,
@@ -12426,6 +12467,7 @@ exports.SectionLayout = SectionLayout;
12426
12467
  exports.SpecNavigator = SpecNavigator;
12427
12468
  exports.WorkflowBuilder = WorkflowBuilder;
12428
12469
  exports.WorkflowObservabilityFeature = WorkflowObservabilityFeature;
12470
+ exports.WorkflowSwitcher = WorkflowSwitcher;
12429
12471
  exports.cn = cn;
12430
12472
  exports.getLayoutedElements = getLayoutedElements;
12431
12473
  //# sourceMappingURL=index.cjs.map