chore: UI Nits onboarding v3 (#25409)
* Fix UI nits * fix bio + team name on invite orgs * use bg-cal-muted * Fix error from mass edit * Update apps/web/public/static/locales/en/common.json Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * fix org labels * Fix i18n --------- Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
parent
d9cddd85ff
commit
ff1533d344
@@ -64,10 +64,10 @@ export function EmailInviteForm({
|
||||
|
||||
<div
|
||||
className={
|
||||
showTeamSelect ? "flex flex-col gap-2" : "scroll-bar flex max-h-72 flex-col gap-1 overflow-y-auto"
|
||||
showTeamSelect ? "flex flex-col gap-2" : "scroll-bar flex max-h-72 flex-col gap-2 overflow-y-auto"
|
||||
}>
|
||||
{fields.map((field, index) => (
|
||||
<div key={field.id} className="flex items-start gap-0.5 p-0.5">
|
||||
<div key={field.id} className="flex items-start gap-2">
|
||||
<div className={showTeamSelect ? "grid flex-1 items-start gap-2 md:grid-cols-2" : "flex-1"}>
|
||||
<TextField
|
||||
labelSrOnly
|
||||
|
||||
@@ -28,7 +28,7 @@ export const OnboardingLayout = ({ userEmail, currentStep, totalSteps, children
|
||||
const column2 = childrenArray[1];
|
||||
|
||||
return (
|
||||
<div className="bg-muted flex min-h-screen w-full flex-col items-center justify-between overflow-clip rounded-[12px] px-4 py-2 md:px-6">
|
||||
<div className="bg-cal-muted flex min-h-screen w-full flex-col items-center justify-between overflow-clip rounded-[12px] px-4 py-2 md:px-6">
|
||||
{/* Logo and container - centered */}
|
||||
<div className="flex w-full flex-1 flex-col items-center justify-center gap-6">
|
||||
<Logo className="mt-4 h-5 w-auto shrink-0" />
|
||||
|
||||
@@ -94,14 +94,14 @@ export const OnboardingBrowserView = ({
|
||||
<Icon name="arrow-right" className="text-subtle h-4 w-4" />
|
||||
<Icon name="rotate-cw" className="text-subtle h-4 w-4" />
|
||||
</div>
|
||||
<div className="bg-muted flex w-full min-w-0 items-center gap-2 rounded-[32px] px-3 py-2">
|
||||
<div className="bg-cal-muted flex w-full min-w-0 items-center gap-2 rounded-[32px] px-3 py-2">
|
||||
<Icon name="lock" className="text-subtle h-4 w-4" />
|
||||
<p className="text-default truncate text-sm font-medium leading-tight">{displayUrl}</p>
|
||||
</div>
|
||||
<Icon name="ellipsis-vertical" className="text-subtle h-4 w-4" />
|
||||
</div>
|
||||
{/* Content */}
|
||||
<div className="bg-muted h-full pl-11 pt-11">
|
||||
<div className="bg-cal-muted h-full pl-11 pt-11">
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
key={pathname}
|
||||
|
||||
@@ -63,6 +63,7 @@ export const OnboardingInviteBrowserView = ({
|
||||
const displayName = useOrganizationInvites
|
||||
? organizationDetails.name || teamName || "Deel"
|
||||
: teamName || teamDetails.name || "Deel";
|
||||
const displayBio = useOrganizationInvites ? organizationDetails.bio || "" : teamDetails.bio || "";
|
||||
const avatar = useOrganizationInvites ? organizationBrand.logo || null : teamBrand.logo || null;
|
||||
|
||||
// Get invites based on context - use watched invites if provided, otherwise fall back to store
|
||||
@@ -117,7 +118,7 @@ export const OnboardingInviteBrowserView = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="border-subtle bg-muted hidden h-full w-full flex-col overflow-hidden rounded-l-2xl border xl:flex">
|
||||
<div className="border-subtle bg-cal-muted hidden h-full w-full flex-col overflow-hidden rounded-l-2xl border xl:flex">
|
||||
{/* Content */}
|
||||
<div className="h-full px-6 pt-6">
|
||||
<AnimatePresence mode="wait">
|
||||
@@ -142,21 +143,23 @@ export const OnboardingInviteBrowserView = ({
|
||||
/>
|
||||
<div className="flex w-full flex-col items-start gap-1">
|
||||
<h2 className="text-emphasis font-cal w-full text-left text-xl font-semibold leading-tight">
|
||||
{displayInviterName} invited you to join {displayName}
|
||||
{displayName}
|
||||
</h2>
|
||||
<p className="text-subtle text-left text-sm font-normal leading-tight">
|
||||
We're emailing you all the details
|
||||
{displayBio || "We're emailing you all the details"}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Email Body */}
|
||||
<div className="bg-default border-subtle mt-3 grid grid-cols-3 gap-4 rounded-t-2xl border p-6 opacity-60">
|
||||
<div className="bg-default border-subtle mt-3 grid grid-cols-3 gap-4 rounded-t-2xl border p-6">
|
||||
{displayItems.map((item, index) => (
|
||||
<div
|
||||
key={`${item.email}-${index}`}
|
||||
className="bg-default border-subtle flex aspect-square w-full min-w-0 flex-col items-center justify-center gap-2 overflow-hidden rounded-lg border p-4">
|
||||
className={`bg-default border-subtle flex aspect-square w-full min-w-0 flex-col items-center justify-center gap-2 overflow-hidden rounded-lg border p-4 ${
|
||||
!item.isReal ? "opacity-60" : ""
|
||||
}`}>
|
||||
<Avatar size="mdLg" imageSrc={undefined} alt={item.name} className="mt-4" />
|
||||
<div className="flex w-full min-w-0 flex-col items-center gap-4">
|
||||
<div className="flex w-full min-w-0 flex-col items-center">
|
||||
|
||||
@@ -88,14 +88,14 @@ export const OnboardingOrganizationBrowserView = ({
|
||||
<Icon name="arrow-right" className="text-subtle h-4 w-4" />
|
||||
<Icon name="rotate-cw" className="text-subtle h-4 w-4" />
|
||||
</div>
|
||||
<div className="bg-muted flex w-full min-w-0 items-center gap-2 rounded-[32px] px-3 py-2">
|
||||
<div className="bg-cal-muted flex w-full min-w-0 items-center gap-2 rounded-[32px] px-3 py-2">
|
||||
<Icon name="lock" className="text-subtle h-4 w-4" />
|
||||
<p className="text-default truncate text-sm font-medium leading-tight">{displayUrl}</p>
|
||||
</div>
|
||||
<Icon name="ellipsis-vertical" className="text-subtle h-4 w-4" />
|
||||
</div>
|
||||
{/* Content */}
|
||||
<div className="bg-muted h-full pl-11 pt-11">
|
||||
<div className="bg-cal-muted h-full pl-11 pt-11">
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
key={pathname}
|
||||
|
||||
@@ -54,7 +54,7 @@ export const OnboardingTeamsBrowserView = ({
|
||||
<Icon name="arrow-right" className="text-subtle h-4 w-4" />
|
||||
<Icon name="rotate-cw" className="text-subtle h-4 w-4" />
|
||||
</div>
|
||||
<div className="bg-muted flex w-full items-center gap-2 rounded-[32px] px-3 py-2">
|
||||
<div className="bg-cal-muted flex w-full items-center gap-2 rounded-[32px] px-3 py-2">
|
||||
<Icon name="lock" className="text-subtle h-4 w-4" />
|
||||
<p className="text-default text-sm font-medium leading-tight">{webappUrl}/teams</p>
|
||||
</div>
|
||||
@@ -62,7 +62,7 @@ export const OnboardingTeamsBrowserView = ({
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="bg-muted h-full pl-11 pt-11">
|
||||
<div className="bg-cal-muted h-full pl-11 pt-11">
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
key={pathname}
|
||||
@@ -149,7 +149,7 @@ export const OnboardingTeamsBrowserView = ({
|
||||
))
|
||||
) : (
|
||||
<div className="flex flex-col items-center justify-center gap-3 px-5 py-12">
|
||||
<div className="bg-muted flex h-16 w-16 items-center justify-center rounded-full">
|
||||
<div className="bg-cal-muted flex h-16 w-16 items-center justify-center rounded-full">
|
||||
<Icon name="users" className="text-subtle h-8 w-8" />
|
||||
</div>
|
||||
<div className="flex flex-col gap-1 text-center">
|
||||
|
||||
@@ -126,7 +126,7 @@ export const OnboardingView = ({ userEmail }: OnboardingViewProps) => {
|
||||
</div>
|
||||
}>
|
||||
{/* Card */}
|
||||
<div className="bg-muted border-muted relative flex min-h-0 w-full flex-col overflow-hidden rounded-xl border p-1">
|
||||
<div className="bg-cal-muted border-muted relative flex min-h-0 w-full flex-col overflow-hidden rounded-xl border p-1">
|
||||
<div className="rounded-inherit flex w-full flex-col items-start overflow-clip">
|
||||
{/* Plan options */}
|
||||
<RadioAreaGroup.Group
|
||||
@@ -174,7 +174,7 @@ export const OnboardingView = ({ userEmail }: OnboardingViewProps) => {
|
||||
</OnboardingCard>
|
||||
|
||||
{/* Right column - Icon display */}
|
||||
<div className="bg-muted border-subtle hidden h-full w-full rounded-l-2xl border-b border-l border-t xl:flex xl:items-center xl:justify-center">
|
||||
<div className="bg-cal-muted border-subtle hidden h-full w-full rounded-l-2xl border-b border-l border-t xl:flex xl:items-center xl:justify-center">
|
||||
<AnimatePresence mode="wait">
|
||||
{selectedPlanData && (
|
||||
<PlanIcon
|
||||
|
||||
@@ -109,7 +109,7 @@ export const OrganizationBrandView = ({ userEmail }: OrganizationBrandViewProps)
|
||||
<div className="flex w-full flex-col gap-2">
|
||||
<p className="text-emphasis text-sm font-medium leading-4">{t("onboarding_banner_label")}</p>
|
||||
<div className="flex w-full flex-col gap-2">
|
||||
<div className="bg-muted border-muted relative h-[92px] w-full overflow-hidden rounded-md border">
|
||||
<div className="bg-cal-muted border-muted relative h-[92px] w-full overflow-hidden rounded-md border">
|
||||
{bannerPreview && (
|
||||
<img
|
||||
src={bannerPreview}
|
||||
@@ -143,7 +143,7 @@ export const OrganizationBrandView = ({ userEmail }: OrganizationBrandViewProps)
|
||||
<div className="flex w-full flex-col gap-2">
|
||||
<p className="text-emphasis text-sm font-medium leading-4">{t("logo")}</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="bg-muted border-muted relative h-16 w-16 shrink-0 overflow-hidden rounded-md border">
|
||||
<div className="bg-cal-muted border-muted relative h-16 w-16 shrink-0 overflow-hidden rounded-md border">
|
||||
{logoPreview && (
|
||||
<img
|
||||
src={logoPreview}
|
||||
|
||||
@@ -105,7 +105,7 @@ export const OrganizationDetailsView = ({ userEmail }: OrganizationDetailsViewPr
|
||||
<div className="flex w-full flex-col gap-4 rounded-xl">
|
||||
{/* Organization Name */}
|
||||
<div className="flex w-full flex-col gap-1.5">
|
||||
<Label className="text-emphasis text-sm font-medium leading-4">
|
||||
<Label className="text-emphasis mb-0 text-sm font-medium leading-4">
|
||||
{t("organization_name")}
|
||||
</Label>
|
||||
<TextField
|
||||
@@ -124,7 +124,7 @@ export const OrganizationDetailsView = ({ userEmail }: OrganizationDetailsViewPr
|
||||
|
||||
{/* Organization Bio */}
|
||||
<div className="flex w-full flex-col gap-1.5">
|
||||
<Label className="text-emphasis text-sm font-medium leading-4">
|
||||
<Label className="text-emphasis mb-0 text-sm font-medium leading-4">
|
||||
{t("onboarding_org_bio_label")}
|
||||
</Label>
|
||||
<TextArea
|
||||
|
||||
@@ -76,7 +76,7 @@ export function ValidatedOrganizationSlug({
|
||||
|
||||
return (
|
||||
<div className="flex w-full flex-col gap-1.5">
|
||||
<Label className="text-emphasis text-sm font-medium leading-4">Organization link</Label>
|
||||
<Label className="text-emphasis mb-0 text-sm font-medium leading-4">Organization link</Label>
|
||||
<TextField
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
|
||||
@@ -148,7 +148,9 @@ export const OrganizationCSVUploadModal = ({ isOpen, onClose }: OrganizationCSVU
|
||||
<Logo className="h-10 w-auto" />
|
||||
</div>
|
||||
|
||||
<div className="relative mx-auto flex items-center justify-center" style={{ width: 320, height: 180 }}>
|
||||
<div
|
||||
className="relative mx-auto flex items-center justify-center"
|
||||
style={{ width: 320, height: 180 }}>
|
||||
<div
|
||||
className="from-default to-muted border-subtle flex items-center justify-center rounded-2xl border bg-gradient-to-br p-8 shadow-sm"
|
||||
style={{ width: 200, height: 150 }}>
|
||||
@@ -165,7 +167,11 @@ export const OrganizationCSVUploadModal = ({ isOpen, onClose }: OrganizationCSVU
|
||||
) : (
|
||||
<div className="flex flex-col items-center gap-3">
|
||||
<div className="from-default to-muted border-subtle flex items-center justify-center rounded-full border bg-gradient-to-b p-4 shadow-sm">
|
||||
<Icon name="upload" className="text-emphasis opacity-70" style={{ width: 32, height: 32 }} />
|
||||
<Icon
|
||||
name="upload"
|
||||
className="text-emphasis opacity-70"
|
||||
style={{ width: 32, height: 32 }}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-subtle text-center text-sm">{t("upload_csv_subtitle")}</p>
|
||||
</div>
|
||||
@@ -179,7 +185,7 @@ export const OrganizationCSVUploadModal = ({ isOpen, onClose }: OrganizationCSVU
|
||||
</div>
|
||||
|
||||
<div className="mb-2 flex flex-col gap-3">
|
||||
<div className="bg-muted border-subtle flex items-center gap-3 rounded-lg border p-4">
|
||||
<div className="bg-cal-muted border-subtle flex items-center gap-3 rounded-lg border p-4">
|
||||
<div className="from-default to-muted border-subtle flex items-center justify-center rounded-full border bg-gradient-to-b p-2 shadow-sm">
|
||||
<Icon name="download" className="text-emphasis" style={{ width: 16, height: 16 }} />
|
||||
</div>
|
||||
@@ -192,7 +198,7 @@ export const OrganizationCSVUploadModal = ({ isOpen, onClose }: OrganizationCSVU
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="bg-muted border-subtle flex items-center gap-3 rounded-lg border p-4">
|
||||
<div className="bg-cal-muted border-subtle flex items-center gap-3 rounded-lg border p-4">
|
||||
<div className="from-default to-muted border-subtle flex items-center justify-center rounded-full border bg-gradient-to-b p-2 shadow-sm">
|
||||
<Icon name="upload" className="text-emphasis" style={{ width: 16, height: 16 }} />
|
||||
</div>
|
||||
@@ -220,7 +226,7 @@ export const OrganizationCSVUploadModal = ({ isOpen, onClose }: OrganizationCSVU
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-muted border-subtle mt-6 flex items-center justify-between rounded-b-2xl border-t px-8 py-6">
|
||||
<div className="bg-cal-muted border-subtle mt-6 flex items-center justify-between rounded-b-2xl border-t px-8 py-6">
|
||||
<Button color="minimal" onClick={handleClose} disabled={isUploading}>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
@@ -236,4 +242,3 @@ export const OrganizationCSVUploadModal = ({ isOpen, onClose }: OrganizationCSVU
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
+3
-3
@@ -167,9 +167,9 @@ export const OrganizationInviteEmailView = ({ userEmail }: OrganizationInviteEma
|
||||
</div>
|
||||
</div>
|
||||
}>
|
||||
<div className="flex h-full w-full flex-col gap-4">
|
||||
<Form form={form} handleSubmit={handleContinue} className="h-full w-full">
|
||||
<div className="flex h-full w-full flex-col gap-4">
|
||||
<div className="flex w-full flex-col gap-4">
|
||||
<Form form={form} handleSubmit={handleContinue} className="w-full">
|
||||
<div className="flex w-full flex-col gap-4">
|
||||
<EmailInviteForm
|
||||
fields={fields}
|
||||
append={append}
|
||||
|
||||
@@ -12,7 +12,7 @@ type OnboardingCardProps = {
|
||||
|
||||
export const OnboardingCard = ({ title, subtitle, children, footer, isLoading }: OnboardingCardProps) => {
|
||||
return (
|
||||
<div className="bg-muted border-muted relative rounded-xl border p-1">
|
||||
<div className="bg-cal-muted border-muted relative rounded-xl border p-1">
|
||||
<div className="rounded-inherit flex w-full flex-col items-start overflow-clip">
|
||||
{/* Card Header */}
|
||||
<div className="flex w-full gap-1.5 px-5 py-4">
|
||||
|
||||
@@ -38,7 +38,7 @@ export const OnboardingLayout = ({ userEmail, currentStep, children }: Onboardin
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="bg-muted flex items-center gap-2 rounded-full px-3 py-2">
|
||||
<div className="bg-cal-muted flex items-center gap-2 rounded-full px-3 py-2">
|
||||
<p className="text-emphasis text-sm font-medium leading-none">{userEmail}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -136,7 +136,7 @@ export const TeamDetailsView = ({ userEmail }: TeamDetailsViewProps) => {
|
||||
|
||||
{/* Team Name */}
|
||||
<div className="flex w-full flex-col gap-1.5">
|
||||
<Label className="text-emphasis text-sm font-medium leading-4">{t("team_name")}</Label>
|
||||
<Label className="text-emphasis mb-0 text-sm font-medium leading-4">{t("team_name")}</Label>
|
||||
<TextField
|
||||
value={teamName}
|
||||
onChange={(e) => setTeamName(e.target.value)}
|
||||
@@ -154,7 +154,7 @@ export const TeamDetailsView = ({ userEmail }: TeamDetailsViewProps) => {
|
||||
|
||||
{/* Team Bio */}
|
||||
<div className="flex w-full flex-col gap-1.5">
|
||||
<Label className="text-emphasis text-sm font-medium leading-4">{t("team_bio")}</Label>
|
||||
<Label className="text-emphasis mb-0 text-sm font-medium leading-4">{t("team_bio")}</Label>
|
||||
<TextArea
|
||||
value={teamBio}
|
||||
onChange={(e) => setTeamBio(e.target.value)}
|
||||
|
||||
@@ -87,7 +87,7 @@ export function ValidatedTeamSlug({ value, onChange, onValidationChange }: Valid
|
||||
|
||||
return (
|
||||
<div className="flex w-full flex-col gap-1.5">
|
||||
<Label className="text-emphasis text-sm font-medium leading-4">{t("team_url")}</Label>
|
||||
<Label className="text-emphasis mb-0 text-sm font-medium leading-4">{t("team_url")}</Label>
|
||||
<TextField
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
|
||||
@@ -185,7 +185,7 @@ export const CSVUploadModal = ({ isOpen, onClose }: CSVUploadModalProps) => {
|
||||
|
||||
<div className="mb-2 flex flex-col gap-3">
|
||||
{/* Download template */}
|
||||
<div className="bg-muted border-subtle flex items-center gap-3 rounded-lg border p-4">
|
||||
<div className="bg-cal-muted border-subtle flex items-center gap-3 rounded-lg border p-4">
|
||||
<div className="from-default to-muted border-subtle flex items-center justify-center rounded-full border bg-gradient-to-b p-2 shadow-sm">
|
||||
<Icon name="download" className="text-emphasis" style={{ width: 16, height: 16 }} />
|
||||
</div>
|
||||
@@ -199,7 +199,7 @@ export const CSVUploadModal = ({ isOpen, onClose }: CSVUploadModalProps) => {
|
||||
</div>
|
||||
|
||||
{/* File upload */}
|
||||
<div className="bg-muted border-subtle flex items-center gap-3 rounded-lg border p-4">
|
||||
<div className="bg-cal-muted border-subtle flex items-center gap-3 rounded-lg border p-4">
|
||||
<div className="from-default to-muted border-subtle flex items-center justify-center rounded-full border bg-gradient-to-b p-2 shadow-sm">
|
||||
<Icon name="upload" className="text-emphasis" style={{ width: 16, height: 16 }} />
|
||||
</div>
|
||||
@@ -227,7 +227,7 @@ export const CSVUploadModal = ({ isOpen, onClose }: CSVUploadModalProps) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-muted border-subtle mt-6 flex items-center justify-between rounded-b-2xl border-t px-8 py-6">
|
||||
<div className="bg-cal-muted border-subtle mt-6 flex items-center justify-between rounded-b-2xl border-t px-8 py-6">
|
||||
<Button color="minimal" onClick={handleClose} disabled={isUploading}>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
|
||||
@@ -138,7 +138,7 @@ export const TeamInviteEmailView = ({ userEmail }: TeamInviteEmailViewProps) =>
|
||||
{/* Left column - Main content */}
|
||||
<div className="flex h-full w-full flex-col gap-4">
|
||||
<OnboardingCard
|
||||
title={t("invite_via_email")}
|
||||
title={t("invite")}
|
||||
subtitle={t("team_invite_subtitle")}
|
||||
footer={
|
||||
<div className="flex w-full items-center justify-end gap-4">
|
||||
|
||||
@@ -399,7 +399,7 @@
|
||||
"welcome_to_calcom": "Welcome to {{appName}}",
|
||||
"personal_welcome_description": "You're all set! Start scheduling meetings and managing your calendar.",
|
||||
"unlimited_event_types": "Unlimited event types",
|
||||
"workflows_feature": "Workflows (or another popular feature)",
|
||||
"workflows_feature": "Workflows",
|
||||
"and_more": "And more…",
|
||||
"welcome_instructions": "Tell us what to call you and let us know what timezone you're in. You'll be able to edit this later.",
|
||||
"connect_caldav": "Connect to CalDav (Beta)",
|
||||
@@ -2558,7 +2558,7 @@
|
||||
"no_organization_slug": "There was an error creating teams for this organization. Missing URL slug.",
|
||||
"copy_link_org": "Copy link to organization",
|
||||
"welcome_to_organizations": "Welcome to Organizations!",
|
||||
"organizations_welcome_description": "We're excited to connect your bookers with your team members. With your Teams's plan you get:",
|
||||
"organizations_welcome_description": "We're excited to connect your bookers with your team members. With your Organization's plan you get:",
|
||||
"1_parent_team_unlimited_subteams": "1 parent team and unlimited sub-teams",
|
||||
"organization_workflows": "Organization workflows",
|
||||
"custom_subdomain": "Yourcompany.cal.com subdomain",
|
||||
|
||||
Reference in New Issue
Block a user