Skip to content

Commit

Permalink
update the styles of the onboarding steps
Browse files Browse the repository at this point in the history
  • Loading branch information
nilscox committed Aug 29, 2024
1 parent e319df2 commit b8c11d8
Show file tree
Hide file tree
Showing 13 changed files with 223 additions and 126 deletions.
52 changes: 33 additions & 19 deletions src/components/accept-or-decline-invitation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,28 +64,42 @@ export function AcceptOrDeclineInvitation({ invitation }: AcceptOrDeclineInvitat
}

return (
<div className="col items-center gap-6">
<div className="col w-full max-w-xl items-center gap-6 text-center">
<h1 className="typo-heading">
<T id="title" values={{ organizationName: invitation.organization.name }} />
<T
id="title"
values={{
organization: (children) => <div className="mt-1 text-4xl">{children}</div>,
organizationName: invitation.organization.name,
}}
/>
</h1>

<p className="text-dim">
<T id="description" values={{ name: invitation.inviter.name, email: invitation.inviter.email }} />
</p>

<div className="row gap-4 ">
<Button onClick={() => acceptMutation.mutate()} loading={acceptMutation.isPending}>
<T id="accept" />
</Button>

<Button
variant="outline"
color="gray"
onClick={() => declineMutation.mutate()}
loading={declineMutation.isPending}
>
<T id="decline" />
</Button>
<div className="col gap-4">
<div className="font-medium text-dim">
<T
id="description"
values={{
name: invitation.inviter.name,
email: <span className="text-green">{invitation.inviter.email}</span>,
}}
/>
</div>

<div className="row justify-center gap-4">
<Button
size={3}
color="gray"
onClick={() => declineMutation.mutate()}
loading={declineMutation.isPending}
>
<T id="decline" />
</Button>

<Button size={3} onClick={() => acceptMutation.mutate()} loading={acceptMutation.isPending}>
<T id="accept" />
</Button>
</div>
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/address-field/address-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type AddressFieldOwnProps = {
type AddressFieldProps = AddressFieldOwnProps &
Pick<
React.ComponentProps<typeof Autocomplete<AutofillSuggestion>>,
'required' | 'size' | 'label' | 'placeholder'
'required' | 'size' | 'label' | 'placeholder' | 'className'
>;

export const AddressField = ({ value, onChange, errors, ...props }: AddressFieldProps) => {
Expand Down
8 changes: 4 additions & 4 deletions src/components/error-boundary/account-locked.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ export function AccountLocked() {
const { onOpen } = useTallyDialog('wQRgBY');

return (
<SecondaryLayout className="col max-w-xl gap-4 text-center">
<SecondaryLayout className="col mx-auto max-w-xl gap-4 text-center">
<div className="typo-heading">
<T id="title" />
</div>

<div className="text-xs text-dim">
<div className="text-xs font-medium text-dim">
<T
id="line1"
values={{
Expand All @@ -28,11 +28,11 @@ export function AccountLocked() {
/>
</div>

<div>
<div className="text-dim">
<T id="line2" />
</div>

<div>
<div className="text-dim">
<T
id="line3"
values={{
Expand Down
89 changes: 44 additions & 45 deletions src/components/payment-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,12 @@ const stylesDark = {
};

type PaymentFormProps = {
theme?: 'dark' | 'light';
plan?: OrganizationPlan;
onPlanChanged?: () => void;
renderFooter: (formState: FormState<{ address: Address }>) => React.ReactNode;
};

export function PaymentForm({ theme: themeProp, plan, onPlanChanged, renderFooter }: PaymentFormProps) {
export function PaymentForm({ plan, onPlanChanged, renderFooter }: PaymentFormProps) {
const t = T.useTranslate();
const organization = useOrganization();

Expand Down Expand Up @@ -134,63 +133,63 @@ export function PaymentForm({ theme: themeProp, plan, onPlanChanged, renderFoote
});

const theme = useThemeModeOrPreferred();
const style = (themeProp ?? theme) === ThemeMode.light ? stylesLight : stylesDark;
const style = theme === ThemeMode.light ? stylesLight : stylesDark;

return (
<form onSubmit={handleSubmit(form, mutation.mutateAsync)} className="col gap-6">
<div className="col gap-3">
<Field>
<div className="grid grid-cols-2 gap-4">
<Field className="col-span-2">
<FieldLabel>
<T id="cardNumberLabel" />
</FieldLabel>
<CardNumberElement options={{ classes, style }} />
</Field>

<div className="row gap-2">
<Field className="flex-1">
<FieldLabel>
<T id="cardNumberLabel" />
</FieldLabel>
<CardExpiryElement options={{ classes, style }} />
</Field>

<Field className="flex-1">
<FieldLabel>
<T id="cardNumberLabel" />
</FieldLabel>
<CardCvcElement options={{ classes, style }} />
</Field>
</div>
<Field className="flex-1">
<FieldLabel>
<T id="expirationLabel" />
</FieldLabel>
<CardExpiryElement options={{ classes, style }} />
</Field>

<Controller
control={form.control}
name="address"
render={({ field }) => (
<AddressField
required
size={3}
label={<T id="addressLabel" />}
placeholder={t('addressPlaceholder')}
value={field.value}
onChange={field.onChange}
errors={{
line1: form.formState.errors.address?.line1?.message,
line2: form.formState.errors.address?.line2?.message,
city: form.formState.errors.address?.city?.message,
postalCode: form.formState.errors.address?.postalCode?.message,
state: form.formState.errors.address?.state?.message,
country: form.formState.errors.address?.country?.message,
}}
/>
)}
/>
<Field className="flex-1">
<FieldLabel>
<T id="cvcLabel" />
</FieldLabel>
<CardCvcElement options={{ classes, style }} />
</Field>

<p className="text-xs text-dim">
<T id="temporaryHoldMessage" />
</p>
<div className="col-span-2">
<Controller
control={form.control}
name="address"
render={({ field }) => (
<AddressField
required
size={3}
label={<T id="addressLabel" />}
placeholder={t('addressPlaceholder')}
value={field.value}
onChange={field.onChange}
errors={{
line1: form.formState.errors.address?.line1?.message,
line2: form.formState.errors.address?.line2?.message,
city: form.formState.errors.address?.city?.message,
postalCode: form.formState.errors.address?.postalCode?.message,
state: form.formState.errors.address?.state?.message,
country: form.formState.errors.address?.country?.message,
}}
/>
)}
/>
</div>
</div>

{renderFooter(form.formState)}

<p className="text-xs text-dim">
<T id="temporaryHoldMessage" />
</p>
</form>
);
}
Expand Down
18 changes: 9 additions & 9 deletions src/intl/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@
"errorBoundary": {
"accountLocked": {
"title": "We cannot offer you access to Koyeb",
"line1": "Your account matches patterns often associated with violations of our <terms>terms of service</terms>",
"line1": "Your account matches patterns often associated with violations of our <terms>Terms of Service</terms>",
"line2": "While we cannot provide details about the reason(s) triggering this behavior, we have determined that providing access to Koyeb is not possible",
"line3": "If you believe this is a bug, you can <validate>validate your account</validate>"
},
Expand Down Expand Up @@ -225,7 +225,7 @@
"pricePerSecond": "{price}/second"
},
"invitation": {
"title": "You have been invited to join the {organizationName} organization on Koyeb",
"title": "You have been invited to join the <organization>{organizationName} organization</organization>",
"description": "You were invited by {name} ({email})",
"accept": "Join organization",
"decline": "Decline",
Expand Down Expand Up @@ -264,7 +264,7 @@
"cvcLabel": "CVC",
"addressLabel": "Address",
"addressPlaceholder": "Street address",
"temporaryHoldMessage": "A temporary hold of USD $1 will be placed on the card and then refunded immediately. One free service available, pay-per-use for the rest with per-second precision.",
"temporaryHoldMessage": "A temporary hold of USD $1 will be placed on the card and then refunded immediately",
"paymentMethodTimeoutTitle": "We could not register your payment method",
"paymentMethodTimeoutDescription": "Please try again later or {contactUs} if the problem persists"
},
Expand All @@ -283,16 +283,17 @@
"onboarding": {
"emailValidation": {
"title": "Confirm your email address",
"line1": "We sent an email to {email}",
"line1": "We sent an email to <green>{email}</green>",
"line2": "Please confirm your email address by clicking the link we just sent to your inbox",
"resendValidationEmail": "Resend validation email",
"resendInvitationSuccessNotification": "An email validation was sent again to <strong>{email}</strong>",
"resendValidationEmail": "Resend verification email",
"resendEmailSuccessNotification": "A verification email was sent again to <strong>{email}</strong>",
"emailAddressValidated": "Your email address was validated"
},
"joinOrganization": {
"title": "What is your organization's name?",
"canBeChanged": "You can always change it later if you need to",
"tooltip": "An organization is a space containing all your Koyeb resources that you can use for your own projects or to collaborate as a team. The organization name must be unique and is used to compose your apps public URL. You can change it at any time.",
"continue": "Continue",
"organizationNameLabel": "Organization's name",
"organizationNameRules": {
"maxLength": "Maximum 39 characters",
"letters": "Letters are only lowercase",
Expand All @@ -303,7 +304,6 @@
"qualification": {
"title": "Tell us a bit about you",
"line1": "Your answers will help us improve your experience",
"continue": "Continue",
"fullName": {
"label": "What is your full name?"
},
Expand Down Expand Up @@ -382,7 +382,7 @@
},
"paymentMethod": {
"title": "Get started for free",
"line1": "To prevent abuse, a credit card is required",
"line1": "To prevent abuse, we need additional credit card verification",
"submit": "Get started"
},
"automaticReview": {
Expand Down
2 changes: 1 addition & 1 deletion src/layouts/secondary/secondary-layout-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export function SecondaryLayoutHeader({ background }: { background?: boolean })
return (
<header
className={clsx(
'row sticky top-0 flex-wrap items-center gap-6 px-6 py-4',
'row sticky top-0 z-10 flex-wrap items-center gap-6 px-6 py-4',
background && 'bg-gradient-to-b from-neutral from-75% to-transparent',
)}
>
Expand Down
2 changes: 1 addition & 1 deletion src/layouts/secondary/secondary-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function BackgroundTexture() {
return (
<div
// eslint-disable-next-line tailwindcss/no-arbitrary-value
className="pointer-events-none fixed bottom-0 right-0 size-[92rem] translate-x-1/2 translate-y-1/2 bg-repeat opacity-40"
className="pointer-events-none fixed bottom-0 right-0 size-[92rem] translate-x-1/2 translate-y-1/2 bg-repeat opacity-10 md:opacity-40"
style={{
backgroundImage: `url("data:image/svg+xml,${encodeURIComponent(grid)}"`,
maskImage: 'radial-gradient(circle at center, black 0, transparent 65%)',
Expand Down
27 changes: 18 additions & 9 deletions src/pages/onboarding/email-validation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { useApiMutationFn } from 'src/api/use-api';
import { notify } from 'src/application/notify';
import { Translate } from 'src/intl/translate';

import { OnboardingStepper } from './stepper';

const T = Translate.prefix('onboarding.emailValidation');

export function EmailValidation() {
Expand All @@ -15,27 +17,34 @@ export function EmailValidation() {
const mutation = useMutation({
...useApiMutationFn('resendValidationEmail', {}),
onSuccess() {
notify.success(t('resendInvitationSuccessNotification', { email: user.email }));
notify.success(t('resendEmailSuccessNotification', { email: user.email }));
},
});

return (
<section className="col gap-4 text-center">
<section className="col w-full max-w-xl items-start gap-6">
<OnboardingStepper step={1} />

<h1 className="typo-heading">
<T id="title" />
</h1>

<div className="text-xs text-dim">
<T id="line1" values={{ email: user.email }} />
<div className="col max-w-sm gap-4 text-dim">
<p className="font-medium">
<T id="line1" values={{ email: user.email, green }} />
</p>
<p>
<T id="line2" />
</p>
</div>

<div>
<T id="line2" />
</div>

<Button className="self-center" loading={mutation.isPending} onClick={() => mutation.mutate()}>
<Button loading={mutation.isPending} onClick={() => mutation.mutate()}>
<T id="resendValidationEmail" />
</Button>
</section>
);
}

const green = (children: React.ReactNode) => {
return <span className="text-green">{children}</span>;
};
Loading

0 comments on commit b8c11d8

Please sign in to comment.