UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: auth screens, error pages и новый канон внешних контуров
This commit is contained in:
@@ -23,21 +23,18 @@ export function AuthBanner(props: TAuthBanner) {
|
||||
|
||||
if (!message) return <></>;
|
||||
return (
|
||||
<div
|
||||
role="alert"
|
||||
className="relative flex items-center gap-2 rounded-md border border-accent-strong/50 bg-accent-primary/10 p-2"
|
||||
>
|
||||
<div role="alert" className="nodedc-auth-banner relative flex items-center gap-2 p-3">
|
||||
<div className="grid size-4 flex-shrink-0 place-items-center">
|
||||
<Info size={16} className="text-accent-primary" />
|
||||
<Info size={16} className="text-current" />
|
||||
</div>
|
||||
<p className="w-full text-13 font-medium text-accent-primary">{message}</p>
|
||||
<p className="w-full text-13 font-medium text-current">{message}</p>
|
||||
<button
|
||||
type="button"
|
||||
className="relative ml-auto grid size-6 place-items-center rounded-xs text-accent-primary/80 transition-all hover:bg-accent-primary/20"
|
||||
className="relative ml-auto grid size-6 place-items-center rounded-full text-current/80 transition-all hover:bg-white/10"
|
||||
onClick={() => handleBannerData?.(undefined)}
|
||||
aria-label={t("aria_labels.auth_forms.close_alert")}
|
||||
>
|
||||
<CloseIcon className="size-4" />
|
||||
<CloseIcon className="size-4 text-current" />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -83,9 +83,9 @@ type TAuthHeaderBase = {
|
||||
|
||||
export function AuthHeaderBase(props: TAuthHeaderBase) {
|
||||
return (
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-h4-semibold text-primary">{props.header}</span>
|
||||
<span className="text-h4-semibold text-placeholder">{props.subHeader}</span>
|
||||
<div className="flex flex-col gap-2">
|
||||
<span className="text-[2rem] leading-10 font-semibold text-primary">{props.header}</span>
|
||||
<span className="text-[1.9rem] leading-10 font-semibold text-placeholder">{props.subHeader}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -157,8 +157,8 @@ export const AuthRoot = observer(function AuthRoot(props: TAuthRoot) {
|
||||
|
||||
function AuthContainer({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="mt-10 flex w-full flex-grow flex-col items-center justify-center py-6">
|
||||
<div className="relative flex w-full max-w-[22.5rem] flex-col gap-6">{children}</div>
|
||||
<div className="mt-6 flex w-full flex-grow flex-col items-center justify-center py-8">
|
||||
<div className="nodedc-auth-shell relative flex w-full max-w-[28rem] flex-col gap-6">{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -56,9 +56,10 @@ export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailFo
|
||||
</label>
|
||||
<div
|
||||
className={cn(
|
||||
`relative flex items-center rounded-md border bg-surface-1`,
|
||||
!isFocused && Boolean(emailError?.email) ? `border-danger-strong` : `border-strong`
|
||||
"nodedc-auth-input-shell relative flex items-center",
|
||||
!isFocused && Boolean(emailError?.email) && "border-danger-strong/0"
|
||||
)}
|
||||
data-error={!isFocused && Boolean(emailError?.email)}
|
||||
onFocus={() => {
|
||||
setIsFocused(true);
|
||||
}}
|
||||
@@ -73,7 +74,7 @@ export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailFo
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder={t("auth.common.email.placeholder")}
|
||||
className={`h-10 w-full border-0 disable-autofill-style placeholder:text-placeholder autofill:bg-danger-primary focus:bg-none active:bg-transparent`}
|
||||
className="nodedc-auth-input h-12 w-full pr-12 disable-autofill-style autofill:bg-danger-primary focus:bg-none active:bg-transparent"
|
||||
autoComplete="off"
|
||||
autoFocus
|
||||
ref={inputRef}
|
||||
@@ -100,7 +101,7 @@ export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailFo
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
|
||||
<Button type="submit" variant="primary" className="nodedc-auth-primary-button" size="xl" disabled={isButtonDisabled}>
|
||||
{isSubmitting ? <Spinner height="20px" width="20px" /> : t("common.continue")}
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
@@ -88,7 +88,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||
<Link
|
||||
data-ph-element={AUTH_TRACKER_ELEMENTS.FORGOT_PASSWORD_FROM_SIGNIN}
|
||||
href={`/accounts/forgot-password?email=${encodeURIComponent(email)}`}
|
||||
className="text-11 font-medium text-accent-primary"
|
||||
className="nodedc-auth-link text-11 font-medium"
|
||||
>
|
||||
{t("auth.common.forgot_password")}
|
||||
</Link>
|
||||
@@ -174,7 +174,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||
<label htmlFor="email" className="text-13 font-medium text-tertiary">
|
||||
{t("auth.common.email.label")}
|
||||
</label>
|
||||
<div className={`relative flex items-center rounded-md border border-strong bg-surface-1`}>
|
||||
<div className="nodedc-auth-input-shell relative flex items-center">
|
||||
<Input
|
||||
id="email"
|
||||
name="email"
|
||||
@@ -182,7 +182,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||
value={passwordFormData.email}
|
||||
onChange={(e) => handleFormChange("email", e.target.value)}
|
||||
placeholder={t("auth.common.email.placeholder")}
|
||||
className={`h-10 w-full border-0 disable-autofill-style placeholder:text-placeholder`}
|
||||
className="nodedc-auth-input h-12 w-full pr-12 disable-autofill-style"
|
||||
disabled
|
||||
/>
|
||||
{passwordFormData.email.length > 0 && (
|
||||
@@ -202,7 +202,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||
<label htmlFor="password" className="text-13 font-medium text-tertiary">
|
||||
{mode === EAuthModes.SIGN_IN ? t("auth.common.password.label") : t("auth.common.password.set_password")}
|
||||
</label>
|
||||
<div className="relative flex items-center rounded-md bg-surface-1">
|
||||
<div className="nodedc-auth-input-shell relative flex items-center">
|
||||
<Input
|
||||
type={showPassword?.password ? "text" : "password"}
|
||||
id="password"
|
||||
@@ -210,7 +210,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||
value={passwordFormData.password}
|
||||
onChange={(e) => handleFormChange("password", e.target.value)}
|
||||
placeholder={t("auth.common.password.placeholder")}
|
||||
className="h-10 w-full border border-strong !bg-surface-1 pr-12 disable-autofill-style placeholder:text-placeholder"
|
||||
className="nodedc-auth-input h-12 w-full pr-12 disable-autofill-style"
|
||||
onFocus={() => setIsPasswordInputFocused(true)}
|
||||
onBlur={() => setIsPasswordInputFocused(false)}
|
||||
autoComplete="off"
|
||||
@@ -239,7 +239,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||
<label htmlFor="confirm-password" className="text-13 font-medium text-tertiary">
|
||||
{t("auth.common.password.confirm_password.label")}
|
||||
</label>
|
||||
<div className="relative flex items-center rounded-md bg-surface-1">
|
||||
<div className="nodedc-auth-input-shell relative flex items-center">
|
||||
<Input
|
||||
type={showPassword?.retypePassword ? "text" : "password"}
|
||||
id="confirm-password"
|
||||
@@ -247,7 +247,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||
value={passwordFormData.confirm_password}
|
||||
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
||||
placeholder={t("auth.common.password.confirm_password.placeholder")}
|
||||
className="h-10 w-full border border-strong !bg-surface-1 pr-12 disable-autofill-style placeholder:text-placeholder"
|
||||
className="nodedc-auth-input h-12 w-full pr-12 disable-autofill-style"
|
||||
onFocus={() => setIsRetryPasswordInputFocused(true)}
|
||||
onBlur={() => setIsRetryPasswordInputFocused(false)}
|
||||
autoComplete="off"
|
||||
@@ -280,7 +280,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||
<div className="space-y-2.5">
|
||||
{mode === EAuthModes.SIGN_IN ? (
|
||||
<>
|
||||
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
|
||||
<Button type="submit" variant="primary" className="nodedc-auth-primary-button" size="xl" disabled={isButtonDisabled}>
|
||||
{isSubmitting ? (
|
||||
<Spinner height="20px" width="20px" />
|
||||
) : isSMTPConfigured ? (
|
||||
@@ -295,7 +295,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||
data-ph-element={AUTH_TRACKER_ELEMENTS.SIGN_IN_WITH_UNIQUE_CODE}
|
||||
onClick={redirectToUniqueCodeSignIn}
|
||||
variant="secondary"
|
||||
className="w-full"
|
||||
className="nodedc-empty-state-secondary w-full"
|
||||
size="xl"
|
||||
>
|
||||
{t("auth.common.sign_in_with_unique_code")}
|
||||
@@ -303,7 +303,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
|
||||
<Button type="submit" variant="primary" className="nodedc-auth-primary-button" size="xl" disabled={isButtonDisabled}>
|
||||
{isSubmitting ? <Spinner height="20px" width="20px" /> : t("auth_actions.sign_up")}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -15,7 +15,7 @@ type AuthBaseProps = {
|
||||
|
||||
export function AuthBase({ authType }: AuthBaseProps) {
|
||||
return (
|
||||
<div className="relative z-10 flex h-screen w-screen flex-col items-center overflow-hidden overflow-y-auto px-8 pt-6 pb-10">
|
||||
<div className="relative z-10 flex h-screen w-screen flex-col items-center overflow-hidden overflow-y-auto bg-canvas px-8 pt-8 pb-10">
|
||||
<AuthHeader type={authType} />
|
||||
<AuthRoot authMode={authType} />
|
||||
</div>
|
||||
|
||||
@@ -50,7 +50,7 @@ export const AuthHeader = observer(function AuthHeader({ type }: AuthHeaderProps
|
||||
<Link
|
||||
data-ph-element={AUTH_TRACKER_ELEMENTS.NAVIGATE_TO_SIGN_UP}
|
||||
href={authContentMap[type].linkHref}
|
||||
className="text-body-sm-semibold text-accent-primary hover:underline"
|
||||
className="nodedc-auth-link text-body-sm-semibold"
|
||||
>
|
||||
{t(authContentMap[type].linkText)}
|
||||
</Link>
|
||||
@@ -71,9 +71,9 @@ export function AuthHeaderBase(props: TAuthHeaderBase) {
|
||||
return (
|
||||
<>
|
||||
<PageHead title={pageTitle + " - NODE.DC"} />
|
||||
<div className="sticky top-0 flex w-full flex-shrink-0 items-center justify-between gap-6">
|
||||
<div className="sticky top-0 flex w-full flex-shrink-0 items-center justify-between gap-6 px-2 py-1">
|
||||
<Link href="/">
|
||||
<PlaneLockup height={20} width={95} className="text-primary" />
|
||||
<PlaneLockup height={40} width={190} className="text-primary transition-opacity hover:opacity-90" />
|
||||
</Link>
|
||||
{additionalAction}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user