Skip to content

Commit 6ce864e

Browse files
authored
feat(ui): add agent share button (#1323)
Signed-off-by: Petr Kadlec <petr@puradesign.cz>
1 parent de40ff1 commit 6ce864e

File tree

4 files changed

+61
-9
lines changed

4 files changed

+61
-9
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Copyright 2025 © BeeAI a Series of LF Projects, LLC
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import { Share } from '@carbon/icons-react';
7+
import { Button } from '@carbon/react';
8+
import { useCopyToClipboard } from 'usehooks-ts';
9+
10+
import { useToast } from '#contexts/Toast/index.ts';
11+
import type { Agent } from '#modules/agents/api/types.ts';
12+
import { routes } from '#utils/router.ts';
13+
14+
interface Props {
15+
agent: Agent;
16+
}
17+
18+
export function AgentShareButton({ agent }: Props) {
19+
const [, copy] = useCopyToClipboard();
20+
const { addToast } = useToast();
21+
22+
const handleShare = () => {
23+
copy(`${window.location.origin}${routes.agentRun({ providerId: agent.provider.id })}`);
24+
addToast({ kind: 'info', title: 'Link has been copied to clipboard!' });
25+
};
26+
27+
return (
28+
<Button kind="tertiary" size="sm" renderIcon={Share} onClick={handleShare}>
29+
Share agent
30+
</Button>
31+
);
32+
}

apps/beeai-ui/src/components/AppHeader/AppHeader.module.scss

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
line-height: math.div(20, 14);
2929
}
3030

31-
.agentDetailButtonContainer {
32-
text-align: end;
31+
.buttons {
32+
display: flex;
33+
justify-content: flex-end;
34+
gap: $spacing-03;
3335
}

apps/beeai-ui/src/components/AppHeader/AppHeader.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { isNotNull } from '#utils/helpers.ts';
1414

1515
import { Container } from '../layouts/Container';
1616
import { AgentDetailButton } from './AgentDetailButton';
17+
import { AgentShareButton } from './AgentShareButton';
1718
import classes from './AppHeader.module.scss';
1819
import { AppHeaderNav } from './AppHeaderNav';
1920

@@ -39,7 +40,8 @@ export function AppHeader({ className }: Props) {
3940
<>
4041
<p className={classes.agentName}>{agent.name}</p>
4142

42-
<div className={classes.agentDetailButtonContainer}>
43+
<div className={classes.buttons}>
44+
<AgentShareButton agent={agent} />
4345
<AgentDetailButton />
4446
</div>
4547
</>

apps/beeai-ui/src/components/Tooltip/Tooltip.tsx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,19 @@ interface Props {
3434
placement?: Placement;
3535
size?: 'sm' | 'md' | 'lg';
3636
asChild?: boolean;
37+
isEnabled?: boolean;
38+
isOpen?: boolean;
3739
}
3840

39-
export function Tooltip({ content, placement = 'bottom', size = 'md', asChild, children }: PropsWithChildren<Props>) {
41+
export function Tooltip({
42+
content,
43+
placement = 'bottom',
44+
size = 'md',
45+
asChild,
46+
isEnabled = true,
47+
isOpen: isOpenControlled,
48+
children,
49+
}: PropsWithChildren<Props>) {
4050
const arrowRef = useRef(null);
4151

4252
const SIZE = {
@@ -59,10 +69,12 @@ export function Tooltip({ content, placement = 'bottom', size = 'md', asChild, c
5969

6070
const [isOpen, setIsOpen] = useState(false);
6171

72+
const isControlled = isOpenControlled !== undefined;
73+
6274
const { refs, floatingStyles, context } = useFloating({
6375
placement,
64-
open: isOpen,
65-
onOpenChange: setIsOpen,
76+
open: isControlled ? isOpenControlled : isOpen,
77+
onOpenChange: isControlled ? undefined : setIsOpen,
6678
whileElementsMounted: autoUpdate,
6779
middleware: [
6880
offset(SIZE.ArrowHeight + SIZE.Offset),
@@ -76,8 +88,12 @@ export function Tooltip({ content, placement = 'bottom', size = 'md', asChild, c
7688
],
7789
});
7890

79-
const hover = useHover(context, { move: false, handleClose: safePolygon() });
80-
const focus = useFocus(context);
91+
const hover = useHover(context, {
92+
move: false,
93+
handleClose: safePolygon(),
94+
enabled: !isControlled,
95+
});
96+
const focus = useFocus(context, { enabled: !isControlled });
8197
const dismiss = useDismiss(context);
8298
const role = useRole(context, { role: 'tooltip' });
8399

@@ -91,7 +107,7 @@ export function Tooltip({ content, placement = 'bottom', size = 'md', asChild, c
91107
{children}
92108
</Comp>
93109

94-
{isOpen && (
110+
{(isControlled ? isOpenControlled : isOpen) && isEnabled && (
95111
<FloatingPortal>
96112
<div
97113
ref={refs.setFloating}

0 commit comments

Comments
 (0)