Skip to content

Commit d42f22d

Browse files
committed
Tweak design
Tool: gitpod/catfood.gitpod.cloud
1 parent 99b0b71 commit d42f22d

File tree

2 files changed

+88
-65
lines changed

2 files changed

+88
-65
lines changed

components/dashboard/src/components/forms/InputField.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,18 @@ type Props = {
1616
topMargin?: boolean;
1717
className?: string;
1818
disabled?: boolean;
19+
labelHidden?: boolean;
1920
};
2021

2122
export const InputField: FunctionComponent<Props> = memo(
22-
({ label, id, hint, error, topMargin = true, className, children, disabled = false }) => {
23+
({ label, id, hint, error, topMargin = true, className, children, disabled = false, labelHidden = false }) => {
2324
return (
2425
<div className={cn("flex flex-col space-y-2", { "mt-4": topMargin }, className)}>
2526
{label && (
2627
<label
2728
className={cn(
2829
"text-md font-semibold",
30+
{ "sr-only": labelHidden },
2931
disabled
3032
? "text-gray-400 dark:text-gray-400"
3133
: error

components/dashboard/src/teams/TeamOnboarding.tsx

Lines changed: 85 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ import { Textarea } from "@podkit/forms/TextArea";
2424
import Modal, { ModalFooter, ModalBody, ModalHeader } from "../components/Modal";
2525
import { Button } from "@podkit/buttons/Button";
2626
import { SwitchInputField } from "@podkit/switch/Switch";
27-
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "@podkit/select/Select";
27+
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@podkit/dropdown/DropDown";
2828

2929
const sampleMarkdown = `“With Gitpod, you'll boost your productivity and streamline your workflow, giving you the freedom to work how you want while helping our team meet its efficiency goals.”
3030
3131
**Hannah Cole** - CTO Acme, Inc.
3232
`;
33+
const gitpodWelcomeSubheading = `Gitpod’s sandboxed, ephemeral development environments enable you to use your existing tools without worrying about vulnerabilities impacting their local machines.`;
3334

3435
export default function TeamOnboardingPage() {
3536
useDocumentTitle("Organization Settings - Onboarding");
@@ -121,41 +122,43 @@ export default function TeamOnboardingPage() {
121122
members once they sign up and join your organization.
122123
</Subheading>
123124

125+
<InputField
126+
label="Enabled"
127+
hint={<>Enable showing the message to new organization members.</>}
128+
id="show-welcome-message"
129+
>
130+
<SwitchInputField
131+
id="show-welcome-message"
132+
checked={showWelcomeMessage}
133+
disabled={!isOwner || updateTeamSettings.isLoading}
134+
onCheckedChange={setShowWelcomeMessage}
135+
label=""
136+
/>
137+
</InputField>
138+
124139
<span className="text-pk-content-secondary text-sm">
125140
Here's a preview of the welcome message that will be shown to your organization members:
126141
</span>
127142
<WelcomeMessagePreview
128143
welcomeMessage={welcomeMessage}
129144
setWelcomeMessageEditorOpen={setWelcomeMessageEditorOpen}
130145
avatarURL={avatarURL}
146+
disabled={!showWelcomeMessage}
131147
/>
132148

133-
<Modal onClose={() => setWelcomeMessageEditorOpen(false)} visible={welcomeMessageEditorOpen}>
149+
<Modal
150+
onClose={() => setWelcomeMessageEditorOpen(false)}
151+
visible={welcomeMessageEditorOpen}
152+
containerClassName="min-[576px]:max-w-[650px]"
153+
>
134154
<ModalHeader>Edit welcome message</ModalHeader>
135155
<ModalBody>
136-
<InputField
137-
label="Enabled"
138-
hint={<>Enable showing the message to new organization members.</>}
139-
id="show-welcome-message"
140-
>
141-
<SwitchInputField
142-
id="show-welcome-message"
143-
checked={showWelcomeMessage}
144-
disabled={!isOwner || updateTeamSettings.isLoading}
145-
onCheckedChange={setShowWelcomeMessage}
146-
label=""
147-
/>
148-
</InputField>
149-
150-
<OrgMemberSelect
151-
avatarURL={avatarURL}
152-
setAvatarURL={setAvatarURL}
153-
disabled={!showWelcomeMessage}
154-
/>
155156
<WelcomeMessageEditor
156157
welcomeMessage={welcomeMessage}
157158
setWelcomeMessage={setWelcomeMessage}
158159
disabled={!showWelcomeMessage}
160+
avatarURL={avatarURL}
161+
setAvatarURL={setAvatarURL}
159162
/>
160163
</ModalBody>
161164
<ModalFooter>
@@ -176,28 +179,27 @@ export default function TeamOnboardingPage() {
176179
type WelcomeMessagePreviewProps = {
177180
welcomeMessage: string;
178181
avatarURL: string | undefined;
182+
disabled?: boolean;
179183
setWelcomeMessageEditorOpen: (open: boolean) => void;
180184
};
181185
const WelcomeMessagePreview = ({
182186
welcomeMessage,
183187
avatarURL,
188+
disabled,
184189
setWelcomeMessageEditorOpen,
185190
}: WelcomeMessagePreviewProps) => {
186191
return (
187192
<div className="max-w-2xl mx-auto">
188193
<div className="flex justify-between gap-2 items-center">
189194
<Heading2 className="py-6">Welcome to Gitpod</Heading2>
190-
<Button variant="secondary" onClick={() => setWelcomeMessageEditorOpen(true)}>
195+
<Button variant="secondary" onClick={() => setWelcomeMessageEditorOpen(true)} disabled={disabled}>
191196
Edit
192197
</Button>
193198
</div>
194-
<Subheading>
195-
Gitpod’s sandboxed, ephemeral development environments enable you to use your existing tools without
196-
worrying about vulnerabilities impacting their local machines.
197-
</Subheading>
199+
<Subheading>{gitpodWelcomeSubheading}</Subheading>
198200
{/* todo: sanitize md */}
199201
<div className="p-8 my-4 bg-pk-surface-secondary text-pk-content-primary rounded-xl flex flex-col gap-5 items-center justify-center">
200-
<img src={avatarURL} alt="" className="w-12 h-12 rounded-full" />
202+
{avatarURL && <img src={avatarURL} alt="" className="w-12 h-12 rounded-full" />}
201203
<MDEditor.Markdown
202204
source={welcomeMessage}
203205
className="md-preview space-y-4 text-center bg-pk-surface-secondary"
@@ -211,18 +213,33 @@ type WelcomeMessageEditorProps = {
211213
welcomeMessage: string;
212214
setWelcomeMessage: (welcomeMessage: string) => void;
213215
disabled?: boolean;
216+
avatarURL: string | undefined;
217+
setAvatarURL: (avatarURL: string | undefined) => void;
214218
};
215-
const WelcomeMessageEditor = ({ welcomeMessage, setWelcomeMessage, disabled }: WelcomeMessageEditorProps) => {
219+
const WelcomeMessageEditor = ({
220+
welcomeMessage,
221+
setWelcomeMessage,
222+
disabled,
223+
avatarURL,
224+
setAvatarURL,
225+
}: WelcomeMessageEditorProps) => {
216226
return (
217-
<InputField label="Welcome message" error={undefined} className="mb-4">
218-
<Textarea
219-
className="bg-pk-surface-secondary text-pk-content-primary w-full p-4 rounded-xl min-h-[400px]"
220-
value={welcomeMessage}
221-
placeholder="Write a welcome message to your organization members. Markdown formatting is supported."
222-
onChange={(e) => setWelcomeMessage(e.target.value)}
223-
disabled={disabled}
224-
/>
225-
</InputField>
227+
<div className="space-y-4">
228+
<TextInput readOnly value="Welcome to Gitpod" className="cursor-default"></TextInput>
229+
<Textarea value={gitpodWelcomeSubheading} readOnly className="cursor-default resize-none" />
230+
<div className="w-full flex justify-center">
231+
<OrgMemberInput avatarURL={avatarURL} setAvatarURL={setAvatarURL} disabled={disabled} />
232+
</div>
233+
<InputField label="Welcome message" error={undefined} className="mb-4" labelHidden>
234+
<Textarea
235+
className="bg-pk-surface-secondary text-pk-content-primary w-full p-4 rounded-xl min-h-[150px]"
236+
value={welcomeMessage}
237+
placeholder="Write a welcome message to your organization members. Markdown formatting is supported."
238+
onChange={(e) => setWelcomeMessage(e.target.value)}
239+
disabled={disabled}
240+
/>
241+
</InputField>
242+
</div>
226243
);
227244
};
228245

@@ -231,35 +248,39 @@ type OrgMemberSelectProps = {
231248
setAvatarURL: (avatarURL: string | undefined) => void;
232249
disabled?: boolean;
233250
};
234-
const OrgMemberSelect = ({ avatarURL, setAvatarURL, disabled }: OrgMemberSelectProps) => {
251+
const OrgMemberInput = ({ avatarURL, setAvatarURL, disabled }: OrgMemberSelectProps) => {
235252
const { data: members } = useListOrganizationMembers();
236253

237254
return (
238-
<InputField label="Show an avatar on the welcome message" error={undefined} className="mb-4">
239-
<Select value={avatarURL} onValueChange={setAvatarURL} disabled={disabled}>
240-
<SelectTrigger>
241-
<SelectValue placeholder="No member" />
242-
</SelectTrigger>
243-
<SelectContent>
244-
<SelectGroup>
245-
<SelectItem value="disabled">No member</SelectItem>
246-
</SelectGroup>
247-
<SelectGroup>
248-
{members?.map((member) => (
249-
<SelectItem key={member.userId} value={member.avatarUrl || member.userId}>
250-
<div className="flex items-center gap-2">
251-
<img
252-
src={member.avatarUrl}
253-
className="w-4 h-4 rounded-full"
254-
alt={member.fullName}
255-
/>
256-
{member.fullName}
257-
</div>
258-
</SelectItem>
259-
))}
260-
</SelectGroup>
261-
</SelectContent>
262-
</Select>
263-
</InputField>
255+
<DropdownMenu>
256+
<DropdownMenuTrigger>
257+
<div className="flex flex-col justify-center items-center gap-2">
258+
{avatarURL ? (
259+
<img src={avatarURL} alt="" className="w-16 h-16 rounded-full" />
260+
) : (
261+
<div className="w-16 h-16 rounded-full bg-[#EA71DE]" />
262+
)}
263+
<Button variant="secondary" size="sm">
264+
Change Photo
265+
</Button>
266+
</div>
267+
</DropdownMenuTrigger>
268+
<DropdownMenuContent>
269+
<DropdownMenuItem key="disabled" onClick={() => setAvatarURL(undefined)}>
270+
<div className="flex items-center gap-2">
271+
<div className="w-4 h-4 rounded-full bg-pk-surface-tertiary" />
272+
Disable image
273+
</div>
274+
</DropdownMenuItem>
275+
{members?.map((member) => (
276+
<DropdownMenuItem key={member.userId} onClick={() => setAvatarURL(member.avatarUrl)}>
277+
<div className="flex items-center gap-2">
278+
<img src={member.avatarUrl} alt={member.fullName} className="w-4 h-4 rounded-full" />
279+
{member.fullName}
280+
</div>
281+
</DropdownMenuItem>
282+
))}
283+
</DropdownMenuContent>
284+
</DropdownMenu>
264285
);
265286
};

0 commit comments

Comments
 (0)