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

Commitc8edada

Browse files
refactor: redesign workspace status on workspaces table (#17425)
Closes#17310**Before:**<img width="1624" alt="Screenshot 2025-04-16 at 11 49 52"src="https://github.com/user-attachments/assets/4fb6c8e5-329f-476f-99bb-192c0f9562a2"/>**After:**<img width="1624" alt="Screenshot 2025-04-16 at 11 49 19"src="https://github.com/user-attachments/assets/c7025fee-fefd-4064-9101-d7a1b364dd80"/>**Notice!**- I've create a new size variation for the badge, `xs`. Since we reducedthe line-height for the `text-xs` to be 16px instead of 18px, having asmaller badge, reducing the vertical size and horizontal paddings, justworked better.- I have to update Figma to reflect these changes. I tried, but I wasnot able to get it working and updated correctly. I'm going to take apause during this week to learn that.- Updated the destructive, and warning badges to use borders as definedin the designs[here](https://www.figma.com/design/WfqIgsTFXN2BscBSSyXWF8/Coder-kit?node-id=489-3472&t=gfnYeLOIFUqHx6qv-0).
1 parentaa02c9f commitc8edada

File tree

6 files changed

+119
-41
lines changed

6 files changed

+119
-41
lines changed

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ export const badgeVariants = cva(
1717
default:
1818
"border-transparent bg-surface-secondary text-content-secondary shadow",
1919
warning:
20-
"border-transparent bg-surface-orange text-content-warning shadow",
20+
"border border-solid border-border-warning bg-surface-orange text-content-warning shadow",
21+
destructive:
22+
"border border-solid border-border-destructive bg-surface-red text-content-highlight-red shadow",
2123
},
2224
size:{
25+
xs:"text-2xs font-regular h-5 [&_svg]:hidden rounded px-1.5",
2326
sm:"text-2xs font-regular h-5.5 [&_svg]:size-icon-xs",
2427
md:"text-xs font-medium [&_svg]:size-icon-sm",
2528
},

‎site/src/index.css

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@
2828
--surface-grey:2405%96%;
2929
--surface-orange:34100%92%;
3030
--surface-sky:20194%86%;
31+
--surface-red:093%94%;
3132
--border-default:2406%90%;
3233
--border-success:14276%36%;
3334
--border-warning:30.66,97.16%,72.35%;
3435
--border-destructive:084%60%;
35-
--border-hover:240,5%,34%;
36+
--border-warning:2796%61%;
37+
--border-hover:2405%34%;
3638
--overlay-default:2405%84%/80%;
3739
--radius:0.5rem;
3840
--highlight-purple:26283%58%;
@@ -66,10 +68,12 @@
6668
--surface-grey:2406%10%;
6769
--surface-orange:1381%15%;
6870
--surface-sky:20480%16%;
71+
--surface-red:075%15%;
6972
--border-default:2404%16%;
7073
--border-success:14276%36%;
7174
--border-warning:30.66,97.16%,72.35%;
7275
--border-destructive:091%71%;
76+
--border-warning:3197%72%;
7377
--border-hover:240,5%,34%;
7478
--overlay-default:24010%4%/80%;
7579
--highlight-purple:25295%85%;

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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
importAutoDeleteIconfrom"@mui/icons-material/AutoDelete";
2-
importRecyclingIconfrom"@mui/icons-material/Recycling";
31
importTooltipfrom"@mui/material/Tooltip";
42
importtype{Workspace}from"api/typesGenerated";
5-
import{Pill}from"components/Pill/Pill";
3+
import{Badge}from"components/Badge/Badge";
64
import{formatDistanceToNow}from"date-fns";
75
importtype{FC}from"react";
86

@@ -35,9 +33,9 @@ export const WorkspaceDormantBadge: FC<WorkspaceDormantBadgeProps> = ({
3533
</>
3634
}
3735
>
38-
<Pillrole="status"icon={<AutoDeleteIcon/>}type="error">
36+
<Badgerole="status"variant="destructive"size="xs">
3937
Deletion Pending
40-
</Pill>
38+
</Badge>
4139
</Tooltip>
4240
) :(
4341
<Tooltip
@@ -50,9 +48,9 @@ export const WorkspaceDormantBadge: FC<WorkspaceDormantBadgeProps> = ({
5048
</>
5149
}
5250
>
53-
<Pillrole="status"icon={<RecyclingIcon/>}type="warning">
51+
<Badgerole="status"variant="warning"size="xs">
5452
Dormant
55-
</Pill>
53+
</Badge>
5654
</Tooltip>
5755
);
5856
};

‎site/src/pages/WorkspacesPage/WorkspacesTable.tsx

Lines changed: 68 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ import { AvatarData } from "components/Avatar/AvatarData";
1313
import{AvatarDataSkeleton}from"components/Avatar/AvatarDataSkeleton";
1414
import{InfoTooltip}from"components/InfoTooltip/InfoTooltip";
1515
import{Stack}from"components/Stack/Stack";
16+
import{
17+
StatusIndicator,
18+
StatusIndicatorDot,
19+
typeStatusIndicatorProps,
20+
}from"components/StatusIndicator/StatusIndicator";
1621
import{
1722
Table,
1823
TableBody,
@@ -25,19 +30,26 @@ import {
2530
TableLoaderSkeleton,
2631
TableRowSkeleton,
2732
}from"components/TableLoader/TableLoader";
33+
importdayjsfrom"dayjs";
34+
importrelativeTimefrom"dayjs/plugin/relativeTime";
2835
import{useClickableTableRow}from"hooks/useClickableTableRow";
2936
import{useDashboard}from"modules/dashboard/useDashboard";
3037
import{WorkspaceAppStatus}from"modules/workspaces/WorkspaceAppStatus/WorkspaceAppStatus";
3138
import{WorkspaceDormantBadge}from"modules/workspaces/WorkspaceDormantBadge/WorkspaceDormantBadge";
3239
import{WorkspaceOutdatedTooltip}from"modules/workspaces/WorkspaceOutdatedTooltip/WorkspaceOutdatedTooltip";
33-
import{WorkspaceStatusBadge}from"modules/workspaces/WorkspaceStatusBadge/WorkspaceStatusBadge";
34-
import{LastUsed}from"pages/WorkspacesPage/LastUsed";
3540
import{typeFC,typeReactNode,useMemo}from"react";
3641
import{useNavigate}from"react-router-dom";
3742
import{cn}from"utils/cn";
38-
import{getDisplayWorkspaceTemplateName}from"utils/workspace";
43+
import{
44+
typeDisplayWorkspaceStatusType,
45+
getDisplayWorkspaceStatus,
46+
getDisplayWorkspaceTemplateName,
47+
lastUsedMessage,
48+
}from"utils/workspace";
3949
import{WorkspacesEmpty}from"./WorkspacesEmpty";
4050

51+
dayjs.extend(relativeTime);
52+
4153
exportinterfaceWorkspacesTableProps{
4254
workspaces?:readonlyWorkspace[];
4355
checkedWorkspaces:readonlyWorkspace[];
@@ -125,8 +137,7 @@ export const WorkspacesTable: FC<WorkspacesTableProps> = ({
125137
</TableHead>
126138
{hasAppStatus&&<TableHeadclassName="w-2/6">Activity</TableHead>}
127139
<TableHeadclassName="w-2/6">Template</TableHead>
128-
<TableHeadclassName="w-1/6">Last used</TableHead>
129-
<TableHeadclassName="w-1/6">Status</TableHead>
140+
<TableHeadclassName="w-2/6">Status</TableHead>
130141
<TableHeadclassName="w-0"/>
131142
</TableRow>
132143
</TableHeader>
@@ -248,26 +259,7 @@ export const WorkspacesTable: FC<WorkspacesTableProps> = ({
248259
/>
249260
</TableCell>
250261

251-
<TableCell>
252-
<LastUsedlastUsedAt={workspace.last_used_at}/>
253-
</TableCell>
254-
255-
<TableCell>
256-
<divclassName="flex items-center gap-2">
257-
<WorkspaceStatusBadgeworkspace={workspace}/>
258-
{workspace.latest_build.status==="running"&&
259-
!workspace.health.healthy&&(
260-
<InfoTooltip
261-
type="warning"
262-
title="Workspace is unhealthy"
263-
message="Your workspace is running but some agents are unhealthy."
264-
/>
265-
)}
266-
{workspace.dormant_at&&(
267-
<WorkspaceDormantBadgeworkspace={workspace}/>
268-
)}
269-
</div>
270-
</TableCell>
262+
<WorkspaceStatusCellworkspace={workspace}/>
271263

272264
<TableCell>
273265
<divclassName="flex pl-4">
@@ -345,14 +337,11 @@ const TableLoader: FC<TableLoaderProps> = ({ canCheckWorkspaces }) => {
345337
<TableCellclassName="w-2/6">
346338
<AvatarDataSkeleton/>
347339
</TableCell>
348-
<TableCellclassName="w-1/6">
349-
<Skeletonvariant="text"width="75%"/>
350-
</TableCell>
351-
<TableCellclassName="w-1/6">
352-
<Skeletonvariant="text"width="75%"/>
340+
<TableCellclassName="w-2/6">
341+
<Skeletonvariant="text"width="50%"/>
353342
</TableCell>
354343
<TableCellclassName="w-0">
355-
<Skeletonvariant="text"width="75%"/>
344+
<Skeletonvariant="text"width="25%"/>
356345
</TableCell>
357346
</TableRowSkeleton>
358347
</TableLoaderSkeleton>
@@ -362,3 +351,51 @@ const TableLoader: FC<TableLoaderProps> = ({ canCheckWorkspaces }) => {
362351
constcantBeChecked=(workspace:Workspace)=>{
363352
return["deleting","pending"].includes(workspace.latest_build.status);
364353
};
354+
355+
typeWorkspaceStatusCellProps={
356+
workspace:Workspace;
357+
};
358+
359+
constvariantByStatusType:Record<
360+
DisplayWorkspaceStatusType,
361+
StatusIndicatorProps["variant"]
362+
>={
363+
active:"pending",
364+
inactive:"inactive",
365+
success:"success",
366+
error:"failed",
367+
danger:"warning",
368+
warning:"warning",
369+
};
370+
371+
constWorkspaceStatusCell:FC<WorkspaceStatusCellProps>=({ workspace})=>{
372+
const{ text, type}=getDisplayWorkspaceStatus(
373+
workspace.latest_build.status,
374+
workspace.latest_build.job,
375+
);
376+
377+
return(
378+
<TableCell>
379+
<divclassName="flex flex-col">
380+
<StatusIndicatorvariant={variantByStatusType[type]}>
381+
<StatusIndicatorDot/>
382+
{text}
383+
{workspace.latest_build.status==="running"&&
384+
!workspace.health.healthy&&(
385+
<InfoTooltip
386+
type="warning"
387+
title="Workspace is unhealthy"
388+
message="Your workspace is running but some agents are unhealthy."
389+
/>
390+
)}
391+
{workspace.dormant_at&&(
392+
<WorkspaceDormantBadgeworkspace={workspace}/>
393+
)}
394+
</StatusIndicator>
395+
<spanclassName="text-xs font-medium text-content-secondary ml-6">
396+
{lastUsedMessage(workspace.last_used_at)}
397+
</span>
398+
</div>
399+
</TableCell>
400+
);
401+
};

‎site/src/utils/workspace.tsx

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,29 @@ export const getDisplayWorkspaceTemplateName = (
168168
:workspace.template_name;
169169
};
170170

171+
exporttypeDisplayWorkspaceStatusType=
172+
|"success"
173+
|"active"
174+
|"inactive"
175+
|"error"
176+
|"warning"
177+
|"danger";
178+
179+
typeDisplayWorkspaceStatus={
180+
text:string;
181+
type:DisplayWorkspaceStatusType;
182+
icon:React.ReactNode;
183+
};
184+
171185
exportconstgetDisplayWorkspaceStatus=(
172186
workspaceStatus:TypesGen.WorkspaceStatus,
173187
provisionerJob?:TypesGen.ProvisionerJob,
174-
)=>{
188+
):DisplayWorkspaceStatus=>{
175189
switch(workspaceStatus){
176190
caseundefined:
177191
return{
178192
text:"Loading",
193+
type:"active",
179194
icon:<PillSpinner/>,
180195
}asconst;
181196
case"running":
@@ -307,3 +322,23 @@ const FALLBACK_ICON = "/icon/widgets.svg";
307322
exportconstgetResourceIconPath=(resourceType:string):string=>{
308323
returnBUILT_IN_ICON_PATHS[resourceType]??FALLBACK_ICON;
309324
};
325+
326+
exportconstlastUsedMessage=(lastUsedAt:string|Date):string=>{
327+
constt=dayjs(lastUsedAt);
328+
constnow=dayjs();
329+
letmessage=t.fromNow();
330+
331+
if(t.isAfter(now.subtract(1,"hour"))){
332+
message="Now";
333+
}elseif(t.isAfter(now.subtract(3,"day"))){
334+
message=t.fromNow();
335+
}elseif(t.isAfter(now.subtract(1,"month"))){
336+
message=t.fromNow();
337+
}elseif(t.isAfter(now.subtract(100,"year"))){
338+
message=t.fromNow();
339+
}else{
340+
message="Never";
341+
}
342+
343+
returnmessage;
344+
};

‎site/tailwind.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ module.exports = {
4949
grey:"hsl(var(--surface-grey))",
5050
orange:"hsl(var(--surface-orange))",
5151
sky:"hsl(var(--surface-sky))",
52+
red:"hsl(var(--surface-red))",
5253
},
5354
border:{
5455
DEFAULT:"hsl(var(--border-default))",

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp