Custom UI Abstraxion Authentication
This guide explains how to implement Abstraxion authentication without using the legacy modal UI, giving you complete control over the user experience during the authentication flow.
Overview
Starting with version @burnt-labs/[email protected]
and later, you can implement a custom UI for the Abstraxion authentication process. This allows you to:
Display your own loading states and branding during authentication
Create a seamless authentication experience that matches your app's design
Handle the redirect flow programmatically
Key Changes
1. No Legacy Modal UI Import Required
The Abstraxion CSS import is no longer needed when using custom UI authentication:
- import "@burnt-labs/abstraxion/dist/index.css";
2. Direct Login Method
The useAbstraxionAccount
hook now provides a login
method that handles authentication without showing the legacy modal:
const { data: account, login, logout, isConnecting } = useAbstraxionAccount();
3. Custom Loading States
You can implement your own loading UI while authentication is in progress:
const [isLoggingIn, setIsLoggingIn] = useState(false);
const handleLogin = async () => {
try {
setIsLoggingIn(true);
await login();
} catch (error) {
console.error("There's been an error logging in");
} finally {
setIsLoggingIn(false);
}
};
Implementation Example
Here's a complete example showing how to implement custom UI authentication:
"use client";
import { useState, useEffect } from "react";
import {
useAbstraxionAccount,
useAbstraxionSigningClient,
} from "@burnt-labs/abstraxion";
import { Button } from "@burnt-labs/ui";
import "@burnt-labs/ui/dist/index.css";
export default function Page(): JSX.Element {
const { data: account, login, logout, isConnecting } = useAbstraxionAccount();
const { client } = useAbstraxionSigningClient();
const [isLoggingIn, setIsLoggingIn] = useState(false);
// Handle login with custom loading state
const handleLogin = async () => {
try {
setIsLoggingIn(true);
await login();
} catch (error) {
console.error("There's been an error logging in");
} finally {
setIsLoggingIn(false);
}
};
// Auto-login after redirect
useEffect(() => {
const searchParams = new URLSearchParams(window.location.search);
if (searchParams.get("granted") === "true") {
handleLogin();
}
}, []);
// Custom loading UI
if (isLoggingIn) {
return (
<main className="m-auto flex min-h-screen max-w-xs flex-col items-center justify-center gap-4 p-4">
<div className="rounded border border-white/20 p-6 text-center">
<p className="font-bold">You are being redirected...</p>
<p className="text-sm">
Use custom UI to render loading state with your own branding
</p>
</div>
</main>
);
}
return (
<main className="m-auto flex min-h-screen max-w-xs flex-col items-center justify-center gap-4 p-4">
<h1 className="text-2xl font-bold tracking-tighter text-white">
ABSTRAXION
</h1>
<Button
fullWidth
onClick={handleLogin}
structure="base"
disabled={isConnecting}
>
{account.bech32Address ? (
<div className="flex items-center justify-center">VIEW ACCOUNT</div>
) : isConnecting ? (
"LOADING..."
) : (
"CONNECT"
)}
</Button>
{account.bech32Address && (
<Button onClick={logout}>LOGOUT</Button>
)}
</main>
);
}
Important Changes from Legacy Modal Authentication
1. Remove Abstraxion Component
The <Abstraxion />
component is no longer needed:
- import { Abstraxion, useModal } from "@burnt-labs/abstraxion";
+ import { useAbstraxionAccount } from "@burnt-labs/abstraxion";
// Remove legacy modal state management
- const [, setShowModal] = useModal();
// Remove Abstraxion component
- <Abstraxion onClose={() => setShowModal(false)} />
2. Updated AbstraxionContext
The AbstraxionContext
now includes the login
method and handles redirect authentication automatically:
// Inside AbstraxionContextProvider
async function login() {
try {
setIsConnecting(true);
await abstraxionAuth.login();
} catch (error) {
console.log(error);
throw error;
} finally {
setIsConnecting(false);
}
}
// Auto-login on redirect
useEffect(() => {
const searchParams = new URLSearchParams(window.location.search);
if (searchParams.get("granted") === "true") {
login().catch((error) => {
console.error("Failed to finish login:", error);
});
}
}, []);
3. Simplified Loading Component
The built-in Loading component has been simplified to show only a spinner, allowing you to implement your own loading UI:
// Old Loading component with built-in text
- <h1>Connecting...</h1>
- <h2>Signing you in... Don't close the window.</h2>
// New simplified Loading component
+ <Spinner />
Migration Guide
To migrate from legacy modal to custom UI authentication:
Remove CSS import: Delete the Abstraxion CSS import
Remove legacy modal components: Remove
Abstraxion
component anduseModal
hookUse login method: Replace legacy modal trigger with the
login()
methodAdd custom loading UI: Implement your own loading state
Handle redirects: The redirect handling is automatic with the new implementation
Benefits
Better UX control: Full control over the authentication flow UI
Consistent branding: Loading states match your app's design
Cleaner code: No need to manage legacy modal state
Improved performance: Less CSS to load
Demo
A complete working example is available in the xion.js demo app.
Last updated
Was this helpful?