npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@iblai/web-containers

v1.1.3

Published

ibl web containers

Downloads

554

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-containers

Package 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 build

Testing

pnpm test

Storybook

pnpm storybook

License

ISC