feat: introduce AuthConnectButton component for streamlined authentication actions
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
- Added AuthConnectButton component to centralize and simplify authentication button rendering across various forms. - Updated existing authentication components to utilize AuthConnectButton, enhancing code reusability and maintainability. - Refactored CSS styles for consistent button appearance and layout in authentication flows.
This commit is contained in:
parent
359931c2f3
commit
be9133e220
@ -936,9 +936,15 @@ html[data-route-scope='drive'] body {
|
||||
}
|
||||
}
|
||||
|
||||
.ultimail-login-connect-action {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ultimail-login .ultimail-login-connect-border {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 2px;
|
||||
border-radius: 9999px;
|
||||
@ -1163,6 +1169,11 @@ html[data-route-scope='drive'] body {
|
||||
.ultimail-login .ultimail-login-connect-border {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.ultimail-login-connect-action .ultimail-login-connect-border,
|
||||
.ultimail-login-card-frame .ultimail-login-connect-border {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
|
||||
66
components/auth/auth-connect-button.tsx
Normal file
66
components/auth/auth-connect-button.tsx
Normal file
@ -0,0 +1,66 @@
|
||||
"use client"
|
||||
|
||||
import Link from "next/link"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
type AuthConnectButtonCommon = {
|
||||
children: React.ReactNode
|
||||
className?: string
|
||||
}
|
||||
|
||||
type AuthConnectButtonAsButton = AuthConnectButtonCommon &
|
||||
React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
||||
href?: undefined
|
||||
}
|
||||
|
||||
type AuthConnectButtonAsAnchor = AuthConnectButtonCommon &
|
||||
React.AnchorHTMLAttributes<HTMLAnchorElement> & {
|
||||
href: string
|
||||
}
|
||||
|
||||
type AuthConnectButtonAsLink = AuthConnectButtonCommon &
|
||||
Omit<React.ComponentProps<typeof Link>, "href"> & {
|
||||
href: string
|
||||
as: "link"
|
||||
}
|
||||
|
||||
export type AuthConnectButtonProps =
|
||||
| AuthConnectButtonAsButton
|
||||
| AuthConnectButtonAsAnchor
|
||||
| AuthConnectButtonAsLink
|
||||
|
||||
/** UltiSpace gradient CTA — full width, centered in auth flows. */
|
||||
export function AuthConnectButton(props: AuthConnectButtonProps) {
|
||||
const { children, className } = props
|
||||
const btnClass = cn("ultimail-login-connect-btn w-full", className)
|
||||
|
||||
let control: React.ReactNode
|
||||
if ("as" in props && props.as === "link") {
|
||||
const { as: _as, href, className: _c, children: _ch, ...linkProps } = props
|
||||
control = (
|
||||
<Link href={href} className={btnClass} {...linkProps}>
|
||||
{children}
|
||||
</Link>
|
||||
)
|
||||
} else if ("href" in props && props.href) {
|
||||
const { href, className: _c, children: _ch, ...anchorProps } = props
|
||||
control = (
|
||||
<a href={href} className={btnClass} {...anchorProps}>
|
||||
{children}
|
||||
</a>
|
||||
)
|
||||
} else {
|
||||
const { className: _c, children: _ch, ...buttonProps } = props
|
||||
control = (
|
||||
<button className={btnClass} {...buttonProps}>
|
||||
{children}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="ultimail-login-connect-action">
|
||||
<div className="ultimail-login-connect-border">{control}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -1,9 +1,9 @@
|
||||
"use client"
|
||||
|
||||
import { useCallback, useEffect, useMemo, useState } from "react"
|
||||
import Link from "next/link"
|
||||
import { Loader2 } from "lucide-react"
|
||||
import { AuthCard } from "@/components/auth/auth-card"
|
||||
import { AuthConnectButton } from "@/components/auth/auth-connect-button"
|
||||
import { FlowChallengeForm } from "@/components/auth/flow-challenge-form"
|
||||
import {
|
||||
AUTH_FLOW_SLUGS,
|
||||
@ -131,17 +131,15 @@ export function AuthFlowPage({
|
||||
Redirection en cours…
|
||||
</p>
|
||||
) : null}
|
||||
<div className="ultimail-login-connect-border w-full">
|
||||
{successExternal ? (
|
||||
<a href={successHref} className="ultimail-login-connect-btn">
|
||||
{successActionLabel}
|
||||
</a>
|
||||
) : (
|
||||
<Link href={successHref} className="ultimail-login-connect-btn">
|
||||
{successActionLabel}
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
{successExternal ? (
|
||||
<AuthConnectButton href={successHref}>
|
||||
{successActionLabel}
|
||||
</AuthConnectButton>
|
||||
) : (
|
||||
<AuthConnectButton as="link" href={successHref}>
|
||||
{successActionLabel}
|
||||
</AuthConnectButton>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<FlowChallengeForm
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
import { useEffect, useMemo, useRef, useState } from "react"
|
||||
import { Loader2 } from "lucide-react"
|
||||
import { AuthConnectButton } from "@/components/auth/auth-connect-button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import type { FlowChallenge } from "@/lib/auth/flow-api"
|
||||
@ -151,22 +152,20 @@ export function FlowChallengeForm({
|
||||
) : null}
|
||||
|
||||
{isKnownComponent(component) ? (
|
||||
<div className="ultimail-login-connect-border pt-1">
|
||||
<button
|
||||
type="submit"
|
||||
disabled={submitting}
|
||||
className="ultimail-login-connect-btn w-full disabled:opacity-60"
|
||||
>
|
||||
{submitting ? (
|
||||
<>
|
||||
<Loader2 className="size-4 animate-spin" aria-hidden />
|
||||
<span>Patientez…</span>
|
||||
</>
|
||||
) : (
|
||||
primaryAction
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<AuthConnectButton
|
||||
type="submit"
|
||||
disabled={submitting}
|
||||
className="disabled:opacity-60"
|
||||
>
|
||||
{submitting ? (
|
||||
<>
|
||||
<Loader2 className="size-4 animate-spin" aria-hidden />
|
||||
<span>Patientez…</span>
|
||||
</>
|
||||
) : (
|
||||
primaryAction
|
||||
)}
|
||||
</AuthConnectButton>
|
||||
) : null}
|
||||
</form>
|
||||
)
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
"use client"
|
||||
|
||||
import Link from "next/link"
|
||||
import { Sparkles } from "lucide-react"
|
||||
import { AuthCard } from "@/components/auth/auth-card"
|
||||
import { AuthConnectButton } from "@/components/auth/auth-connect-button"
|
||||
|
||||
type LoginFormProps = {
|
||||
loginHref: string
|
||||
@ -25,26 +25,22 @@ export function LoginForm({
|
||||
<div className="flex w-full flex-col gap-3 text-center text-sm text-muted-foreground">
|
||||
<p>
|
||||
Pas encore de compte ?{" "}
|
||||
<Link className="font-medium text-primary underline" href={signupHref}>
|
||||
<a className="font-medium text-primary underline" href={signupHref}>
|
||||
Créer un compte
|
||||
</Link>
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<Link className="font-medium text-primary underline" href={forgotPasswordHref}>
|
||||
<a className="font-medium text-primary underline" href={forgotPasswordHref}>
|
||||
Mot de passe oublié ?
|
||||
</Link>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="flex justify-center">
|
||||
<div className="ultimail-login-connect-border w-full">
|
||||
<a href={loginHref} className="ultimail-login-connect-btn">
|
||||
<Sparkles className="size-4 shrink-0" strokeWidth={2} aria-hidden />
|
||||
Se connecter avec UltiSpace
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<AuthConnectButton href={loginHref}>
|
||||
<Sparkles className="size-4 shrink-0" strokeWidth={2} aria-hidden />
|
||||
Se connecter avec UltiSpace
|
||||
</AuthConnectButton>
|
||||
</AuthCard>
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user