Skip to content

Commit a87a444

Browse files
authored
feat: show sharing info at bottom of AppLink's tooltip (#21197)
for #19974 `ShareIcon`, which returns a MUI tooltip, had these problems: 1. There was no Storybook story which rendered the "Open external URL" tooltip 2. `AppLink` renders a button. If it has tooltip text, this button is also a Radix `TooltipTrigger`. Since `ShareIcon` is rendered as a child of the `AppLink` button, `ShareIcon`'s tooltip (a nested tooltip) was never appearing. I did try turning `ShareIcon` into a Radix tooltip as well, but I still couldn't get the nested tooltip's text to appear, and nested tooltips are not very accessible. AFAIK there's no way to focus a child element of a button. I've deleted the separate `ShareIcon` component and moved `ShareIcon`'s tooltip text to the bottom of `AppLink`'s tooltip: ## before <img width="175" height="121" alt="image" src="https://github.com/user-attachments/assets/ad17927e-c3d1-499b-83f8-a5832b777305" /> ^The `UsersIcon` on the right is a MUI tooltip trigger, but it can't receive focus. It's supposed to show the text "Shared with all authenticated users" when focused ## after <img width="228" height="121" alt="image" src="https://github.com/user-attachments/assets/adc202c1-57cd-4a80-8f94-f7f32897d286" />
1 parent 37e8b89 commit a87a444

3 files changed

Lines changed: 55 additions & 49 deletions

File tree

‎site/src/modules/resources/AppLink/AppLink.stories.tsx‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,19 @@ export const ExternalAppNotInstalled: Story = {
7777
},
7878
};
7979

80+
export const ExternalAppShareable: Story = {
81+
args: {
82+
workspace: MockWorkspace,
83+
app: {
84+
...MockWorkspaceApp,
85+
url: "vscode://open",
86+
external: true,
87+
sharing_level: "authenticated",
88+
},
89+
agent: MockWorkspaceAgent,
90+
},
91+
};
92+
8093
export const SharingLevelOwner: Story = {
8194
args: {
8295
workspace: MockWorkspace,

‎site/src/modules/resources/AppLink/AppLink.tsx‎

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,19 @@ import {
99
TooltipTrigger,
1010
} from "components/Tooltip/Tooltip";
1111
import { useProxy } from "contexts/ProxyContext";
12-
import { CircleAlertIcon } from "lucide-react";
12+
import {
13+
Building2Icon,
14+
CircleAlertIcon,
15+
GlobeIcon,
16+
type LucideIcon,
17+
SquareArrowOutUpRightIcon,
18+
UsersIcon,
19+
} from "lucide-react";
1320
import { isExternalApp, needsSessionToken } from "modules/apps/apps";
1421
import { useAppLink } from "modules/apps/useAppLink";
1522
import { type FC, type ReactNode, useState } from "react";
1623
import { AgentButton } from "../AgentButton";
1724
import { BaseIcon } from "./BaseIcon";
18-
import { ShareIcon } from "./ShareIcon";
1925

2026
export const DisplayAppNameMap: Record<TypesGen.DisplayApp, string> = {
2127
port_forwarding_helper: "Ports",
@@ -115,21 +121,32 @@ export const AppLink: FC<AppLinkProps> = ({
115121
}
116122

117123
const canShare = app.sharing_level !== "owner";
124+
const { shareTooltip, shareIcon: ShareIcon } = canShare
125+
? app.external
126+
? {
127+
shareTooltip: "Open external URL",
128+
shareIcon: SquareArrowOutUpRightIcon,
129+
}
130+
: shareDetails[app.sharing_level]
131+
: {
132+
shareTooltip: null,
133+
shareIcon: null,
134+
};
118135

119136
const button = grouped ? (
120137
<DropdownMenuItem asChild>
121138
<a href={canClick ? link.href : undefined} onClick={link.onClick}>
122139
{icon}
123140
{link.label}
124-
{canShare && <ShareIcon app={app} />}
141+
{ShareIcon && <ShareIcon />}
125142
</a>
126143
</DropdownMenuItem>
127144
) : (
128145
<AgentButton asChild>
129146
<a href={canClick ? link.href : undefined} onClick={link.onClick}>
130147
{icon}
131148
{link.label}
132-
{canShare && <ShareIcon app={app} />}
149+
{ShareIcon && <ShareIcon />}
133150
</a>
134151
</AgentButton>
135152
);
@@ -146,10 +163,31 @@ export const AppLink: FC<AppLinkProps> = ({
146163
{app.tooltip}
147164
</Markdown>
148165
) : null}
166+
{shareTooltip}
149167
</TooltipContent>
150168
</Tooltip>
151169
);
152170
}
153171

154172
return button;
155173
};
174+
175+
const shareDetails: {
176+
[SharingLevel in TypesGen.WorkspaceAppSharingLevel as Exclude<
177+
SharingLevel,
178+
"owner"
179+
>]: { shareTooltip: string; shareIcon: LucideIcon };
180+
} = {
181+
authenticated: {
182+
shareTooltip: "Shared with all authenticated users",
183+
shareIcon: UsersIcon,
184+
},
185+
organization: {
186+
shareTooltip: "Shared with organization members",
187+
shareIcon: Building2Icon,
188+
},
189+
public: {
190+
shareTooltip: "Shared publicly",
191+
shareIcon: GlobeIcon,
192+
},
193+
};

‎site/src/modules/resources/AppLink/ShareIcon.tsx‎

Lines changed: 0 additions & 45 deletions
This file was deleted.

0 commit comments

Comments
 (0)