@iblai/web-containers
v1.1.3
Published
ibl web containers
Downloads
554
Keywords
Readme
@iblai/web-containers
A comprehensive React component library for IBL AI applications, built with shadcn/ui, Radix UI, and Tailwind CSS.
Installation
pnpm add @iblai/web-containersPackage Structure
The package is organized into multiple entry points:
@iblai/web-containers- Framework-agnostic components (works with any React app)@iblai/web-containers/next- Next.js-specific components (requires Next.js)@iblai/web-containers/sso- SSO utilities for handling authentication callbacks
Import Examples
// Framework-agnostic components (any React app)
import { Button, Card, LoginButton, SignupButton } from '@iblai/web-containers';
// Next.js-specific components (requires Next.js)
import { SsoLogin, ErrorPage, UserProfileDropdown } from '@iblai/web-containers/next';
// SSO utilities for custom implementations
import { handleSsoCallback, parseSsoData } from '@iblai/web-containers/sso';Overview
The web-containers package provides:
- Pre-built UI components following IBL AI design system
- Chat interfaces for AI mentor interactions
- Authentication components (LoginButton, SignupButton)
- Profile management components
- Subscription and billing components
- Form components with validation
- Notification system
- shadcn/ui components with IBL AI theming
Getting Started
Basic Setup
import { Button, Card, Input } from '@iblai/web-containers';
function MyComponent() {
return (
<Card>
<h2>Hello World</h2>
<Input placeholder="Enter text..." />
<Button>Submit</Button>
</Card>
);
}With Theming
import { ThemeProvider } from 'next-themes';
function App() {
return (
<ThemeProvider attribute="class" defaultTheme="light">
<YourApp />
</ThemeProvider>
);
}Authentication Components
Login Button
Redirect users to the auth SPA for login:
import { LoginButton } from '@iblai/web-containers';
function NavBar() {
return (
<nav>
<LoginButton
authUrl="https://auth.example.com"
appName="mentor"
platformKey="my-tenant"
label="Log In"
variant="default"
/>
</nav>
);
}Signup Button
Redirect users to signup/join flow:
import { SignupButton } from '@iblai/web-containers';
function LandingPage() {
return (
<div>
<h1>Join IBL AI</h1>
<SignupButton
authUrl="https://auth.example.com"
tenantKey="my-tenant"
label="Sign Up for Free"
variant="outline"
/>
</div>
);
}Combined Auth Buttons
import { LoginButton, SignupButton } from '@iblai/web-containers';
import { isLoggedIn } from '@iblai/web-utils';
function Header() {
if (isLoggedIn()) {
return <UserMenu />;
}
return (
<div className="flex gap-x-2">
<LoginButton
authUrl="https://auth.example.com"
appName="mentor"
label="Log In"
/>
<SignupButton
authUrl="https://auth.example.com"
label="Sign Up"
variant="outline"
/>
</div>
);
}SSO Login Component (Next.js)
Note: This component requires Next.js. Import from
@iblai/web-containers/next.
Handle SSO callbacks in your Next.js app:
// app/sso-login/page.tsx
import { SsoLogin } from '@iblai/web-containers/next';
const LOCAL_STORAGE_KEYS = {
CURRENT_TENANT: 'IBL_CURRENT_TENANT',
USER_DATA: 'IBL_USER_DATA',
TENANTS: 'IBL_TENANTS',
};
export default function SsoLoginPage() {
return (
<SsoLogin
localStorageKeys={LOCAL_STORAGE_KEYS}
defaultRedirectPath="/"
onLoginSuccess={(data) => {
console.log('Login successful:', data);
}}
/>
);
}SSO Utilities (Framework-agnostic)
For non-Next.js React applications, use the SSO utilities directly:
import {
handleSsoCallback,
parseSsoData,
DEFAULT_SSO_STORAGE_KEYS,
} from '@iblai/web-containers/sso';
// In your SSO callback handler
function handleCallback() {
const urlParams = new URLSearchParams(window.location.search);
const encodedData = urlParams.get('data');
if (encodedData) {
const result = handleSsoCallback({
encodedData,
localStorageKeys: DEFAULT_SSO_STORAGE_KEYS,
redirectPathKey: 'redirect-to',
defaultRedirectPath: '/',
});
if (result.success) {
window.location.href = result.redirectPath;
}
}
}UI Components
Buttons
import { Button } from '@iblai/web-containers';
<Button variant="default">Default</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
<Button size="sm">Small</Button>
<Button size="lg">Large</Button>
<Button disabled>Disabled</Button>Cards
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
} from '@iblai/web-containers';
<Card>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card description goes here</CardDescription>
</CardHeader>
<CardContent>
<p>Card content</p>
</CardContent>
<CardFooter>
<Button>Action</Button>
</CardFooter>
</Card>Forms
import {
Form,
FormField,
FormItem,
FormLabel,
FormControl,
FormMessage,
Input,
Button,
} from '@iblai/web-containers';
import { useForm } from '@tanstack/react-form';
function LoginForm() {
const form = useForm({
defaultValues: {
email: '',
password: '',
},
onSubmit: async ({ value }) => {
await login(value);
},
});
return (
<form onSubmit={form.handleSubmit}>
<FormField name="email">
{(field) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input
type="email"
value={field.state.value}
onChange={(e) => field.handleChange(e.target.value)}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
</FormField>
<Button type="submit">Sign In</Button>
</form>
);
}Dialogs
import {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
Button,
} from '@iblai/web-containers';
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you sure?</DialogTitle>
<DialogDescription>
This action cannot be undone.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button variant="outline">Cancel</Button>
<Button>Confirm</Button>
</DialogFooter>
</DialogContent>
</Dialog>Dropdowns
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
Button,
} from '@iblai/web-containers';
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline">Open Menu</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Settings</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>Logout</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>Chat Components
Chat Container
Full-featured chat interface for AI mentors:
import { ChatContainer } from '@iblai/web-containers';
function MentorChat() {
return (
<ChatContainer
mentorId="mentor-123"
tenantKey="my-tenant"
wsUrl="wss://api.example.com/chat"
wsToken="your-token"
onSessionCreate={(sessionId) => {
console.log('Session created:', sessionId);
}}
/>
);
}Chat Message
Display individual chat messages:
import { ChatMessage } from '@iblai/web-containers';
<ChatMessage
message={{
id: '1',
content: 'Hello! How can I help you?',
role: 'assistant',
timestamp: new Date(),
}}
isStreaming={false}
/>Chat Input
Input field for sending messages:
import { ChatInput } from '@iblai/web-containers';
<ChatInput
onSend={(message) => {
console.log('Sending:', message);
}}
placeholder="Type your message..."
disabled={false}
/>Profile Components
User Profile Dropdown (Next.js)
Note: This component requires Next.js. Import from
@iblai/web-containers/next.
import { UserProfileDropdown } from '@iblai/web-containers/next';
<UserProfileDropdown
user={{
name: 'John Doe',
email: '[email protected]',
avatar: 'https://example.com/avatar.jpg',
}}
onLogout={() => handleLogout()}
onProfileClick={() => navigate('/profile')}
/>Profile Settings
import { ProfileSettings } from '@iblai/web-containers';
<ProfileSettings
user={{
name: 'John Doe',
email: '[email protected]',
bio: 'Software developer',
}}
onUpdate={(data) => {
console.log('Updated:', data);
}}
/>Notification Components
Toast Notifications
import { useToast } from '@iblai/web-containers';
function MyComponent() {
const { toast } = useToast();
const showNotification = () => {
toast({
title: 'Success',
description: 'Your changes have been saved.',
variant: 'default',
});
};
return <Button onClick={showNotification}>Save</Button>;
}Notification Center
import { NotificationCenter } from '@iblai/web-containers';
<NotificationCenter
notifications={[
{
id: '1',
title: 'New message',
description: 'You have a new message from AI Mentor',
timestamp: new Date(),
read: false,
},
]}
onMarkAsRead={(id) => console.log('Mark as read:', id)}
onClearAll={() => console.log('Clear all')}
/>Subscription Components
Subscription Badge
import { SubscriptionBadge } from '@iblai/web-containers';
<SubscriptionBadge
plan="pro"
status="active"
/>Pricing Cards
import { PricingCard } from '@iblai/web-containers';
<PricingCard
title="Pro Plan"
price="$29"
period="month"
features={[
'Unlimited AI chats',
'Priority support',
'Advanced analytics',
]}
onSubscribe={() => handleSubscribe('pro')}
/>Advanced Components
Date Picker
import { Calendar } from '@iblai/web-containers';
import { useState } from 'react';
function DateSelector() {
const [date, setDate] = useState<Date | undefined>(new Date());
return (
<Calendar
mode="single"
selected={date}
onSelect={setDate}
/>
);
}Select
import {
Select,
SelectTrigger,
SelectValue,
SelectContent,
SelectItem,
} from '@iblai/web-containers';
<Select onValueChange={(value) => console.log(value)}>
<SelectTrigger>
<SelectValue placeholder="Select option" />
</SelectTrigger>
<SelectContent>
<SelectItem value="option1">Option 1</SelectItem>
<SelectItem value="option2">Option 2</SelectItem>
<SelectItem value="option3">Option 3</SelectItem>
</SelectContent>
</Select>Tabs
import {
Tabs,
TabsList,
TabsTrigger,
TabsContent,
} from '@iblai/web-containers';
<Tabs defaultValue="tab1">
<TabsList>
<TabsTrigger value="tab1">Tab 1</TabsTrigger>
<TabsTrigger value="tab2">Tab 2</TabsTrigger>
</TabsList>
<TabsContent value="tab1">Content 1</TabsContent>
<TabsContent value="tab2">Content 2</TabsContent>
</Tabs>Accordion
import {
Accordion,
AccordionItem,
AccordionTrigger,
AccordionContent,
} from '@iblai/web-containers';
<Accordion type="single" collapsible>
<AccordionItem value="item-1">
<AccordionTrigger>Question 1</AccordionTrigger>
<AccordionContent>Answer 1</AccordionContent>
</AccordionItem>
<AccordionItem value="item-2">
<AccordionTrigger>Question 2</AccordionTrigger>
<AccordionContent>Answer 2</AccordionContent>
</AccordionItem>
</Accordion>Styling
All components use Tailwind CSS and support custom className props:
<Button className="bg-blue-500 hover:bg-blue-600">
Custom Styled Button
</Button>
<Card className="shadow-lg border-2">
Custom Card
</Card>Theme Customization
Customize the theme in your tailwind.config.js:
module.exports = {
theme: {
extend: {
colors: {
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))',
},
},
},
},
}TypeScript Support
All components are fully typed:
import type {
ButtonProps,
CardProps,
ChatMessageProps,
UserProfileProps,
} from '@iblai/web-containers';
const buttonProps: ButtonProps = {
variant: 'default',
size: 'md',
disabled: false,
};Accessibility
All components follow WAI-ARIA guidelines and support:
- Keyboard navigation
- Screen reader support
- Focus management
- ARIA labels and descriptions
Contributing
We welcome contributions! Please read our contributing guidelines.
Development
Building
pnpm buildTesting
pnpm testStorybook
pnpm storybookLicense
ISC
