Authentication
15 blocksAuthentication 01
Preview
npx nateui@latest add SignInSimpleDark
import Checkbox from '@/components/ui/Checkbox'
import Link from '@/components/ui/Link'
import SignInForm from '@/components/patterns/SignInForm'
const assetBase = 'https://statics.nateui.com/img'
export default function SignInSimple() {
return (
<div className="flex min-h-[640px] w-full items-center justify-center px-4 py-10">
<section
aria-labelledby="sign-in-simple-title"
className="w-full max-w-sm"
>
<div className="mb-9 text-center">
<div className="mx-auto mb-7 flex size-9 items-center justify-center rounded-control bg-card shadow-card">
<img
alt="NateUI"
className="h-5 w-5"
src={`${assetBase}/logos/logo-collapsed.svg`}
/>
</div>
<h3
id="sign-in-simple-title"
className="text-2xl font-semibold leading-tight text-foreground"
>
Sign in to your account
</h3>
<p className="mt-2 text-muted-foreground">
Enter your credentials to continue.
</p>
</div>
<SignInForm
hint={
<div className="mb-7 flex flex-wrap items-center justify-between gap-2 mt-4">
<Checkbox className="text-sm" name="remember-device">
Remember this device
</Checkbox>
<Link
href="#password-recovery"
className="shrink-0 text-sm font-medium text-primary"
>
Forgot password?
</Link>
</div>
}
/>
<p className="mt-8 text-center text-sm text-muted-foreground">
New here?{' '}
<Link href="#sign-up" className="font-medium text-primary">
Create an account
</Link>
</p>
</section>
</div>
)
}
Authentication 02
Preview
npx nateui@latest add SignInSSODark
import Button from '@/components/ui/Button'
import Link from '@/components/ui/Link'
import Divider from '@/components/composites/Divider'
import SignInForm from '@/components/patterns/SignInForm'
const assetBase = 'https://statics.nateui.com/img'
export default function SignInSSO() {
return (
<div className="flex min-h-[640px] w-full items-center justify-center px-4 py-12">
<section aria-labelledby="sign-in-sso-title" className="w-full max-w-sm">
<header className="mb-8 text-center">
<div className="mx-auto mb-8 flex items-center justify-center">
<img
alt="NateUI"
className="size-8"
src={`${assetBase}/logos/logo-collapsed.svg`}
/>
</div>
<h3
id="sign-in-sso-title"
className="text-2xl font-semibold leading-tight text-foreground"
>
Sign in
</h3>
<p className="mt-4 text-muted-foreground">
Use your email or a connected account.
</p>
</header>
<div>
<SignInForm />
<div className="flex items-center gap-2 py-8">
<Divider className="my-0" />
<span>or</span>
<Divider className="my-0" />
</div>
<div className="space-y-3">
<Button
block
icon={
<img
alt=""
className="h-5 w-5 object-contain"
src={`${assetBase}/thumbs/brands/google.png`}
/>
}
type="button"
variant="default"
>
Continue with Google
</Button>
<Button
block
icon={
<svg
aria-hidden="true"
className="h-5 w-5"
fill="currentColor"
viewBox="0 0 24 24"
>
<path d="M10.226 17.284c-2.965-.36-5.054-2.493-5.054-5.256 0-1.123.404-2.336 1.078-3.144-.292-.741-.247-2.314.09-2.965.898-.112 2.111.36 2.83 1.01.853-.269 1.752-.404 2.853-.404 1.1 0 1.999.135 2.807.382.696-.629 1.932-1.1 2.83-.988.315.606.36 2.179.067 2.942.72.854 1.101 2 1.101 3.167 0 2.763-2.089 4.852-5.098 5.234.763.494 1.28 1.572 1.28 2.807v2.336c0 .674.561 1.056 1.235.786 4.066-1.55 7.255-5.615 7.255-10.646C23.5 6.188 18.334 1 11.978 1 5.62 1 .5 6.188.5 12.545c0 4.986 3.167 9.12 7.435 10.669.606.225 1.19-.18 1.19-.786V20.63a2.9 2.9 0 0 1-1.078.224c-1.483 0-2.359-.808-2.987-2.313-.247-.607-.517-.966-1.034-1.033-.27-.023-.359-.135-.359-.27 0-.27.45-.471.898-.471.652 0 1.213.404 1.797 1.235.45.651.921.943 1.483.943.561 0 .92-.202 1.437-.719.382-.381.674-.718.944-.943" />
</svg>
}
type="button"
variant="default"
>
Continue with GitHub
</Button>
</div>
</div>
<p className="mt-8 text-center text-muted-foreground">
Need an account?{' '}
<Link
className="font-medium text-primary"
href="#create-account"
>
Create one
</Link>
</p>
</section>
</div>
)
}
Authentication 03
Preview
npx nateui@latest add SignInSignUpSegmentDark
import { useState } from 'react'
import Button from '@/components/ui/Button'
import Checkbox from '@/components/ui/Checkbox'
import Link from '@/components/ui/Link'
import Segment from '@/components/ui/Segment'
import SignInForm from '@/components/patterns/SignInForm'
import SignUpForm from '@/components/patterns/SignUpForm'
const assetBase = 'https://statics.nateui.com/img'
type AuthMode = 'sign-in' | 'sign-up'
export default function SignInSignUpSegment() {
const [mode, setMode] = useState<AuthMode>('sign-in')
return (
<div className="flex min-h-[720px] w-full items-center justify-center px-4 py-12">
<section
aria-labelledby="sign-in-sign-up-segment-title"
className="w-full max-w-sm"
>
<header className="mb-8 text-center">
<h3
id="sign-in-sign-up-segment-title"
className="text-2xl font-semibold leading-tight text-foreground"
>
Account access
</h3>
<p className="mt-2 text-muted-foreground">
Sign in or create an account to continue.
</p>
</header>
<Segment
aria-label="Account access mode"
className="mb-8 w-full"
value={mode}
onChange={(value) => setMode(value as AuthMode)}
>
<Segment.Item value="sign-up">
Create account
</Segment.Item>
<Segment.Item value="sign-in">Sign in</Segment.Item>
</Segment>
{mode === 'sign-in' ? (
<SignInForm />
) : (
<SignUpForm fields={['userName', 'email', 'password']} />
)}
<div className="mt-4">
<Button
block
icon={
<img
alt=""
className="h-5 w-5 object-contain"
src={`${assetBase}/thumbs/brands/google.png`}
/>
}
type="button"
variant="default"
>
Continue with Google
</Button>
</div>
</section>
</div>
)
}
Authentication 04
Preview
npx nateui@latest add SignInCardDark
import Button from '@/components/ui/Button'
import Card from '@/components/ui/Card'
import Link from '@/components/ui/Link'
import SignInForm from '@/components/patterns/SignInForm'
import { PiKey } from 'react-icons/pi'
const assetBase = 'https://statics.nateui.com/img'
export default function SignInCard() {
return (
<div className="flex min-h-screen w-full items-center justify-center bg-muted px-4 py-8">
<section aria-labelledby="sign-in-card-title" className="w-full max-w-sm">
<header className="mb-8 text-center">
<img
alt="NateUI"
className="mx-auto h-8 w-8"
src={`${assetBase}/logos/logo-collapsed.svg`}
/>
<h3
id="sign-in-card-title"
className="mt-4 text-2xl font-semibold"
>
Sign in to NateUI
</h3>
<p className="mt-2 text-muted-foreground">
Use your account to continue.
</p>
</header>
<Card bodyClass="p-8">
<div className="space-y-4">
<Button
block
icon={
<img
alt=""
className="h-5 w-5 object-contain"
src={`${assetBase}/thumbs/brands/google.png`}
/>
}
type="button"
variant="default"
>
Continue with Google
</Button>
<Button
block
icon={<PiKey aria-hidden="true" />}
type="button"
variant="default"
>
Continue with SSO
</Button>
</div>
<div className="my-4 flex items-center gap-3" aria-hidden="true">
<div className="flex-1 border-t" />
<span className="font-medium uppercase">
Or
</span>
<div className="flex-1 border-t" />
</div>
<SignInForm
hint={
<div className="mt-4 mb-5 flex justify-end">
<Link
className="font-medium text-primary"
href="#password-reset"
>
Forgot password?
</Link>
</div>
}
submitText="Sign in with email"
/>
</Card>
<footer className="mt-8 space-y-4 text-center text-muted-foreground">
<p>
Need an account?{' '}
<Link href="#create-account" className="font-medium text-primary">
Create one
</Link>
</p>
</footer>
</section>
</div>
)
}
Authentication 05
Preview
npx nateui@latest add SignUpEmailPasswordDark
import Button from '@/components/ui/Button'
import Link from '@/components/ui/Link'
import Divider from '@/components/composites/Divider'
import SignUpForm from '@/components/patterns/SignUpForm'
const assetBase = 'https://statics.nateui.com/img'
export default function SignUpEmailPassword() {
return (
<div className="flex min-h-[760px] w-full items-center justify-center px-4 py-12">
<section
aria-labelledby="sign-up-email-password-title"
className="w-full max-w-sm"
>
<header className="mb-8 text-center">
<div className="mx-auto mb-7 flex items-center justify-center">
<img
alt=""
className="h-9 w-auto dark:hidden"
src={`${assetBase}/logos/logo-collapsed.svg`}
/>
<img
alt="NateUI"
className="hidden h-9 w-auto dark:block"
src={`${assetBase}/logos/logo-collapsed-white.svg`}
/>
</div>
<h3
id="sign-up-email-password-title"
className="text-2xl font-semibold text-foreground"
>
Create an account
</h3>
<p className="mt-2 text-muted-foreground">
Set up your account to continue.
</p>
</header>
<Button
block
icon={
<img
alt=""
className="h-5 w-5 object-contain"
src={`${assetBase}/thumbs/brands/google.png`}
/>
}
type="button"
variant="default"
>
Continue with Google
</Button>
<div className="flex items-center gap-2 py-7">
<Divider className="my-0" />
<span className="text-xs text-muted-foreground">or</span>
<Divider className="my-0" />
</div>
<SignUpForm
fields={['email', 'password']}
submitText="Create account"
submittingText="Creating account..."
/>
<p className="mt-7 text-center text-sm text-muted-foreground">
Have an account?{' '}
<Link href="#sign-in" className="font-medium text-foreground">
Sign in
</Link>
</p>
</section>
</div>
)
}
Authentication 06
Preview
npx nateui@latest add SignUpSimpleDark
import Button from '@/components/ui/Button'
import Link from '@/components/ui/Link'
import Divider from '@/components/composites/Divider'
import SignUpForm from '@/components/patterns/SignUpForm'
const assetBase = 'https://statics.nateui.com/img'
export default function SignUpSimple() {
return (
<div className="flex min-h-full w-full justify-center px-4 py-10">
<section
aria-labelledby="sign-up-simple-title"
className="w-full max-w-sm"
>
<header className="mb-8">
<h3
id="sign-up-simple-title"
className="text-2xl font-semibold text-foreground"
>
Sign up
</h3>
<p className="mt-2 text-muted-foreground">
Create an account and verify your details to get
started. Already have an account?{' '}
<Link href="#sign-in" className="font-medium text-foreground">
Sign in
</Link>
</p>
</header>
<SignUpForm
fields={['email']}
submitText="Sign up"
submittingText="Signing up..."
/>
<div className="flex items-center gap-2 py-6">
<Divider className="my-0" />
<span>or</span>
<Divider className="my-0" />
</div>
<Button
block
icon={
<img
alt=""
className="h-5 w-5 object-contain"
src={`${assetBase}/thumbs/brands/google.png`}
/>
}
type="button"
variant="default"
>
Continue with Google
</Button>
<p className="mt-8 text-xs text-muted-foreground">
By signing up, you agree to the{' '}
<Link
href="#privacy-policy"
className="font-medium text-foreground"
>
Privacy Policy
</Link>{' '}
and{' '}
<Link
href="#terms-of-service"
className="font-medium text-foreground"
>
Terms of Service
</Link>
.
</p>
</section>
</div>
)
}
Authentication 07
Preview
npx nateui@latest add VerifyOTPDark
import Link from '@/components/ui/Link'
import OTPVerificationForm from '@/components/patterns/OTPVerificationForm'
import { PiArrowLeft } from 'react-icons/pi'
export default function VerifyOTP() {
return (
<div className="flex min-h-full w-full items-center justify-center px-4 py-10">
<section
aria-labelledby="verify-otp-title"
className="w-full max-w-90"
>
<header className="mb-8">
<h3
id="verify-otp-title"
className="text-2xl font-semibold text-foreground"
>
Verify OTP
</h3>
<p className="mt-2 text-muted-foreground">
We sent a verification code to user@example.com.
</p>
</header>
<OTPVerificationForm
autoFocus={false}
codeLength={6}
hint={
<p className="mb-4 text-muted-foreground">
Didn't receive it?{' '}
<Link
href="#resend-code"
className="font-medium text-foreground"
>
Resend code
</Link>
</p>
}
inputClassName="h-12"
label={null}
submitText="Verify"
submittingText="Verifying..."
height={53}
/>
<div className="mt-8 text-center">
<Link
href="#sign-in"
className="inline-flex items-center gap-2 font-medium"
>
<PiArrowLeft aria-hidden="true" className="text-base" />
Back to sign in
</Link>
</div>
</section>
</div>
)
}
Authentication 08
Preview
npx nateui@latest add EmailVerificationCompleteDark
import IconFrame from '@/components/composites/IconFrame'
import Button from '@/components/ui/Button'
import Link from '@/components/ui/Link'
import { PiArrowLeft, PiCheckCircle } from 'react-icons/pi'
export default function EmailVerificationComplete() {
return (
<div className="flex min-h-full w-full items-center justify-center px-4 py-10">
<section
aria-labelledby="email-verification-complete-title"
className="w-full max-w-sm text-center"
>
<IconFrame
size={48}
className="mx-auto"
variant="layered"
>
<PiCheckCircle aria-hidden="true" className="text-2xl" />
</IconFrame>
<header className="mt-8">
<h3
id="email-verification-complete-title"
className="text-2xl font-semibold text-foreground"
>
Verification complete
</h3>
<p className="text-muted-foreground mt-4">
Your email address is verified.
Continue to access your account.
</p>
</header>
<Button block variant="solid" className="mt-8">
Continue
</Button>
<div className="mt-8">
<Link
href="#sign-in"
className="inline-flex items-center gap-2 font-medium"
>
<PiArrowLeft aria-hidden="true" className="text-base" />
Back to sign in
</Link>
</div>
</section>
</div>
)
}
Authentication 09
Preview
npx nateui@latest add ForgotPasswordDark
import ForgotPasswordForm from '@/components/patterns/ForgotPasswordForm'
import Link from '@/components/ui/Link'
import { PiArrowLeft } from 'react-icons/pi'
const assetBase = 'https://statics.nateui.com/img'
export default function ForgotPassword() {
return (
<div className="flex min-h-full w-full items-center justify-center px-4 py-8">
<section aria-labelledby="forgot-password-title" className="w-full max-w-sm">
<header className="mt-4 text-center">
<h3 id="forgot-password-title" className="text-2xl font-semibold text-foreground">
Forgot password?
</h3>
<p className="mt-4 text-muted-foreground">
Provide the account email and we will send you a recovery instructions email.
</p>
</header>
<ForgotPasswordForm
className="mt-8"
emailSent={false}
submitText="Email me a reset link"
submittingText="Sending reset link..."
/>
<div className="mt-8 text-center">
<Link
href="#sign-in"
className="inline-flex items-center gap-2 font-medium text-foreground"
>
<PiArrowLeft aria-hidden="true" className="text-base" />
Return to sign in
</Link>
</div>
</section>
</div>
)
}
Authentication 10
Preview
npx nateui@latest add AuthCardBackgroundCenteredDark
import { useEffect, useRef } from 'react'
import Button from '@/components/ui/Button'
import Card from '@/components/ui/Card'
import Checkbox from '@/components/ui/Checkbox'
import Link from '@/components/ui/Link'
import AuthShellCentered from '@/components/layouts/AuthShellCentered'
import SignInForm from '@/components/patterns/SignInForm'
const assetBase = 'https://statics.nateui.com/img'
const STRAND_COUNT = 22
const STRAND_WIDTH = 1.5
const SAMPLES_PER_STRAND = 72
const RISE = 0.82
const RUN = 0.86
const rotationFor = (width: number, height: number) =>
-Math.atan2(RISE * height, RUN * width)
const OVERSCAN = 1.02
const SPACING = 0.011
const FAN_START = 0.25
const FAN_END = 1.95
const AMPLITUDE = 0.085
const FREQUENCY = 0.45
const PHASE_STEP = 0.13
const TWIST = 0.22
const BULGE = 0.3
const FLOW_SPEED = 0.22
const EDGE_FADE_IN = 0.24
const EDGE_FADE_OUT = 0.18
const RAMP = [
[65, 89, 208],
[200, 79, 192],
[255, 205, 112],
]
const lerp = (from: number, to: number, ratio: number) => from + (to - from) * ratio
const sampleRamp = (ratio: number) => {
const scaled = ratio * (RAMP.length - 1)
const index = Math.max(0, Math.min(RAMP.length - 2, Math.floor(scaled)))
const from = RAMP[index]
const to = RAMP[index + 1] ?? from
return [0, 1, 2]
.map((channel) =>
Math.round(lerp(from[channel], to[channel], scaled - index)),
)
.join(', ')
}
const strands = Array.from({ length: STRAND_COUNT }, (_, index) => {
const ratio = STRAND_COUNT <= 1 ? 0 : index / (STRAND_COUNT - 1)
return {
phase: PHASE_STEP * (index - (STRAND_COUNT - 1) / 2),
offset: (ratio - 0.5) * STRAND_COUNT * SPACING,
solid: sampleRamp(ratio),
}
})
const FlowLinesBackdrop = () => {
const canvasRef = useRef<HTMLCanvasElement>(null)
useEffect(() => {
const canvas = canvasRef.current
if (!canvas) {
return
}
const context = canvas.getContext('2d')
if (!context) {
return
}
let width = 0
let height = 0
let frame = 0
const measure = () => {
const ratio = Math.min(window.devicePixelRatio || 1, 2)
const bounds = canvas.getBoundingClientRect()
width = bounds.width
height = bounds.height
canvas.width = Math.max(1, Math.round(width * ratio))
canvas.height = Math.max(1, Math.round(height * ratio))
context.setTransform(ratio, 0, 0, ratio, 0, 0)
}
const points: { x: number; y: number }[] = Array.from(
{ length: SAMPLES_PER_STRAND + 1 },
() => ({ x: 0, y: 0 }),
)
const draw = (elapsed: number) => {
context.clearRect(0, 0, width, height)
context.lineWidth = STRAND_WIDTH
context.lineCap = 'round'
context.lineJoin = 'round'
const midX = width / 2
const midY = height / 2
const rotation = rotationFor(width, height)
const angleCos = Math.cos(rotation)
const angleSin = Math.sin(rotation)
const span =
(width * Math.abs(angleCos) + height * Math.abs(angleSin)) *
OVERSCAN
const travel = FLOW_SPEED * elapsed
const frequency = FREQUENCY * Math.PI * 2
for (const strand of strands) {
for (let step = 0; step <= SAMPLES_PER_STRAND; step++) {
const along = step / SAMPLES_PER_STRAND
// Amplitude swells through the middle of the run.
const bulge = 1 + BULGE * Math.sin(along * Math.PI)
const wave =
Math.sin(frequency * along + strand.phase + travel) +
TWIST *
Math.sin(
0.5 * frequency * along -
2 * strand.phase +
0.7 * travel,
)
const fan = FAN_START + (FAN_END - FAN_START) * along
const flatX = (along - 0.5) * span
const flatY =
strand.offset * height * fan +
wave * 0.5 * bulge * AMPLITUDE * height
const point = points[step]
point.x = midX + flatX * angleCos - flatY * angleSin
point.y = midY + flatX * angleSin + flatY * angleCos
}
const first = points[0]
const last = points[points.length - 1]
const gradient = context.createLinearGradient(
first.x,
first.y,
last.x,
last.y,
)
gradient.addColorStop(0, `rgba(${strand.solid}, 0)`)
gradient.addColorStop(EDGE_FADE_IN, `rgba(${strand.solid}, 1)`)
gradient.addColorStop(
1 - EDGE_FADE_OUT,
`rgba(${strand.solid}, 1)`,
)
gradient.addColorStop(1, `rgba(${strand.solid}, 0)`)
context.strokeStyle = gradient
context.beginPath()
context.moveTo(first.x, first.y)
for (let step = 1; step < points.length - 1; step++) {
const current = points[step]
const next = points[step + 1]
context.quadraticCurveTo(
current.x,
current.y,
(current.x + next.x) / 2,
(current.y + next.y) / 2,
)
}
context.lineTo(last.x, last.y)
context.stroke()
}
}
const stillness = window.matchMedia('(prefers-reduced-motion: reduce)')
const observer = new ResizeObserver(() => {
measure()
draw(0)
})
const run = (timestamp: number) => {
draw(timestamp / 1000)
frame = window.requestAnimationFrame(run)
}
const start = () => {
window.cancelAnimationFrame(frame)
measure()
draw(0)
if (stillness.matches) {
return
}
frame = window.requestAnimationFrame(run)
}
start()
observer.observe(canvas)
stillness.addEventListener('change', start)
return () => {
window.cancelAnimationFrame(frame)
observer.disconnect()
stillness.removeEventListener('change', start)
}
}, [])
return (
<canvas
aria-hidden="true"
className="pointer-events-none absolute inset-0 h-full w-full opacity-30"
ref={canvasRef}
/>
)
}
export default function AuthCardBackgroundCentered() {
return (
<AuthShellCentered
className="relative overflow-hidden bg-card"
overlay={<FlowLinesBackdrop />}
header={
<header className="relative flex items-center justify-center p-4">
<img
alt=""
className="h-7 w-auto dark:hidden"
src={`${assetBase}/logos/logo.svg`}
/>
<img
alt="NateUI"
className="hidden h-7 w-auto dark:block"
src={`${assetBase}/logos/logo-white.svg`}
/>
</header>
}
footer={
<footer className="relative p-4 text-center text-muted-foreground">
Protected by SSO and device verification.
</footer>
}
>
<section
aria-labelledby="auth-card-background-centered-title"
className="relative"
>
<Card
className="relative isolate bg-transparent after:absolute after:inset-0 after:-z-10 after:rounded-card after:bg-card/20 after:backdrop-blur-sm"
bodyClass="p-8"
>
<Button
block
icon={
<img
alt=""
className="h-5 w-5 object-contain"
src={`${assetBase}/thumbs/brands/google.png`}
/>
}
type="button"
variant="default"
>
Continue with Google
</Button>
<div className="my-4 flex items-center gap-2" aria-hidden="true">
<div className="flex-1 border-t" />
<span className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
Or
</span>
<div className="flex-1 border-t" />
</div>
<SignInForm
hint={
<div className="mb-8 mt-4 flex flex-wrap items-center justify-between gap-2">
<Checkbox name="remember-device">
Keep me signed in
</Checkbox>
<Link
className="shrink-0 font-medium text-primary"
href="#password-recovery"
>
Forgot password?
</Link>
</div>
}
/>
</Card>
<p className="mt-8 text-center text-muted-foreground">
New to NateUI?{' '}
<Link href="#sign-up" className="font-medium text-primary">
Create an account
</Link>
</p>
</section>
</AuthShellCentered>
)
}
Authentication 11
Preview
npx nateui@latest add AuthTileGridCenteredDark
import Button from '@/components/ui/Button'
import Link from '@/components/ui/Link'
import Divider from '@/components/composites/Divider'
import AuthShellCentered from '@/components/layouts/AuthShellCentered'
import SignInForm from '@/components/patterns/SignInForm'
const assetBase = 'https://statics.nateui.com/img'
const integrations = [
{ file: 'dropbox.png', cell: 'col-start-[2] row-start-[1]' },
{ file: 'slack.png', cell: 'col-start-[4] row-start-[3]' },
{ file: 'notion.png', cell: 'col-start-[7] row-start-[1]' },
{ file: 'zapier.png', cell: 'col-start-[9] row-start-[3]' },
{ file: 'figma.png', cell: 'col-start-[12] row-start-[2]' },
{ file: 'github.png', cell: 'col-start-[15] row-start-[1]' },
{ file: 'stripe.png', cell: 'col-start-[16] row-start-[3]' },
]
const plates = [
'col-start-[6] row-start-[2]',
'col-start-[11] row-start-[3]',
'col-start-[14] row-start-[2]',
'col-start-[3] row-start-[2]',
'col-start-[10] row-start-[1]',
]
export default function AuthTileGridCentered() {
return (
<AuthShellCentered
className="relative overflow-hidden bg-card"
overlay={
<div
aria-hidden="true"
className="pointer-events-none absolute inset-x-0 top-0 flex justify-center mask-b-from-30% mask-x-from-85%"
>
<div className="grid w-fit grid-cols-[repeat(16,64px)] grid-rows-[repeat(4,64px)] bg-[linear-gradient(to_right,var(--color-border)_1px,transparent_1px),linear-gradient(to_bottom,var(--color-border)_1px,transparent_1px)] [background-size:64px_64px]">
{plates.map((cell) => (
<div
key={cell}
className={`size-16 bg-primary-soft ${cell}`}
/>
))}
{integrations.map(({ file, cell }) => (
<div
key={file}
className={`flex size-16 items-center justify-center p-4 ${cell}`}
>
<img
alt=""
className="h-full w-full object-contain"
src={`${assetBase}/thumbs/brands/${file}`}
/>
</div>
))}
</div>
</div>
}
>
<section
aria-labelledby="auth-tile-grid-centered-title"
className="relative w-full"
>
<h3
id="auth-tile-grid-centered-title"
className="mb-8 text-center text-2xl font-semibold text-foreground"
>
Sign In
</h3>
<SignInForm
hint={
<div className="mt-4 mb-8 text-right">
<Link
className="font-medium text-primary"
href="#password-recovery"
>
Forgot password?
</Link>
</div>
}
submitText="Log in"
submittingText="Logging in..."
/>
<Divider className="my-8" />
<Button
block
icon={
<img
alt=""
className="h-5 w-5 object-contain"
src={`${assetBase}/thumbs/brands/google.png`}
/>
}
type="button"
variant="default"
>
Continue with Google
</Button>
<p className="mt-8 text-center text-muted-foreground">
Don't have an account?{' '}
<Link className="font-medium text-primary" href="#sign-up">
Create an account
</Link>
</p>
</section>
</AuthShellCentered>
)
}
Authentication 12
Preview
npx nateui@latest add AuthSideImageDark
import Button from '@/components/ui/Button'
import Checkbox from '@/components/ui/Checkbox'
import Link from '@/components/ui/Link'
import Divider from '@/components/composites/Divider'
import AuthShellSide from '@/components/layouts/AuthShellSide'
import SignInForm from '@/components/patterns/SignInForm'
const assetBase = 'https://statics.nateui.com/img'
export default function AuthSideImage() {
return (
<AuthShellSide
className="h-screen"
sideContent={
<aside className="relative hidden flex-1 overflow-hidden rounded-xl lg:flex max-w-[520px]">
<img
alt=""
className="h-full w-full object-cover"
src={`${assetBase}/thumbs/misc/img-15.png`}
/>
</aside>
}
>
<section aria-labelledby="auth-side-image-title" className="w-full">
<header className="mb-8">
<div className="mb-4 flex items-center">
<img
alt=""
className="h-9 w-auto dark:hidden"
src={`${assetBase}/logos/logo-collapsed.svg`}
/>
<img
alt="NateUI"
className="hidden h-9 w-auto dark:block"
src={`${assetBase}/logos/logo-collapsed-white.svg`}
/>
</div>
<h3
id="auth-side-image-title"
className="text-2xl font-semibold leading-tight text-foreground"
>
Welcome back
</h3>
</header>
<div className="grid grid-cols-2 gap-4">
<Button
block
icon={
<img
alt=""
className="h-5 w-5 object-contain"
src={`${assetBase}/thumbs/brands/google.png`}
/>
}
type="button"
variant="default"
>
Google
</Button>
<Button
block
icon={
<img
alt=""
className="h-5 w-5 object-contain"
src={`${assetBase}/thumbs/brands/github.png`}
/>
}
type="button"
variant="default"
>
GitHub
</Button>
</div>
<div className="flex items-center gap-2 py-4">
<Divider className="my-0" />
<span>or</span>
<Divider className="my-0" />
</div>
<SignInForm
hint={
<div className="mt-4 mb-8 flex flex-wrap items-center justify-between gap-2">
<Checkbox name="remember-device">
Remember me
</Checkbox>
<Link
className="shrink-0 font-medium text-primary"
href="#password-recovery"
>
Forgot password?
</Link>
</div>
}
submitText="Sign in"
submittingText="Signing in..."
/>
<p className="mt-8 text-center text-muted-foreground">
New here?{' '}
<Link href="#sign-up" className="font-medium text-primary">
Create an account
</Link>
</p>
</section>
</AuthShellSide>
)
}
Authentication 13
Preview
npx nateui@latest add AuthCentredSplitDark
import Link from '@/components/ui/Link'
import AuthShellCentredSplit from '@/components/layouts/AuthShellCentredSplit'
import SignUpForm from '@/components/patterns/SignUpForm'
const assetBase = 'https://statics.nateui.com/img'
export default function AuthCentredSplit() {
return (
<AuthShellCentredSplit
className="bg-background text-foreground"
containerClass=" max-w-[950px] mx-auto"
header={
<div className="flex w-full items-center">
<img
alt=""
className="h-7 w-auto dark:hidden"
src={`${assetBase}/logos/logo.svg`}
/>
<img
alt="NateUI"
className="hidden h-7 w-auto dark:block"
src={`${assetBase}/logos/logo-white.svg`}
/>
</div>
}
footer={
<div className="flex w-full flex-col items-center gap-4 text-sm text-muted-foreground sm:flex-row sm:justify-between">
<div className="flex items-center gap-2">
<span>
Copyright © {`${new Date().getFullYear()}`} NateUI, Inc.
</span>
</div>
<div className="flex items-center gap-6">
<Link
className="text-muted-foreground hover:text-foreground"
href="#terms-of-service"
>
Terms of Service
</Link>
<Link
className="text-muted-foreground hover:text-foreground"
href="#privacy-policy"
>
Privacy Policy
</Link>
</div>
</div>
}
sideContent={
<div className="relative flex h-full items-center overflow-hidden bg-primary px-12 py-12 text-primary-foreground">
<img
alt=""
className="pointer-events-none absolute inset-0 h-full w-full object-cover opacity-10 select-none"
src={`${assetBase}/thumbs/misc/img-16.png`}
/>
<div className="relative max-w-sm">
<p className="font-semibold uppercase tracking-wide text-primary-foreground/90">
Start your 30 days free trial
</p>
<h2 className="mt-4 text-3xl font-semibold leading-tight text-primary-foreground max-w-[300px]">
Every customer chat in a single queue
</h2>
<blockquote className="mt-8 text-base leading-relaxed text-primary-foreground/90">
<p>
“We were juggling four inboxes and a spreadsheet.
First reply is now under an hour.”
</p>
<footer className="mt-4 font-medium text-primary-foreground">
Priya Raman,
<br />
Support Lead at Northwind
</footer>
</blockquote>
</div>
</div>
}
>
<section aria-labelledby="auth-centred-split-title">
<h3
id="auth-centred-split-title"
className="mb-8 text-2xl font-semibold text-foreground"
>
Create an account
</h3>
<SignUpForm
fields={[
'email',
'userName',
'password',
]}
submitText="Create my account"
submittingText="Creating account..."
/>
<p className="mt-8 text-center text-muted-foreground">
Already have an account?{' '}
<Link className="font-medium text-primary" href="#log-in">
Sign in
</Link>
</p>
</section>
</AuthShellCentredSplit>
)
}
Authentication 14
Preview
npx nateui@latest add AuthSidePanelDark
import Button from '@/components/ui/Button'
import Link from '@/components/ui/Link'
import AuthShellSide from '@/components/layouts/AuthShellSide'
import SignUpForm from '@/components/patterns/SignUpForm'
const assetBase = 'https://statics.nateui.com/img'
const GRID_WIDTH = 'w-[470px]'
const DIVIDER_COLOR = 'divide-white/40'
const SVG_OPACITY = 'opacity-10'
export default function AuthSidePanel() {
return (
<AuthShellSide
className="h-screen"
sideContent={
<aside className="relative hidden w-[520px] max-w-[720px] flex-1 overflow-hidden rounded-xl border border-gray-200 bg-primary lg:flex dark:border-gray-800">
<div className={`z-10 flex flex-1 flex-col justify-between divide-y ${DIVIDER_COLOR}`}>
<div className={`relative flex flex-1 divide-x ${DIVIDER_COLOR}`}>
<div className="relative flex-1">
<div className="absolute -bottom-1 -right-1 z-20 h-2 w-2 bg-white" />
</div>
<div className={`relative ${GRID_WIDTH}`}>
<div className="absolute left-0 top-0 h-full w-full bg-primary">
<svg
width="100%"
height="100%"
viewBox="0 0 161 161"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={SVG_OPACITY}
preserveAspectRatio="none"
>
<path d="M50.7645 0.428005V160.572" stroke="white" strokeWidth="0.5px" />
<path d="M80.6943 0.428005V160.572" stroke="white" strokeWidth="0.5px" />
<path d="M110.624 0.386559V160.531" stroke="white" strokeWidth="0.5px" />
</svg>
</div>
</div>
<div className="relative flex-1">
<div className="absolute -bottom-1 -left-1 z-20 h-2 w-2 bg-white" />
</div>
</div>
<div className={`z-10 flex divide-x ${DIVIDER_COLOR}`}>
<div className="flex-1 bg-primary text-white/30 bg-[repeating-linear-gradient(125deg,_transparent,_transparent_6px,_currentColor_6px,_currentColor_7px)]" />
<div className={`relative ${GRID_WIDTH}`}>
<div className="absolute bottom-0 left-0 -z-10 h-full w-full bg-primary">
<svg
width="100%"
height="100%"
viewBox="0 0 161 161"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={SVG_OPACITY}
preserveAspectRatio="none"
>
<g clipPath="url(#auth-side-panel-grid-clip)">
<rect x={11.1172} y={10.9229} width={139.154} height={139.154} stroke="white" strokeWidth="0.5px" strokeLinejoin="round" />
<path d="M50.7645 0.428005V160.572" stroke="white" strokeWidth="0.5px" />
<path d="M80.6943 0.428005V160.572" stroke="white" strokeWidth="0.5px" />
<path d="M110.624 0.386559V160.531" stroke="white" strokeWidth="0.5px" />
<path d="M0.622345 50.5702H160.766" stroke="white" strokeWidth="0.5px" />
<path d="M0.622345 80.5H160.766" stroke="white" strokeWidth="0.5px" />
<path d="M0.622345 110.43H160.766" stroke="white" strokeWidth="0.5px" />
<circle cx={80.6943} cy={80.5} r={69.5771} stroke="white" strokeWidth="0.5px" />
<ellipse cx={80.6943} cy={80.5} rx={42.3682} ry={42.3682} stroke="white" strokeWidth="0.5px" />
<ellipse cx={80.6943} cy={80.5} rx={29.9298} ry={29.9298} stroke="white" strokeWidth="0.5px" />
<path d="M11.1172 10.9229L150.271 150.077" stroke="white" strokeWidth="0.5px" />
<path d="M150.271 10.9229L11.1172 150.077" stroke="white" strokeWidth="0.5px" />
</g>
<defs>
<clipPath id="auth-side-panel-grid-clip">
<rect width={161} height={161} fill="white" />
</clipPath>
</defs>
</svg>
</div>
<div className={`z-10 flex h-[470px] items-center justify-center border border-white/40 bg-white/20 ${GRID_WIDTH}`}>
<div className="max-w-[340px] px-4">
<img
alt="NateUI"
className="mx-auto h-10"
src={`${assetBase}/logos/logo-white-collapsed.svg`}
/>
<h2 className="mt-8 text-3xl font-semibold text-white">
Start your journey with us!
</h2>
<p className="mt-4 text-base font-light text-white/80">
Discover the power of our app and unlock a world
of possibilities.
</p>
<Button
className="mt-8 text-foreground dark:border-gray-100 dark:bg-gray-100 dark:text-gray-900 dark:hover:border-gray-200 dark:hover:bg-gray-200"
size="lg"
>
Learn More
</Button>
</div>
</div>
</div>
<div className="flex-1 bg-primary text-white/30 bg-[repeating-linear-gradient(125deg,_transparent,_transparent_6px,_currentColor_6px,_currentColor_7px)]" />
</div>
<div className={`flex flex-1 divide-x ${DIVIDER_COLOR}`}>
<div className="relative flex-1">
<div className="absolute -right-1 -top-1 z-20 h-2 w-2 bg-white" />
</div>
<div className={`relative ${GRID_WIDTH}`}>
<div className="absolute left-0 top-0 h-full w-full bg-primary">
<svg
width="100%"
height="100%"
viewBox="0 0 161 161"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={SVG_OPACITY}
preserveAspectRatio="none"
>
<path d="M50.7645 0.428005V160.572" stroke="white" strokeWidth="0.5px" />
<path d="M80.6943 0.428005V160.572" stroke="white" strokeWidth="0.5px" />
<path d="M110.624 0.386559V160.531" stroke="white" strokeWidth="0.5px" />
</svg>
</div>
</div>
<div className="relative flex-1">
<div className="absolute -left-1 -top-1 z-20 h-2 w-2 bg-white" />
</div>
</div>
</div>
</aside>
}
>
<section aria-labelledby="auth-side-panel-title" className="w-full">
<header className="mb-8">
<h3
id="auth-side-panel-title"
className="text-2xl font-semibold leading-tight text-foreground"
>
Create your account
</h3>
<p className="mt-2 text-muted-foreground">
Tell us a bit about yourself to get started.
</p>
</header>
<SignUpForm
fields={[
'email',
'userName',
'password',
]}
submitText="Create my account"
submittingText="Creating account..."
/>
<p className="mt-8 text-center text-muted-foreground">
Already have an account?{' '}
<Link className="font-medium text-primary" href="#log-in">
Sign in
</Link>
</p>
</section>
</AuthShellSide>
)
}
Authentication 15
Preview
npx nateui@latest add AuthSideSplitDark
import Button from '@/components/ui/Button'
import Link from '@/components/ui/Link'
import Divider from '@/components/composites/Divider'
import AuthShellSplit from '@/components/layouts/AuthShellSplit'
import SignInForm from '@/components/patterns/SignInForm'
const assetBase = 'https://statics.nateui.com/img'
export default function AuthSideSplit() {
return (
<AuthShellSplit
className="h-screen"
sideContent={
<aside className="relative hidden flex-col overflow-hidden rounded-card bg-gradient-to-b from-primary/20 via-primary/5 to-background lg:flex">
<div className="px-8 pt-12 xl:px-12 xl:pt-16">
<h2 className="text-2xl xl:text-3xl leading-tight">
Know where every relationship stands.
</h2>
<p className="mt-2 xl:text-base text-muted-foreground">
Connection strength, owner, and open deals on one
screen — so a warm account never quietly goes cold.
</p>
</div>
<div className="relative mt-12 min-h-0 flex-1 overflow-hidden mask-b-from-55% xl:mt-16">
<div className="absolute left-8 top-0 h-[115%] w-[130%] rounded-[30px] xl:rounded-[40px] bg-inverse/10 p-2 xl:left-12">
<img
alt=""
className="h-full w-full rounded-[24px] object-cover object-left-top"
src={`${assetBase}/thumbs/misc/img-30.png`}
/>
</div>
</div>
</aside>
}
>
<section aria-labelledby="auth-side-split-title" className="w-full">
<div className="mb-4 flex items-center">
<img
alt=""
className="h-9 w-auto dark:hidden"
src={`${assetBase}/logos/logo-collapsed.svg`}
/>
<img
alt="NateUI"
className="hidden h-9 w-auto dark:block"
src={`${assetBase}/logos/logo-collapsed-white.svg`}
/>
</div>
<header className="mb-8">
<h3
id="auth-side-split-title"
className="text-2xl font-semibold leading-tight text-foreground"
>
Welcome back
</h3>
</header>
<div className="grid grid-cols-2 gap-4">
<Button
block
icon={
<img
alt=""
className="h-5 w-5 object-contain"
src={`${assetBase}/thumbs/brands/google.png`}
/>
}
type="button"
variant="default"
>
Google
</Button>
<Button
block
icon={
<svg
aria-hidden="true"
className="h-5 w-5"
fill="currentColor"
viewBox="0 0 24 24"
>
<path d="M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zm3.24-2.939c.84-1.012 1.402-2.42 1.245-3.827-1.207.052-2.665.805-3.532 1.817-.78.896-1.454 2.335-1.271 3.715 1.336.104 2.717-.688 3.558-1.705z" />
</svg>
}
type="button"
variant="default"
>
Apple
</Button>
</div>
<div className="flex items-center gap-2 py-4">
<Divider className="my-0" />
<span>or</span>
<Divider className="my-0" />
</div>
<SignInForm
hint={
<div className="mt-4 mb-8">
<Link
className="font-medium text-primary"
href="#password-recovery"
>
Forgot password?
</Link>
</div>
}
submitText="Log in"
submittingText="Logging in..."
/>
<p className="mt-8 text-center text-muted-foreground">
New here?{' '}
<Link href="#sign-up" className="font-medium text-primary">
Create an account
</Link>
</p>
</section>
</AuthShellSplit>
)
}