Skip to content

Commit 55c8e5a

Browse files
authored
workspace switcher + new elements (in storybook) (#1148)
1 parent 7e6f963 commit 55c8e5a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+4224
-588
lines changed

frontend/app/asset/thunder.svg

Lines changed: 5 additions & 0 deletions
Loading

frontend/app/asset/workspace.svg

Lines changed: 8 additions & 0 deletions
Loading

frontend/app/element/avatar.less

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2024, Command Line Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
@import "../mixins.less";
5+
6+
.avatar {
7+
position: relative;
8+
width: 50px;
9+
height: 50px;
10+
border-radius: 50%;
11+
background-color: var(--border-color);
12+
display: flex;
13+
justify-content: center;
14+
align-items: center;
15+
color: var(--main-text-color);
16+
font-size: 18px;
17+
text-transform: uppercase;
18+
19+
.avatar-image {
20+
width: 100%;
21+
height: 100%;
22+
border-radius: 50%;
23+
object-fit: cover;
24+
}
25+
26+
.avatar-initials {
27+
font-weight: bold;
28+
}
29+
30+
.status-indicator {
31+
position: absolute;
32+
bottom: 2px;
33+
right: 2px;
34+
width: 12px;
35+
height: 12px;
36+
border-radius: 50%;
37+
background-color: transparent;
38+
39+
&.online {
40+
background-color: var(--success-color);
41+
}
42+
43+
&.offline {
44+
background-color: var(--grey-text-color);
45+
}
46+
47+
&.busy {
48+
background-color: var(--error-color);
49+
}
50+
51+
&.away {
52+
background-color: var(--warning-color);
53+
}
54+
}
55+
56+
.avatar-dims-mixin();
57+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2024, Command Line Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import type { Meta, StoryObj } from "@storybook/react";
5+
import { Avatar } from "./avatar";
6+
7+
const meta = {
8+
title: "Elements/Avatar",
9+
component: Avatar,
10+
args: {
11+
name: "John Doe",
12+
status: "offline",
13+
imageUrl: "",
14+
},
15+
argTypes: {
16+
name: {
17+
control: { type: "text" },
18+
description: "The name of the user",
19+
},
20+
status: {
21+
control: { type: "select", options: ["online", "offline", "busy", "away"] },
22+
description: "The status of the user",
23+
},
24+
imageUrl: {
25+
control: { type: "text" },
26+
description: "Optional image URL for the avatar",
27+
},
28+
},
29+
} satisfies Meta<typeof Avatar>;
30+
31+
export default meta;
32+
type Story = StoryObj<typeof meta>;
33+
34+
// Default case (without an image, default status: offline)
35+
export const Default: Story = {
36+
args: {
37+
name: "John Doe",
38+
status: "offline",
39+
imageUrl: "",
40+
},
41+
};
42+
43+
// Online status with an image
44+
export const OnlineWithImage: Story = {
45+
args: {
46+
name: "Alice Smith",
47+
status: "online",
48+
imageUrl: "https://i.pravatar.cc/150?u=a042581f4e29026704d",
49+
},
50+
};
51+
52+
// Busy status without an image
53+
export const BusyWithoutImage: Story = {
54+
args: {
55+
name: "Michael Johnson",
56+
status: "busy",
57+
imageUrl: "",
58+
},
59+
};
60+
61+
// Away status with an image
62+
export const AwayWithImage: Story = {
63+
args: {
64+
name: "Sarah Connor",
65+
status: "away",
66+
imageUrl: "https://i.pravatar.cc/150?u=a042581f4e29026704d",
67+
},
68+
};

frontend/app/element/avatar.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2024, Command Line Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
import { memo } from "react";
4+
5+
import clsx from "clsx";
6+
import "./avatar.less";
7+
8+
interface AvatarProps {
9+
name: string;
10+
status: "online" | "offline" | "busy" | "away";
11+
className?: string;
12+
imageUrl?: string;
13+
}
14+
15+
const Avatar = memo(({ name, status = "offline", className, imageUrl }: AvatarProps) => {
16+
const getInitials = (name: string) => {
17+
const nameParts = name.split(" ");
18+
const initials = nameParts.map((part) => part[0]).join("");
19+
return initials.toUpperCase();
20+
};
21+
22+
return (
23+
<div className={clsx("avatar", status, className)} title="status">
24+
{imageUrl ? (
25+
<img src={imageUrl} alt={`${name}'s avatar`} className="avatar-image" />
26+
) : (
27+
<div className="avatar-initials">{getInitials(name)}</div>
28+
)}
29+
<div className={`status-indicator ${status}`} />
30+
</div>
31+
);
32+
});
33+
34+
Avatar.displayName = "Avatar";
35+
36+
export { Avatar };

frontend/app/element/button.less

Lines changed: 8 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright 2024, Command Line Inc.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
@import "../mixins.less";
5+
46
.button {
57
// override default button appearance
68
border: 1px solid transparent;
@@ -155,150 +157,10 @@
155157
outline-offset: 2px;
156158
}
157159

158-
// customs styles here
159-
&.border-radius-2 {
160-
border-radius: 4px;
161-
}
162-
163-
&.border-radius-3 {
164-
border-radius: 4px;
165-
}
166-
167-
&.border-radius-4 {
168-
border-radius: 4px;
169-
}
170-
171-
&.border-radius-5 {
172-
border-radius: 4px;
173-
}
174-
175-
&.border-radius-6 {
176-
border-radius: 4px;
177-
}
178-
179-
&.border-radius-10 {
180-
border-radius: 10px;
181-
}
182-
183-
&.vertical-padding-0 {
184-
padding-top: 0px;
185-
padding-bottom: 0px;
186-
}
187-
188-
&.vertical-padding-1 {
189-
padding-top: 1px;
190-
padding-bottom: 1px;
191-
}
192-
193-
&.vertical-padding-2 {
194-
padding-top: 2px;
195-
padding-bottom: 2px;
196-
}
197-
198-
&.vertical-padding-3 {
199-
padding-top: 3px;
200-
padding-bottom: 3px;
201-
}
202-
203-
&.vertical-padding-4 {
204-
padding-top: 4px;
205-
padding-bottom: 4px;
206-
}
207-
208-
&.vertical-padding-5 {
209-
padding-top: 5px;
210-
padding-bottom: 5px;
211-
}
212-
213-
&.vertical-padding-6 {
214-
padding-top: 6px;
215-
padding-bottom: 6px;
216-
}
217-
218-
&.vertical-padding-7 {
219-
padding-top: 7px;
220-
padding-bottom: 7px;
221-
}
222-
223-
&.vertical-padding-8 {
224-
padding-top: 8px;
225-
padding-bottom: 8px;
226-
}
227-
228-
&.vertical-padding-9 {
229-
padding-top: 9px;
230-
padding-bottom: 9px;
231-
}
232-
233-
&.vertical-padding-10 {
234-
padding-top: 10px;
235-
padding-bottom: 10px;
236-
}
237-
238-
&.horizontal-padding-0 {
239-
padding-left: 0px;
240-
padding-right: 0px;
241-
}
242-
243-
&.horizontal-padding-1 {
244-
padding-left: 1px;
245-
padding-right: 1px;
246-
}
247-
248-
&.horizontal-padding-2 {
249-
padding-left: 2px;
250-
padding-right: 2px;
251-
}
252-
253-
&.horizontal-padding-3 {
254-
padding-left: 3px;
255-
padding-right: 3px;
256-
}
257-
258-
&.horizontal-padding-4 {
259-
padding-left: 4px;
260-
padding-right: 4px;
261-
}
262-
263-
&.horizontal-padding-5 {
264-
padding-left: 5px;
265-
padding-right: 5px;
266-
}
267-
268-
&.horizontal-padding-6 {
269-
padding-left: 6px;
270-
padding-right: 6px;
271-
}
272-
273-
&.horizontal-padding-7 {
274-
padding-left: 7px;
275-
padding-right: 7px;
276-
}
277-
278-
&.horizontal-padding-8 {
279-
padding-left: 8px;
280-
padding-right: 8px;
281-
}
282-
283-
&.horizontal-padding-9 {
284-
padding-left: 9px;
285-
padding-right: 9px;
286-
}
287-
288-
&.horizontal-padding-10 {
289-
padding-left: 10px;
290-
padding-right: 10px;
291-
}
292-
293-
&.font-size-11 {
294-
font-size: 11px;
295-
}
296-
297-
&.font-weight-500 {
298-
font-weight: 500;
299-
}
300-
301-
&.font-weight-600 {
302-
font-weight: 600;
303-
}
160+
// Include mixins
161+
.border-radius-mixin();
162+
.vertical-padding-mixin();
163+
.horizontal-padding-mixin();
164+
.font-size-mixin();
165+
.font-weight-mixin();
304166
}

0 commit comments

Comments
 (0)