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

Commit5448a26

Browse files
feat: migrate Alert component from MUI to shadcn and update to new Alert designs (#18412)
--- Although originally created with Blink most of the PR has beenre-written since then## SummaryThis PR migrates the Alert component from MUI to shadcn implementationwhile maintaining full backward compatibility with the existing API.Updates Alerts to new design in Figma.Figma design:https://www.figma.com/design/WfqIgsTFXN2BscBSSyXWF8/Coder-kit?node-id=3522-3005&m=dev<img width="1008" height="623" alt="Screenshot 2025-12-18 at 20 37 32"src="https://github.com/user-attachments/assets/8b2077f1-f746-4a9a-8b58-3ec3477c247b"/>---------Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>Co-authored-by: jaaydenh <1858163+jaaydenh@users.noreply.github.com>Co-authored-by: Jaayden Halko <jaayden@coder.com>
1 parent44a46db commit5448a26

File tree

33 files changed

+250
-116
lines changed

33 files changed

+250
-116
lines changed

‎site/src/components/Alert/Alert.stories.tsx‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,37 @@ export const WarningWithActionAndDismiss: Story = {
5454
severity:"warning",
5555
},
5656
};
57+
58+
exportconstInfo:Story={
59+
args:{
60+
children:"This is an informational message",
61+
severity:"info",
62+
},
63+
};
64+
65+
exportconstErrorSeverity:Story={
66+
args:{
67+
children:"This is an error message",
68+
severity:"error",
69+
},
70+
};
71+
72+
exportconstWarningProminent:Story={
73+
args:{
74+
children:
75+
"This is a high risk warning. Use this design only for high risk warnings.",
76+
severity:"warning",
77+
prominent:true,
78+
dismissible:true,
79+
},
80+
};
81+
82+
exportconstErrorProminent:Story={
83+
args:{
84+
children:
85+
"This is a crucial error. Use this design only for crucial errors.",
86+
severity:"error",
87+
prominent:true,
88+
dismissible:true,
89+
},
90+
};
Lines changed: 114 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,151 @@
1-
importMuiAlert,{
2-
typeAlertColorasMuiAlertColor,
3-
typeAlertPropsasMuiAlertProps,
4-
}from"@mui/material/Alert";
5-
importCollapsefrom"@mui/material/Collapse";
1+
import{cva}from"class-variance-authority";
62
import{Button}from"components/Button/Button";
3+
import{
4+
CircleAlertIcon,
5+
CircleCheckIcon,
6+
InfoIcon,
7+
TriangleAlertIcon,
8+
XIcon,
9+
}from"lucide-react";
710
import{
811
typeFC,
12+
forwardRef,
913
typePropsWithChildren,
1014
typeReactNode,
1115
useState,
1216
}from"react";
13-
exporttypeAlertColor=MuiAlertColor;
17+
import{cn}from"utils/cn";
18+
19+
constalertVariants=cva(
20+
"relative w-full rounded-lg border border-solid p-4 text-left",
21+
{
22+
variants:{
23+
severity:{
24+
info:"",
25+
success:"",
26+
warning:"",
27+
error:"",
28+
},
29+
prominent:{
30+
true:"",
31+
false:"",
32+
},
33+
},
34+
compoundVariants:[
35+
{
36+
prominent:false,
37+
className:"border-border-default bg-surface-secondary",
38+
},
39+
{
40+
severity:"success",
41+
prominent:true,
42+
className:"border-border-success bg-surface-green",
43+
},
44+
{
45+
severity:"warning",
46+
prominent:true,
47+
className:"border-border-warning bg-surface-orange",
48+
},
49+
{
50+
severity:"error",
51+
prominent:true,
52+
className:"border-border-destructive bg-surface-red",
53+
},
54+
],
55+
defaultVariants:{
56+
severity:"info",
57+
prominent:false,
58+
},
59+
},
60+
);
61+
62+
constseverityIcons={
63+
info:{icon:InfoIcon,className:"text-highlight-sky"},
64+
success:{icon:CircleCheckIcon,className:"text-content-success"},
65+
warning:{icon:TriangleAlertIcon,className:"text-content-warning"},
66+
error:{icon:CircleAlertIcon,className:"text-content-destructive"},
67+
}asconst;
68+
69+
exporttypeAlertColor="info"|"success"|"warning"|"error";
1470

15-
exporttypeAlertProps=MuiAlertProps&{
71+
exporttypeAlertProps={
1672
actions?:ReactNode;
1773
dismissible?:boolean;
1874
onDismiss?:()=>void;
75+
severity?:AlertColor;
76+
prominent?:boolean;
77+
children?:ReactNode;
78+
className?:string;
1979
};
2080

2181
exportconstAlert:FC<AlertProps>=({
2282
children,
2383
actions,
2484
dismissible,
2585
severity="info",
86+
prominent=false,
2687
onDismiss,
27-
...alertProps
88+
className,
89+
...props
2890
})=>{
2991
const[open,setOpen]=useState(true);
3092

31-
// Can't only rely on MUI's hiding behavior inside flex layouts, because even
32-
// though MUI will make a dismissed alert have zero height, the alert will
33-
// still behave as a flex child and introduce extra row/column gaps
3493
if(!open){
3594
returnnull;
3695
}
3796

97+
const{icon:Icon,className:iconClassName}=severityIcons[severity];
98+
3899
return(
39-
<Collapsein>
40-
<MuiAlert
41-
{...alertProps}
42-
css={{textAlign:"left"}}
43-
severity={severity}
44-
action={
45-
<>
46-
{/* CTAs passed in by the consumer */}
47-
{actions}
100+
<div
101+
role="alert"
102+
className={cn(alertVariants({ severity, prominent}),className)}
103+
{...props}
104+
>
105+
<divclassName="flex items-center justify-between gap-4 text-sm">
106+
<divclassName="flex flex-row items-start gap-3">
107+
<IconclassName={cn("size-icon-sm mt-[3px]",iconClassName)}/>
108+
<divclassName="flex-1">{children}</div>
109+
</div>
110+
<divclassName="flex items-center gap-2">
111+
{actions}
48112

49-
{/* close CTA */}
50-
{dismissible&&(
51-
<Button
52-
variant="subtle"
53-
size="sm"
54-
onClick={()=>{
55-
setOpen(false);
56-
onDismiss?.();
57-
}}
58-
data-testid="dismiss-banner-btn"
59-
>
60-
Dismiss
61-
</Button>
62-
)}
63-
</>
64-
}
65-
>
66-
{children}
67-
</MuiAlert>
68-
</Collapse>
113+
{dismissible&&(
114+
<Button
115+
variant="subtle"
116+
size="icon"
117+
className="!size-auto !min-w-0 !p-0"
118+
onClick={()=>{
119+
setOpen(false);
120+
onDismiss?.();
121+
}}
122+
data-testid="dismiss-banner-btn"
123+
aria-label="Dismiss"
124+
>
125+
<XIconclassName="!size-icon-sm !p-0"/>
126+
</Button>
127+
)}
128+
</div>
129+
</div>
130+
</div>
69131
);
70132
};
71133

72134
exportconstAlertDetail:FC<PropsWithChildren>=({ children})=>{
73135
return(
74-
<span
75-
css={(theme)=>({color:theme.palette.text.secondary,fontSize:13})}
76-
data-chromatic="ignore"
77-
>
136+
<spanclassName="m-0 text-sm"data-chromatic="ignore">
78137
{children}
79138
</span>
80139
);
81140
};
141+
142+
exportconstAlertTitle=forwardRef<
143+
HTMLHeadingElement,
144+
React.HTMLAttributes<HTMLHeadingElement>
145+
>(({ className, ...props},ref)=>(
146+
<h1
147+
ref={ref}
148+
className={cn("m-0 mb-1 text-sm font-medium",className)}
149+
{...props}
150+
/>
151+
));

‎site/src/components/Alert/ErrorAlert.tsx‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
importAlertTitlefrom"@mui/material/AlertTitle";
21
import{getErrorDetail,getErrorMessage,getErrorStatus}from"api/errors";
32
importtype{FC}from"react";
43
import{Link}from"../Link/Link";
5-
import{Alert,AlertDetail,typeAlertProps}from"./Alert";
4+
import{Alert,AlertDetail,typeAlertProps,AlertTitle}from"./Alert";
65

76
typeErrorAlertProps=Readonly<
87
Omit<AlertProps,"severity"|"children">&{error:unknown}
@@ -18,7 +17,7 @@ export const ErrorAlert: FC<ErrorAlertProps> = ({ error, ...alertProps }) => {
1817
constshouldDisplayDetail=message!==detail;
1918

2019
return(
21-
<Alertseverity="error"{...alertProps}>
20+
<Alertseverity="error"prominent{...alertProps}>
2221
{
2322
// When the error is a Forbidden response we include a link for the user to
2423
// go back to a known viewable page.

‎site/src/components/Badge/Badge.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const badgeVariants = cva(
2424
"border border-solid border-border-destructive bg-surface-red text-highlight-red shadow",
2525
green:
2626
"border border-solid border-border-green bg-surface-green text-highlight-green shadow",
27-
info:"border border-solid border-border-sky bg-surface-sky text-highlight-sky shadow",
27+
info:"border border-solid border-border-pending bg-surface-sky text-highlight-sky shadow",
2828
},
2929
size:{
3030
xs:"text-2xs font-regular h-5 [&_svg]:hidden rounded px-1.5",

‎site/src/components/GitDeviceAuth/GitDeviceAuth.tsx‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
importtype{Interpolation,Theme}from"@emotion/react";
2-
importAlertTitlefrom"@mui/material/AlertTitle";
32
importCircularProgressfrom"@mui/material/CircularProgress";
43
importLinkfrom"@mui/material/Link";
54
importtype{ApiErrorResponse}from"api/errors";
65
importtype{ExternalAuthDevice}from"api/typesGenerated";
76
import{isAxiosError}from"axios";
8-
import{Alert,AlertDetail}from"components/Alert/Alert";
7+
import{Alert,AlertDetail,AlertTitle}from"components/Alert/Alert";
98
import{CopyButton}from"components/CopyButton/CopyButton";
109
import{ExternalLinkIcon}from"lucide-react";
1110
importtype{FC}from"react";
@@ -102,7 +101,9 @@ export const GitDeviceAuth: FC<GitDeviceAuthProps> = ({
102101
break;
103102
caseDeviceExchangeError.AccessDenied:
104103
status=(
105-
<Alertseverity="error">Access to the Git provider was denied.</Alert>
104+
<Alertseverity="error"prominent>
105+
Access to the Git provider was denied.
106+
</Alert>
106107
);
107108
break;
108109
default:

‎site/src/modules/provisioners/ProvisionerAlert.tsx‎

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
importtype{Theme}from"@emotion/react";
2-
importAlertTitlefrom"@mui/material/AlertTitle";
3-
import{Alert,typeAlertColor,AlertDetail}from"components/Alert/Alert";
1+
import{
2+
Alert,
3+
typeAlertColor,
4+
AlertDetail,
5+
AlertTitle,
6+
}from"components/Alert/Alert";
47
import{ProvisionerTag}from"modules/provisioners/ProvisionerTag";
58
importtype{FC}from"react";
9+
import{cn}from"utils/cn";
10+
611
exportenumAlertVariant{
712
// Alerts are usually styled with a full rounded border and meant to use as a visually distinct element of the page.
813
// The Standalone variant conforms to this styling.
@@ -21,20 +26,21 @@ interface ProvisionerAlertProps {
2126
variant?:AlertVariant;
2227
}
2328

24-
constgetAlertStyles=(variant:AlertVariant,severity:AlertColor)=>{
25-
switch(variant){
26-
caseAlertVariant.Inline:
27-
return{
28-
css:(theme:Theme)=>({
29-
borderRadius:0,
30-
border:0,
31-
borderBottom:`1px solid${theme.palette.divider}`,
32-
borderLeft:`2px solid${theme.palette[severity].main}`,
33-
}),
34-
};
35-
default:
36-
return{};
29+
constseverityBorderColors:Record<AlertColor,string>={
30+
info:"border-l-highlight-sky",
31+
success:"border-l-content-success",
32+
warning:"border-l-content-warning",
33+
error:"border-l-content-destructive",
34+
};
35+
36+
constgetAlertClassName=(variant:AlertVariant,severity:AlertColor)=>{
37+
if(variant===AlertVariant.Inline){
38+
returncn(
39+
"rounded-none border-0 border-b border-l-2 border-solid border-b-border-default",
40+
severityBorderColors[severity],
41+
);
3742
}
43+
returnundefined;
3844
};
3945

4046
exportconstProvisionerAlert:FC<ProvisionerAlertProps>=({
@@ -45,7 +51,7 @@ export const ProvisionerAlert: FC<ProvisionerAlertProps> = ({
4551
variant=AlertVariant.Standalone,
4652
})=>{
4753
return(
48-
<Alertseverity={severity}{...getAlertStyles(variant,severity)}>
54+
<Alertseverity={severity}className={getAlertClassName(variant,severity)}>
4955
<AlertTitle>{title}</AlertTitle>
5056
<AlertDetail>
5157
<div>{detail}</div>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export const WildcardHostnameWarning: FC<WildcardHostnameWarningProps> = ({
4040
return(
4141
<Alert
4242
severity="warning"
43+
prominent
4344
className={
4445
hasResources
4546
?"rounded-none border-0 border-l-2 border-l-warning border-b-divider"

‎site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const ClassicParameterFlowDeprecationWarning: FC<
1616
}
1717

1818
return(
19-
<Alertseverity="warning"className="mb-2">
19+
<Alertseverity="warning"className="mb-2"prominent>
2020
<div>
2121
This template is using the classic parameter flow, which will be{" "}
2222
<strong>deprecated</strong> and removed in a future release. Please

‎site/src/modules/workspaces/WorkspaceMoreActions/ChangeWorkspaceVersionDialog.tsx‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import{css}from"@emotion/css";
2-
importAlertTitlefrom"@mui/material/AlertTitle";
32
importAutocompletefrom"@mui/material/Autocomplete";
43
importCircularProgressfrom"@mui/material/CircularProgress";
54
importTextFieldfrom"@mui/material/TextField";
65
import{templateVersions}from"api/queries/templates";
76
importtype{TemplateVersion,Workspace}from"api/typesGenerated";
8-
import{Alert}from"components/Alert/Alert";
7+
import{Alert,AlertTitle}from"components/Alert/Alert";
98
import{Avatar}from"components/Avatar/Avatar";
109
import{AvatarData}from"components/Avatar/AvatarData";
1110
import{ConfirmDialog}from"components/Dialogs/ConfirmDialog/ConfirmDialog";

‎site/src/modules/workspaces/WorkspaceMoreActions/DownloadLogsDialog.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ export const DownloadLogsDialog: FC<DownloadLogsDialogProps> = ({
146146
</p>
147147

148148
{!isWorkspaceHealthy&&isLoadingFiles&&(
149-
<Alertseverity="warning">
149+
<Alertseverity="warning"prominent>
150150
Your workspace is unhealthy. Some logs may be unavailable for
151151
download.
152152
</Alert>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp