Skip to content

Commit

Permalink
fix(clerk-js): UI fixes for <SignIn/> & <SignUp/> to match components (
Browse files Browse the repository at this point in the history
…#2625)

* fix(clerk-js): Applied fixes to match the designs

* chore(repo): Add Changeset

* chore(clerk-js): Update card action descriptor in ResetPassword
  • Loading branch information
octoper authored Jan 18, 2024
1 parent a6308c6 commit 31912c1
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 116 deletions.
2 changes: 2 additions & 0 deletions .changeset/odd-islands-attack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
84 changes: 50 additions & 34 deletions packages/clerk-js/src/ui/components/SignIn/ResetPassword.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ export const _ResetPassword = () => {
}
};

const goBack = () => {
return navigate('../');
};

return (
<Card.Root>
<Card.Content>
Expand All @@ -105,43 +109,55 @@ export const _ResetPassword = () => {
<Form.Root
onSubmit={resetPassword}
onBlur={validateForm}
gap={8}
>
{/* For password managers */}
<input
readOnly
data-testid='hidden-identifier'
id='identifier-field'
name='identifier'
value={signIn.identifier || ''}
style={{ display: 'none' }}
/>
<Form.ControlRow elementId={passwordField.id}>
<Form.PasswordInput
{...passwordField.props}
isRequired
autoFocus
/>
</Form.ControlRow>
<Form.ControlRow elementId={confirmField.id}>
<Form.PasswordInput
{...confirmField.props}
onChange={e => {
if (e.target.value) {
setConfirmPasswordFeedback(e.target.value);
}
return confirmField.props.onChange(e);
}}
<Col gap={6}>
{/* For password managers */}
<input
readOnly
data-testid='hidden-identifier'
id='identifier-field'
name='identifier'
value={signIn.identifier || ''}
style={{ display: 'none' }}
/>
</Form.ControlRow>
{!requiresNewPassword && (
<Form.ControlRow elementId={sessionsField.id}>
<Form.Checkbox {...sessionsField.props} />
<Form.ControlRow elementId={passwordField.id}>
<Form.PasswordInput
{...passwordField.props}
isRequired
autoFocus
/>
</Form.ControlRow>
)}
<Form.SubmitButton
isDisabled={!canSubmit}
localizationKey={localizationKeys('signIn.resetPassword.formButtonPrimary')}
/>
<Form.ControlRow elementId={confirmField.id}>
<Form.PasswordInput
{...confirmField.props}
onChange={e => {
if (e.target.value) {
setConfirmPasswordFeedback(e.target.value);
}
return confirmField.props.onChange(e);
}}
/>
</Form.ControlRow>
{!requiresNewPassword && (
<Form.ControlRow elementId={sessionsField.id}>
<Form.Checkbox {...sessionsField.props} />
</Form.ControlRow>
)}
</Col>
<Col gap={4}>
<Form.SubmitButton
isDisabled={!canSubmit}
localizationKey={localizationKeys('signIn.resetPassword.formButtonPrimary')}
/>
<Card.Action elementId='alternativeMethods'>
<Card.ActionLink
elementDescriptor={descriptors.backLink}
localizationKey={localizationKeys('backButton')}
onClick={goBack}
/>
</Card.Action>
</Col>
</Form.Root>
</Col>
</Card.Content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export const SignInFactorOnePasswordCard = (props: SignInFactorOnePasswordProps)
return (
<Flow.Part part='password'>
<Card.Root>
<Card.Content>
<Card.Content gap={4}>
<Card.Alert>{card.error}</Card.Alert>
<Header.Root gap={1}>
<Header.Title localizationKey={localizationKeys('signIn.password.title')} />
Expand All @@ -111,7 +111,7 @@ export const SignInFactorOnePasswordCard = (props: SignInFactorOnePasswordProps)
>
<Form.Root
onSubmit={handlePasswordSubmit}
gap={6}
gap={8}
>
{/* For password managers */}
<input
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const SignInFactorTwoAlternativeMethods = (props: AlternativeMethodsProps
};

const AlternativeMethodsList = (props: AlternativeMethodsProps & { onHavingTroubleClick: React.MouseEventHandler }) => {
const { onHavingTroubleClick, onFactorSelected } = props;
const { onHavingTroubleClick, onFactorSelected, onBackLinkClick } = props;
const card = useCardState();
const { supportedSecondFactors } = useCoreSignIn();

Expand All @@ -48,7 +48,7 @@ const AlternativeMethodsList = (props: AlternativeMethodsProps & { onHavingTroub
{/*TODO: extract main in its own component */}
<Col
elementDescriptor={descriptors.main}
gap={8}
gap={4}
>
<Col gap={2}>
{supportedSecondFactors.sort(backupCodePrefFactorComparator).map((factor, i) => (
Expand All @@ -63,18 +63,26 @@ const AlternativeMethodsList = (props: AlternativeMethodsProps & { onHavingTroub
/>
))}
</Col>
<Card.Action elementId='alternativeMethods'>
{onBackLinkClick && (
<Card.ActionLink
localizationKey={localizationKeys('backButton')}
onClick={props.onBackLinkClick}
/>
)}
</Card.Action>
</Col>
</Card.Content>

<Card.Footer>
<Card.Action elementId='havingTrouble'>
<Card.ActionText localizationKey={localizationKeys('signIn.alternativeMethods.actionText')} />
<Card.ActionLink
localizationKey={localizationKeys('signIn.alternativeMethods.actionLink')}
onClick={onHavingTroubleClick}
/>
</Card.Action>
</Card.Content>

<Card.Footer />
</Card.Footer>
</Card.Root>
</Flow.Part>
);
Expand Down
25 changes: 15 additions & 10 deletions packages/clerk-js/src/ui/components/SignIn/SignInStart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -305,16 +305,21 @@ export function _SignInStart(): JSX.Element {
/>
)}
{standardFormAttributes.length ? (
<Form.Root onSubmit={handleFirstPartySubmit}>
<Form.ControlRow elementId={identifierField.id}>
<DynamicField
actionLabel={nextIdentifier?.action}
onActionClicked={switchToNextIdentifier}
{...identifierFieldProps}
autoFocus={shouldAutofocus}
/>
</Form.ControlRow>
<InstantPasswordRow field={passwordBasedInstance ? instantPasswordField : undefined} />
<Form.Root
onSubmit={handleFirstPartySubmit}
gap={8}
>
<Col>
<Form.ControlRow elementId={identifierField.id}>
<DynamicField
actionLabel={nextIdentifier?.action}
onActionClicked={switchToNextIdentifier}
{...identifierFieldProps}
autoFocus={shouldAutofocus}
/>
</Form.ControlRow>
<InstantPasswordRow field={passwordBasedInstance ? instantPasswordField : undefined} />
</Col>
<Form.SubmitButton hasArrow />
</Form.Root>
) : null}
Expand Down
131 changes: 68 additions & 63 deletions packages/clerk-js/src/ui/components/SignUp/SignUpForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import { localizationKeys, useAppearance } from '../../customizables';
import { Col, localizationKeys, useAppearance } from '../../customizables';
import { Form } from '../../elements';
import { mqu } from '../../styledSystem';
import type { FormControlState } from '../../utils';
Expand Down Expand Up @@ -29,72 +29,77 @@ export const SignUpForm = (props: SignUpFormProps) => {
};

return (
<Form.Root onSubmit={handleSubmit}>
{(shouldShow('firstName') || shouldShow('lastName')) && (
<Form.ControlRow
elementId='name'
sx={{
[mqu.sm]: {
flexWrap: 'wrap',
},
}}
>
{shouldShow('firstName') && (
<Form.Root
onSubmit={handleSubmit}
gap={8}
>
<Col gap={6}>
{(shouldShow('firstName') || shouldShow('lastName')) && (
<Form.ControlRow
elementId='name'
sx={{
[mqu.sm]: {
flexWrap: 'wrap',
},
}}
>
{shouldShow('firstName') && (
<Form.PlainInput
{...formState.firstName.props}
isRequired={fields.firstName!.required}
isOptional={!fields.firstName!.required}
/>
)}
{shouldShow('lastName') && (
<Form.PlainInput
{...formState.lastName.props}
isRequired={fields.lastName!.required}
isOptional={!fields.lastName!.required}
/>
)}
</Form.ControlRow>
)}
{shouldShow('username') && (
<Form.ControlRow elementId='username'>
<Form.PlainInput
{...formState.firstName.props}
isRequired={fields.firstName!.required}
isOptional={!fields.firstName!.required}
{...formState.username.props}
isRequired={fields.username!.required}
isOptional={!fields.username!.required}
/>
)}
{shouldShow('lastName') && (
</Form.ControlRow>
)}
{shouldShow('emailAddress') && (
<Form.ControlRow elementId='emailAddress'>
<Form.PlainInput
{...formState.lastName.props}
isRequired={fields.lastName!.required}
isOptional={!fields.lastName!.required}
{...formState.emailAddress.props}
isRequired={fields.emailAddress!.required}
isOptional={!fields.emailAddress!.required}
actionLabel={canToggleEmailPhone ? 'Use phone instead' : undefined}
onActionClicked={canToggleEmailPhone ? () => handleEmailPhoneToggle('phoneNumber') : undefined}
/>
)}
</Form.ControlRow>
)}
{shouldShow('username') && (
<Form.ControlRow elementId='username'>
<Form.PlainInput
{...formState.username.props}
isRequired={fields.username!.required}
isOptional={!fields.username!.required}
/>
</Form.ControlRow>
)}
{shouldShow('emailAddress') && (
<Form.ControlRow elementId='emailAddress'>
<Form.PlainInput
{...formState.emailAddress.props}
isRequired={fields.emailAddress!.required}
isOptional={!fields.emailAddress!.required}
actionLabel={canToggleEmailPhone ? 'Use phone instead' : undefined}
onActionClicked={canToggleEmailPhone ? () => handleEmailPhoneToggle('phoneNumber') : undefined}
/>
</Form.ControlRow>
)}
{shouldShow('phoneNumber') && (
<Form.ControlRow elementId='phoneNumber'>
<Form.PhoneInput
{...formState.phoneNumber.props}
isRequired={fields.phoneNumber!.required}
isOptional={!fields.phoneNumber!.required}
actionLabel={canToggleEmailPhone ? 'Use email instead' : undefined}
onActionClicked={canToggleEmailPhone ? () => handleEmailPhoneToggle('emailAddress') : undefined}
/>
</Form.ControlRow>
)}
{shouldShow('password') && (
<Form.ControlRow elementId='password'>
<Form.PasswordInput
{...formState.password.props}
isRequired={fields.password!.required}
isOptional={!fields.password!.required}
/>
</Form.ControlRow>
)}
</Form.ControlRow>
)}
{shouldShow('phoneNumber') && (
<Form.ControlRow elementId='phoneNumber'>
<Form.PhoneInput
{...formState.phoneNumber.props}
isRequired={fields.phoneNumber!.required}
isOptional={!fields.phoneNumber!.required}
actionLabel={canToggleEmailPhone ? 'Use email instead' : undefined}
onActionClicked={canToggleEmailPhone ? () => handleEmailPhoneToggle('emailAddress') : undefined}
/>
</Form.ControlRow>
)}
{shouldShow('password') && (
<Form.ControlRow elementId='password'>
<Form.PasswordInput
{...formState.password.props}
isRequired={fields.password!.required}
isOptional={!fields.password!.required}
/>
</Form.ControlRow>
)}
</Col>
<Form.SubmitButton
hasArrow
localizationKey={localizationKeys('formButtonPrimary')}
Expand Down
2 changes: 1 addition & 1 deletion packages/clerk-js/src/ui/elements/Card/CardRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const CardRoot = React.forwardRef<HTMLDivElement, CardRootProps>((props,
maxWidth: `calc(100vw - ${t.sizes.$20})`,
width: t.sizes.$100,
boxShadow: t.shadows.$cardBoxShadow,
borderRadius: t.radii.$xl,
borderRadius: t.radii.$lg,
color: t.colors.$colorText,
position: 'relative',
overflow: 'hidden',
Expand Down
3 changes: 2 additions & 1 deletion packages/clerk-js/src/ui/elements/CodeControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,11 @@ export const OTPCodeControl = React.forwardRef<{ reset: any }>((_, ref) => {
onKeyDown={handleOnKeyDown(index)}
onInput={handleOnInput(index)}
onPaste={handleOnPaste(index)}
id={`digit-${index}-field`}
ref={node => (refs.current[index] = node)}
autoFocus={index === 0 || undefined}
autoComplete='one-time-code'
aria-label={`${index === 0 ? 'Enter verification code. ' : ''} Digit ${index + 1}`}
aria-label={`${index === 0 ? 'Enter verification code. ' : ''}Digit ${index + 1}`}
isDisabled={isDisabled || isLoading || disabled || feedbackType === 'success'}
hasError={feedbackType === 'error'}
isSuccessfullyFilled={feedbackType === 'success'}
Expand Down

0 comments on commit 31912c1

Please sign in to comment.