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 {
|
.ultimail-login .ultimail-login-connect-border {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
border-radius: 9999px;
|
border-radius: 9999px;
|
||||||
@ -1163,6 +1169,11 @@ html[data-route-scope='drive'] body {
|
|||||||
.ultimail-login .ultimail-login-connect-border {
|
.ultimail-login .ultimail-login-connect-border {
|
||||||
width: auto;
|
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) {
|
@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"
|
"use client"
|
||||||
|
|
||||||
import { useCallback, useEffect, useMemo, useState } from "react"
|
import { useCallback, useEffect, useMemo, useState } from "react"
|
||||||
import Link from "next/link"
|
|
||||||
import { Loader2 } from "lucide-react"
|
import { Loader2 } from "lucide-react"
|
||||||
import { AuthCard } from "@/components/auth/auth-card"
|
import { AuthCard } from "@/components/auth/auth-card"
|
||||||
|
import { AuthConnectButton } from "@/components/auth/auth-connect-button"
|
||||||
import { FlowChallengeForm } from "@/components/auth/flow-challenge-form"
|
import { FlowChallengeForm } from "@/components/auth/flow-challenge-form"
|
||||||
import {
|
import {
|
||||||
AUTH_FLOW_SLUGS,
|
AUTH_FLOW_SLUGS,
|
||||||
@ -131,18 +131,16 @@ export function AuthFlowPage({
|
|||||||
Redirection en cours…
|
Redirection en cours…
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
<div className="ultimail-login-connect-border w-full">
|
|
||||||
{successExternal ? (
|
{successExternal ? (
|
||||||
<a href={successHref} className="ultimail-login-connect-btn">
|
<AuthConnectButton href={successHref}>
|
||||||
{successActionLabel}
|
{successActionLabel}
|
||||||
</a>
|
</AuthConnectButton>
|
||||||
) : (
|
) : (
|
||||||
<Link href={successHref} className="ultimail-login-connect-btn">
|
<AuthConnectButton as="link" href={successHref}>
|
||||||
{successActionLabel}
|
{successActionLabel}
|
||||||
</Link>
|
</AuthConnectButton>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
) : (
|
) : (
|
||||||
<FlowChallengeForm
|
<FlowChallengeForm
|
||||||
challenge={challenge}
|
challenge={challenge}
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import { useEffect, useMemo, useRef, useState } from "react"
|
import { useEffect, useMemo, useRef, useState } from "react"
|
||||||
import { Loader2 } from "lucide-react"
|
import { Loader2 } from "lucide-react"
|
||||||
|
import { AuthConnectButton } from "@/components/auth/auth-connect-button"
|
||||||
import { Input } from "@/components/ui/input"
|
import { Input } from "@/components/ui/input"
|
||||||
import { Label } from "@/components/ui/label"
|
import { Label } from "@/components/ui/label"
|
||||||
import type { FlowChallenge } from "@/lib/auth/flow-api"
|
import type { FlowChallenge } from "@/lib/auth/flow-api"
|
||||||
@ -151,11 +152,10 @@ export function FlowChallengeForm({
|
|||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{isKnownComponent(component) ? (
|
{isKnownComponent(component) ? (
|
||||||
<div className="ultimail-login-connect-border pt-1">
|
<AuthConnectButton
|
||||||
<button
|
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={submitting}
|
disabled={submitting}
|
||||||
className="ultimail-login-connect-btn w-full disabled:opacity-60"
|
className="disabled:opacity-60"
|
||||||
>
|
>
|
||||||
{submitting ? (
|
{submitting ? (
|
||||||
<>
|
<>
|
||||||
@ -165,8 +165,7 @@ export function FlowChallengeForm({
|
|||||||
) : (
|
) : (
|
||||||
primaryAction
|
primaryAction
|
||||||
)}
|
)}
|
||||||
</button>
|
</AuthConnectButton>
|
||||||
</div>
|
|
||||||
) : null}
|
) : null}
|
||||||
</form>
|
</form>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import Link from "next/link"
|
|
||||||
import { Sparkles } from "lucide-react"
|
import { Sparkles } from "lucide-react"
|
||||||
import { AuthCard } from "@/components/auth/auth-card"
|
import { AuthCard } from "@/components/auth/auth-card"
|
||||||
|
import { AuthConnectButton } from "@/components/auth/auth-connect-button"
|
||||||
|
|
||||||
type LoginFormProps = {
|
type LoginFormProps = {
|
||||||
loginHref: string
|
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">
|
<div className="flex w-full flex-col gap-3 text-center text-sm text-muted-foreground">
|
||||||
<p>
|
<p>
|
||||||
Pas encore de compte ?{" "}
|
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
|
Créer un compte
|
||||||
</Link>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<Link className="font-medium text-primary underline" href={forgotPasswordHref}>
|
<a className="font-medium text-primary underline" href={forgotPasswordHref}>
|
||||||
Mot de passe oublié ?
|
Mot de passe oublié ?
|
||||||
</Link>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="flex justify-center">
|
<AuthConnectButton href={loginHref}>
|
||||||
<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 />
|
<Sparkles className="size-4 shrink-0" strokeWidth={2} aria-hidden />
|
||||||
Se connecter avec UltiSpace
|
Se connecter avec UltiSpace
|
||||||
</a>
|
</AuthConnectButton>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</AuthCard>
|
</AuthCard>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user