Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4fa9d30

Browse files
refactor: update app buttons to use the new button component (#17684)
Related to#17311- Replaces the MUI Buttons by the new shadcn/ui buttons. This changeallows the reuse of app links, and terminal buttons using the `asChild`capability from the Radix components- Uses the new [proposeddesign](https://www.figma.com/design/OR75XeUI0Z3ksqt1mHsNQw/Workspace-views?node-id=1014-8242&t=wtUXJRN1SfyZiFKn-0)- Updates the button styles to support image tags as icons- Uses the new Tooltip component for the app buttons**Before:**<img width="1243" alt="Screenshot 2025-05-05 at 17 55 49"src="https://github.com/user-attachments/assets/e689e9dc-d8e1-4c9d-ba09-ef1479a501f1"/>**After:**<img width="1264" alt="Screenshot 2025-05-05 at 18 05 38"src="https://github.com/user-attachments/assets/8fafbe20-f063-46ab-86cf-2e0381bba889"/>
1 parenta7e8285 commit4fa9d30

File tree

12 files changed

+128
-167
lines changed

12 files changed

+128
-167
lines changed

‎site/e2e/helpers.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,9 @@ export async function openTerminalWindow(
10421042
):Promise<Page>{
10431043
// Wait for the web terminal to open in a new tab
10441044
constpagePromise=context.waitForEvent("page");
1045-
awaitpage.getByTestId("terminal").click({timeout:60_000});
1045+
awaitpage
1046+
.getByRole("link",{name:/terminal/i})
1047+
.click({timeout:60_000});
10461048
constterminal=awaitpagePromise;
10471049
awaitterminal.waitForLoadState("domcontentloaded");
10481050

‎site/src/components/Button/Button.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ const buttonVariants = cva(
1313
text-sm font-semibold font-medium cursor-pointer no-underline
1414
focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-content-link
1515
disabled:pointer-events-none disabled:text-content-disabled
16-
[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:p-0.5`,
16+
[&:is(a):not([href])]:pointer-events-none [&:is(a):not([href])]:text-content-disabled
17+
[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:p-0.5
18+
[&>img]:pointer-events-none [&>img]:shrink-0 [&>img]:p-0.5`,
1719
{
1820
variants:{
1921
variant:{
@@ -28,11 +30,11 @@ const buttonVariants = cva(
2830
},
2931

3032
size:{
31-
lg:"min-w-20 h-10 px-3 py-2 [&_svg]:size-icon-lg",
32-
sm:"min-w-20 h-8 px-2 py-1.5 text-xs [&_svg]:size-icon-sm",
33+
lg:"min-w-20 h-10 px-3 py-2 [&_svg]:size-icon-lg [&>img]:size-icon-lg",
34+
sm:"min-w-20 h-8 px-2 py-1.5 text-xs [&_svg]:size-icon-sm [&>img]:size-icon-sm",
3335
xs:"min-w-8 py-1 px-2 text-2xs rounded-md",
34-
icon:"size-8 px-1.5 [&_svg]:size-icon-sm",
35-
"icon-lg":"size-10 px-2 [&_svg]:size-icon-lg",
36+
icon:"size-8 px-1.5 [&_svg]:size-icon-sm [&>img]:size-icon-sm",
37+
"icon-lg":"size-10 px-2 [&_svg]:size-icon-lg [&>img]:size-icon-lg",
3638
},
3739
},
3840
defaultVariants:{

‎site/src/components/ExternalImage/ExternalImage.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ import { getExternalImageStylesFromUrl } from "theme/externalImages";
55
exportconstExternalImage=forwardRef<
66
HTMLImageElement,
77
ImgHTMLAttributes<HTMLImageElement>
8-
>((attrs,ref)=>{
8+
>((props,ref)=>{
99
consttheme=useTheme();
1010

1111
return(
12-
// biome-ignore lint/a11y/useAltText:no reasonable alt to provide
12+
// biome-ignore lint/a11y/useAltText:alt should be passed in as a prop
1313
<img
1414
ref={ref}
15-
css={getExternalImageStylesFromUrl(theme.externalImages,attrs.src)}
16-
{...attrs}
15+
css={getExternalImageStylesFromUrl(theme.externalImages,props.src)}
16+
{...props}
1717
/>
1818
);
1919
});

‎site/src/modules/dashboard/Navbar/ProxyMenu.tsx

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -81,32 +81,25 @@ export const ProxyMenu: FC<ProxyMenuProps> = ({ proxyContextValue }) => {
8181
</span>
8282

8383
{selectedProxy ?(
84-
<divcss={{display:"flex",gap:8,alignItems:"center"}}>
85-
<divcss={{width:16,height:16,lineHeight:0}}>
86-
<img
87-
// Empty alt text used because we don't want to double up on
88-
// screen reader announcements from visually-hidden span
89-
alt=""
90-
src={selectedProxy.icon_url}
91-
css={{
92-
objectFit:"contain",
93-
width:"100%",
94-
height:"100%",
95-
}}
96-
/>
97-
</div>
84+
<>
85+
<img
86+
// Empty alt text used because we don't want to double up on
87+
// screen reader announcements from visually-hidden span
88+
alt=""
89+
src={selectedProxy.icon_url}
90+
/>
9891

9992
<Latency
10093
latency={latencies?.[selectedProxy.id]?.latencyMS}
10194
isLoading={proxyLatencyLoading(selectedProxy)}
10295
size={24}
10396
/>
104-
</div>
97+
</>
10598
) :(
10699
"Select Proxy"
107100
)}
108101

109-
<ChevronDownIconclassName="text-content-primary !size-icon-xs"/>
102+
<ChevronDownIconclassName="text-content-primary !size-icon-sm"/>
110103
</Button>
111104

112105
<Menu

‎site/src/modules/management/OrganizationSidebarView.tsx

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,25 +62,23 @@ export const OrganizationSidebarView: FC<
6262
<Button
6363
variant="outline"
6464
aria-expanded={isPopoverOpen}
65-
className="w-60justify-between p-2 h-11"
65+
className="w-60gap-2 justify-start"
6666
>
67-
<divclassName="flex flex-row gap-2 items-center p-2 truncate">
68-
{activeOrganization ?(
69-
<>
70-
<Avatar
71-
size="sm"
72-
src={activeOrganization.icon}
73-
fallback={activeOrganization.display_name}
74-
/>
75-
<spanclassName="truncate">
76-
{activeOrganization.display_name||activeOrganization.name}
77-
</span>
78-
</>
79-
) :(
80-
<spanclassName="truncate">No organization selected</span>
81-
)}
82-
</div>
83-
<ChevronDown/>
67+
{activeOrganization ?(
68+
<>
69+
<Avatar
70+
size="sm"
71+
src={activeOrganization.icon}
72+
fallback={activeOrganization.display_name}
73+
/>
74+
<spanclassName="truncate">
75+
{activeOrganization.display_name||activeOrganization.name}
76+
</span>
77+
</>
78+
) :(
79+
<spanclassName="truncate">No organization selected</span>
80+
)}
81+
<ChevronDownclassName="ml-auto !size-icon-sm"/>
8482
</Button>
8583
</PopoverTrigger>
8684
<PopoverContentalign="start"className="w-60">
Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,8 @@
1-
importButton,{typeButtonProps}from"@mui/material/Button";
1+
import{Button,typeButtonProps}from"components/Button/Button";
22
import{forwardRef}from"react";
33

44
exportconstAgentButton=forwardRef<HTMLButtonElement,ButtonProps>(
55
(props,ref)=>{
6-
const{ children, ...buttonProps}=props;
7-
8-
return(
9-
<Button
10-
{...buttonProps}
11-
color="neutral"
12-
size="xlarge"
13-
variant="contained"
14-
ref={ref}
15-
css={(theme)=>({
16-
padding:"12px 20px",
17-
color:theme.palette.text.primary,
18-
// Making them smaller since those icons don't have a padding around them
19-
"& .MuiButton-startIcon, & .MuiButton-endIcon":{
20-
width:16,
21-
height:16,
22-
23-
"& svg, & img":{width:"100%",height:"100%"},
24-
},
25-
})}
26-
>
27-
{children}
28-
</Button>
29-
);
6+
return<Buttonvariant="outline"ref={ref}{...props}/>;
307
},
318
);

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

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
importLinkfrom"@mui/material/Link";
2-
importTooltipfrom"@mui/material/Tooltip";
31
importtype{
42
Workspace,
53
WorkspaceAgent,
64
WorkspaceAgentContainer,
75
}from"api/typesGenerated";
6+
import{
7+
Tooltip,
8+
TooltipContent,
9+
TooltipProvider,
10+
TooltipTrigger,
11+
}from"components/Tooltip/Tooltip";
812
import{ExternalLinkIcon}from"lucide-react";
913
importtype{FC}from"react";
1014
import{portForwardURL}from"utils/portForward";
@@ -74,29 +78,27 @@ export const AgentDevcontainerCard: FC<AgentDevcontainerCardProps> = ({
7478
constlinkDest=hasHostBind
7579
?portForwardURL(
7680
wildcardHostname,
77-
port.host_port!,
81+
port.host_port,
7882
agent.name,
7983
workspace.name,
8084
workspace.owner_name,
8185
location.protocol==="https" ?"https" :"http",
8286
)
8387
:"";
8488
return(
85-
<Tooltipkey={portLabel}title={helperText}>
86-
<span>
87-
<Link
88-
key={portLabel}
89-
color="inherit"
90-
component={AgentButton}
91-
underline="none"
92-
startIcon={<ExternalLinkIconclassName="size-icon-sm"/>}
93-
disabled={!hasHostBind}
94-
href={linkDest}
95-
>
96-
{portLabel}
97-
</Link>
98-
</span>
99-
</Tooltip>
89+
<TooltipProviderkey={portLabel}>
90+
<Tooltip>
91+
<TooltipTrigger>
92+
<AgentButtondisabled={!hasHostBind}asChild>
93+
<ahref={linkDest}>
94+
<ExternalLinkIcon/>
95+
{portLabel}
96+
</a>
97+
</AgentButton>
98+
</TooltipTrigger>
99+
<TooltipContent>{helperText}</TooltipContent>
100+
</Tooltip>
101+
</TooltipProvider>
100102
);
101103
})}
102104
</div>

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

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import{useTheme}from"@emotion/react";
22
importErrorOutlineIconfrom"@mui/icons-material/ErrorOutline";
3-
importCircularProgressfrom"@mui/material/CircularProgress";
4-
importLinkfrom"@mui/material/Link";
5-
importTooltipfrom"@mui/material/Tooltip";
63
import{API}from"api/api";
74
importtype*asTypesGenfrom"api/typesGenerated";
85
import{displayError}from"components/GlobalSnackbar/utils";
6+
import{Spinner}from"components/Spinner/Spinner";
7+
import{
8+
Tooltip,
9+
TooltipContent,
10+
TooltipProvider,
11+
TooltipTrigger,
12+
}from"components/Tooltip/Tooltip";
913
import{useProxy}from"contexts/ProxyContext";
10-
import{typeFC,typeMouseEvent,useState}from"react";
14+
import{typeFC,useState}from"react";
1115
import{createAppLinkHref}from"utils/apps";
1216
import{generateRandomString}from"utils/random";
1317
import{AgentButton}from"../AgentButton";
@@ -75,21 +79,7 @@ export const AppLink: FC<AppLinkProps> = ({ app, workspace, agent }) => {
7579

7680
letprimaryTooltip="";
7781
if(app.health==="initializing"){
78-
icon=(
79-
// This is a hack to make the spinner appear in the center of the start
80-
// icon space
81-
<span
82-
css={{
83-
display:"flex",
84-
width:"100%",
85-
height:"100%",
86-
alignItems:"center",
87-
justifyContent:"center",
88-
}}
89-
>
90-
<CircularProgresssize={14}/>
91-
</span>
92-
);
82+
icon=<Spinnerloading/>;
9383
primaryTooltip="Initializing...";
9484
}
9585
if(app.health==="unhealthy"){
@@ -112,22 +102,13 @@ export const AppLink: FC<AppLinkProps> = ({ app, workspace, agent }) => {
112102
canClick=false;
113103
}
114104

115-
constisPrivateApp=app.sharing_level==="owner";
116-
117-
return(
118-
<Tooltiptitle={primaryTooltip}>
119-
<Link
120-
color="inherit"
121-
component={AgentButton}
122-
startIcon={icon}
123-
endIcon={isPrivateApp ?undefined :<ShareIconapp={app}/>}
124-
disabled={!canClick}
125-
href={href}
126-
css={{
127-
pointerEvents:canClick ?undefined :"none",
128-
textDecoration:"none !important",
129-
}}
130-
onClick={async(event:MouseEvent<HTMLElement>)=>{
105+
constcanShare=app.sharing_level!=="owner";
106+
107+
constbutton=(
108+
<AgentButtonasChild>
109+
<a
110+
href={canClick ?href :undefined}
111+
onClick={async(event)=>{
131112
if(!canClick){
132113
return;
133114
}
@@ -187,8 +168,23 @@ export const AppLink: FC<AppLinkProps> = ({ app, workspace, agent }) => {
187168
}
188169
}}
189170
>
171+
{icon}
190172
{appDisplayName}
191-
</Link>
192-
</Tooltip>
173+
{canShare&&<ShareIconapp={app}/>}
174+
</a>
175+
</AgentButton>
193176
);
177+
178+
if(primaryTooltip){
179+
return(
180+
<TooltipProvider>
181+
<Tooltip>
182+
<TooltipTriggerasChild>{button}</TooltipTrigger>
183+
<TooltipContent>{primaryTooltip}</TooltipContent>
184+
</Tooltip>
185+
</TooltipProvider>
186+
);
187+
}
188+
189+
returnbutton;
194190
};

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

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
importLinkfrom"@mui/material/Link";
21
import{TerminalIcon}from"components/Icons/TerminalIcon";
32
importtype{FC,MouseEvent}from"react";
43
import{generateRandomString}from"utils/random";
@@ -39,23 +38,21 @@ export const TerminalLink: FC<TerminalLinkProps> = ({
3938
}/terminal?${params.toString()}`;
4039

4140
return(
42-
<Link
43-
underline="none"
44-
color="inherit"
45-
component={AgentButton}
46-
startIcon={<TerminalIcon/>}
47-
href={href}
48-
onClick={(event:MouseEvent<HTMLElement>)=>{
49-
event.preventDefault();
50-
window.open(
51-
href,
52-
Language.terminalTitle(generateRandomString(12)),
53-
"width=900,height=600",
54-
);
55-
}}
56-
data-testid="terminal"
57-
>
58-
{DisplayAppNameMap.web_terminal}
59-
</Link>
41+
<AgentButtonasChild>
42+
<a
43+
href={href}
44+
onClick={(event:MouseEvent<HTMLElement>)=>{
45+
event.preventDefault();
46+
window.open(
47+
href,
48+
Language.terminalTitle(generateRandomString(12)),
49+
"width=900,height=600",
50+
);
51+
}}
52+
>
53+
<TerminalIcon/>
54+
{DisplayAppNameMap.web_terminal}
55+
</a>
56+
</AgentButton>
6057
);
6158
};

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp